]> Witch of Git - jade-rose/blob - toolchain/src/inst/parse.rs
Upgrade spec to v0.2.1
[jade-rose] / toolchain / src / inst / parse.rs
1 use super::{AddImm, AluI, Data, Inst, LdSt, Op1, OpI3, OpR, Reg, Special, U3};
2 use nom::{
3 branch::alt,
4 bytes::complete::tag_no_case,
5 character::complete::{char, digit1, hex_digit1, oct_digit1, one_of, space1},
6 combinator::{complete, map, map_opt, map_res, opt, recognize, value},
7 multi::many1,
8 sequence::{pair, preceded},
9 IResult,
10 };
11 use std::convert::TryFrom;
12
13 pub fn parse_inst(s: &str) -> Option<Inst> {
14 complete(inst)(s).ok().map(|x| x.1)
15 }
16
17 pub fn inst(s: &str) -> IResult<&str, Inst> {
18 alt((
19 alt((
20 fixed("TRAP", Inst::Trap),
21 fixed("NOPE", Inst::Nope),
22 fixed("PRNT", Inst::Prnt),
23 fixed("CABA", Inst::CAbA),
24 fixed("COFA", Inst::COfA),
25 )),
26 alt((
27 fixed("ZERO", Inst::Alu1(Op1::Zero)),
28 fixed("LSL1", Inst::Alu1(Op1::Lsl1)),
29 fixed("LSR1", Inst::Alu1(Op1::Lsr1)),
30 fixed("ASR1", Inst::Alu1(Op1::Asr1)),
31 fixed("INCR", Inst::Alu1(Op1::Incr)),
32 fixed("DECR", Inst::Alu1(Op1::Decr)),
33 fixed("COMP", Inst::Alu1(Op1::Comp)),
34 fixed("NEGT", Inst::Alu1(Op1::Negt)),
35 )),
36 alt((
37 fixed("GET1", Inst::Get(Special::Data(Data::D1))),
38 fixed("GET2", Inst::Get(Special::Data(Data::D2))),
39 fixed("GETC", Inst::Get(Special::Code)),
40 fixed("SET1", Inst::Set(Special::Data(Data::D1))),
41 fixed("SET2", Inst::Set(Special::Data(Data::D2))),
42 fixed("SETC", Inst::Set(Special::Code)),
43 )),
44 alt((
45 with_reg("GETR", |r| Inst::GetR(r)),
46 with_reg("SETR", |r| Inst::SetR(r)),
47 with_reg("SWAP", |r| Inst::Swap(r)),
48 with_reg("ISLT", |r| Inst::IsLt(r)),
49 )),
50 alt((
51 with_reg("ADDR", |r| Inst::AluR(OpR::Add, r)),
52 with_reg("SUBR", |r| Inst::AluR(OpR::Sub, r)),
53 with_reg("ANDR", |r| Inst::AluR(OpR::And, r)),
54 with_reg("IORR", |r| Inst::AluR(OpR::Ior, r)),
55 with_reg("XORR", |r| Inst::AluR(OpR::Xor, r)),
56 with_reg("LSLR", |r| Inst::AluR(OpR::Lsl, r)),
57 with_reg("LSRR", |r| Inst::AluR(OpR::Lsr, r)),
58 with_reg("ASRR", |r| Inst::AluR(OpR::Asr, r)),
59 )),
60 alt((
61 with_reg_bang("LD1U", |r, b| Inst::Mem(LdSt::Ld, Data::D1, r, b)),
62 with_reg_bang("ST1U", |r, b| Inst::Mem(LdSt::St, Data::D1, r, b)),
63 with_reg_bang("LD2U", |r, b| Inst::Mem(LdSt::Ld, Data::D2, r, b)),
64 with_reg_bang("ST2U", |r, b| Inst::Mem(LdSt::St, Data::D2, r, b)),
65 )),
66 alt((
67 with_imm8("ANDI", |imm| Inst::AluI(AluI::And(imm))),
68 with_imm8("IORI", |imm| Inst::AluI(AluI::Ior(imm))),
69 with_imm8("XORI", |imm| Inst::AluI(AluI::Xor(imm))),
70 )),
71 with_add_imm("ADDI", |imm| Inst::AluI(AluI::Add(imm))),
72 alt((
73 with_imm3("ROLI", |imm| Inst::AluI(AluI::Compact(OpI3::Rol, imm))),
74 with_imm3("LSLI", |imm| Inst::AluI(AluI::Compact(OpI3::Lsl, imm))),
75 with_imm3("LSRI", |imm| Inst::AluI(AluI::Compact(OpI3::Lsr, imm))),
76 with_imm3("ASRI", |imm| Inst::AluI(AluI::Compact(OpI3::Asr, imm))),
77 with_imm3("CLRI", |imm| Inst::AluI(AluI::Compact(OpI3::Clr, imm))),
78 with_imm3("INSI", |imm| Inst::AluI(AluI::Compact(OpI3::Ins, imm))),
79 with_imm3("TOGI", |imm| Inst::AluI(AluI::Compact(OpI3::Tog, imm))),
80 with_imm3("EXTI", |imm| Inst::AluI(AluI::Compact(OpI3::Ext, imm))),
81 )),
82 alt((
83 with_off("BEZI", |off| Inst::BEzI(off)),
84 with_off("JOFI", |off| Inst::JOfI(off)),
85 with_imm8("CABI", |imm| Inst::CAbI(imm)),
86 with_off("COFI", |off| Inst::COfI(off)),
87 with_fimm8("GETI", |imm| Inst::GetI(imm)),
88 )),
89 ))(s)
90 }
91
92 fn fixed<'s>(tag: &'s str, inst: Inst) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
93 value(inst, tag_no_case(tag))
94 }
95
96 fn reg(s: &str) -> IResult<&str, Reg> {
97 let raw = preceded(tag_no_case("r"), digit1);
98 let num = map_res(raw, |x: &str| x.parse());
99 map_opt(num, Reg::new)(s)
100 }
101
102 fn imm_dec(s: &str) -> IResult<&str, i16> {
103 let text = recognize(pair(opt(one_of("+-")), digit1));
104 let prefix = alt((tag_no_case("#d"), tag_no_case("#")));
105 map_res(preceded(prefix, text), |x: &str| x.parse())(s)
106 }
107
108 fn imm_hex(s: &str) -> IResult<&str, i16> {
109 let text = recognize(hex_digit1);
110 map_res(preceded(tag_no_case("#x"), text), |x| {
111 i16::from_str_radix(x, 16)
112 })(s)
113 }
114
115 fn imm_oct(s: &str) -> IResult<&str, i16> {
116 let text = recognize(oct_digit1);
117 map_res(preceded(tag_no_case("#o"), text), |x| {
118 i16::from_str_radix(x, 8)
119 })(s)
120 }
121
122 fn imm_bin(s: &str) -> IResult<&str, i16> {
123 let text = recognize(many1(one_of("01")));
124 map_res(preceded(tag_no_case("#b"), text), |x| {
125 i16::from_str_radix(x, 2)
126 })(s)
127 }
128
129 fn imm(s: &str) -> IResult<&str, i16> {
130 alt((imm_hex, imm_oct, imm_bin, imm_dec))(s)
131 }
132
133 fn imm8(s: &str) -> IResult<&str, u8> {
134 map_res(imm, TryFrom::try_from)(s)
135 }
136
137 fn simm8(s: &str) -> IResult<&str, i8> {
138 map_res(imm, TryFrom::try_from)(s)
139 }
140
141 fn fimm8(s: &str) -> IResult<&str, u8> {
142 alt((imm8, map(simm8, |x| x as u8)))(s)
143 }
144
145 fn add_imm(s: &str) -> IResult<&str, AddImm> {
146 map_opt(map_res(imm, TryFrom::try_from), AddImm::new)(s)
147 }
148
149 fn imm3(s: &str) -> IResult<&str, U3> {
150 map_opt(map_res(imm, TryFrom::try_from), U3::new)(s)
151 }
152
153 fn imm_off(s: &str) -> IResult<&str, i8> {
154 map_res(imm, TryFrom::try_from)(s)
155 }
156
157 fn with_reg<'s>(
158 tag: &'s str,
159 make_inst: impl Fn(Reg) -> Inst,
160 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
161 let reg = preceded(pair(tag_no_case(tag), space1), reg);
162 map(reg, make_inst)
163 }
164
165 fn with_reg_bang<'s>(
166 tag: &'s str,
167 make_inst: impl Fn(Reg, bool) -> Inst,
168 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
169 let reg_bang = pair(
170 preceded(pair(tag_no_case(tag), space1), reg),
171 map(opt(char('!')), |x| x.is_some()),
172 );
173 map(reg_bang, move |(r, b)| make_inst(r, b))
174 }
175
176 fn with_imm8<'s>(
177 tag: &'s str,
178 make_inst: impl Fn(u8) -> Inst,
179 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
180 let imm = preceded(pair(tag_no_case(tag), space1), imm8);
181 map(imm, make_inst)
182 }
183
184 fn with_add_imm<'s>(
185 tag: &'s str,
186 make_inst: impl Fn(AddImm) -> Inst,
187 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
188 let imm = preceded(pair(tag_no_case(tag), space1), add_imm);
189 map(imm, make_inst)
190 }
191
192 fn with_imm3<'s>(
193 tag: &'s str,
194 make_inst: impl Fn(U3) -> Inst,
195 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
196 let imm = preceded(pair(tag_no_case(tag), space1), imm3);
197 map(imm, make_inst)
198 }
199
200 fn with_off<'s>(
201 tag: &'s str,
202 make_inst: impl Fn(i8) -> Inst,
203 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
204 let imm = preceded(pair(tag_no_case(tag), space1), imm_off);
205 map(imm, make_inst)
206 }
207
208 fn with_fimm8<'s>(
209 tag: &'s str,
210 make_inst: impl Fn(u8) -> Inst,
211 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
212 let imm = preceded(pair(tag_no_case(tag), space1), fimm8);
213 map(imm, make_inst)
214 }