diff --git a/forge_core/src/ast.rs b/forge_core/src/ast.rs index 1e55f99..1ce8eaa 100644 --- a/forge_core/src/ast.rs +++ b/forge_core/src/ast.rs @@ -135,6 +135,19 @@ pub enum Operator { Mul, Div, Mod, + And, + Or, + BitAnd, + BitOr, + Xor, + Lt, + Le, + Gt, + Ge, + Eq, + Ne, + Lshift, + Rshift, } #[derive(PartialEq, Clone, Debug)] diff --git a/forge_core/src/forge.pest b/forge_core/src/forge.pest index 2cd78d5..5da8603 100644 --- a/forge_core/src/forge.pest +++ b/forge_core/src/forge.pest @@ -25,8 +25,28 @@ sub = { "-" } mul = { "*" } div = { "/" } modulus = { "%" } +log_and = { "&&" } +log_or = { "||" } +bit_and = { "&" } +bit_or = { "|" } +xor = { "^" } +lt = { "<" } +le = { "<=" } +gt = { ">" } +ge = { ">=" } +eq = { "==" } +ne = { "!=" } +lshift = { "<<" } +rshift = { ">>" } -operator = _{ add | sub | mul | div | modulus } +operator = _{ + add | sub | + mul | div | modulus | + log_and | log_or | + bit_and | bit_or | xor | + lshift | rshift | + lt | le | gt | ge | + eq | ne } expr = { val ~ (operator ~ val)* } val = { // These are what get evaluated and left on the stack: number | // Literal numbers diff --git a/forge_core/src/forge_parser.rs b/forge_core/src/forge_parser.rs index a83434e..2061a88 100644 --- a/forge_core/src/forge_parser.rs +++ b/forge_core/src/forge_parser.rs @@ -12,6 +12,14 @@ lazy_static::lazy_static! { // Precedence is defined lowest to highest PrattParser::new() + .op(Op::infix(log_or, Left)) + .op(Op::infix(log_and, Left)) + .op(Op::infix(bit_or, Left)) + .op(Op::infix(xor, Left)) + .op(Op::infix(bit_and, Left)) + .op(Op::infix(eq, Left) | Op::infix(ne, Left)) + .op(Op::infix(gt, Left) | Op::infix(ge, Left) | Op::infix(lt, Left) | Op::infix(le, Left)) + .op(Op::infix(lshift, Left) | Op::infix(rshift, Left)) .op(Op::infix(add, Left) | Op::infix(sub, Left)) .op(Op::infix(mul, Left) | Op::infix(div, Left) | Op::infix(modulus, Left)) }; @@ -475,6 +483,19 @@ impl AstNode for Operator { "*" => Self::Mul, "/" => Self::Div, "%" => Self::Mod, + "&&" => Self::And, + "||" => Self::Or, + "&" => Self::BitAnd, + "|" => Self::BitOr, + "^" => Self::Xor, + ">" => Self::Gt, + ">=" => Self::Ge, + "<" => Self::Lt, + "<=" => Self::Le, + "==" => Self::Eq, + "!=" => Self::Ne, + "<<" => Self::Lshift, + ">>" => Self::Rshift, _ => unreachable!(), } } @@ -744,6 +765,40 @@ mod test { Ok(Expr(Expr(2.into(), Mul, 3.into()).into(), Add, 4.into())) ); + assert_eq!( + Node::from_str("1 || 2 && 3"), + Ok(Expr(1.into(), Or, Expr(2.into(), And, 3.into()).into())) + ); + + assert_eq!( + Node::from_str("2 && &blah"), + Ok(Expr(2.into(), And, Address("blah".into()).into())) + ); + + assert_eq!( + Node::from_str("2 & &blah"), + Ok(Expr(2.into(), BitAnd, Address("blah".into()).into())) + ); + + assert_eq!( + Node::from_str("1 | 2 ^ 3"), + Ok(Expr(1.into(), BitOr, Expr(2.into(), Xor, 3.into()).into())) + ); + + assert_eq!( + Node::from_str("x == y > z"), + Ok(Expr( + Name("x".into()).into(), + Eq, + Expr(Name("y".into()).into(), Gt, Name("z".into()).into()).into() + )) + ); + + assert_eq!( + Node::from_str("1 << 6"), + Ok(Expr(1.into(), Lshift, 6.into())) + ); + // Parens assert_eq!( Node::from_str("(1 + 2) * 3"),