]> Witch of Git - jade-rose/blob - toolchain/src/inst/parse.rs
Update ISA spec to v0.2.2
[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, terminated},
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("STOP", Inst::Stop),
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 sign(s: &str) -> IResult<&str, i16> {
103 alt((
104 value(1, char('+')),
105 value(-1, char('-')),
106 value(1, tag_no_case("")),
107 ))(s)
108 }
109
110 fn imm_dec(s: &str) -> IResult<&str, i16> {
111 let prefix = terminated(sign, opt(tag_no_case("0d")));
112 map_res(pair(prefix, digit1), |p: (i16, &str)| {
113 p.1.parse::<i16>().map(|x| x * p.0)
114 })(s)
115 }
116
117 fn imm_hex(s: &str) -> IResult<&str, i16> {
118 let text = recognize(hex_digit1);
119 map_res(preceded(tag_no_case("0x"), text), |x| {
120 i16::from_str_radix(x, 16)
121 })(s)
122 }
123
124 fn imm_oct(s: &str) -> IResult<&str, i16> {
125 let text = recognize(oct_digit1);
126 map_res(preceded(tag_no_case("0o"), text), |x| {
127 i16::from_str_radix(x, 8)
128 })(s)
129 }
130
131 fn imm_bin(s: &str) -> IResult<&str, i16> {
132 let text = recognize(many1(one_of("01")));
133 map_res(preceded(tag_no_case("0b"), text), |x| {
134 i16::from_str_radix(x, 2)
135 })(s)
136 }
137
138 fn imm(s: &str) -> IResult<&str, i16> {
139 alt((imm_hex, imm_oct, imm_bin, imm_dec))(s)
140 }
141
142 fn imm8(s: &str) -> IResult<&str, u8> {
143 map_res(imm, TryFrom::try_from)(s)
144 }
145
146 fn simm8(s: &str) -> IResult<&str, i8> {
147 map_res(imm, TryFrom::try_from)(s)
148 }
149
150 fn fimm8(s: &str) -> IResult<&str, u8> {
151 alt((imm8, map(simm8, |x| x as u8)))(s)
152 }
153
154 fn add_imm(s: &str) -> IResult<&str, AddImm> {
155 map_opt(map_res(imm, TryFrom::try_from), AddImm::new)(s)
156 }
157
158 fn imm3(s: &str) -> IResult<&str, U3> {
159 map_opt(map_res(imm, TryFrom::try_from), U3::new)(s)
160 }
161
162 fn imm_off(s: &str) -> IResult<&str, i8> {
163 map_res(imm, TryFrom::try_from)(s)
164 }
165
166 fn with_reg<'s>(
167 tag: &'s str,
168 make_inst: impl Fn(Reg) -> Inst,
169 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
170 let reg = preceded(pair(tag_no_case(tag), space1), reg);
171 map(reg, make_inst)
172 }
173
174 fn with_reg_bang<'s>(
175 tag: &'s str,
176 make_inst: impl Fn(Reg, bool) -> Inst,
177 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
178 let reg_bang = pair(
179 preceded(pair(tag_no_case(tag), space1), reg),
180 map(opt(char('!')), |x| x.is_some()),
181 );
182 map(reg_bang, move |(r, b)| make_inst(r, b))
183 }
184
185 fn with_imm8<'s>(
186 tag: &'s str,
187 make_inst: impl Fn(u8) -> Inst,
188 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
189 let imm = preceded(pair(tag_no_case(tag), space1), imm8);
190 map(imm, make_inst)
191 }
192
193 fn with_add_imm<'s>(
194 tag: &'s str,
195 make_inst: impl Fn(AddImm) -> Inst,
196 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
197 let imm = preceded(pair(tag_no_case(tag), space1), add_imm);
198 map(imm, make_inst)
199 }
200
201 fn with_imm3<'s>(
202 tag: &'s str,
203 make_inst: impl Fn(U3) -> Inst,
204 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
205 let imm = preceded(pair(tag_no_case(tag), space1), imm3);
206 map(imm, make_inst)
207 }
208
209 fn with_off<'s>(
210 tag: &'s str,
211 make_inst: impl Fn(i8) -> Inst,
212 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
213 let imm = preceded(pair(tag_no_case(tag), space1), imm_off);
214 map(imm, make_inst)
215 }
216
217 fn with_fimm8<'s>(
218 tag: &'s str,
219 make_inst: impl Fn(u8) -> Inst,
220 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
221 let imm = preceded(pair(tag_no_case(tag), space1), fimm8);
222 map(imm, make_inst)
223 }