Skip to content

Commit

Permalink
Fixed operator precedence #19
Browse files Browse the repository at this point in the history
  • Loading branch information
clarkmcc committed Sep 18, 2023
1 parent 70f9632 commit be39e23
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 10 deletions.
52 changes: 42 additions & 10 deletions parser/src/cel.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,42 @@ match {
}

pub Expression: Expression = {
<left:Expression> <op:ArithmeticOp> <right:Member> => Expression::Arithmetic(left.into(), op, right.into()),
<left:Expression> <op:RelationOp> <right:Member> => Expression::Relation(left.into(), op, right.into()),
<condition:Expression> "?" <left:Member> ":" <right:Primary> => Expression::Ternary(condition.into(), left.into(), right.into()),
<left:Expression> "||" <right:Member> => Expression::Or(left.into(), right.into()),
<left:Expression> "&&" <right:Member> => Expression::And(left.into(), right.into()),
<op:UnaryOp> <right:Member> => Expression::Unary(op, right.into()),
Conditional
};

pub Conditional: Expression = {
<condition:LogicalOr> "?" <if_true:LogicalOr> ":" <if_false:Conditional> => Expression::Ternary(condition.into(), if_true.into(), if_false.into()),
LogicalOr
};

pub LogicalOr: Expression = {
<left:LogicalOr> "||" <right:LogicalAnd> => Expression::Or(left.into(), right.into()),
LogicalAnd
};

pub LogicalAnd: Expression = {
<left:LogicalAnd> "&&" <right:Relations> => Expression::And(left.into(), right.into()),
Relations
};

pub Relations: Expression = {
<left:ArithmeticAddSub> <op:RelationOp> <right:ArithmeticAddSub> => Expression::Relation(left.into(), op, right.into()),
ArithmeticAddSub
};

pub ArithmeticAddSub: Expression = {
<left:ArithmeticAddSub> <op:ArithmeticOpAddSub> <right:ArithmeticMulDivMod> => Expression::Arithmetic(left.into(), op, right.into()),
ArithmeticMulDivMod
};

Member,
pub ArithmeticMulDivMod: Expression = {
<left:ArithmeticMulDivMod> <op:ArithmeticOpMulDivMod> <right:Unary> => Expression::Arithmetic(left.into(), op, right.into()),
Unary
};

pub Unary: Expression = {
<op:UnaryOp> <right:Member> => Expression::Unary(op, right.into()),
Member
};

pub Member: Expression = {
Expand Down Expand Up @@ -64,14 +92,18 @@ CommaSeparated<T>: Vec<T> = {
}
};

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,
Expand Down
15 changes: 15 additions & 0 deletions parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()))),
)),
),
);
}
}

0 comments on commit be39e23

Please sign in to comment.