Add grouped expression support for binary operators.

This commit is contained in:
Jeremy Wall 2018-04-16 19:54:11 -05:00
parent 4265b0177b
commit 0d0f66f9c7

View File

@ -239,11 +239,11 @@ named!(simple_expression<TokenIter, Expression, error::Error>,
); );
fn tuple_to_binary_expression( fn tuple_to_binary_expression(
tpl: (Position, BinaryExprType, Value, Expression), tpl: (Position, BinaryExprType, Expression, Expression),
) -> ParseResult<Expression> { ) -> ParseResult<Expression> {
Ok(Expression::Binary(BinaryOpDef { Ok(Expression::Binary(BinaryOpDef {
kind: tpl.1, kind: tpl.1,
left: tpl.2, left: Box::new(tpl.2),
right: Box::new(tpl.3), right: Box::new(tpl.3),
pos: Position::new(tpl.0.line as usize, tpl.0.column as usize), pos: Position::new(tpl.0.line as usize, tpl.0.column as usize),
})) }))
@ -251,14 +251,10 @@ fn tuple_to_binary_expression(
macro_rules! do_binary_expr { macro_rules! do_binary_expr {
($i:expr, $subrule:ident!( $($args:tt)* ), $typ:expr) => { ($i:expr, $subrule:ident!( $($args:tt)* ), $typ:expr) => {
// NOTE(jwall): Nom macros do magic with their inputs. They in fact
// rewrite your macro argumets for you. Which means we require this $i
// paramater even though we don't explicitely pass it below. I don't
// particularly like this but I'm living with it for now.
map_res!($i, map_res!($i,
do_parse!( do_parse!(
pos: pos >> pos: pos >>
left: value >> left: alt!(simple_expression | grouped_expression) >>
$subrule!($($args)*) >> $subrule!($($args)*) >>
right: expression >> right: expression >>
(pos, $typ, left, right) (pos, $typ, left, right)
@ -286,28 +282,54 @@ named!(div_expression<TokenIter, Expression, error::Error>,
do_binary_expr!(punct!("/"), BinaryExprType::Div) do_binary_expr!(punct!("/"), BinaryExprType::Div)
); );
fn tuple_to_compare_expression(
tpl: (Position, CompareType, Expression, Expression),
) -> ParseResult<Expression> {
Ok(Expression::Compare(ComparisonDef {
kind: tpl.1,
left: Box::new(tpl.2),
right: Box::new(tpl.3),
pos: Position::new(tpl.0.line as usize, tpl.0.column as usize),
}))
}
macro_rules! do_compare_expr {
($i:expr, $subrule:ident!( $($args:tt)* ), $typ:expr) => {
map_res!($i,
do_parse!(
pos: pos >>
left: alt!(simple_expression | grouped_expression) >>
$subrule!($($args)*) >>
right: expression >>
(pos, $typ, left, right)
),
tuple_to_compare_expression
)
};
}
named!(eqeq_expression<TokenIter, Expression, error::Error>, named!(eqeq_expression<TokenIter, Expression, error::Error>,
do_binary_expr!(punct!("=="), BinaryExprType::Equal) do_compare_expr!(punct!("=="), CompareType::Equal)
); );
named!(not_eqeq_expression<TokenIter, Expression, error::Error>, named!(not_eqeq_expression<TokenIter, Expression, error::Error>,
do_binary_expr!(punct!("!="), BinaryExprType::NotEqual) do_compare_expr!(punct!("!="), CompareType::NotEqual)
); );
named!(lt_eqeq_expression<TokenIter, Expression, error::Error>, named!(lt_eqeq_expression<TokenIter, Expression, error::Error>,
do_binary_expr!(punct!("<="), BinaryExprType::LTEqual) do_compare_expr!(punct!("<="), CompareType::LTEqual)
); );
named!(gt_eqeq_expression<TokenIter, Expression, error::Error>, named!(gt_eqeq_expression<TokenIter, Expression, error::Error>,
do_binary_expr!(punct!(">="), BinaryExprType::GTEqual) do_compare_expr!(punct!(">="), CompareType::GTEqual)
); );
named!(gt_expression<TokenIter, Expression, error::Error>, named!(gt_expression<TokenIter, Expression, error::Error>,
do_binary_expr!(punct!(">"), BinaryExprType::GT) do_compare_expr!(punct!(">"), CompareType::GT)
); );
named!(lt_expression<TokenIter, Expression, error::Error>, named!(lt_expression<TokenIter, Expression, error::Error>,
do_binary_expr!(punct!("<"), BinaryExprType::LT) do_compare_expr!(punct!("<"), CompareType::LT)
); );
fn expression_to_grouped_expression(e: Expression) -> ParseResult<Expression> { fn expression_to_grouped_expression(e: Expression) -> ParseResult<Expression> {
@ -826,41 +848,39 @@ mod test {
use nom::IResult; use nom::IResult;
macro_rules! assert_parse { macro_rules! assert_parse {
($parsemac:ident( $i:expr ), $out:expr) => { ($parsemac: ident($i: expr), $out: expr) => {
assert_parse!($i, $parsemac, $out) assert_parse!($i, $parsemac, $out)
}; };
($i:expr, $f:expr, $out:expr) => { ($i: expr, $f: expr, $out: expr) => {{
{ let input = LocatedSpan::new($i);
let input = LocatedSpan::new($i); match tokenize(input) {
match tokenize(input) { Err(e) => assert!(false, format!("Tokenizer Error: {:?}", e)),
Err(e) => assert!(false, format!("Tokenizer Error: {:?}", e)), Ok(val) => match $f(TokenIter {
Ok(val) => { source: val.as_slice(),
match $f(TokenIter{source: val.as_slice()}) { }) {
IResult::Done(_, result) => assert_eq!(result, $out), IResult::Done(_, result) => assert_eq!(result, $out),
other => assert!(false, format!("Expected Done got {:?}", other)), other => assert!(false, format!("Expected Done got {:?}", other)),
} },
}, }
} };};
};
}
} }
macro_rules! assert_error { macro_rules! assert_error {
($parsemac:ident( $i:expr )) => { ($parsemac: ident($i: expr)) => {
assert_error!($i, $parsemac) assert_error!($i, $parsemac)
}; };
($i:expr, $f:expr) => { ($i: expr, $f: expr) => {{
{ let input = LocatedSpan::new($i);
let input = LocatedSpan::new($i); match tokenize(input) {
match tokenize(input) { Err(_) => assert!(true),
Err(_) => assert!(true), Ok(val) => {
Ok(val) => { let result = $f(TokenIter {
let result = $f(TokenIter{source: val.as_slice()}); source: val.as_slice(),
assert!(result.is_err(), format!("Not an error: {:?}", result)) });
}, assert!(result.is_err(), format!("Not an error: {:?}", result))
} }
} }
} }};
} }
#[test] #[test]
@ -1133,7 +1153,7 @@ mod test {
expression("1 + 1"), expression("1 + 1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
@ -1142,7 +1162,7 @@ mod test {
expression("1 - 1"), expression("1 - 1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Sub, kind: BinaryExprType::Sub,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
@ -1151,7 +1171,7 @@ mod test {
expression("1 * 1"), expression("1 * 1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Mul, kind: BinaryExprType::Mul,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
@ -1160,43 +1180,43 @@ mod test {
expression("1 / 1"), expression("1 / 1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Div, kind: BinaryExprType::Div,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
); );
assert_parse!( assert_parse!(
expression("1 > 1"), expression("1 > 1"),
Expression::Binary(BinaryOpDef { Expression::Compare(ComparisonDef {
kind: BinaryExprType::GT, kind: CompareType::GT,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
); );
assert_parse!( assert_parse!(
expression("1 < 1"), expression("1 < 1"),
Expression::Binary(BinaryOpDef { Expression::Compare(ComparisonDef {
kind: BinaryExprType::LT, kind: CompareType::LT,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
); );
assert_parse!( assert_parse!(
expression("1 <= 1"), expression("1 <= 1"),
Expression::Binary(BinaryOpDef { Expression::Compare(ComparisonDef {
kind: BinaryExprType::LTEqual, kind: CompareType::LTEqual,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
); );
assert_parse!( assert_parse!(
expression("1 >= 1"), expression("1 >= 1"),
Expression::Binary(BinaryOpDef { Expression::Compare(ComparisonDef {
kind: BinaryExprType::GTEqual, kind: CompareType::GTEqual,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 5)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
@ -1205,7 +1225,7 @@ mod test {
expression("1+1"), expression("1+1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 3)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 3)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
@ -1214,7 +1234,7 @@ mod test {
expression("1-1"), expression("1-1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Sub, kind: BinaryExprType::Sub,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 3)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 3)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
@ -1223,7 +1243,7 @@ mod test {
expression("1*1"), expression("1*1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Mul, kind: BinaryExprType::Mul,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 3)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 3)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
@ -1232,7 +1252,7 @@ mod test {
expression("1/1"), expression("1/1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Div, kind: BinaryExprType::Div,
left: Value::Int(value_node!(1, 1, 1)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 3)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 3)))),
pos: Position::new(1, 1), pos: Position::new(1, 1),
}) })
@ -1292,7 +1312,7 @@ mod test {
expression("(1 + 1)"), expression("(1 + 1)"),
Expression::Grouped(Box::new(Expression::Binary(BinaryOpDef { Expression::Grouped(Box::new(Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(value_node!(1, 1, 2)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 2)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 6)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 6)))),
pos: Position::new(1, 2), // FIXME(jwall): grouped expressions appear to be getting positioned wrong pos: Position::new(1, 2), // FIXME(jwall): grouped expressions appear to be getting positioned wrong
}))) })))
@ -1481,7 +1501,7 @@ mod test {
grouped_expression("(1 + 1)"), grouped_expression("(1 + 1)"),
Expression::Grouped(Box::new(Expression::Binary(BinaryOpDef { Expression::Grouped(Box::new(Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(value_node!(1, 1, 2)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 2)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 6)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 6)))),
pos: Position::new(1, 2), pos: Position::new(1, 2),
}))) })))
@ -1821,7 +1841,7 @@ mod test {
}), }),
Statement::Expression(Expression::Binary(BinaryOpDef { Statement::Expression(Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(value_node!(1, 1, 35)), left: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 35)))),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 37)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 37)))),
pos: Position::new(1, 35), pos: Position::new(1, 35),
})), })),