diff --git a/CHANGELOG.md b/CHANGELOG.md index ef7683a..37fbcbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,6 @@ ## TODO -- Test correct operator precedence - Implement functions as first class citizens - Parse __more__ binary operators - Parse more complex bindings @@ -23,6 +22,7 @@ - [ ] Test semantic analysis - [ ] Generate php code from current AST +- [x] Test correct operator precedence ## v0.1.2 diff --git a/src/semantic/checks/expression/funtion_call.rs b/src/semantic/checks/expression/funtion_call.rs index 2c8dcbb..44ebac3 100644 --- a/src/semantic/checks/expression/funtion_call.rs +++ b/src/semantic/checks/expression/funtion_call.rs @@ -161,7 +161,7 @@ mod tests { let label = &err.labels[0]; assert_eq!( label.message, - "Expected this expression to be a function, found a `Int`" + "Expected this expression to be a function, found a Value(\"Int\")" ); assert_eq!(label.start, 0); assert_eq!(label.end, 6); diff --git a/src/syntax/parsers/expression/factor.rs b/src/syntax/parsers/expression/factor.rs index 6974f73..f610248 100644 --- a/src/syntax/parsers/expression/factor.rs +++ b/src/syntax/parsers/expression/factor.rs @@ -8,7 +8,7 @@ use crate::{ /// Parses a factor expression. /// /// ```ebnf -/// factor = unary, (("/" | "*", "%"), unary)*; +/// factor = unary, (("/" | "*" | "%"), unary)*; /// ``` pub fn try_parse(tokens: &Vec, pos: usize) -> ParsingResult { let (unary, next_pos) = match super::unary::try_parse(tokens, pos) { @@ -181,4 +181,34 @@ mod tests { _ => panic!("Expected a binary operator"), } } + + #[test] + fn should_parse_mixed_with_unary_ops() { + let tokens = get_tokens(&String::from("2 * -4")).unwrap(); + let (result, next) = try_parse(&tokens, 0).unwrap(); + assert_eq!(next, 4); + + match result { + Expression::BinaryOperator(lexpr, rexpr, op) => { + assert_eq!(op.value, "*"); + let Expression::Int(left_value) = *lexpr else { + panic!("Expected an Int expression") + }; + assert_eq!(left_value.value, "2"); + + let Expression::UnaryOperator(op, right_expr) = *rexpr else { + panic!("Expected a unary operator on the right") + }; + assert_eq!(op.value, "-"); + + let Expression::Int(right_value) = *right_expr else { + panic!("Expected an Int expression"); + }; + assert_eq!(right_value.value, "4"); + } + _ => { + panic!("Expected a binary operator, got {:?}", result) + } + } + } } diff --git a/src/syntax/parsers/expression/term.rs b/src/syntax/parsers/expression/term.rs index 528ca97..51673ad 100644 --- a/src/syntax/parsers/expression/term.rs +++ b/src/syntax/parsers/expression/term.rs @@ -49,6 +49,8 @@ fn parse_many<'a>( #[cfg(test)] mod tests { + use core::panic; + use super::*; use crate::lexic::get_tokens; use crate::lexic::token::TokenType; @@ -179,4 +181,37 @@ mod tests { _ => panic!("Expected a binary operator"), } } + + #[test] + fn should_parse_correct_precedence() { + let tokens = get_tokens(&String::from("1 + 2 * 3")).unwrap(); + let (result, next) = try_parse(&tokens, 0).unwrap(); + assert_eq!(next, 5); + match result { + Expression::BinaryOperator(lexpr, rexpr, op) => { + assert_eq!(op.value, "+"); + + match (*lexpr, *rexpr) { + (Expression::Int(lvalue), Expression::BinaryOperator(llexpr, rrexpr, oop)) => { + assert_eq!(oop.value, "*"); + assert_eq!(lvalue.value, "1"); + + match (*llexpr, *rrexpr) { + (Expression::Int(left), Expression::Int(right)) => { + assert_eq!(left.value, "2"); + assert_eq!(right.value, "3"); + } + _ => { + panic!("Expected left to be an int, right to be an int") + } + } + } + _ => { + panic!("Expected left to be an int, right to be a binary op") + } + } + } + _ => panic!("Expected a binary op, got {:?}", result), + } + } }