1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

Merge pull request #173 from Schaeff/fix-terms-precedence

Fix terms precedence
This commit is contained in:
JacobEberhardt 2018-11-30 16:31:38 +01:00 committed by GitHub
commit 45657acb9b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 296 additions and 82 deletions

View file

@ -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 };

View file

@ -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)
);
}
}
}