use pest::Parser; use pest_derive::Parser; pub mod ast; pub mod error; pub mod parser; pub mod rev_mapper; pub mod semantics; use ast::*; use crate::error::{IntoErr, ParseError}; #[derive(Parser)] #[grammar = "./src/grammar.pest"] pub struct MistParser; pub struct Program { pub mod_attributes: Vec, pub items: Vec, } pub fn parse<'a>(source: &'a str) -> Result>> { let mut pairs = MistParser::parse(Rule::program, source)?; let mut statements = vec![]; let mut analyzer = error::AstErrorAnalyzer(None); for pair in pairs.next().unwrap().into_inner() { if pair.as_rule() != Rule::EOI { statements.push(analyzer.get(TopLevel::try_from(pair)).get()?); } } match analyzer.build(statements) { Ok(v) => { let (mod_attributes, items): (Vec<_>, Vec<_>) = v .into_iter() .partition(|item| matches!(item.0.item, TopLevelKind::ModAttribute)); Ok(Program { items, mod_attributes, }) } Err(e) => { let rec = e.recovered.clone(); let mut e2 = e.get(); e2.recovered = rec; Err(ParseError::Ast(e2)) } } } pub fn parse_module<'a>( source: &'a str, ) -> Result, ParseError<'a, Option<(Visibility, Identifier)>>> { let mut pairs = MistParser::parse(Rule::module_program, source)?; if let Some(v) = pairs .next() .unwrap() .into_inner() .next() .map(TopLevel::try_from) .transpose() .get()? { if let TopLevelKind::DeclareModule(vis, name) = &v.0.item { Ok(Some((vis.clone(), name.clone()))) } else { Ok(None) } } else { Ok(None) } } #[macro_export] macro_rules! ast_ensure { ($pair:expr, $rule:expr $(, $rules:expr)* => $body:block) => { if $pair.as_rule() == $rule $(|| $pair.as_rule() == $rules)* $body else { Err(AstError { span: $pair.as_span(), error_code: crate::error::ErrorCode::AstGenBug, error_message: format!("Possible bug: expected {:?}, got {:?}", $rule, $pair.as_rule()), recovered: None, }) } }; } #[macro_export] macro_rules! ast_expr { (use $r:expr, $($v:expr),* $(,)?) => {{ let mut analyzer = $crate::error::AstErrorAnalyzer(None); $( analyzer.get($v).get()?; )* analyzer.build($r) }}; ($($item:ident)::+ { $($k:ident: $v:expr),* $(,)? }) => {{ let mut analyzer = $crate::error::AstErrorAnalyzer(None); let v = $($item)::+ { $($k: analyzer.get($v).get()?),* }; analyzer.build(v) }}; ($($item:ident)::+ ( $($v:expr),* $(,)? )) => {{ let mut analyzer = $crate::error::AstErrorAnalyzer(None); let v = $($item)::+ ( $(analyzer.get($v).get()?),* ); analyzer.build(v) }}; (( $($v:expr),* $(,)? )) => {{ let mut analyzer = $crate::error::AstErrorAnalyzer(None); let v = ( $(analyzer.get($v).get()?),* ); analyzer.build(v) }}; ($($item:ident)::+) => { $($item)::+ }; }