intuicio_frontend_assembler/
parser.rs1use crate::{
2 AsmEnum, AsmEnumVariant, AsmExpression, AsmFile, AsmFunction, AsmFunctionParameter, AsmLiteral,
3 AsmModule, AsmOperation, AsmStruct, AsmStructField,
4};
5use intuicio_core::Visibility;
6use pest::{Parser, iterators::Pair};
7use pest_derive::Parser;
8use std::{fmt::Debug, str::FromStr};
9
10#[derive(Parser)]
11#[grammar = "grammar.pest"]
12pub struct AsmParser;
13
14pub fn parse(content: &str) -> Result<AsmFile, String> {
15 match AsmParser::parse(Rule::file, content) {
16 Ok(mut pairs) => {
17 let pair = pairs.next().unwrap();
18 match pair.as_rule() {
19 Rule::file => Ok(parse_file(pair)),
20 rule => unreachable!("{:?}", rule),
21 }
22 }
23 Err(error) => Err(format!("{}", error)),
24 }
25}
26
27fn parse_file(pair: Pair<Rule>) -> AsmFile {
28 let mut result = AsmFile::default();
29 for pair in pair.into_inner() {
30 match pair.as_rule() {
31 Rule::file_item => {
32 let pair = pair.into_inner().next().unwrap();
33 match pair.as_rule() {
34 Rule::import => {
35 result
36 .dependencies
37 .push(parse_string(pair.into_inner().next().unwrap()));
38 }
39 Rule::module => {
40 result.modules.push(parse_module(pair));
41 }
42 rule => unreachable!("{:?}", rule),
43 }
44 }
45 Rule::EOI => {}
46 rule => unreachable!("{:?}", rule),
47 }
48 }
49 result
50}
51
52fn parse_module(pair: Pair<Rule>) -> AsmModule {
53 let mut pairs = pair.into_inner();
54 let mut result = AsmModule {
55 name: parse_identifier(pairs.next().unwrap()),
56 structs: vec![],
57 enums: vec![],
58 functions: vec![],
59 };
60 for pair in pairs {
61 let pair = pair.into_inner().next().unwrap();
62 match pair.as_rule() {
63 Rule::function => {
64 result.functions.push(parse_function(pair));
65 }
66 Rule::structure => {
67 result.structs.push(parse_structure(pair));
68 }
69 Rule::enumerator => {
70 result.enums.push(parse_enumerator(pair));
71 }
72 rule => unreachable!("{:?}", rule),
73 }
74 }
75 result
76}
77
78fn parse_structure(pair: Pair<Rule>) -> AsmStruct {
79 let mut pairs = pair.into_inner();
80 let mut result = parse_struct_header(pairs.next().unwrap());
81 result.fields = parse_struct_fields(pairs.next().unwrap());
82 result
83}
84
85fn parse_struct_fields(pair: Pair<Rule>) -> Vec<AsmStructField> {
86 pair.into_inner().map(parse_struct_field).collect()
87}
88
89fn parse_struct_field(pair: Pair<Rule>) -> AsmStructField {
90 let pairs = pair.into_inner();
91 let mut result = AsmStructField {
92 meta: None,
93 name: Default::default(),
94 visibility: Visibility::Public,
95 module_name: None,
96 type_name: Default::default(),
97 };
98 for pair in pairs {
99 match pair.as_rule() {
100 Rule::visibility => {
101 result.visibility = parse_visibility(pair);
102 }
103 Rule::identifier => {
104 result.name = parse_identifier(pair);
105 }
106 Rule::path_module => {
107 result.module_name = Some(parse_path_name(pair));
108 }
109 Rule::path_type => {
110 result.type_name = parse_path_name(pair.into_inner().next().unwrap());
111 }
112 rule => unreachable!("{:?}", rule),
113 }
114 }
115 result
116}
117
118fn parse_struct_header(pair: Pair<Rule>) -> AsmStruct {
119 let pairs = pair.into_inner();
120 let mut result = AsmStruct {
121 meta: None,
122 name: Default::default(),
123 visibility: Visibility::Public,
124 fields: vec![],
125 };
126 for pair in pairs {
127 match pair.as_rule() {
128 Rule::visibility => {
129 result.visibility = parse_visibility(pair);
130 }
131 Rule::path_struct => {
132 result.name = parse_path_name(pair);
133 }
134 rule => unreachable!("{:?}", rule),
135 }
136 }
137 result
138}
139
140fn parse_enumerator(pair: Pair<Rule>) -> AsmEnum {
141 let mut pairs = pair.into_inner();
142 let mut result = parse_enumerator_header(pairs.next().unwrap());
143 result.variants = parse_enumerator_variants(pairs.next().unwrap());
144 result
145}
146
147fn parse_enumerator_variants(pair: Pair<Rule>) -> Vec<AsmEnumVariant> {
148 pair.into_inner().map(parse_enumerator_variant).collect()
149}
150
151fn parse_enumerator_variant(pair: Pair<Rule>) -> AsmEnumVariant {
152 let pairs = pair.into_inner();
153 let mut result = AsmEnumVariant {
154 meta: None,
155 name: Default::default(),
156 fields: vec![],
157 discriminant: None,
158 };
159 for pair in pairs {
160 match pair.as_rule() {
161 Rule::identifier => {
162 result.name = parse_identifier(pair);
163 }
164 Rule::structure_fields => {
165 result.fields = parse_struct_fields(pair);
166 }
167 rule => unreachable!("{:?}", rule),
168 }
169 }
170 result
171}
172
173fn parse_enumerator_header(pair: Pair<Rule>) -> AsmEnum {
174 let pairs = pair.into_inner();
175 let mut result = AsmEnum {
176 meta: None,
177 name: Default::default(),
178 visibility: Visibility::Public,
179 variants: vec![],
180 default_variant: None,
181 };
182 for pair in pairs {
183 match pair.as_rule() {
184 Rule::visibility => {
185 result.visibility = parse_visibility(pair);
186 }
187 Rule::path_enum => {
188 result.name = parse_path_name(pair);
189 }
190 rule => unreachable!("{:?}", rule),
191 }
192 }
193 result
194}
195
196fn parse_function(pair: Pair<Rule>) -> AsmFunction {
197 let mut pairs = pair.into_inner();
198 let mut result = parse_function_header(pairs.next().unwrap());
199 result.inputs = parse_function_parameters(pairs.next().unwrap());
200 result.outputs = parse_function_parameters(pairs.next().unwrap());
201 result.script = parse_scope(pairs.next().unwrap());
202 result
203}
204
205fn parse_scope(pair: Pair<Rule>) -> Vec<AsmOperation> {
206 pair.into_inner().map(parse_operation).collect()
207}
208
209fn parse_operation(pair: Pair<Rule>) -> AsmOperation {
210 let pair = pair.into_inner().next().unwrap();
211 match pair.as_rule() {
212 Rule::push_literal => parse_push_literal(pair),
213 Rule::stack_drop => AsmOperation::Expression(AsmExpression::StackDrop),
214 Rule::make_register => parse_make_register(pair),
215 Rule::drop_register => parse_drop_register(pair),
216 Rule::push_from_register => parse_push_from_register(pair),
217 Rule::pop_to_register => parse_pop_to_register(pair),
218 Rule::call_function => parse_call_function(pair),
219 Rule::branch_scope => parse_branch_scope(pair),
220 Rule::loop_scope => parse_loop_scope(pair),
221 Rule::pop_scope => AsmOperation::PopScope,
222 rule => unreachable!("{:?}", rule),
223 }
224}
225
226fn parse_loop_scope(pair: Pair<Rule>) -> AsmOperation {
227 AsmOperation::LoopScope {
228 script: parse_scope(pair.into_inner().next().unwrap()),
229 }
230}
231
232fn parse_branch_scope(pair: Pair<Rule>) -> AsmOperation {
233 let mut pairs = pair.into_inner();
234 AsmOperation::BranchScope {
235 script_success: parse_scope(pairs.next().unwrap()),
236 script_failure: pairs.next().map(parse_scope),
237 }
238}
239
240fn parse_call_function(pair: Pair<Rule>) -> AsmOperation {
241 let pairs = pair.into_inner();
242 let mut name = Default::default();
243 let mut module_name = None;
244 let mut type_name = None;
245 let mut visibility = None;
246 for pair in pairs {
247 match pair.as_rule() {
248 Rule::visibility => {
249 visibility = Some(parse_visibility(pair));
250 }
251 Rule::path_module => {
252 module_name = Some(parse_path_name(pair));
253 }
254 Rule::path_type => {
255 type_name = Some(parse_path_name(pair.into_inner().next().unwrap()));
256 }
257 Rule::path_function => {
258 name = parse_path_name(pair);
259 }
260 rule => unreachable!("{:?}", rule),
261 }
262 }
263 AsmOperation::CallFunction {
264 name,
265 module_name,
266 type_name,
267 visibility,
268 }
269}
270
271fn parse_pop_to_register(pair: Pair<Rule>) -> AsmOperation {
272 AsmOperation::PopToRegister {
273 index: parse_literal::<usize>(pair),
274 }
275}
276
277fn parse_push_from_register(pair: Pair<Rule>) -> AsmOperation {
278 AsmOperation::PushFromRegister {
279 index: parse_literal::<usize>(pair),
280 }
281}
282
283fn parse_drop_register(pair: Pair<Rule>) -> AsmOperation {
284 AsmOperation::DropRegister {
285 index: parse_literal::<usize>(pair),
286 }
287}
288
289fn parse_make_register(pair: Pair<Rule>) -> AsmOperation {
290 let pairs = pair.into_inner();
291 let mut name = Default::default();
292 let mut module_name = None;
293 for pair in pairs {
294 match pair.as_rule() {
295 Rule::path_module => {
296 module_name = Some(parse_path_name(pair));
297 }
298 Rule::path_type => {
299 name = parse_path_name(pair);
300 }
301 rule => unreachable!("{:?}", rule),
302 }
303 }
304 AsmOperation::MakeRegister { name, module_name }
305}
306
307macro_rules! parse_literal {
308 ($type:ty, $pair:expr) => {{
309 let pair = $pair.into_inner().next().unwrap();
310 match pair.as_rule() {
311 Rule::integer | Rule::index => <$type>::from_str(pair.as_str()).unwrap(),
312 Rule::hex_inner => <$type>::from_str_radix(pair.as_str(), 16).unwrap(),
313 Rule::binary_inner => <$type>::from_str_radix(pair.as_str(), 2).unwrap(),
314 rule => unreachable!("{:?}", rule),
315 }
316 }};
317}
318
319fn parse_push_literal(pair: Pair<Rule>) -> AsmOperation {
320 let pair = pair
321 .into_inner()
322 .next()
323 .unwrap()
324 .into_inner()
325 .next()
326 .unwrap();
327 match pair.as_rule() {
328 Rule::literal_unit => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::Unit)),
329 Rule::literal_bool_false => {
330 AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::Bool(false)))
331 }
332 Rule::literal_bool_true => {
333 AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::Bool(true)))
334 }
335 Rule::literal_i8 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::I8(
336 parse_literal!(i8, pair),
337 ))),
338 Rule::literal_i16 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::I16(
339 parse_literal!(i16, pair),
340 ))),
341 Rule::literal_i32 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::I32(
342 parse_literal!(i32, pair),
343 ))),
344 Rule::literal_i64 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::I64(
345 parse_literal!(i64, pair),
346 ))),
347 Rule::literal_i128 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::I128(
348 parse_literal!(i128, pair),
349 ))),
350 Rule::literal_isize => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::Isize(
351 parse_literal!(isize, pair),
352 ))),
353 Rule::literal_u8 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::U8(
354 parse_literal!(u8, pair),
355 ))),
356 Rule::literal_u16 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::U16(
357 parse_literal!(u16, pair),
358 ))),
359 Rule::literal_u32 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::U32(
360 parse_literal!(u32, pair),
361 ))),
362 Rule::literal_u64 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::U64(
363 parse_literal!(u64, pair),
364 ))),
365 Rule::literal_u128 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::U128(
366 parse_literal!(u128, pair),
367 ))),
368 Rule::literal_usize => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::Usize(
369 parse_literal!(usize, pair),
370 ))),
371 Rule::literal_f32 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::F32(
372 parse_literal::<f32>(pair),
373 ))),
374 Rule::literal_f64 => AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::F64(
375 parse_literal::<f64>(pair),
376 ))),
377 Rule::literal_char => {
378 AsmOperation::Expression(AsmExpression::Literal(AsmLiteral::Char(parse_literal::<
379 char,
380 >(pair))))
381 }
382 Rule::literal_string => AsmOperation::Expression(AsmExpression::Literal(
383 AsmLiteral::String(parse_string(pair)),
384 )),
385 rule => unreachable!("{:?}", rule),
386 }
387}
388
389fn parse_function_parameters(pair: Pair<Rule>) -> Vec<AsmFunctionParameter> {
390 pair.into_inner().map(parse_function_parameter).collect()
391}
392
393fn parse_function_parameter(pair: Pair<Rule>) -> AsmFunctionParameter {
394 let mut pairs = pair.into_inner();
395 let mut result = AsmFunctionParameter {
396 meta: None,
397 name: parse_identifier(pairs.next().unwrap()),
398 module_name: None,
399 type_name: Default::default(),
400 };
401 for pair in pairs {
402 match pair.as_rule() {
403 Rule::path_module => {
404 result.module_name = Some(parse_path_name(pair));
405 }
406 Rule::path_type => {
407 result.type_name = parse_path_name(pair.into_inner().next().unwrap());
408 }
409 rule => unreachable!("{:?}", rule),
410 }
411 }
412 result
413}
414
415fn parse_function_header(pair: Pair<Rule>) -> AsmFunction {
416 let pairs = pair.into_inner();
417 let mut result = AsmFunction {
418 meta: None,
419 name: Default::default(),
420 type_name: None,
421 visibility: Visibility::Public,
422 inputs: vec![],
423 outputs: vec![],
424 script: vec![],
425 };
426 for pair in pairs {
427 match pair.as_rule() {
428 Rule::visibility => {
429 result.visibility = parse_visibility(pair);
430 }
431 Rule::path_type => {
432 result.type_name = Some(parse_path_name(pair.into_inner().next().unwrap()));
433 }
434 Rule::path_function => {
435 result.name = parse_path_name(pair);
436 }
437 rule => unreachable!("{:?}", rule),
438 }
439 }
440 result
441}
442
443fn parse_path_name(pair: Pair<Rule>) -> String {
444 parse_identifier(pair.into_inner().next().unwrap())
445}
446
447fn parse_visibility(pair: Pair<Rule>) -> Visibility {
448 match pair.into_inner().next().unwrap().as_rule() {
449 Rule::visibility_public => Visibility::Public,
450 Rule::visibility_internal => Visibility::Module,
451 Rule::visibility_private => Visibility::Private,
452 rule => unreachable!("{:?}", rule),
453 }
454}
455
456fn parse_literal<T>(pair: Pair<Rule>) -> T
457where
458 T: FromStr,
459 <T as FromStr>::Err: Debug,
460{
461 pair.into_inner()
462 .next()
463 .unwrap()
464 .as_str()
465 .parse::<T>()
466 .unwrap()
467}
468
469fn parse_string(pair: Pair<Rule>) -> String {
470 snailquote::unescape(pair.as_str()).unwrap()
471}
472
473fn parse_identifier(pair: Pair<Rule>) -> String {
474 pair.as_str().to_owned()
475}