diff --git a/src/parser.rs b/src/parser.rs index b95af99..abd7421 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -133,9 +133,7 @@ impl Parser { fn parse_let_statement(&mut self) -> Option> { let value = self.expect_peek_ident()?; - let name = Identifier { - value, - }; + let name = Identifier { value }; if !self.expect_peek(TokenType::Assign) { return None; @@ -198,9 +196,7 @@ impl Parser { } fn parse_identifier(&mut self, value: String) -> Rc { - Rc::new(Identifier { - value, - }) + Rc::new(Identifier { value }) } fn parse_integer_literal(&mut self, value: u64) -> Rc { @@ -253,6 +249,25 @@ impl Parser { }) } + fn parse_grouped_expression(&mut self) -> Rc { + self.next(); + + let expr = self.parse_expression(Precedence::Lowest); + + if !self.expect_peek(TokenType::Rparen) { + // TODO: add errors + return Rc::new(DummyExpression {}); + } + let expr = if let Some(expr) = expr { + expr + } else { + // TODO: add errors + return Rc::new(DummyExpression {}); + }; + + expr + } + fn expect_peek(&mut self, token_type: TokenType) -> bool { let peek_token = if let Some(token) = &self.peek_token { token @@ -373,6 +388,7 @@ impl Parser { })), True => Some(Box::new(Self::parse_boolean)), False => Some(Box::new(Self::parse_boolean)), + Lparen => Some(Box::new(Self::parse_grouped_expression)), _ => None, } } @@ -416,11 +432,10 @@ mod tests { use crate::{ ast::{ - Boolean, DummyExpression, Expression, ExpressionStatement, Identifier, Infix, - InfixOperator, IntegerLiteral, Let, Prefix, PrefixOperator, Program, Return, Statement, + Boolean, Expression, ExpressionStatement, Identifier, Infix, InfixOperator, + IntegerLiteral, Let, Prefix, PrefixOperator, Program, Return, }, lexer::Lexer, - token::{Token, TokenType}, }; use super::Parser; @@ -445,15 +460,11 @@ mod tests { Program { statements: vec![ Rc::new(Let { - name: Identifier { - value: "x".into() - }, + name: Identifier { value: "x".into() }, value: Rc::new(IntegerLiteral { value: 5 }) }), Rc::new(Let { - name: Identifier { - value: "y".into() - }, + name: Identifier { value: "y".into() }, value: Rc::new(IntegerLiteral { value: 10 }) }), Rc::new(Let { @@ -573,7 +584,6 @@ mod tests { fn prefix_expressions() { struct Test { input: String, - token: Token, operator: PrefixOperator, value: i64, } @@ -581,13 +591,11 @@ mod tests { let tests = vec![ Test { input: "!15".into(), - token: Token::Bang, operator: PrefixOperator::Bang, value: 15, }, Test { input: "-15".into(), - token: Token::Minus, operator: PrefixOperator::Minus, value: 15, }, @@ -716,13 +724,9 @@ mod tests { operator: InfixOperator::Asterisk, left: Rc::new(Prefix { operator: PrefixOperator::Minus, - right: Rc::new(Identifier { - value: "a".into(), - }), - }), - right: Rc::new(Identifier { - value: "b".into(), + right: Rc::new(Identifier { value: "a".into() }), }), + right: Rc::new(Identifier { value: "b".into() }), }), }, Test { @@ -731,9 +735,7 @@ mod tests { operator: PrefixOperator::Bang, right: Rc::new(Prefix { operator: PrefixOperator::Minus, - right: Rc::new(Identifier { - value: "a".into(), - }), + right: Rc::new(Identifier { value: "a".into() }), }), }), }, @@ -743,16 +745,10 @@ mod tests { operator: InfixOperator::Plus, left: Rc::new(Infix { operator: InfixOperator::Plus, - left: Rc::new(Identifier { - value: "a".into(), - }), - right: Rc::new(Identifier { - value: "b".into(), - }), - }), - right: Rc::new(Identifier { - value: "c".into(), + left: Rc::new(Identifier { value: "a".into() }), + right: Rc::new(Identifier { value: "b".into() }), }), + right: Rc::new(Identifier { value: "c".into() }), }), }, Test { @@ -761,16 +757,10 @@ mod tests { operator: InfixOperator::Minus, left: Rc::new(Infix { operator: InfixOperator::Plus, - left: Rc::new(Identifier { - value: "a".into(), - }), - right: Rc::new(Identifier { - value: "b".into(), - }), - }), - right: Rc::new(Identifier { - value: "c".into(), + left: Rc::new(Identifier { value: "a".into() }), + right: Rc::new(Identifier { value: "b".into() }), }), + right: Rc::new(Identifier { value: "c".into() }), }), }, Test { @@ -779,16 +769,10 @@ mod tests { operator: InfixOperator::Asterisk, left: Rc::new(Infix { operator: InfixOperator::Asterisk, - left: Rc::new(Identifier { - value: "a".into(), - }), - right: Rc::new(Identifier { - value: "b".into(), - }), - }), - right: Rc::new(Identifier { - value: "c".into(), + left: Rc::new(Identifier { value: "a".into() }), + right: Rc::new(Identifier { value: "b".into() }), }), + right: Rc::new(Identifier { value: "c".into() }), }), }, Test { @@ -797,33 +781,21 @@ mod tests { operator: InfixOperator::Slash, left: Rc::new(Infix { operator: InfixOperator::Asterisk, - left: Rc::new(Identifier { - value: "a".into(), - }), - right: Rc::new(Identifier { - value: "b".into(), - }), - }), - right: Rc::new(Identifier { - value: "c".into(), + left: Rc::new(Identifier { value: "a".into() }), + right: Rc::new(Identifier { value: "b".into() }), }), + right: Rc::new(Identifier { value: "c".into() }), }), }, Test { input: "a + b / c".into(), expression: Rc::new(Infix { operator: InfixOperator::Plus, - left: Rc::new(Identifier { - value: "a".into(), - }), + left: Rc::new(Identifier { value: "a".into() }), right: Rc::new(Infix { operator: InfixOperator::Slash, - left: Rc::new(Identifier { - value: "b".into(), - }), - right: Rc::new(Identifier { - value: "c".into(), - }), + left: Rc::new(Identifier { value: "b".into() }), + right: Rc::new(Identifier { value: "c".into() }), }), }), }, @@ -835,32 +807,20 @@ mod tests { operator: InfixOperator::Plus, left: Rc::new(Infix { operator: InfixOperator::Plus, - left: Rc::new(Identifier { - value: "a".into(), - }), + left: Rc::new(Identifier { value: "a".into() }), right: Rc::new(Infix { operator: InfixOperator::Asterisk, - left: Rc::new(Identifier { - value: "b".into(), - }), - right: Rc::new(Identifier { - value: "c".into(), - }), + left: Rc::new(Identifier { value: "b".into() }), + right: Rc::new(Identifier { value: "c".into() }), }), }), right: Rc::new(Infix { operator: InfixOperator::Slash, - left: Rc::new(Identifier { - value: "d".into(), - }), - right: Rc::new(Identifier { - value: "e".into(), - }), + left: Rc::new(Identifier { value: "d".into() }), + right: Rc::new(Identifier { value: "e".into() }), }), }), - right: Rc::new(Identifier { - value: "f".into(), - }), + right: Rc::new(Identifier { value: "f".into() }), }), }, Test { @@ -923,6 +883,68 @@ mod tests { }), }), }, + Test { + input: "1 + (2 + 3) + 4".into(), + expression: Rc::new(Infix { + operator: InfixOperator::Plus, + left: Rc::new(Infix { + operator: InfixOperator::Plus, + left: Rc::new(IntegerLiteral { value: 1 }), + right: Rc::new(Infix { + operator: InfixOperator::Plus, + left: Rc::new(IntegerLiteral { value: 2 }), + right: Rc::new(IntegerLiteral { value: 3 }), + }), + }), + right: Rc::new(IntegerLiteral { value: 4 }), + }), + }, + Test { + input: "(5 + 5) * 2".into(), + expression: Rc::new(Infix { + operator: InfixOperator::Asterisk, + left: Rc::new(Infix { + operator: InfixOperator::Plus, + left: Rc::new(IntegerLiteral { value: 5 }), + right: Rc::new(IntegerLiteral { value: 5 }), + }), + right: Rc::new(IntegerLiteral { value: 2 }), + }), + }, + Test { + input: "2 / (5 + 5)".into(), + expression: Rc::new(Infix { + operator: InfixOperator::Slash, + left: Rc::new(IntegerLiteral { value: 2 }), + right: Rc::new(Infix { + operator: InfixOperator::Plus, + left: Rc::new(IntegerLiteral { value: 5 }), + right: Rc::new(IntegerLiteral { value: 5 }), + }), + }), + }, + Test { + input: "-(5 + 5)".into(), + expression: Rc::new(Prefix { + operator: PrefixOperator::Minus, + right: Rc::new(Infix { + operator: InfixOperator::Plus, + left: Rc::new(IntegerLiteral { value: 5 }), + right: Rc::new(IntegerLiteral { value: 5 }), + }), + }), + }, + Test { + input: "!(true == true)".into(), + expression: Rc::new(Prefix { + operator: PrefixOperator::Bang, + right: Rc::new(Infix { + operator: InfixOperator::Eq, + left: Rc::new(Boolean { value: true }), + right: Rc::new(Boolean { value: true }), + }), + }), + }, ]; for test in tests {