1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +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>( fn parse_factor<T: Field>(
input: &String, input: &String,
pos: &Position, pos: &Position,
@ -257,10 +270,9 @@ fn parse_factor<T: Field>(
}, },
Err(err) => Err(err), Err(err) => Err(err),
}, },
(Token::Ide(x), s1, p1) => match next_token::<T>(&s1, &p1) { (Token::Ide(x), s1, p1) => match parse_identified1(x, s1, p1) {
(Token::Open, s2, p2) => parse_function_call(x, s2, p2), Ok((e2, s2, p2)) => parse_factor1(e2, s2, p2),
(Token::LeftBracket, s2, p2) => parse_array_select(x, s2, p2), e => e,
_ => parse_factor1(Expression::Identifier(x), s1, p1),
}, },
(Token::Num(x), s1, p1) => parse_factor1(Expression::Number(x), s1, p1), (Token::Num(x), s1, p1) => parse_factor1(Expression::Number(x), s1, p1),
(t1, _, p1) => Err(Error { (t1, _, p1) => Err(Error {
@ -338,10 +350,7 @@ pub fn parse_function_call<T: Field>(
match next_token::<T>(&s, &p) { match next_token::<T>(&s, &p) {
// no arguments // no arguments
(Token::Close, s1, p1) => { (Token::Close, s1, p1) => {
match parse_term1(Expression::FunctionCall(ide, args), s1, p1) { return parse_term1(Expression::FunctionCall(ide, args), s1, p1);
Ok((e2, s2, p2)) => return parse_expr1(e2, s2, p2),
Err(err) => return Err(err),
}
} }
// at least one argument // at least one argument
(_, _, _) => match parse_expr(&s, &p) { (_, _, _) => match parse_expr(&s, &p) {
@ -353,10 +362,7 @@ pub fn parse_function_call<T: Field>(
p = p2; p = p2;
} }
(Token::Close, s2, p2) => { (Token::Close, s2, p2) => {
match parse_term1(Expression::FunctionCall(ide, args), s2, p2) { return parse_term1(Expression::FunctionCall(ide, args), s2, p2)
Ok((e3, s3, p3)) => return parse_expr1(e3, s3, p3),
Err(err) => return Err(err),
}
} }
(t2, _, p2) => { (t2, _, p2) => {
return Err(Error { return Err(Error {
@ -430,14 +436,11 @@ pub fn parse_array_select<T: Field>(
match next_token::<T>(&input, &pos) { match next_token::<T>(&input, &pos) {
(_, _, _) => match parse_expr(&input, &pos) { (_, _, _) => match parse_expr(&input, &pos) {
Ok((e1, s1, p1)) => match next_token::<T>(&s1, &p1) { 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), Expression::Select(box Expression::Identifier(ide), box e1),
s2, s2,
p2, p2,
) { ),
Ok((e3, s3, p3)) => parse_expr1(e3, s3, p3),
Err(err) => Err(err),
},
(t2, _, p2) => Err(Error { (t2, _, p2) => Err(Error {
expected: vec![Token::RightBracket], expected: vec![Token::RightBracket],
got: t2, got: t2,
@ -469,13 +472,12 @@ pub fn parse_expr<T: Field>(
}, },
Err(err) => Err(err), Err(err) => Err(err),
}, },
(Token::Ide(x), s1, p1) => match next_token::<T>(&s1, &p1) { (Token::Ide(x), s1, p1) => match parse_identified1(x, s1, p1) {
(Token::Open, s2, p2) => parse_function_call(x, s2, p2), Ok((e2, s2, p2)) => match parse_term1(e2, s2, p2) {
(Token::LeftBracket, s2, p2) => parse_array_select(x, s2, p2), Ok((e3, s3, p3)) => parse_expr1(e3, s3, p3),
_ => match parse_term1(Expression::Identifier(x), s1, p1) { e => e,
Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2),
Err(err) => Err(err),
}, },
e => e,
}, },
(Token::Num(x), s1, p1) => match parse_term1(Expression::Number(x), s1, p1) { (Token::Num(x), s1, p1) => match parse_term1(Expression::Number(x), s1, p1) {
Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2), Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2),
@ -495,6 +497,169 @@ mod tests {
use super::*; use super::*;
use field::FieldPrime; 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] #[test]
fn parse_if_then_else_ok() { fn parse_if_then_else_ok() {
let pos = Position { line: 45, col: 121 }; let pos = Position { line: 45, col: 121 };

View file

@ -389,73 +389,79 @@ fn parse_statement1<T: Field>(
Err(err) => Err(err), Err(err) => Err(err),
}, },
(Token::Open, s1, p1) => match parse_function_call(ide, s1, p1) { (Token::Open, s1, p1) => match parse_function_call(ide, s1, p1) {
Ok((e3, s3, p3)) => match next_token(&s3, &p3) { Ok((e3, s3, p3)) => match parse_expr1(e3, s3, p3) {
(Token::Eqeq, s4, p4) => match parse_expr(&s4, &p4) { Ok((e4, s4, p4)) => match next_token(&s4, &p4) {
Ok((e5, s5, p5)) => match next_token(&s5, &p5) { (Token::Eqeq, s5, p5) => match parse_expr(&s5, &p5) {
(Token::InlineComment(_), ref s6, _) => { Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
assert_eq!(s6, ""); (Token::InlineComment(_), ref s7, _) => {
Ok((vec![Statement::Condition(e3, e5)], s5, p5)) assert_eq!(s7, "");
} Ok((vec![Statement::Condition(e4, e6)], s6, p6))
(Token::Unknown(ref t6), ref s6, _) if t6 == "" => { }
assert_eq!(s6, ""); (Token::Unknown(ref t7), ref s7, _) if t7 == "" => {
Ok((vec![Statement::Condition(e3, e5)], s5, p5)) assert_eq!(s7, "");
} Ok((vec![Statement::Condition(e4, e6)], s6, p6))
(t6, _, p6) => Err(Error { }
expected: vec![ (t7, _, p7) => Err(Error {
Token::Add, expected: vec![
Token::Sub, Token::Add,
Token::Pow, Token::Sub,
Token::Mult, Token::Pow,
Token::Div, Token::Mult,
Token::Unknown("".to_string()), Token::Div,
], Token::Unknown("".to_string()),
got: t6, ],
pos: p6, got: t7,
}), pos: p7,
}),
},
Err(err) => Err(err),
}, },
Err(err) => Err(err), (t4, _, p4) => Err(Error {
expected: vec![Token::Eqeq],
got: t4,
pos: p4,
}),
}, },
(t4, _, p4) => Err(Error { Err(err) => Err(err),
expected: vec![Token::Eqeq],
got: t4,
pos: p4,
}),
}, },
Err(err) => Err(err), Err(err) => Err(err),
}, },
(Token::LeftBracket, s1, p1) => match parse_array_select(ide, s1, p1) { (Token::LeftBracket, s1, p1) => match parse_array_select(ide, s1, p1) {
Ok((e3, s3, p3)) => match next_token(&s3, &p3) { Ok((e3, s3, p3)) => match parse_expr1(e3, s3, p3) {
(Token::Eqeq, s4, p4) => match parse_expr(&s4, &p4) { Ok((e4, s4, p4)) => match next_token(&s4, &p4) {
Ok((e5, s5, p5)) => match next_token(&s5, &p5) { (Token::Eqeq, s5, p5) => match parse_expr(&s5, &p5) {
(Token::InlineComment(_), ref s6, _) => { Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
assert_eq!(s6, ""); (Token::InlineComment(_), ref s7, _) => {
Ok((vec![Statement::Condition(e3, e5)], s5, p5)) assert_eq!(s7, "");
} Ok((vec![Statement::Condition(e4, e6)], s6, p6))
(Token::Unknown(ref t6), ref s6, _) if t6 == "" => { }
assert_eq!(s6, ""); (Token::Unknown(ref t7), ref s7, _) if t7 == "" => {
Ok((vec![Statement::Condition(e3, e5)], s5, p5)) assert_eq!(s7, "");
} Ok((vec![Statement::Condition(e4, e6)], s6, p6))
(t6, _, p6) => Err(Error { }
expected: vec![ (t7, _, p7) => Err(Error {
Token::Add, expected: vec![
Token::Sub, Token::Add,
Token::Pow, Token::Sub,
Token::Mult, Token::Pow,
Token::Div, Token::Mult,
Token::Unknown("".to_string()), Token::Div,
], Token::Unknown("".to_string()),
got: t6, ],
pos: p6, got: t7,
}), pos: p7,
}),
},
Err(err) => Err(err),
}, },
Err(err) => Err(err), (Token::Eq, s5, p5) => parse_definition1(Assignee::from(e4), s5, p5),
(t4, _, p4) => Err(Error {
expected: vec![Token::Eqeq],
got: t4,
pos: p4,
}),
}, },
(Token::Eq, s4, p4) => parse_definition1(Assignee::from(e3), s4, p4), Err(err) => Err(err),
(t4, _, p4) => Err(Error {
expected: vec![Token::Eqeq],
got: t4,
pos: p4,
}),
}, },
Err(err) => Err(err), Err(err) => Err(err),
}, },
@ -580,5 +586,48 @@ mod tests {
parse_statement1(String::from("foo"), string, pos) 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)
);
}
} }
} }