Merge pull request #173 from Schaeff/fix-terms-precedence
Fix terms precedence
This commit is contained in:
commit
45657acb9b
2 changed files with 296 additions and 82 deletions
|
@ -240,6 +240,19 @@ fn parse_factor1<T: Field>(
|
|||
}
|
||||
}
|
||||
|
||||
// parse an identifier or select or function call
|
||||
fn parse_identified1<T: Field>(
|
||||
x: String,
|
||||
input: String,
|
||||
position: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
match next_token::<T>(&input, &position) {
|
||||
(Token::Open, s1, p1) => parse_function_call(x, s1, p1),
|
||||
(Token::LeftBracket, s1, p1) => parse_array_select(x, s1, p1),
|
||||
_ => Ok((Expression::Identifier(x), input, position)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_factor<T: Field>(
|
||||
input: &String,
|
||||
pos: &Position,
|
||||
|
@ -257,10 +270,9 @@ fn parse_factor<T: Field>(
|
|||
},
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Ide(x), s1, p1) => match next_token::<T>(&s1, &p1) {
|
||||
(Token::Open, s2, p2) => parse_function_call(x, s2, p2),
|
||||
(Token::LeftBracket, s2, p2) => parse_array_select(x, s2, p2),
|
||||
_ => parse_factor1(Expression::Identifier(x), s1, p1),
|
||||
(Token::Ide(x), s1, p1) => match parse_identified1(x, s1, p1) {
|
||||
Ok((e2, s2, p2)) => parse_factor1(e2, s2, p2),
|
||||
e => e,
|
||||
},
|
||||
(Token::Num(x), s1, p1) => parse_factor1(Expression::Number(x), s1, p1),
|
||||
(t1, _, p1) => Err(Error {
|
||||
|
@ -338,10 +350,7 @@ pub fn parse_function_call<T: Field>(
|
|||
match next_token::<T>(&s, &p) {
|
||||
// no arguments
|
||||
(Token::Close, s1, p1) => {
|
||||
match parse_term1(Expression::FunctionCall(ide, args), s1, p1) {
|
||||
Ok((e2, s2, p2)) => return parse_expr1(e2, s2, p2),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
return parse_term1(Expression::FunctionCall(ide, args), s1, p1);
|
||||
}
|
||||
// at least one argument
|
||||
(_, _, _) => match parse_expr(&s, &p) {
|
||||
|
@ -353,10 +362,7 @@ pub fn parse_function_call<T: Field>(
|
|||
p = p2;
|
||||
}
|
||||
(Token::Close, s2, p2) => {
|
||||
match parse_term1(Expression::FunctionCall(ide, args), s2, p2) {
|
||||
Ok((e3, s3, p3)) => return parse_expr1(e3, s3, p3),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
return parse_term1(Expression::FunctionCall(ide, args), s2, p2)
|
||||
}
|
||||
(t2, _, p2) => {
|
||||
return Err(Error {
|
||||
|
@ -430,14 +436,11 @@ pub fn parse_array_select<T: Field>(
|
|||
match next_token::<T>(&input, &pos) {
|
||||
(_, _, _) => match parse_expr(&input, &pos) {
|
||||
Ok((e1, s1, p1)) => match next_token::<T>(&s1, &p1) {
|
||||
(Token::RightBracket, s2, p2) => match parse_term1(
|
||||
(Token::RightBracket, s2, p2) => parse_term1(
|
||||
Expression::Select(box Expression::Identifier(ide), box e1),
|
||||
s2,
|
||||
p2,
|
||||
) {
|
||||
Ok((e3, s3, p3)) => parse_expr1(e3, s3, p3),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
),
|
||||
(t2, _, p2) => Err(Error {
|
||||
expected: vec![Token::RightBracket],
|
||||
got: t2,
|
||||
|
@ -469,13 +472,12 @@ pub fn parse_expr<T: Field>(
|
|||
},
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Ide(x), s1, p1) => match next_token::<T>(&s1, &p1) {
|
||||
(Token::Open, s2, p2) => parse_function_call(x, s2, p2),
|
||||
(Token::LeftBracket, s2, p2) => parse_array_select(x, s2, p2),
|
||||
_ => match parse_term1(Expression::Identifier(x), s1, p1) {
|
||||
Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2),
|
||||
Err(err) => Err(err),
|
||||
(Token::Ide(x), s1, p1) => match parse_identified1(x, s1, p1) {
|
||||
Ok((e2, s2, p2)) => match parse_term1(e2, s2, p2) {
|
||||
Ok((e3, s3, p3)) => parse_expr1(e3, s3, p3),
|
||||
e => e,
|
||||
},
|
||||
e => e,
|
||||
},
|
||||
(Token::Num(x), s1, p1) => match parse_term1(Expression::Number(x), s1, p1) {
|
||||
Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2),
|
||||
|
@ -495,6 +497,169 @@ mod tests {
|
|||
use super::*;
|
||||
use field::FieldPrime;
|
||||
|
||||
mod terms {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_number_sum() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("1 + 2 + 3");
|
||||
let expr = Expression::Add(
|
||||
box Expression::Add(
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
box Expression::Number(FieldPrime::from(2)),
|
||||
),
|
||||
box Expression::Number(FieldPrime::from(3)),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((expr, String::from(""), pos.col(string.len() as isize))),
|
||||
parse_expr(&string, &pos)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_number_sub() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("1 - 2 - 3");
|
||||
let expr = Expression::Sub(
|
||||
box Expression::Sub(
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
box Expression::Number(FieldPrime::from(2)),
|
||||
),
|
||||
box Expression::Number(FieldPrime::from(3)),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((expr, String::from(""), pos.col(string.len() as isize))),
|
||||
parse_expr(&string, &pos)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_function_call_single_sub() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("1 - f(a)");
|
||||
let expr = Expression::Sub(
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
box Expression::FunctionCall(
|
||||
String::from("f"),
|
||||
vec![Expression::Identifier(String::from("a"))],
|
||||
),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((expr, String::from(""), pos.col(string.len() as isize))),
|
||||
parse_expr(&string, &pos)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_function_call_sub() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("1 - f() - 3");
|
||||
let expr = Expression::Sub(
|
||||
box Expression::Sub(
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
box Expression::FunctionCall(String::from("f"), vec![]),
|
||||
),
|
||||
box Expression::Number(FieldPrime::from(3)),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((expr, String::from(""), pos.col(string.len() as isize))),
|
||||
parse_expr(&string, &pos)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_function_call_add() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("1 + f() + 3");
|
||||
let expr = Expression::Add(
|
||||
box Expression::Add(
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
box Expression::FunctionCall(String::from("f"), vec![]),
|
||||
),
|
||||
box Expression::Number(FieldPrime::from(3)),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((expr, String::from(""), pos.col(string.len() as isize))),
|
||||
parse_expr(&string, &pos)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_select_sub() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("1 - f[2] - 3");
|
||||
let expr = Expression::Sub(
|
||||
box Expression::Sub(
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
box Expression::Select(
|
||||
box Expression::Identifier(String::from("f")),
|
||||
box Expression::Number(FieldPrime::from(2)),
|
||||
),
|
||||
),
|
||||
box Expression::Number(FieldPrime::from(3)),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((expr, String::from(""), pos.col(string.len() as isize))),
|
||||
parse_expr(&string, &pos)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_select_add() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("1 + f[2] + 3");
|
||||
let expr = Expression::Add(
|
||||
box Expression::Add(
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
box Expression::Select(
|
||||
box Expression::Identifier(String::from("f")),
|
||||
box Expression::Number(FieldPrime::from(2)),
|
||||
),
|
||||
),
|
||||
box Expression::Number(FieldPrime::from(3)),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((expr, String::from(""), pos.col(string.len() as isize))),
|
||||
parse_expr(&string, &pos)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_identifier_sub() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("1 - f - 3");
|
||||
let expr = Expression::Sub(
|
||||
box Expression::Sub(
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
box Expression::Identifier(String::from("f")),
|
||||
),
|
||||
box Expression::Number(FieldPrime::from(3)),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((expr, String::from(""), pos.col(string.len() as isize))),
|
||||
parse_expr(&string, &pos)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_identifier_add() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("1 + f + 3");
|
||||
let expr = Expression::Add(
|
||||
box Expression::Add(
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
box Expression::Identifier(String::from("f")),
|
||||
),
|
||||
box Expression::Number(FieldPrime::from(3)),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((expr, String::from(""), pos.col(string.len() as isize))),
|
||||
parse_expr(&string, &pos)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_if_then_else_ok() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
|
|
|
@ -389,18 +389,19 @@ fn parse_statement1<T: Field>(
|
|||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Open, s1, p1) => match parse_function_call(ide, s1, p1) {
|
||||
Ok((e3, s3, p3)) => match next_token(&s3, &p3) {
|
||||
(Token::Eqeq, s4, p4) => match parse_expr(&s4, &p4) {
|
||||
Ok((e5, s5, p5)) => match next_token(&s5, &p5) {
|
||||
(Token::InlineComment(_), ref s6, _) => {
|
||||
assert_eq!(s6, "");
|
||||
Ok((vec![Statement::Condition(e3, e5)], s5, p5))
|
||||
Ok((e3, s3, p3)) => match parse_expr1(e3, s3, p3) {
|
||||
Ok((e4, s4, p4)) => match next_token(&s4, &p4) {
|
||||
(Token::Eqeq, s5, p5) => match parse_expr(&s5, &p5) {
|
||||
Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
|
||||
(Token::InlineComment(_), ref s7, _) => {
|
||||
assert_eq!(s7, "");
|
||||
Ok((vec![Statement::Condition(e4, e6)], s6, p6))
|
||||
}
|
||||
(Token::Unknown(ref t6), ref s6, _) if t6 == "" => {
|
||||
assert_eq!(s6, "");
|
||||
Ok((vec![Statement::Condition(e3, e5)], s5, p5))
|
||||
(Token::Unknown(ref t7), ref s7, _) if t7 == "" => {
|
||||
assert_eq!(s7, "");
|
||||
Ok((vec![Statement::Condition(e4, e6)], s6, p6))
|
||||
}
|
||||
(t6, _, p6) => Err(Error {
|
||||
(t7, _, p7) => Err(Error {
|
||||
expected: vec![
|
||||
Token::Add,
|
||||
Token::Sub,
|
||||
|
@ -409,8 +410,8 @@ fn parse_statement1<T: Field>(
|
|||
Token::Div,
|
||||
Token::Unknown("".to_string()),
|
||||
],
|
||||
got: t6,
|
||||
pos: p6,
|
||||
got: t7,
|
||||
pos: p7,
|
||||
}),
|
||||
},
|
||||
Err(err) => Err(err),
|
||||
|
@ -423,19 +424,22 @@ fn parse_statement1<T: Field>(
|
|||
},
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::LeftBracket, s1, p1) => match parse_array_select(ide, s1, p1) {
|
||||
Ok((e3, s3, p3)) => match next_token(&s3, &p3) {
|
||||
(Token::Eqeq, s4, p4) => match parse_expr(&s4, &p4) {
|
||||
Ok((e5, s5, p5)) => match next_token(&s5, &p5) {
|
||||
(Token::InlineComment(_), ref s6, _) => {
|
||||
assert_eq!(s6, "");
|
||||
Ok((vec![Statement::Condition(e3, e5)], s5, p5))
|
||||
Ok((e3, s3, p3)) => match parse_expr1(e3, s3, p3) {
|
||||
Ok((e4, s4, p4)) => match next_token(&s4, &p4) {
|
||||
(Token::Eqeq, s5, p5) => match parse_expr(&s5, &p5) {
|
||||
Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
|
||||
(Token::InlineComment(_), ref s7, _) => {
|
||||
assert_eq!(s7, "");
|
||||
Ok((vec![Statement::Condition(e4, e6)], s6, p6))
|
||||
}
|
||||
(Token::Unknown(ref t6), ref s6, _) if t6 == "" => {
|
||||
assert_eq!(s6, "");
|
||||
Ok((vec![Statement::Condition(e3, e5)], s5, p5))
|
||||
(Token::Unknown(ref t7), ref s7, _) if t7 == "" => {
|
||||
assert_eq!(s7, "");
|
||||
Ok((vec![Statement::Condition(e4, e6)], s6, p6))
|
||||
}
|
||||
(t6, _, p6) => Err(Error {
|
||||
(t7, _, p7) => Err(Error {
|
||||
expected: vec![
|
||||
Token::Add,
|
||||
Token::Sub,
|
||||
|
@ -444,13 +448,13 @@ fn parse_statement1<T: Field>(
|
|||
Token::Div,
|
||||
Token::Unknown("".to_string()),
|
||||
],
|
||||
got: t6,
|
||||
pos: p6,
|
||||
got: t7,
|
||||
pos: p7,
|
||||
}),
|
||||
},
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Eq, s4, p4) => parse_definition1(Assignee::from(e3), s4, p4),
|
||||
(Token::Eq, s5, p5) => parse_definition1(Assignee::from(e4), s5, p5),
|
||||
(t4, _, p4) => Err(Error {
|
||||
expected: vec![Token::Eqeq],
|
||||
got: t4,
|
||||
|
@ -459,6 +463,8 @@ fn parse_statement1<T: Field>(
|
|||
},
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
_ => match parse_term1(Expression::Identifier(ide), input, pos) {
|
||||
Ok((e2, s2, p2)) => match parse_expr1(e2, s2, p2) {
|
||||
Ok((e3, s3, p3)) => match next_token(&s3, &p3) {
|
||||
|
@ -580,5 +586,48 @@ mod tests {
|
|||
parse_statement1(String::from("foo"), string, pos)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn left_call_in_assertion2() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("() - g() - 1 == 1");
|
||||
let cond = Statement::Condition(
|
||||
Expression::Sub(
|
||||
box Expression::Sub(
|
||||
box Expression::FunctionCall(String::from("foo"), vec![]),
|
||||
box Expression::FunctionCall(String::from("g"), vec![]),
|
||||
),
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
),
|
||||
Expression::Number(FieldPrime::from(1)),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((vec![cond], String::from(""), pos.col(string.len() as isize))),
|
||||
parse_statement1(String::from("foo"), string, pos)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn left_select_in_assertion2() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("[3] - g() - 1 == 1");
|
||||
let cond = Statement::Condition(
|
||||
Expression::Sub(
|
||||
box Expression::Sub(
|
||||
box Expression::Select(
|
||||
box Expression::Identifier(String::from("foo")),
|
||||
box Expression::Number(FieldPrime::from(3)),
|
||||
),
|
||||
box Expression::FunctionCall(String::from("g"), vec![]),
|
||||
),
|
||||
box Expression::Number(FieldPrime::from(1)),
|
||||
),
|
||||
Expression::Number(FieldPrime::from(1)),
|
||||
);
|
||||
assert_eq!(
|
||||
Ok((vec![cond], String::from(""), pos.col(string.len() as isize))),
|
||||
parse_statement1(String::from("foo"), string, pos)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue