Making a error recovery system

This commit is contained in:
2026-05-15 12:09:30 +02:00
parent 3aba4a359b
commit 216c61228c
5 changed files with 72 additions and 3 deletions
+2
View File
@@ -12,4 +12,6 @@ void main() {
app_instance.boot(); app_instance.boot();
app_instance.run(); app_instance.run();
hi
} }
+1 -1
View File
@@ -108,7 +108,7 @@ where
span: ast_err.span, span: ast_err.span,
error_code: ast_err.error_code, error_code: ast_err.error_code,
error_message: ast_err.error_message, error_message: ast_err.error_message,
recovered: None, recovered: Some(items),
}), }),
None => Ok(items), None => Ok(items),
} }
+65
View File
@@ -26,3 +26,68 @@ pub fn parse<'a>(source: &'a str) -> Result<Vec<TopLevel>, ParseError<'a, Vec<To
Ok(statements) Ok(statements)
} }
#[macro_export]
macro_rules! ast_expr {
($($item:ident)::+ { $($k:ident: $v:expr),* $(,)? }) => {{
let mut err = None;
let v = $($item)::+ {
$(
$k: {
let r = $v.get();
if let Err(e) = r {
err = Some(e.clone().get());
if let Some(recovered) = e.recovered {
Ok(recovered)
} else {
Err(e)
}
} else {
r
}
}.get()?
),*
};
if let Some(mut e) = err {
e.recovered = Some(v);
Err(e)
} else {
Ok(v)
}
}};
($($item:ident)::+ ( $($v:expr),* $(,)? )) => {{
let mut err = None;
let v = $($item)::+ ( $({
let r = $v.get();
if let Err(e) = r {
err = Some(e.clone().get());
if let Some(recovered) = e.recovered {
Ok(recovered)
} else {
Err(e)
}
} else {
r
}
}.get()?),* );
if let Some(mut e) = err {
e.recovered = Some(v);
Err(e)
} else {
Ok(v)
}
}};
($($item:ident)::+) => {
$($item)::+
};
}
+2 -1
View File
@@ -1,6 +1,7 @@
use crate::{ use crate::{
Rule, Rule,
ast::*, ast::*,
ast_expr,
error::{AstError, AstResult, ErrorCode, GetParseError, collect_recovered}, error::{AstError, AstResult, ErrorCode, GetParseError, collect_recovered},
parser::listen_rule, parser::listen_rule,
}; };
@@ -10,7 +11,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Block {
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
if pair.as_rule() == Rule::block { if pair.as_rule() == Rule::block {
Ok(Block(collect_recovered(pair.into_inner()).get()?)) ast_expr!(Block(collect_recovered(pair.into_inner())))
} else { } else {
Err(AstError { Err(AstError {
span: pair.as_span(), span: pair.as_span(),
+2 -1
View File
@@ -7,6 +7,7 @@ pub mod impl_decl;
use crate::{ use crate::{
Rule, Rule,
ast::*, ast::*,
ast_expr,
error::{AstError, GetParseError, collect_recovered}, error::{AstError, GetParseError, collect_recovered},
parser::consume_rule, parser::consume_rule,
}; };
@@ -43,7 +44,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for TopLevelKind {
Path::try_from(inner.next().unwrap()).get()?, Path::try_from(inner.next().unwrap()).get()?,
), ),
Rule::function_decl => TopLevelKind::FunctionDecl(pair.try_into().get()?), Rule::function_decl => return ast_expr!(TopLevelKind::FunctionDecl(pair.try_into())),
Rule::struct_decl => TopLevelKind::StructDecl { Rule::struct_decl => TopLevelKind::StructDecl {
visibility: Visibility::try_from(&mut inner).get()?, visibility: Visibility::try_from(&mut inner).get()?,