1use pest::Parser;
2use pest_derive::Parser;
3
4pub mod ast;
5pub mod error;
6pub mod parser;
7pub mod rev_mapper;
8
9use ast::*;
10
11use crate::error::{IntoErr, ParseError};
12
13#[derive(Parser)]
14#[grammar = "./src/grammar.pest"]
15pub struct MistParser;
16
17pub fn parse<'a>(source: &'a str) -> Result<Vec<TopLevel>, ParseError<'a, Vec<TopLevel>>> {
18 let mut pairs = MistParser::parse(Rule::program, source)?;
19
20 let mut statements = vec![];
21
22 let mut analyzer = error::AstErrorAnalyzer(None);
23
24 for pair in pairs.next().unwrap().into_inner() {
25 if pair.as_rule() != Rule::EOI {
26 statements.push(analyzer.get(TopLevel::try_from(pair)).get()?);
27 }
28 }
29
30 match analyzer.build(statements) {
31 Ok(v) => Ok(v),
32 Err(e) => Err(ParseError::Ast(e)),
33 }
34}
35
36#[macro_export]
37macro_rules! ast_ensure {
38 ($pair:expr, $rule:expr $(, $rules:expr)* => $body:block) => {
39 if $pair.as_rule() == $rule $(|| $pair.as_rule() == $rules)*
40 $body
41 else {
42 Err(AstError {
43 span: $pair.as_span(),
44 error_code: crate::error::ErrorCode::AstGenBug,
45 error_message: format!("Possible bug: expected {:?}, got {:?}", $rule, $pair.as_rule()),
46 recovered: None,
47 })
48 }
49 };
50}
51
52#[macro_export]
53macro_rules! ast_expr {
54 (use $r:expr, $($v:expr),* $(,)?) => {{
55 let mut analyzer = $crate::error::AstErrorAnalyzer(None);
56
57 $(
58 analyzer.get($v).get()?;
59 )*
60
61 analyzer.build($r)
62 }};
63
64 ($($item:ident)::+ { $($k:ident: $v:expr),* $(,)? }) => {{
65 let mut analyzer = $crate::error::AstErrorAnalyzer(None);
66
67 let v = $($item)::+ { $($k: analyzer.get($v).get()?),* };
68
69 analyzer.build(v)
70 }};
71
72 ($($item:ident)::+ ( $($v:expr),* $(,)? )) => {{
73 let mut analyzer = $crate::error::AstErrorAnalyzer(None);
74
75 let v = $($item)::+ ( $(analyzer.get($v).get()?),* );
76
77 analyzer.build(v)
78 }};
79
80 (( $($v:expr),* $(,)? )) => {{
81 let mut analyzer = $crate::error::AstErrorAnalyzer(None);
82
83 let v = ( $(analyzer.get($v).get()?),* );
84
85 analyzer.build(v)
86 }};
87
88 ($($item:ident)::+) => {
89 $($item)::+
90 };
91}