diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index a109a0e..7854ab9 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -69,4 +69,4 @@ pub class Logger { return write!(f, "logger ({})", self.prefix); } } -} +} \ No newline at end of file diff --git a/parser/src/ast.rs b/parser/src/ast.rs index bcc5408..d2acb95 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -272,3 +272,9 @@ pub enum Literal { Bool(bool), Tuple(Vec), } + +impl TypeExpr { + pub fn no_px(kind: TypeExprKind) -> Self { + Self(kind, Vec::new()) + } +} diff --git a/parser/src/error.rs b/parser/src/error.rs index a3bf8cc..ebec476 100644 --- a/parser/src/error.rs +++ b/parser/src/error.rs @@ -1,3 +1,7 @@ +use std::fmt::Debug; + +use pest::iterators::Pair; + use crate::Rule; pub type AstResult<'a, T, ET = T> = Result>; @@ -18,7 +22,8 @@ pub struct AstError<'a, T> { #[derive(Debug, Clone)] pub enum ErrorCode { - InvalidStatement = 200, + InvalidStatement, + AstGenBug, } impl From> for ParseError<'_, T> { @@ -42,40 +47,48 @@ impl<'a, F> AstError<'a, F> { recovered: None, } } -} -pub trait GetParseError<'a, F> { - fn get(self) -> AstResult<'a, F, T>; -} - -impl<'a, F> GetParseError<'a, F> for AstResult<'a, F> { - fn get(self) -> AstResult<'a, F, T> { - match self { - Ok(v) => Ok(v), - Err(e) => Err(e.get()), - } + pub fn bug_unimplemented(pair: Pair<'a, Rule>) -> AstResult<'a, T, F> { + Err(Self { + span: pair.as_span(), + error_code: ErrorCode::AstGenBug, + error_message: format!("Possible bug, unimplemented: {:#?}", pair.as_rule()), + recovered: None, + }) } } -impl<'a, F> GetParseError<'a, Option> for Result, AstError<'a, F>> { - fn get(self) -> AstResult<'a, Option, T> { - match self { - Ok(v) => Ok(v), - Err(e) => Err(e.get()), - } +pub trait IntoErr { + fn get(self) -> T; + fn get_map(self, m: impl Fn(FA) -> FR) -> T; +} + +impl<'a, T, TE, TE2> IntoErr, TE, TE2> for AstResult<'a, T, TE> { + fn get(self) -> AstResult<'a, T, TE2> { + self.map_err(AstError::get) + } + + fn get_map(self, m: impl Fn(TE) -> TE2) -> AstResult<'a, T, TE2> { + self.map_err(|e| AstError { + span: e.span, + error_code: e.error_code, + error_message: e.error_message, + recovered: e.recovered.map(m), + }) } } -impl<'a, F> GetParseError<'a, Option>> for Result>, AstError<'a, F>> { - fn get(self) -> AstResult<'a, Option>, T> { - match self { - Ok(v) => Ok(v), - Err(e) => Err(e.get()), - } +pub trait GetLength { + fn len(&self) -> usize; +} + +impl GetLength for Result, E> { + fn len(&self) -> usize { + if let Ok(v) = self { v.len() } else { 0 } } } -pub fn collect_recovered<'a, T, ET>( +pub fn collect_recovered<'a, T: Debug, ET>( pairs: impl Iterator>, ) -> AstResult<'a, Vec, Vec> where @@ -84,7 +97,7 @@ where collect_recovered_map(pairs, T::try_from) } -pub fn collect_recovered_map<'a, T, F, ET>( +pub fn collect_recovered_map<'a, T: Debug, F, ET>( pairs: impl Iterator>, f: F, ) -> AstResult<'a, Vec, Vec> @@ -108,8 +121,39 @@ where span: ast_err.span, error_code: ast_err.error_code, error_message: ast_err.error_message, - recovered: None, + recovered: Some(items), }), None => Ok(items), } } + +pub struct AstErrorAnalyzer<'a, T>(pub Option>); + +impl<'a, T> AstErrorAnalyzer<'a, T> { + pub fn get>( + &mut self, + r: AstResult<'a, V, V2>, + ) -> AstResult<'a, V, V2> { + if let Err(e) = r { + self.0 = Some(e.clone().get()); + + if let Some(recovered) = e.recovered { + Ok(recovered.into()) + } else { + Err(e) + } + } else { + r + } + } + + pub fn build(self, v: T) -> AstResult<'a, T> { + if let Some(mut e) = self.0 { + e.recovered = Some(v); + + Err(e) + } else { + Ok(v) + } + } +} diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 13b699f..945c825 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -357,8 +357,10 @@ assign_statement = { // CONDITIONALS // ------------------------------------------------------ +statement_branch = { "(" ~ expr ~ ")" ~ statement } + else_if = { - "else" ~ "if" ~ "(" ~ expr ~ ")" ~ statement + "else" ~ "if" ~ statement_branch } else_if_list = { @@ -366,7 +368,7 @@ else_if_list = { } if_stmt = { - "if" ~ "(" ~ expr ~ ")" ~ statement ~ else_if_list ~ ("else" ~ statement)? + "if" ~ statement_branch ~ else_if_list ~ ("else" ~ statement)? } // ------------------------------------------------------ @@ -374,7 +376,7 @@ if_stmt = { // ------------------------------------------------------ while_stmt = { - "while" ~ "(" ~ expr ~ ")" ~ statement + "while" ~ statement_branch } c_for_stmt = { diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 5ab2bbf..df5cbf5 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -7,7 +7,7 @@ pub mod parser; use ast::*; -use crate::error::{GetParseError, ParseError}; +use crate::error::{IntoErr, ParseError}; #[derive(Parser)] #[grammar = "./src/grammar.pest"] @@ -18,11 +18,55 @@ pub fn parse<'a>(source: &'a str) -> Result, ParseError<'a, Vec Ok(v), + Err(e) => Err(ParseError::Ast(e)), + } +} + +#[macro_export] +macro_rules! ast_ensure { + ($pair:expr, $rule:expr => $body:block) => { + if $pair.as_rule() == $rule + $body + else { + Err(AstError { + span: $pair.as_span(), + error_code: crate::error::ErrorCode::AstGenBug, + error_message: format!("Possible bug: expected {:?}, got {}", $rule, $pair), + recovered: None, + }) + } + }; +} + +#[macro_export] +macro_rules! ast_expr { + ($($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) + }}; + + ($($item:ident)::+) => { + $($item)::+ + }; } diff --git a/parser/src/parser/common/decl.rs b/parser/src/parser/common/decl.rs index d9a3dc5..4cf8bfb 100644 --- a/parser/src/parser/common/decl.rs +++ b/parser/src/parser/common/decl.rs @@ -1,7 +1,8 @@ use crate::{ Rule, ast::*, - error::{AstError, GetParseError}, + ast_expr, + error::{AstError, AstResult, IntoErr}, parser::listen_rule, }; @@ -13,14 +14,13 @@ impl<'a> TryFrom> for VarDeclStmt { Rule::var_decl_statement => { let mut inner = pair.into_inner(); - let decl = VarDecl::try_from(inner.next().unwrap()).get()?; - - let init = inner.next().map(Expression::try_from).transpose().get()?; - - Ok(VarDeclStmt { decl, init }) + ast_expr!(VarDeclStmt { + decl: inner.next().unwrap().try_into(), + init: inner.next().map(Expression::try_from).transpose() + }) } - _ => unimplemented!(), + _ => AstError::bug_unimplemented(pair), } } } @@ -33,14 +33,13 @@ impl<'a> TryFrom> for FieldDeclStmt { Rule::class_field => { let mut inner = pair.into_inner(); - let decl = FieldDecl::try_from(inner.next().unwrap()).get()?; - - let init = inner.next().map(Expression::try_from).transpose().get()?; - - Ok(FieldDeclStmt { decl, init }) + ast_expr!(FieldDeclStmt { + decl: inner.next().unwrap().try_into(), + init: inner.next().map(Expression::try_from).transpose(), + }) } - _ => unimplemented!(), + _ => AstError::bug_unimplemented(pair), } } } @@ -62,21 +61,20 @@ impl<'a> TryFrom> for VarDecl { Some(TypeExpr::try_from(pair)) } }) - .transpose() - .get()?; + .transpose(); - let mutable = listen_rule(&mut inner, Rule::mutable); + let mutable: AstResult<'_, bool> = Ok(listen_rule(&mut inner, Rule::mutable)); - let name = Pattern::try_from(inner.next().unwrap()).get()?; + let name = Pattern::try_from(inner.next().unwrap()); - Ok(VarDecl { - mutable, - name, - type_, + ast_expr!(VarDecl { + type_: type_, + mutable: mutable, + name: name, }) } - _ => unimplemented!("{:?}", pair.as_rule()), + _ => AstError::bug_unimplemented(pair), } } } @@ -89,18 +87,14 @@ impl<'a> TryFrom> for FieldDecl { Rule::field => { let mut inner = pair.into_inner(); - let visibility = Visibility::try_from(&mut inner).get()?; - let type_ = TypeExpr::try_from(inner.next().unwrap()).get()?; - let name = Identifier::try_from(inner.next().unwrap()).get()?; - - Ok(FieldDecl { - visibility, - type_, - name, + ast_expr!(FieldDecl { + visibility: Visibility::try_from(&mut inner), + type_: TypeExpr::try_from(inner.next().unwrap()), + name: Identifier::try_from(inner.next().unwrap()), }) } - _ => unimplemented!("{:?}", pair.as_rule()), + _ => AstError::bug_unimplemented(pair), } } } diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index ff0ccd9..e49680d 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -1,7 +1,8 @@ use crate::{ Rule, ast::*, - error::{AstError, AstResult, GetParseError, collect_recovered, collect_recovered_map}, + ast_expr, + error::{AstError, GetLength, IntoErr, collect_recovered, collect_recovered_map}, }; impl<'a> TryFrom> for Expression { @@ -15,32 +16,27 @@ impl<'a> TryFrom> for Expression { Rule::expr => { let prefixes = inner .next() - .map(|p| { - p.into_inner() - .into_iter() - .map(Prefix::try_from) - .collect::, _>>() - }) - .transpose() - .get()? - .unwrap_or_default(); + .map(|p| collect_recovered::(p.into_inner())) + .unwrap_or_else(|| Ok(Vec::new())); - let exp = Expression::try_from(inner.next().unwrap())?; + let exp = Expression::try_from(inner.next().unwrap()); if inner.len() > 0 || prefixes.len() > 0 { - Ok(Expression::Fix { - initial: Box::new(exp), - prefixes, - postfixes: collect_recovered(inner).get()?, + ast_expr!(Expression::Fix { + initial: exp.map(Box::new), + prefixes: prefixes, + postfixes: collect_recovered(inner), }) } else { - Ok(exp) + exp } } - Rule::primary => Expression::try_from(inner.next().unwrap()), - Rule::static_path => Ok(Expression::Path(Path::try_from(pair).get()?)), - Rule::literal => Ok(Expression::Literal(Literal::try_from(pair).get()?)), - _ => unimplemented!("{rule:#?}"), + + Rule::primary => inner.next().unwrap().try_into(), + Rule::static_path => ast_expr!(Expression::Path(pair.try_into())), + Rule::literal => ast_expr!(Expression::Literal(pair.try_into())), + + _ => AstError::bug_unimplemented(pair), } } } @@ -56,7 +52,8 @@ impl<'a> TryFrom> for Prefix { Rule::ref_px => Self::Ref, Rule::new_px => Self::New, Rule::not_px => Self::Not, - _ => unimplemented!("{pair:#?}"), + + _ => return AstError::bug_unimplemented(pair), }) } } @@ -66,29 +63,28 @@ impl<'a> TryFrom> for Postfix { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); - let mut inner = pair.into_inner(); + let mut inner = pair.clone().into_inner(); - Ok(match rule { - Rule::postfix => Postfix::try_from(inner.next().unwrap())?, + match rule { + Rule::postfix => Postfix::try_from(inner.next().unwrap()), Rule::field_px => { - Postfix::FieldAccess(Identifier::try_from(inner.next().unwrap()).get()?) + ast_expr!(Postfix::FieldAccess(inner.next().unwrap().try_into())) } - Rule::call_px => Postfix::Call(collect_recovered(inner).get()?), + Rule::call_px => ast_expr!(Postfix::Call(collect_recovered(inner))), - Rule::struct_px => Postfix::StructCall( - collect_recovered_map(inner, |p| { - let mut pi = p.into_inner(); - Ok(( - Identifier::try_from(pi.next().unwrap())?, - Expression::try_from(pi.next().unwrap()).get()?, - )) - }) - .get()?, - ), + Rule::struct_px => ast_expr!(Postfix::StructCall(collect_recovered_map(inner, |p| { + let mut pi = p.into_inner(); + Ok(( + Identifier::try_from(pi.next().unwrap())?, + Expression::try_from(pi.next().unwrap()).get()?, + )) + }))), - Rule::index_px => Postfix::Index(Expression::try_from(inner.next().unwrap()).get()?), + Rule::index_px => { + ast_expr!(Postfix::Index(Expression::try_from(inner.next().unwrap()))) + } Rule::binary_px => { let op_pair = inner.next().unwrap(); @@ -107,16 +103,15 @@ impl<'a> TryFrom> for Postfix { "&&" => BinaryOp::And, "||" => BinaryOp::Or, - _ => { - unimplemented!("Binary operator not implemented yet: {}", op_pair.as_str()) - } + _ => return AstError::bug_unimplemented(op_pair), }; - Postfix::Binary(op, Expression::try_from(inner.next().unwrap()).get()?) + + Ok(Postfix::Binary(op, inner.next().unwrap().try_into().get()?)) } - Rule::macro_call_px => Postfix::MacroCall(inner.as_str().to_string()), + Rule::macro_call_px => Ok(Postfix::MacroCall(inner.as_str().to_string())), - _ => unimplemented!("{rule:#?}"), - }) + _ => AstError::bug_unimplemented(pair), + } } } diff --git a/parser/src/parser/common/mod.rs b/parser/src/parser/common/mod.rs index 067dba2..206e3c9 100644 --- a/parser/src/parser/common/mod.rs +++ b/parser/src/parser/common/mod.rs @@ -6,7 +6,8 @@ pub mod types; use crate::{ Rule, ast::*, - error::{AstError, GetParseError, collect_recovered}, + ast_ensure, ast_expr, + error::{AstError, IntoErr, collect_recovered}, parser::consume_rule, }; @@ -14,7 +15,9 @@ impl<'a> TryFrom> for Identifier { type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - Ok(Identifier(pair.as_str().to_string())) + ast_ensure!(pair, Rule::identifier => { + Ok(Identifier(pair.as_str().to_string())) + }) } } @@ -24,7 +27,7 @@ impl<'a> TryFrom> for Path { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { Rule::static_path => Ok(Path(collect_recovered(pair.into_inner()).get()?)), - _ => unimplemented!("{pair:#?}"), + _ => AstError::bug_unimplemented(pair), } } } @@ -44,7 +47,7 @@ impl<'a> TryFrom> for Literal { Rule::boolean => Literal::Bool(pair.as_str().parse::().unwrap()), Rule::string_lit => Literal::String(inner.as_str().to_string()), Rule::tuple => Literal::Tuple(collect_recovered(inner).get()?), - _ => unimplemented!("{rule:#?}"), + _ => return AstError::bug_unimplemented(pair), }) } } @@ -56,27 +59,27 @@ impl<'a> TryFrom> for Pattern { let rule = pair.as_rule(); let mut inner = pair.clone().into_inner(); - Ok(match rule { - Rule::tuple_pattern => Pattern::Tuple(collect_recovered(pair.into_inner()).get()?), + match rule { + Rule::tuple_pattern => ast_expr!(Pattern::Tuple(collect_recovered(pair.into_inner()))), - Rule::named_tuple_pattern => Pattern::NamedTuple( - Path::try_from(inner.next().unwrap()).get()?, - collect_recovered(inner).get()?, - ), + Rule::named_tuple_pattern => ast_expr!(Pattern::NamedTuple( + Path::try_from(inner.next().unwrap()), + collect_recovered(inner), + )), - Rule::struct_pattern => Pattern::Struct( - Path::try_from(inner.next().unwrap()).get()?, - collect_recovered(inner).get()?, - ), + Rule::struct_pattern => ast_expr!(Pattern::Struct( + Path::try_from(inner.next().unwrap()), + collect_recovered(inner), + )), - Rule::literal => Pattern::Literal(Literal::try_from(pair).get()?), + Rule::literal => ast_expr!(Pattern::Literal(pair.try_into())), - Rule::identifier => Pattern::Id(Identifier::try_from(pair).get()?), + Rule::identifier => ast_expr!(Pattern::Id(pair.try_into())), - Rule::static_path => Pattern::Path(Path::try_from(pair).get()?), + Rule::static_path => ast_expr!(Pattern::Path(pair.try_into())), - _ => unimplemented!("{rule:?}"), - }) + _ => AstError::bug_unimplemented(pair), + } } } @@ -87,7 +90,7 @@ impl<'a> TryFrom<&mut pest::iterators::Pairs<'a, Rule>> for Visibility { Ok(consume_rule(pairs, Rule::visibility) .map(|pair| -> Result> { if let Some(path) = pair.into_inner().next() { - Ok(Visibility::PublicTarget(Path::try_from(path).get()?)) + ast_expr!(Visibility::PublicTarget(Path::try_from(path))) } else { Ok(Visibility::Public) } diff --git a/parser/src/parser/common/statement.rs b/parser/src/parser/common/statement.rs index 3f5afd5..243e6a3 100644 --- a/parser/src/parser/common/statement.rs +++ b/parser/src/parser/common/statement.rs @@ -1,7 +1,8 @@ use crate::{ Rule, ast::*, - error::{AstError, AstResult, ErrorCode, GetParseError, collect_recovered}, + ast_ensure, ast_expr, + error::{AstError, AstResult, ErrorCode, IntoErr, collect_recovered}, parser::listen_rule, }; @@ -9,19 +10,24 @@ impl<'a> TryFrom> for Block { type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - if pair.as_rule() == Rule::block { - Ok(Block(collect_recovered(pair.into_inner()).get()?)) - } else { - Err(AstError { - span: pair.as_span(), - error_code: ErrorCode::InvalidStatement, - error_message: format!( - "BUG: AST requires a block, this isn't a block, it's a {:?}", - pair.as_rule() - ), - recovered: None, + ast_ensure!(pair, Rule::block => { + ast_expr!(Block(collect_recovered(pair.into_inner()))) + }) + } +} + +impl<'a> TryFrom> for StatementBranch { + type Error = AstError<'a, Self>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let mut inner = pair.clone().into_inner(); + + ast_ensure!(pair, Rule::statement_branch => { + ast_expr!(StatementBranch { + condition: inner.next().unwrap().try_into(), + body: inner.next().unwrap().try_into().map(Box::new), }) - } + }) } } @@ -32,62 +38,65 @@ impl<'a> TryFrom> for Statement { let rule = pair.as_rule(); let mut inner = pair.clone().into_inner(); - Ok(match rule { - Rule::statement => Statement::try_from(inner.next().unwrap())?, + match rule { + Rule::statement => Statement::try_from(inner.next().unwrap()), Rule::expr_stmt => { - Statement::Expression(Expression::try_from(inner.next().unwrap()).get()?) + ast_expr!(Statement::Expression(inner.next().unwrap().try_into())) } - Rule::block => Statement::Block(pair.try_into().get()?), + Rule::block => ast_expr!(Statement::Block(pair.try_into())), - Rule::var_decl_statement => Statement::VarDecl(VarDeclStmt::try_from(pair).get()?), + Rule::var_decl_statement => ast_expr!(Statement::VarDecl(pair.try_into())), Rule::return_stmt => { - Statement::Return(inner.next().map(Expression::try_from).transpose().get()?) + ast_expr!(Statement::Return( + inner.next().map(Expression::try_from).transpose() + )) } - Rule::break_stmt => Statement::Break, + Rule::break_stmt => Ok(Statement::Break), - Rule::continue_stmt => Statement::Continue, + Rule::continue_stmt => Ok(Statement::Continue), Rule::if_stmt => { - let mut inner = inner.skip(2); - - Statement::If { - initial: StatementBranch::try_from(pair).get()?, - else_if: collect_recovered(inner.next().unwrap().into_inner()).get()?, + ast_expr!(Statement::If { + initial: inner.next().unwrap().try_into(), + else_if: collect_recovered(inner.next().unwrap().into_inner()), else_branch: inner .next() .map(Statement::try_from) - .transpose()? - .map(Box::new), - } + .transpose() + .map(|v| v.map(Box::new)) + .get_map(|v| { Some(Box::new(v)) }), + }) } - Rule::while_stmt => Statement::While(pair.try_into().get()?), + Rule::while_stmt => ast_expr!(Statement::While(inner.next().unwrap().try_into())), - Rule::c_for_stmt => Statement::CStyleFor { - init: Box::new(inner.next().unwrap().try_into().get()?), - condition: inner.next().unwrap().try_into().get()?, - update: Box::new(inner.next().unwrap().try_into().get()?), - body: Box::new(inner.next().unwrap().try_into().get()?), - }, - - Rule::for_stmt => Statement::For { - mutable: listen_rule(&mut inner, Rule::mutable), - pattern: inner.next().unwrap().try_into().get()?, - iterator: inner.next().unwrap().try_into().get()?, - body: Box::new(Statement::try_from(inner.next().unwrap())?), - }, - - Rule::assign_statement => Statement::VarAssign(VarAssignStmt { - target: inner.next().unwrap().try_into().get()?, - value: inner.next().unwrap().try_into().get()?, + Rule::c_for_stmt => ast_expr!(Statement::CStyleFor { + init: inner.next().unwrap().try_into().map(Box::new), + condition: inner.next().unwrap().try_into(), + update: inner.next().unwrap().try_into().map(Box::new), + body: inner.next().unwrap().try_into().map(Box::new), }), - Rule::match_stmt => Statement::Match( - inner.next().unwrap().try_into().get()?, + Rule::for_stmt => ast_expr!(Statement::For { + mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>, + pattern: inner.next().unwrap().try_into(), + iterator: inner.next().unwrap().try_into(), + body: inner.next().unwrap().try_into().map(Box::new), + }), + + Rule::assign_statement => ast_expr!(VarAssignStmt { + target: inner.next().unwrap().try_into(), + value: inner.next().unwrap().try_into(), + }) + .map(Statement::VarAssign) + .get_map(Statement::VarAssign), + + Rule::match_stmt => ast_expr!(Statement::Match( + inner.next().unwrap().try_into(), inner .map(|match_itms| { let mut match_inner = match_itms.into_inner(); @@ -96,9 +105,8 @@ impl<'a> TryFrom> for Statement { Block::try_from(match_inner.next().unwrap()).get()?, )) }) - .collect::>>() - .get()?, - ), + .collect::>>(), + )), Rule::unexpected_statement => { return Err(AstError { @@ -109,23 +117,7 @@ impl<'a> TryFrom> for Statement { }); } - _ => unimplemented!("{rule:#?}"), - }) - } -} - -impl<'a> TryFrom> for StatementBranch { - type Error = AstError<'a, Self>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let mut inner = pair.into_inner(); - - let condition = inner.next().unwrap().try_into().get()?; - let body = inner.next().unwrap().try_into().get()?; - - Ok(StatementBranch { - condition, - body: Box::new(body), - }) + _ => AstError::bug_unimplemented(pair), + } } } diff --git a/parser/src/parser/common/types.rs b/parser/src/parser/common/types.rs index 19a91c9..7e64d1c 100644 --- a/parser/src/parser/common/types.rs +++ b/parser/src/parser/common/types.rs @@ -1,7 +1,8 @@ use crate::{ Rule, ast::*, - error::{AstError, GetParseError, collect_recovered}, + ast_expr, + error::{AstError, GetLength, IntoErr, collect_recovered}, parser::{consume_rule, listen_rule}, }; @@ -10,7 +11,7 @@ impl<'a> TryFrom> for TypePostfix { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); - let mut inner = pair.into_inner(); + let mut inner = pair.clone().into_inner(); match rule { Rule::ref_type => { @@ -34,7 +35,8 @@ impl<'a> TryFrom> for TypePostfix { } }) } - _ => unimplemented!("{rule:#?}"), + + _ => AstError::bug_unimplemented(pair), } } } @@ -44,21 +46,21 @@ impl<'a> TryFrom> for TypeExprKind { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); - let mut inner = pair.into_inner(); + let mut inner = pair.clone().into_inner(); match rule { - Rule::tuple_type => Ok(TypeExprKind::Tuple(collect_recovered(inner).get()?)), + Rule::tuple_type => ast_expr!(TypeExprKind::Tuple(collect_recovered(inner))), Rule::path_type => { - let path = Path::try_from(inner.next().unwrap()).get()?; - let params = collect_recovered(inner).get()?; + let path = Path::try_from(inner.next().unwrap()); + let params = collect_recovered(inner); if params.len() == 0 { - Ok(TypeExprKind::Path(path)) + ast_expr!(TypeExprKind::Path(path)) } else { - Ok(TypeExprKind::PathParams(path, params)) + ast_expr!(TypeExprKind::PathParams(path, params)) } } - _ => unimplemented!("{rule:#?}"), + _ => AstError::bug_unimplemented(pair), } } } @@ -68,19 +70,19 @@ impl<'a> TryFrom> for TypeExpr { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); - let mut inner = pair.into_inner(); + let mut inner = pair.clone().into_inner(); match rule { - Rule::type_expr => Ok(TypeExpr( - inner.next().unwrap().try_into().get()?, - collect_recovered(inner).get()?, + Rule::type_expr => ast_expr!(TypeExpr( + inner.next().unwrap().try_into(), + collect_recovered(inner), )), Rule::type_expr_param => Self::try_from(inner.next().unwrap()), - Rule::lifetime => Ok(TypeExpr( - TypeExprKind::Lifetime(inner.next().unwrap().try_into().get()?), - Vec::new(), - )), - _ => unimplemented!("{rule:#?}"), + Rule::lifetime => ast_expr!(TypeExprKind::Lifetime(inner.next().unwrap().try_into())) + .get_map(TypeExpr::no_px) + .map(TypeExpr::no_px), + + _ => AstError::bug_unimplemented(pair), } } } @@ -93,8 +95,8 @@ impl<'a> TryFrom> for Generics { let inner = pair.clone().into_inner(); match rule { - Rule::generics => Ok(Generics(collect_recovered(inner).get()?)), - _ => unimplemented!("{rule:#?}"), + Rule::generics => ast_expr!(Generics(collect_recovered(inner))), + _ => AstError::bug_unimplemented(pair), } } } @@ -106,13 +108,13 @@ impl<'a> TryFrom> for Generic { let mut inner = pair.clone().into_inner(); if let Some(pair) = consume_rule(&mut inner, Rule::lifetime) { - Ok(Generic::Lifetime( - pair.into_inner().next().unwrap().try_into().get()?, + ast_expr!(Generic::Lifetime( + pair.into_inner().next().unwrap().try_into(), )) } else { - Ok(Generic::Type( - inner.next().unwrap().try_into().get()?, - collect_recovered(inner).get()?, + ast_expr!(Generic::Type( + inner.next().unwrap().try_into(), + collect_recovered(inner), )) } } diff --git a/parser/src/parser/items/attribute.rs b/parser/src/parser/items/attribute.rs index 5f64605..f3b22ec 100644 --- a/parser/src/parser/items/attribute.rs +++ b/parser/src/parser/items/attribute.rs @@ -1,7 +1,7 @@ use crate::{ Rule, ast::*, - error::{AstError, GetParseError, collect_recovered}, + error::{AstError, IntoErr, collect_recovered}, }; impl<'a> TryFrom> for Attribute { diff --git a/parser/src/parser/items/class.rs b/parser/src/parser/items/class.rs index 88b2944..86eef27 100644 --- a/parser/src/parser/items/class.rs +++ b/parser/src/parser/items/class.rs @@ -1,7 +1,7 @@ use crate::{ Rule, ast::*, - error::{AstError, GetParseError}, + error::{AstError, IntoErr}, parser::consume_rule, }; @@ -44,7 +44,7 @@ impl<'a> TryFrom> for ClassItem { Rule::method => Ok(ClassItem::Method(pair.try_into().get()?)), - _ => unimplemented!("{rule:#?}"), + _ => AstError::bug_unimplemented(pair), } } } diff --git a/parser/src/parser/items/enums.rs b/parser/src/parser/items/enums.rs index ad8c87e..0f6d8fe 100644 --- a/parser/src/parser/items/enums.rs +++ b/parser/src/parser/items/enums.rs @@ -1,7 +1,7 @@ use crate::{ Rule, ast::*, - error::{AstError, GetParseError, collect_recovered}, + error::{AstError, IntoErr, collect_recovered}, }; impl<'a> TryFrom> for EnumItem { @@ -25,11 +25,11 @@ impl<'a> TryFrom> for EnumItem { .next() .map(|pair| collect_recovered::(pair.into_inner())) .transpose() - .get::()? + .get()? .unwrap_or_default(), )), - _ => unimplemented!("{rule:#?}"), + _ => AstError::bug_unimplemented(pair), } } } diff --git a/parser/src/parser/items/function.rs b/parser/src/parser/items/function.rs index 0787d52..c9500e7 100644 --- a/parser/src/parser/items/function.rs +++ b/parser/src/parser/items/function.rs @@ -1,7 +1,8 @@ use crate::{ Rule, ast::*, - error::{AstError, AstResult, GetParseError, collect_recovered}, + ast_expr, + error::{AstError, AstResult, IntoErr, collect_recovered}, parser::{consume_rule, listen_rule}, }; @@ -10,14 +11,14 @@ impl<'a> TryFrom> for FunctionDecl { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.into_inner(); - let visibility = Visibility::try_from(&mut inner).get()?; - let return_type = TypeExpr::try_from(inner.next().unwrap()).get()?; - let name = Identifier::try_from(inner.next().unwrap()).get()?; + let visibility = Visibility::try_from(&mut inner); + let return_type = TypeExpr::try_from(inner.next().unwrap()); + let name = Identifier::try_from(inner.next().unwrap()); + let generics = consume_rule(&mut inner, Rule::generics) .map(Generics::try_from) .transpose() - .get()? - .unwrap_or_default(); + .map(|v| v.unwrap_or_default()); let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| { let mut param_inner = param.into_inner(); @@ -56,19 +57,17 @@ impl<'a> TryFrom> for FunctionDecl { Ok(params) } }) - .transpose() - .get()? - .unwrap_or_else(|| ParamList(self_param.into_iter().collect())); + .unwrap_or_else(|| Ok(ParamList(self_param.into_iter().collect()))); - let body = inner.next().map(Block::try_from).transpose().get()?; + let body = inner.next().map(Block::try_from).transpose(); - Ok(Self { - visibility, - name, - generics, - params, - return_type, - body, + ast_expr!(Self { + visibility: visibility, + return_type: return_type, + name: name, + generics: generics, + params: params, + body: body, }) } } diff --git a/parser/src/parser/items/impl_decl.rs b/parser/src/parser/items/impl_decl.rs index 98aa43e..6ad4ca4 100644 --- a/parser/src/parser/items/impl_decl.rs +++ b/parser/src/parser/items/impl_decl.rs @@ -1,7 +1,7 @@ use crate::{ Rule, ast::*, - error::{AstError, GetParseError, collect_recovered}, + error::{AstError, IntoErr, collect_recovered}, parser::consume_rule, }; @@ -35,7 +35,7 @@ impl<'a> TryFrom> for ImplDecl { methods: collect_recovered(inner).get()?, }), - _ => unimplemented!("{rule:#?}"), + _ => AstError::bug_unimplemented(pair), } } } diff --git a/parser/src/parser/items/mod.rs b/parser/src/parser/items/mod.rs index 9eba00e..5cbcaab 100644 --- a/parser/src/parser/items/mod.rs +++ b/parser/src/parser/items/mod.rs @@ -7,7 +7,8 @@ pub mod impl_decl; use crate::{ Rule, ast::*, - error::{AstError, GetParseError, collect_recovered}, + ast_expr, + error::{AstError, IntoErr, collect_recovered}, parser::consume_rule, }; @@ -17,14 +18,13 @@ impl<'a> TryFrom> for TopLevel { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.into_inner(); - let attributes = collect_recovered(inner.next().unwrap().into_inner()).get()?; + let attributes = collect_recovered(inner.next().unwrap().into_inner()); - Ok(TopLevel( + ast_expr!(TopLevel( inner .next() .map(TopLevelKind::try_from) - .unwrap_or(Ok(TopLevelKind::ModAttribute)) - .get()?, + .unwrap_or(Ok(TopLevelKind::ModAttribute)), attributes, )) } @@ -37,93 +37,89 @@ impl<'a> TryFrom> for TopLevelKind { let rule = pair.as_rule(); let mut inner = pair.clone().into_inner(); - Ok(match rule { - Rule::import => TopLevelKind::Import( - Visibility::try_from(&mut inner).get()?, - Path::try_from(inner.next().unwrap()).get()?, - ), + match rule { + Rule::import => ast_expr!(TopLevelKind::Import( + Visibility::try_from(&mut inner), + Path::try_from(inner.next().unwrap()), + )), - Rule::function_decl => TopLevelKind::FunctionDecl(pair.try_into().get()?), + Rule::function_decl => ast_expr!(TopLevelKind::FunctionDecl(pair.try_into())), - Rule::struct_decl => TopLevelKind::StructDecl { - visibility: Visibility::try_from(&mut inner).get()?, + Rule::struct_decl => ast_expr!(TopLevelKind::StructDecl { + visibility: Visibility::try_from(&mut inner), - name: inner.next().unwrap().try_into().get()?, + name: inner.next().unwrap().try_into(), generics: consume_rule(&mut inner, Rule::generics) .map(Generics::try_from) .transpose() - .get()? - .unwrap_or_default(), + .map(|v| v.unwrap_or_default()), fields: inner .next() .map(|pair| collect_recovered::(pair.into_inner())) .transpose() - .get()? - .unwrap_or_default(), - }, + .map(|v| v.unwrap_or_default()), + }), - Rule::class_decl => TopLevelKind::ClassDecl { - visibility: Visibility::try_from(&mut inner).get()?, + Rule::class_decl => ast_expr!(TopLevelKind::ClassDecl { + visibility: Visibility::try_from(&mut inner), - name: inner.next().unwrap().try_into().get()?, + name: inner.next().unwrap().try_into(), generics: consume_rule(&mut inner, Rule::generics) .map(Generics::try_from) .transpose() - .get()? - .unwrap_or_default(), + .map(|v| v.unwrap_or_default()), - fields: collect_recovered(inner.next().unwrap().into_inner()).get()?, + fields: collect_recovered(inner.next().unwrap().into_inner()), - constructor: inner.next().unwrap().try_into().get()?, + constructor: inner.next().unwrap().try_into(), - items: collect_recovered(inner).get()?, - }, + items: collect_recovered(inner), + }), - Rule::enum_decl => TopLevelKind::EnumDecl { - visibility: Visibility::try_from(&mut inner).get()?, + Rule::enum_decl => ast_expr!(TopLevelKind::EnumDecl { + visibility: Visibility::try_from(&mut inner), - name: inner.next().unwrap().try_into().get()?, + name: inner.next().unwrap().try_into(), generics: consume_rule(&mut inner, Rule::generics) .map(Generics::try_from) .transpose() - .get()? - .unwrap_or_default(), + .map(|v| v.unwrap_or_default()), - fields: collect_recovered(inner).get()?, - }, + fields: collect_recovered(inner), + }), - Rule::mod_package => TopLevelKind::Mod( - Visibility::try_from(&mut inner).get()?, - inner.next().unwrap().try_into().get()?, - ), + Rule::mod_package => ast_expr!(TopLevelKind::Mod( + Visibility::try_from(&mut inner), + inner.next().unwrap().try_into(), + )), - Rule::impl_for_decl | Rule::impl_decl => TopLevelKind::ImplDecl(pair.try_into().get()?), + Rule::impl_for_decl | Rule::impl_decl => { + ast_expr!(TopLevelKind::ImplDecl(pair.try_into())) + } - Rule::trait_decl => TopLevelKind::TraitDecl { - visibility: Visibility::try_from(&mut inner).get()?, + Rule::trait_decl => ast_expr!(TopLevelKind::TraitDecl { + visibility: Visibility::try_from(&mut inner), - name: inner.next().unwrap().try_into().get()?, + name: inner.next().unwrap().try_into(), generics: consume_rule(&mut inner, Rule::generics) .map(Generics::try_from) .transpose() - .get()? - .unwrap_or_default(), + .map(|v| v.unwrap_or_default()), requirements: consume_rule(&mut inner, Rule::trait_requirements) .map(|pair| collect_recovered::(pair.into_inner())) .transpose() - .get()? - .unwrap_or_default(), + .map(|v| v.unwrap_or_default()), - items: collect_recovered(inner).get()?, - }, + items: collect_recovered(inner), + }), - _ => unimplemented!("{rule:#?}"), - }) + _ => AstError::bug_unimplemented(pair), + } } } diff --git a/src/compiler.rs b/src/compiler.rs index 7b8f585..1510f7a 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -5,6 +5,7 @@ use std::{ time::Instant, }; +use mist_parser::error::ParseError; use serde::Deserialize; #[derive(Deserialize)] @@ -100,7 +101,25 @@ fn build_dir(root: &Path, base_src: &Path, current_dir: &Path, out_dir: &Path) { } }; - let parser_result = mist_parser::parse(&source).map_err(|e| format!("{e:?}")); + let parser_result = mist_parser::parse(&source).map_err(|e| match e { + ParseError::Ast(e) => { + let start_pos = e.span.start_pos().line_col(); + + let span = e.span.as_str(); + + format!( + "\n{}:{}:{}\n \x1b[31mError\x1b[0m: {}\n\t{}{}\t{}", + path.as_os_str().display(), + start_pos.0, + start_pos.1, + e.error_message, + span, + if span.ends_with("\n") { "" } else { "\n" }, + "^".repeat(span.trim().len()), + ) + } + ParseError::PreAst(e) => format!("{e}"), + }); let ast = match parser_result { Ok(ast) => ast,