]> Witch of Git - jade-rose/blob - toolchain/src/inst/parse.rs
Update spec
[jade-rose] / toolchain / src / inst / parse.rs
1 use super::{AddImm, AluI, Data, Inst, Op1, OpI3, OpR, Reg, Special, Target, 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("JABS", Inst::Jump(Target::Abs)),
22 fixed("CABS", Inst::Call(Target::Abs)),
23 fixed("JOFF", Inst::Jump(Target::Off)),
24 fixed("COFF", Inst::Call(Target::Off)),
25 )),
26 alt((
27 with_reg("SWAP", |r| Inst::Swap(r)),
28 with_reg("GETR", |r| Inst::GetR(r)),
29 with_reg("SETR", |r| Inst::SetR(r)),
30 )),
31 alt((
32 fixed("GET1", Inst::Get(Special::Data(Data::D1))),
33 fixed("GET2", Inst::Get(Special::Data(Data::D2))),
34 fixed("GETC", Inst::Get(Special::Code)),
35 fixed("SET1", Inst::Set(Special::Data(Data::D1))),
36 fixed("SET2", Inst::Set(Special::Data(Data::D2))),
37 fixed("SETC", Inst::Set(Special::Code)),
38 fixed("ZERO", Inst::Alu1(Op1::Zero)),
39 fixed("LSL1", Inst::Alu1(Op1::Lsl1)),
40 fixed("LSR1", Inst::Alu1(Op1::Lsr1)),
41 fixed("ASR1", Inst::Alu1(Op1::Asr1)),
42 fixed("INCR", Inst::Alu1(Op1::Incr)),
43 fixed("DECR", Inst::Alu1(Op1::Decr)),
44 fixed("COMP", Inst::Alu1(Op1::Comp)),
45 fixed("NEGT", Inst::Alu1(Op1::Negt)),
46 )),
47 alt((
48 with_reg("ISLT", |r| Inst::IsLt(r)),
49 with_reg("ADDR", |r| Inst::AluR(OpR::Add, r)),
50 with_reg("SUBR", |r| Inst::AluR(OpR::Sub, r)),
51 with_reg("ANDR", |r| Inst::AluR(OpR::And, r)),
52 with_reg("IORR", |r| Inst::AluR(OpR::Ior, r)),
53 with_reg("XORR", |r| Inst::AluR(OpR::Xor, r)),
54 with_reg("LSLR", |r| Inst::AluR(OpR::Lsl, r)),
55 with_reg("LSRR", |r| Inst::AluR(OpR::Lsr, r)),
56 with_reg("ASRR", |r| Inst::AluR(OpR::Asr, r)),
57 )),
58 alt((
59 with_reg_bang("LD1U", |r, b| Inst::LdD(Data::D1, r, b)),
60 with_reg_bang("ST1U", |r, b| Inst::StD(Data::D1, r, b)),
61 with_reg_bang("LD2U", |r, b| Inst::LdD(Data::D2, r, b)),
62 with_reg_bang("ST2U", |r, b| Inst::StD(Data::D2, r, b)),
63 )),
64 alt((
65 with_imm8("ANDI", |imm| Inst::AluI(AluI::And(imm))),
66 with_imm8("IORI", |imm| Inst::AluI(AluI::Ior(imm))),
67 with_imm8("XORI", |imm| Inst::AluI(AluI::Xor(imm))),
68 )),
69 with_add_imm("ADDI", |imm| Inst::AluI(AluI::Add(imm))),
70 alt((
71 with_imm3("ROLI", |imm| Inst::AluI(AluI::Compact(OpI3::Rol, imm))),
72 with_imm3("LSLI", |imm| Inst::AluI(AluI::Compact(OpI3::Lsl, imm))),
73 with_imm3("LSRI", |imm| Inst::AluI(AluI::Compact(OpI3::Lsr, imm))),
74 with_imm3("ASRI", |imm| Inst::AluI(AluI::Compact(OpI3::Asr, imm))),
75 with_imm3("CLRI", |imm| Inst::AluI(AluI::Compact(OpI3::Clr, imm))),
76 with_imm3("SETI", |imm| Inst::AluI(AluI::Compact(OpI3::Set, imm))),
77 with_imm3("TOGI", |imm| Inst::AluI(AluI::Compact(OpI3::Tog, imm))),
78 with_imm3("EXTI", |imm| Inst::AluI(AluI::Compact(OpI3::Ext, imm))),
79 )),
80 alt((
81 with_off("BEZI", |off| Inst::BEzI(off)),
82 with_off("JOFI", |off| Inst::Jump(Target::OffImm(off))),
83 with_off("COFI", |off| Inst::Call(Target::OffImm(off))),
84 )),
85 ))(s)
86 }
87
88 fn fixed<'s>(tag: &'s str, inst: Inst) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
89 value(inst, tag_no_case(tag))
90 }
91
92 fn reg(s: &str) -> IResult<&str, Reg> {
93 let raw = preceded(tag_no_case("r"), digit1);
94 let num = map_res(raw, |x: &str| x.parse());
95 map_opt(num, Reg::new)(s)
96 }
97
98 fn imm_dec(s: &str) -> IResult<&str, i16> {
99 let text = recognize(pair(opt(one_of("+-")), digit1));
100 let prefix = alt((tag_no_case("#d"), tag_no_case("#")));
101 map_res(preceded(prefix, text), |x: &str| x.parse())(s)
102 }
103
104 fn imm_hex(s: &str) -> IResult<&str, i16> {
105 let text = recognize(hex_digit1);
106 map_res(preceded(tag_no_case("#x"), text), |x| {
107 i16::from_str_radix(x, 16)
108 })(s)
109 }
110
111 fn imm_oct(s: &str) -> IResult<&str, i16> {
112 let text = recognize(oct_digit1);
113 map_res(preceded(tag_no_case("#o"), text), |x| {
114 i16::from_str_radix(x, 8)
115 })(s)
116 }
117
118 fn imm_bin(s: &str) -> IResult<&str, i16> {
119 let text = recognize(many1(one_of("01")));
120 map_res(preceded(tag_no_case("#b"), text), |x| {
121 i16::from_str_radix(x, 2)
122 })(s)
123 }
124
125 fn imm(s: &str) -> IResult<&str, i16> {
126 alt((imm_hex, imm_oct, imm_bin, imm_dec))(s)
127 }
128
129 fn imm8(s: &str) -> IResult<&str, u8> {
130 map_res(imm, TryFrom::try_from)(s)
131 }
132
133 fn add_imm(s: &str) -> IResult<&str, AddImm> {
134 map_opt(map_res(imm, TryFrom::try_from), AddImm::new)(s)
135 }
136
137 fn imm3(s: &str) -> IResult<&str, U3> {
138 map_opt(map_res(imm, TryFrom::try_from), U3::new)(s)
139 }
140
141 fn imm_off(s: &str) -> IResult<&str, i8> {
142 map_res(imm, TryFrom::try_from)(s)
143 }
144
145 fn with_reg<'s>(
146 tag: &'s str,
147 make_inst: impl Fn(Reg) -> Inst,
148 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
149 let reg = preceded(pair(tag_no_case(tag), space1), reg);
150 map(reg, make_inst)
151 }
152
153 fn with_reg_bang<'s>(
154 tag: &'s str,
155 make_inst: impl Fn(Reg, bool) -> Inst,
156 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
157 let reg_bang = pair(
158 preceded(pair(tag_no_case(tag), space1), reg),
159 map(opt(char('!')), |x| x.is_some()),
160 );
161 map(reg_bang, move |(r, b)| make_inst(r, b))
162 }
163
164 fn with_imm8<'s>(
165 tag: &'s str,
166 make_inst: impl Fn(u8) -> Inst,
167 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
168 let imm = preceded(pair(tag_no_case(tag), space1), imm8);
169 map(imm, make_inst)
170 }
171
172 fn with_add_imm<'s>(
173 tag: &'s str,
174 make_inst: impl Fn(AddImm) -> Inst,
175 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
176 let imm = preceded(pair(tag_no_case(tag), space1), add_imm);
177 map(imm, make_inst)
178 }
179
180 fn with_imm3<'s>(
181 tag: &'s str,
182 make_inst: impl Fn(U3) -> Inst,
183 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
184 let imm = preceded(pair(tag_no_case(tag), space1), imm3);
185 map(imm, make_inst)
186 }
187
188 fn with_off<'s>(
189 tag: &'s str,
190 make_inst: impl Fn(i8) -> Inst,
191 ) -> impl Fn(&'s str) -> IResult<&'s str, Inst> {
192 let imm = preceded(pair(tag_no_case(tag), space1), imm_off);
193 map(imm, make_inst)
194 }