From 9b04a17fdd9fca30cc215780b784df9da14315cf Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 14 May 2026 23:37:48 +0200 Subject: [PATCH] Error recovery --- parser/src/error.rs | 39 ++++++++++++++++++++++++--- parser/src/lib.rs | 4 +-- parser/src/parser/common/decl.rs | 8 +++--- parser/src/parser/common/expr.rs | 22 +++++++-------- parser/src/parser/common/mod.rs | 12 ++++----- parser/src/parser/common/statement.rs | 6 ++--- parser/src/parser/common/types.rs | 8 +++--- parser/src/parser/items/attribute.rs | 4 +-- parser/src/parser/items/class.rs | 4 +-- parser/src/parser/items/enums.rs | 2 +- parser/src/parser/items/function.rs | 4 +-- parser/src/parser/items/impl_decl.rs | 2 +- parser/src/parser/items/mod.rs | 4 +-- 13 files changed, 76 insertions(+), 43 deletions(-) diff --git a/parser/src/error.rs b/parser/src/error.rs index 74974d1..43a0305 100644 --- a/parser/src/error.rs +++ b/parser/src/error.rs @@ -1,14 +1,15 @@ use crate::Rule; -pub type ParseResult<'a, T> = Result>; +pub type ParseResult<'a, T, ET = T> = Result>; #[derive(Debug, Clone)] -pub enum ParseError<'a> { +pub enum ParseError<'a, T> { PreAst(pest::error::Error), Ast { span: pest::Span<'a>, error_code: ErrorCode, error_message: String, + recovered: Option, }, } @@ -17,8 +18,40 @@ pub enum ErrorCode { InvalidStatement = 200, } -impl From> for ParseError<'_> { +impl<'a, F> ParseError<'a, F> { + pub fn get(self) -> ParseError<'a, T> { + match self { + Self::Ast { + span, + error_code, + error_message, + .. + } => ParseError::Ast { + span, + error_code, + error_message, + recovered: None, + }, + Self::PreAst(pest_err) => ParseError::PreAst(pest_err), + } + } +} + +impl From> for ParseError<'_, T> { fn from(value: pest::error::Error) -> Self { Self::PreAst(value) } } + +pub trait GetParseError<'a, F> { + fn get(self) -> ParseResult<'a, F, T>; +} + +impl<'a, F> GetParseError<'a, F> for ParseResult<'a, F> { + fn get(self) -> ParseResult<'a, F, T> { + match self { + Ok(v) => Ok(v), + Err(e) => Err(e.get()), + } + } +} diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 9b99918..86e8ea7 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -7,7 +7,7 @@ pub mod parser; use ast::*; -use crate::error::ParseResult; +use crate::error::{GetParseError, ParseResult}; #[derive(Parser)] #[grammar = "./src/grammar.pest"] @@ -20,7 +20,7 @@ pub fn parse<'a>(source: &'a str) -> ParseResult<'a, Vec> { for pair in pairs.next().unwrap().into_inner() { if pair.as_rule() != Rule::EOI { - statements.push(TopLevel::try_from(pair)?); + statements.push(TopLevel::try_from(pair).get()?); } } diff --git a/parser/src/parser/common/decl.rs b/parser/src/parser/common/decl.rs index 9ffafdb..0cd3bcb 100644 --- a/parser/src/parser/common/decl.rs +++ b/parser/src/parser/common/decl.rs @@ -1,7 +1,7 @@ use crate::{Rule, ast::*, error::ParseError, parser::listen_rule}; impl<'a> TryFrom> for VarDeclStmt { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { @@ -21,7 +21,7 @@ impl<'a> TryFrom> for VarDeclStmt { } impl<'a> TryFrom> for FieldDeclStmt { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { @@ -41,7 +41,7 @@ impl<'a> TryFrom> for FieldDeclStmt { } impl<'a> TryFrom> for VarDecl { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { @@ -76,7 +76,7 @@ impl<'a> TryFrom> for VarDecl { } impl<'a> TryFrom> for FieldDecl { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index 1269b8a..6c5b804 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -1,11 +1,11 @@ use crate::{ Rule, ast::*, - error::{ParseError, ParseResult}, + error::{GetParseError, ParseError, ParseResult}, }; impl<'a> TryFrom> for Expression { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -19,7 +19,7 @@ impl<'a> TryFrom> for Expression { p.into_inner() .into_iter() .map(Prefix::try_from) - .collect::>>() + .collect::, _>>() }) .transpose()? .unwrap_or_default(); @@ -47,7 +47,7 @@ impl<'a> TryFrom> for Expression { } impl<'a> TryFrom> for Prefix { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { Ok(match pair.as_rule() { @@ -63,7 +63,7 @@ impl<'a> TryFrom> for Prefix { } impl<'a> TryFrom> for Postfix { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -74,11 +74,11 @@ impl<'a> TryFrom> for Postfix { Rule::field_px => Postfix::FieldAccess(Identifier::try_from(inner.next().unwrap())?), - Rule::call_px => Postfix::Call( - inner - .map(Expression::try_from) - .collect::>>()?, - ), + Rule::call_px => Postfix::Call(inner.map(Expression::try_from).collect::, + _, + >>()), Rule::struct_px => Postfix::StructCall( inner @@ -92,7 +92,7 @@ impl<'a> TryFrom> for Postfix { .collect::>>()?, ), - Rule::index_px => Postfix::Index(Expression::try_from(inner.next().unwrap())?), + Rule::index_px => Postfix::Index(Expression::try_from(inner.next().unwrap()).get()?), Rule::binary_px => { let op_pair = inner.next().unwrap(); diff --git a/parser/src/parser/common/mod.rs b/parser/src/parser/common/mod.rs index 9504afd..0dc5dfd 100644 --- a/parser/src/parser/common/mod.rs +++ b/parser/src/parser/common/mod.rs @@ -11,7 +11,7 @@ use crate::{ }; impl<'a> TryFrom> for Identifier { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { Ok(Identifier(pair.as_str().to_string())) @@ -19,7 +19,7 @@ impl<'a> TryFrom> for Identifier { } impl<'a> TryFrom> for Path { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { @@ -34,7 +34,7 @@ impl<'a> TryFrom> for Path { } impl<'a> TryFrom> for Literal { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -58,7 +58,7 @@ impl<'a> TryFrom> for Literal { } impl<'a> TryFrom> for Pattern { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -97,11 +97,11 @@ impl<'a> TryFrom> for Pattern { } impl<'a> TryFrom<&mut pest::iterators::Pairs<'a, Rule>> for Visibility { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pairs: &mut pest::iterators::Pairs<'a, Rule>) -> Result { Ok(consume_rule(pairs, Rule::visibility) - .map(|pair| -> Result> { + .map(|pair| -> Result> { if let Some(path) = pair.into_inner().next() { Ok(Visibility::PublicTarget(Path::try_from(path)?)) } else { diff --git a/parser/src/parser/common/statement.rs b/parser/src/parser/common/statement.rs index f78065d..a95d7e1 100644 --- a/parser/src/parser/common/statement.rs +++ b/parser/src/parser/common/statement.rs @@ -6,7 +6,7 @@ use crate::{ }; impl<'a> TryFrom> for Block { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let statements = pair @@ -25,7 +25,7 @@ impl<'a> TryFrom> for Block { } impl<'a> TryFrom> for Statement { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -115,7 +115,7 @@ impl<'a> TryFrom> for Statement { } impl<'a> TryFrom> for StatementBranch { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.into_inner(); diff --git a/parser/src/parser/common/types.rs b/parser/src/parser/common/types.rs index f5dc265..912f8ae 100644 --- a/parser/src/parser/common/types.rs +++ b/parser/src/parser/common/types.rs @@ -6,7 +6,7 @@ use crate::{ }; impl<'a> TryFrom> for TypePostfix { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -39,7 +39,7 @@ impl<'a> TryFrom> for TypePostfix { } impl<'a> TryFrom> for TypeExprKind { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -69,7 +69,7 @@ impl<'a> TryFrom> for TypeExprKind { } impl<'a> TryFrom> for TypeExpr { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -93,7 +93,7 @@ impl<'a> TryFrom> for TypeExpr { } impl<'a> TryFrom> for Generics { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); diff --git a/parser/src/parser/items/attribute.rs b/parser/src/parser/items/attribute.rs index 89ea34f..44bf9f3 100644 --- a/parser/src/parser/items/attribute.rs +++ b/parser/src/parser/items/attribute.rs @@ -5,7 +5,7 @@ use crate::{ }; impl<'a> TryFrom> for Attribute { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { @@ -41,7 +41,7 @@ impl<'a> TryFrom> for Attribute { let items = next .into_inner() .map(Attribute::try_from) - .collect::>>()?; + .collect::, _>>()?; Ok(Attribute::List { path, items }) } diff --git a/parser/src/parser/items/class.rs b/parser/src/parser/items/class.rs index b80f566..5517ec0 100644 --- a/parser/src/parser/items/class.rs +++ b/parser/src/parser/items/class.rs @@ -1,7 +1,7 @@ use crate::{Rule, ast::*, error::ParseError, parser::consume_rule}; impl<'a> TryFrom> for ClassConstructor { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.into_inner(); @@ -28,7 +28,7 @@ impl<'a> TryFrom> for ClassConstructor { } impl<'a> TryFrom> for ClassItem { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); diff --git a/parser/src/parser/items/enums.rs b/parser/src/parser/items/enums.rs index 883ee77..70e0d8a 100644 --- a/parser/src/parser/items/enums.rs +++ b/parser/src/parser/items/enums.rs @@ -5,7 +5,7 @@ use crate::{ }; impl<'a> TryFrom> for EnumItem { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); diff --git a/parser/src/parser/items/function.rs b/parser/src/parser/items/function.rs index 07520ad..c4d25cf 100644 --- a/parser/src/parser/items/function.rs +++ b/parser/src/parser/items/function.rs @@ -6,7 +6,7 @@ use crate::{ }; impl<'a> TryFrom> for FunctionDecl { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.into_inner(); @@ -72,7 +72,7 @@ impl<'a> TryFrom> for FunctionDecl { } impl<'a> TryFrom> for ParamList { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { Ok(ParamList( diff --git a/parser/src/parser/items/impl_decl.rs b/parser/src/parser/items/impl_decl.rs index 76952a1..6f66f9f 100644 --- a/parser/src/parser/items/impl_decl.rs +++ b/parser/src/parser/items/impl_decl.rs @@ -6,7 +6,7 @@ use crate::{ }; impl<'a> TryFrom> for ImplDecl { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); diff --git a/parser/src/parser/items/mod.rs b/parser/src/parser/items/mod.rs index 540dd2d..e098145 100644 --- a/parser/src/parser/items/mod.rs +++ b/parser/src/parser/items/mod.rs @@ -12,7 +12,7 @@ use crate::{ }; impl<'a> TryFrom> for TopLevel { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.into_inner(); @@ -35,7 +35,7 @@ impl<'a> TryFrom> for TopLevel { } impl<'a> TryFrom> for TopLevelKind { - type Error = ParseError<'a>; + type Error = ParseError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule();