Add operator precedence and refactor expressions
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
437584c844
commit
722e61cc85
3 changed files with 99 additions and 10 deletions
|
|
@ -654,17 +654,33 @@ fn parse_operator<'input>(input: &mut Input<'input>) -> Result<TokenOperator, As
|
|||
fn parse_expression<'input>(
|
||||
input: &mut Input<'input>,
|
||||
) -> Result<TemplateAstExpr<'input>, AstError> {
|
||||
macro_rules! infix {
|
||||
($parser:expr => [ $($side:ident $val:tt => $prec:expr),* $(,)? ]) => {
|
||||
dispatch! { surrounded(ws, parse_operator);
|
||||
$(
|
||||
TokenOperator::$val => Left($prec, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::$val, lhs: Box::new(lhs), rhs: Box::new(rhs) }))
|
||||
),*
|
||||
}
|
||||
};
|
||||
}
|
||||
trace(
|
||||
"expression",
|
||||
expression(surrounded(ws, parse_operand)).infix(dispatch! { surrounded(ws, parse_operator);
|
||||
TokenOperator::Plus => Left(5, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::Plus, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
|
||||
TokenOperator::Minus => Left(5, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::Minus, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
|
||||
TokenOperator::Times => Left(7, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::Times, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
|
||||
TokenOperator::Divide => Left(7, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::Divide, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
|
||||
TokenOperator::And => Left(7, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::And, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
|
||||
TokenOperator::Or => Left(5, |_, lhs, rhs| Ok(TemplateAstExpr::Operation { op: TokenOperator::Or, lhs: Box::new(lhs), rhs: Box::new(rhs) })),
|
||||
_ => winnow::combinator::todo
|
||||
}),
|
||||
expression(surrounded(ws, parse_operand)).infix(
|
||||
infix! { surrounded(ws, parse_operator) => [
|
||||
left Plus => 18,
|
||||
left Minus => 18,
|
||||
left Times => 20,
|
||||
left Divide => 20,
|
||||
left And => 10,
|
||||
left Or => 7,
|
||||
left Equal => 12,
|
||||
left NotEqual => 12,
|
||||
left Greater => 15,
|
||||
left GreaterOrEqual => 15,
|
||||
left Lesser => 15,
|
||||
left LesserOrEqual => 15,
|
||||
] },
|
||||
),
|
||||
)
|
||||
.parse_next(input)
|
||||
}
|
||||
|
|
@ -981,4 +997,15 @@ mod tests {
|
|||
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_logical_expression() {
|
||||
let input = "{{= true && false || 3 >= 2 && 5 == 2 }}";
|
||||
|
||||
let parsed = crate::parser::parse(input.into()).unwrap();
|
||||
|
||||
let ast = panic_pretty(input, parse(parsed.tokens()));
|
||||
|
||||
insta::assert_debug_snapshot!(ast);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
source: src/ast/mod.rs
|
||||
expression: ast
|
||||
---
|
||||
TemplateAst {
|
||||
root: [
|
||||
Interpolation {
|
||||
prev_whitespace_content: None,
|
||||
expression: Operation {
|
||||
op: Or,
|
||||
lhs: Operation {
|
||||
op: And,
|
||||
lhs: Literal {
|
||||
source: [Literal(Bool(true))]"true" (4..8),
|
||||
value: Bool {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
rhs: Literal {
|
||||
source: [Literal(Bool(false))]"false" (12..17),
|
||||
value: Bool {
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
rhs: Operation {
|
||||
op: And,
|
||||
lhs: Operation {
|
||||
op: GreaterOrEqual,
|
||||
lhs: Literal {
|
||||
source: [Literal(Integer(3))]"3" (21..22),
|
||||
value: Integer {
|
||||
value: 3,
|
||||
},
|
||||
},
|
||||
rhs: Literal {
|
||||
source: [Literal(Integer(2))]"2" (26..27),
|
||||
value: Integer {
|
||||
value: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
rhs: Operation {
|
||||
op: Equal,
|
||||
lhs: Literal {
|
||||
source: [Literal(Integer(5))]"5" (31..32),
|
||||
value: Integer {
|
||||
value: 5,
|
||||
},
|
||||
},
|
||||
rhs: Literal {
|
||||
source: [Literal(Integer(2))]"2" (36..37),
|
||||
value: Integer {
|
||||
value: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
post_whitespace_content: None,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
@ -33,7 +33,6 @@ use winnow::stream::Location;
|
|||
use winnow::stream::Recoverable;
|
||||
use winnow::stream::Stream;
|
||||
use winnow::token::any;
|
||||
use winnow::token::literal;
|
||||
use winnow::token::one_of;
|
||||
use winnow::token::rest;
|
||||
use winnow::token::take_until;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue