Making a error recovery system
This commit is contained in:
@@ -12,4 +12,6 @@ void main() {
|
||||
|
||||
app_instance.boot();
|
||||
app_instance.run();
|
||||
|
||||
hi
|
||||
}
|
||||
+1
-1
@@ -108,7 +108,7 @@ 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),
|
||||
}
|
||||
|
||||
@@ -26,3 +26,68 @@ pub fn parse<'a>(source: &'a str) -> Result<Vec<TopLevel>, ParseError<'a, Vec<To
|
||||
|
||||
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)::+
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
Rule,
|
||||
ast::*,
|
||||
ast_expr,
|
||||
error::{AstError, AstResult, ErrorCode, GetParseError, collect_recovered},
|
||||
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> {
|
||||
if pair.as_rule() == Rule::block {
|
||||
Ok(Block(collect_recovered(pair.into_inner()).get()?))
|
||||
ast_expr!(Block(collect_recovered(pair.into_inner())))
|
||||
} else {
|
||||
Err(AstError {
|
||||
span: pair.as_span(),
|
||||
|
||||
@@ -7,6 +7,7 @@ pub mod impl_decl;
|
||||
use crate::{
|
||||
Rule,
|
||||
ast::*,
|
||||
ast_expr,
|
||||
error::{AstError, GetParseError, collect_recovered},
|
||||
parser::consume_rule,
|
||||
};
|
||||
@@ -43,7 +44,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for TopLevelKind {
|
||||
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 {
|
||||
visibility: Visibility::try_from(&mut inner).get()?,
|
||||
|
||||
Reference in New Issue
Block a user