Refactor: Improved expression parsing organization.

Any non-operator expression can be a part of an operator expression.
This cleans up and makes clearer the precendence relationships for parsing.
This commit is contained in:
Jeremy Wall 2018-05-26 09:12:00 -05:00
parent 79bee4e2b4
commit 988698fc01
2 changed files with 39 additions and 33 deletions

View File

@ -254,7 +254,7 @@ fn tuple_to_binary_expression(
/// the most tightly bound expressions. /// the most tightly bound expressions.
macro_rules! do_binary_expr { macro_rules! do_binary_expr {
($i:expr, $oprule:ident!( $($args:tt)* ), $typ:expr) => { ($i:expr, $oprule:ident!( $($args:tt)* ), $typ:expr) => {
do_binary_expr!($i, $oprule!($($args)*), $typ, alt!(grouped_expression | simple_expression)) do_binary_expr!($i, $oprule!($($args)*), $typ, non_op_expression)
}; };
($i:expr, $oprule:ident!( $($args:tt)* ), $typ:expr, $lowerrule:ident) => { ($i:expr, $oprule:ident!( $($args:tt)* ), $typ:expr, $lowerrule:ident) => {
@ -275,14 +275,6 @@ macro_rules! do_binary_expr {
}; };
} }
named!(math_expression<TokenIter, Expression, error::Error>,
alt!(sum_expression | product_expression)
);
named!(sum_expression<TokenIter, Expression, error::Error>,
alt!(add_expression | sub_expression)
);
// trace_macros!(true); // trace_macros!(true);
named!(add_expression<TokenIter, Expression, error::Error>, named!(add_expression<TokenIter, Expression, error::Error>,
do_binary_expr!(punct!("+"), BinaryExprType::Add, alt!(product_expression | simple_expression | grouped_expression)) do_binary_expr!(punct!("+"), BinaryExprType::Add, alt!(product_expression | simple_expression | grouped_expression))
@ -293,8 +285,8 @@ named!(sub_expression<TokenIter, Expression, error::Error>,
do_binary_expr!(punct!("-"), BinaryExprType::Sub, alt!(product_expression | simple_expression | grouped_expression)) do_binary_expr!(punct!("-"), BinaryExprType::Sub, alt!(product_expression | simple_expression | grouped_expression))
); );
named!(product_expression<TokenIter, Expression, error::Error>, named!(sum_expression<TokenIter, Expression, error::Error>,
alt!(mul_expression | div_expression) alt!(add_expression | sub_expression)
); );
named!(mul_expression<TokenIter, Expression, error::Error>, named!(mul_expression<TokenIter, Expression, error::Error>,
@ -305,6 +297,14 @@ named!(div_expression<TokenIter, Expression, error::Error>,
do_binary_expr!(punct!("/"), BinaryExprType::Div) do_binary_expr!(punct!("/"), BinaryExprType::Div)
); );
named!(product_expression<TokenIter, Expression, error::Error>,
alt!(mul_expression | div_expression)
);
named!(math_expression<TokenIter, Expression, error::Error>,
alt!(sum_expression | product_expression)
);
// TODO(jwall): Change comparison operators to use the do_binary_expr! with precedence? // TODO(jwall): Change comparison operators to use the do_binary_expr! with precedence?
fn tuple_to_compare_expression( fn tuple_to_compare_expression(
tpl: (Position, CompareType, Expression, Expression), tpl: (Position, CompareType, Expression, Expression),
@ -356,6 +356,20 @@ named!(lt_expression<TokenIter, Expression, error::Error>,
do_compare_expr!(punct!("<"), CompareType::LT) do_compare_expr!(punct!("<"), CompareType::LT)
); );
named!(compare_expression<TokenIter, Expression, error::Error>,
alt!(
eqeq_expression |
not_eqeq_expression |
lt_eqeq_expression |
gt_eqeq_expression |
lt_expression |
gt_expression)
);
named!(op_expression<TokenIter, Expression, error::Error>,
alt!(math_expression | compare_expression)
);
fn expression_to_grouped_expression(e: Expression) -> ParseResult<Expression> { fn expression_to_grouped_expression(e: Expression) -> ParseResult<Expression> {
Ok(Expression::Grouped(Box::new(e))) Ok(Expression::Grouped(Box::new(e)))
} }
@ -704,6 +718,17 @@ named!(list_op_expression<TokenIter, Expression, error::Error>,
) )
); );
named!(non_op_expression<TokenIter, Expression, error::Error>,
alt!(list_op_expression |
macro_expression |
format_expression |
select_expression |
call_expression |
copy_expression |
grouped_expression |
simple_expression)
);
// NOTE(jwall): HERE THERE BE DRAGONS. The order for these matters // NOTE(jwall): HERE THERE BE DRAGONS. The order for these matters
// a lot. We need to process alternatives in order of decreasing // a lot. We need to process alternatives in order of decreasing
// specificity. Unfortunately this means we are required to go in a // specificity. Unfortunately this means we are required to go in a
@ -715,26 +740,7 @@ named!(list_op_expression<TokenIter, Expression, error::Error>,
// It also means this combinator is risky when used with partial // It also means this combinator is risky when used with partial
// inputs. So handle with care. // inputs. So handle with care.
named!(expression<TokenIter, Expression, error::Error>, named!(expression<TokenIter, Expression, error::Error>,
do_parse!( alt!(complete!(op_expression) | complete!(non_op_expression))
expr: alt!(
complete!(list_op_expression) |
complete!(math_expression) |
complete!(eqeq_expression) |
complete!(not_eqeq_expression) |
complete!(lt_eqeq_expression) |
complete!(gt_eqeq_expression) |
complete!(gt_expression) |
complete!(lt_expression) |
complete!(macro_expression) |
complete!(format_expression) |
complete!(select_expression) |
complete!(call_expression) |
complete!(copy_expression) |
complete!(grouped_expression) |
simple_expression
) >>
(expr)
)
); );
fn expression_to_statement(v: Expression) -> ParseResult<Statement> { fn expression_to_statement(v: Expression) -> ParseResult<Statement> {

View File

@ -363,7 +363,7 @@ fn test_expression_parse() {
1, 1))) 1, 1)))
); );
assert_parse!( assert_parse!(
math_expression("1 + 1"), expression("1 + 1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
@ -381,7 +381,7 @@ fn test_expression_parse() {
}) })
); );
assert_parse!( assert_parse!(
expression("1 * 1"), mul_expression("1 * 1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Mul, kind: BinaryExprType::Mul,
left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),