Ast expression macro
This commit is contained in:
+5
-5
@@ -10,10 +10,10 @@ pub enum ParseError<'a, T> {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AstError<'a, T> {
|
||||
span: pest::Span<'a>,
|
||||
error_code: ErrorCode,
|
||||
error_message: String,
|
||||
recovered: Option<T>,
|
||||
pub span: pest::Span<'a>,
|
||||
pub error_code: ErrorCode,
|
||||
pub error_message: String,
|
||||
pub recovered: Option<T>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -89,7 +89,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,51 @@ pub fn parse<'a>(source: &'a str) -> Result<Vec<TopLevel>, ParseError<'a, Vec<To
|
||||
|
||||
Ok(statements)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! ast_expr {
|
||||
($inner:tt@$item:path { $($name:ident $t:tt $val:tt $($val2:tt)?),*}) => {{
|
||||
$(
|
||||
let $name = $crate::_ast_t!($t $crate::_ast_ti!($inner, $val $($val2)?));
|
||||
)*
|
||||
|
||||
$item { $($name,)* }
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! _ast_t {
|
||||
(: $val:expr) => {
|
||||
$val.get()?
|
||||
};
|
||||
|
||||
(? $val:expr) => {
|
||||
$val.or_else(|e| {
|
||||
if let Some(recovered) = e.recovered {
|
||||
Ok(recovered)
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
})
|
||||
.get()?
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! _ast_ti {
|
||||
($inner:ident, ! $val:ident) => {
|
||||
$val::try_from(&mut $inner)
|
||||
};
|
||||
|
||||
($inner:ident, @ $val:ident) => {
|
||||
$val::try_from($inner.next().unwrap())
|
||||
};
|
||||
|
||||
($inner:ident, ? ($rule:path)) => {
|
||||
$crate::parser::listen_rule(&mut $inner, $rule)
|
||||
};
|
||||
|
||||
($inner:ident, & $val:expr) => {
|
||||
$val
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
Rule,
|
||||
ast::*,
|
||||
ast_expr,
|
||||
error::{AstError, GetParseError},
|
||||
parser::listen_rule,
|
||||
};
|
||||
|
||||
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for VarDeclStmt {
|
||||
@@ -53,7 +53,8 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for VarDecl {
|
||||
Rule::var_decl => {
|
||||
let mut inner = pair.into_inner();
|
||||
|
||||
let type_ = inner
|
||||
Ok(ast_expr!(inner@VarDecl {
|
||||
type_: & (inner
|
||||
.next()
|
||||
.and_then(|pair| {
|
||||
if pair.as_str().trim() == "var" {
|
||||
@@ -62,18 +63,12 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for VarDecl {
|
||||
Some(TypeExpr::try_from(pair))
|
||||
}
|
||||
})
|
||||
.transpose()
|
||||
.get()?;
|
||||
.transpose()),
|
||||
|
||||
let mutable = listen_rule(&mut inner, Rule::mutable);
|
||||
mutable: ?(Rule::mutable),
|
||||
|
||||
let name = Pattern::try_from(inner.next().unwrap()).get()?;
|
||||
|
||||
Ok(VarDecl {
|
||||
mutable,
|
||||
name,
|
||||
type_,
|
||||
})
|
||||
name: @Pattern
|
||||
}))
|
||||
}
|
||||
|
||||
_ => unimplemented!("{:?}", pair.as_rule()),
|
||||
@@ -89,15 +84,11 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> 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,
|
||||
})
|
||||
Ok(ast_expr!(inner@FieldDecl {
|
||||
visibility: !Visibility,
|
||||
type_: @TypeExpr,
|
||||
name: @Identifier
|
||||
}))
|
||||
}
|
||||
|
||||
_ => unimplemented!("{:?}", pair.as_rule()),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
Rule,
|
||||
ast::*,
|
||||
error::{AstError, AstResult},
|
||||
error::{AstError, AstResult, GetParseError},
|
||||
};
|
||||
|
||||
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
|
||||
@@ -72,7 +72,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Postfix {
|
||||
Ok(match rule {
|
||||
Rule::postfix => Postfix::try_from(inner.next().unwrap())?,
|
||||
|
||||
Rule::field_px => Postfix::FieldAccess(Identifier::try_from(inner.next().unwrap())?),
|
||||
Rule::field_px => Postfix::FieldAccess(Identifier::try_from(inner.next().unwrap()).get()?),
|
||||
|
||||
Rule::call_px => Postfix::Call(inner.map(Expression::try_from).collect::<AstResult<
|
||||
'a,
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
pub mod common;
|
||||
pub mod items;
|
||||
|
||||
use crate::Rule;
|
||||
use crate::{Rule, error::AstResult};
|
||||
|
||||
pub fn listen_rule(pairs: &mut pest::iterators::Pairs<'_, Rule>, rule: Rule) -> bool {
|
||||
pub fn listen_rule<'a>(
|
||||
pairs: &mut pest::iterators::Pairs<'_, Rule>,
|
||||
rule: Rule,
|
||||
) -> AstResult<'a, bool> {
|
||||
let consumed = pairs
|
||||
.peek()
|
||||
.map(|p| p.as_rule() == rule)
|
||||
@@ -13,7 +16,7 @@ pub fn listen_rule(pairs: &mut pest::iterators::Pairs<'_, Rule>, rule: Rule) ->
|
||||
pairs.next();
|
||||
}
|
||||
|
||||
consumed
|
||||
Ok(consumed)
|
||||
}
|
||||
|
||||
pub fn consume_rule<'a>(
|
||||
|
||||
Reference in New Issue
Block a user