diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index 38e0217..6ddce04 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -2,14 +2,14 @@ name = "cel-interpreter" description = "An interpreter for the Common Expression Language (CEL)" repository = "https://github.com/clarkmcc/cel-rust" -version = "0.4.0" +version = "0.4.1" authors = ["Tom Forbes ", "Clark McCauley "] edition = "2018" license = "MIT" categories = ["interpreter", "cel"] [dependencies] -cel-parser = { path = "../parser", version = "0.5.0" } +cel-parser = { path = "../parser", version = "0.5.1" } thiserror = "1.0.40" chrono = "0.4.26" nom = "7.1.3" diff --git a/parser/Cargo.toml b/parser/Cargo.toml index c4f3638..85805e5 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -2,7 +2,7 @@ name = "cel-parser" description = "A parser for the Common Expression Language (CEL)" repository = "https://github.com/clarkmcc/cel-rust" -version = "0.5.0" +version = "0.5.1" authors = ["Tom Forbes ", "Clark McCauley "] edition = "2018" license = "MIT" diff --git a/parser/src/cel.lalrpop b/parser/src/cel.lalrpop index 55bfe56..283bb2e 100644 --- a/parser/src/cel.lalrpop +++ b/parser/src/cel.lalrpop @@ -12,14 +12,42 @@ match { } pub Expression: Expression = { - => Expression::Arithmetic(left.into(), op, right.into()), - => Expression::Relation(left.into(), op, right.into()), - "?" ":" => Expression::Ternary(condition.into(), left.into(), right.into()), - "||" => Expression::Or(left.into(), right.into()), - "&&" => Expression::And(left.into(), right.into()), - => Expression::Unary(op, right.into()), + Conditional +}; + +pub Conditional: Expression = { + "?" ":" => Expression::Ternary(condition.into(), if_true.into(), if_false.into()), + LogicalOr +}; + +pub LogicalOr: Expression = { + "||" => Expression::Or(left.into(), right.into()), + LogicalAnd +}; + +pub LogicalAnd: Expression = { + "&&" => Expression::And(left.into(), right.into()), + Relations +}; + +pub Relations: Expression = { + => Expression::Relation(left.into(), op, right.into()), + ArithmeticAddSub +}; + +pub ArithmeticAddSub: Expression = { + => Expression::Arithmetic(left.into(), op, right.into()), + ArithmeticMulDivMod +}; - Member, +pub ArithmeticMulDivMod: Expression = { + => Expression::Arithmetic(left.into(), op, right.into()), + Unary +}; + +pub Unary: Expression = { + => Expression::Unary(op, right.into()), + Member }; pub Member: Expression = { @@ -64,14 +92,18 @@ CommaSeparated: Vec = { } }; -ArithmeticOp: ArithmeticOp = { // (3) +ArithmeticOpAddSub: ArithmeticOp = { "+" => ArithmeticOp::Add, - "-" => ArithmeticOp::Subtract, + "-" => ArithmeticOp::Subtract +}; + +ArithmeticOpMulDivMod: ArithmeticOp = { "*" => ArithmeticOp::Multiply, "/" => ArithmeticOp::Divide, - "%" => ArithmeticOp::Modulus, + "%" => ArithmeticOp::Modulus }; + UnaryOp: UnaryOp = { "!" => UnaryOp::Not, "!!" => UnaryOp::DoubleNot, diff --git a/parser/src/lib.rs b/parser/src/lib.rs index d0a48aa..3a8bcce 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -491,4 +491,19 @@ mod tests { ), ); } + + #[test] + fn test_operator_precedence() { + assert_parse_eq( + "a && b == 'string'", + And( + Box::new(Ident("a".to_string().into())), + Box::new(Relation( + Box::new(Ident("b".to_string().into())), + RelationOp::Equals, + Box::new(Expression::Atom(String("string".to_string().into()))), + )), + ), + ); + } }