From a1c316a43ef7b3a018ff943f38d845859660fbfc Mon Sep 17 00:00:00 2001 From: ishanjain28 Date: Mon, 20 Jan 2020 16:57:19 +0530 Subject: [PATCH] Added more tests for call expression parser --- src/parser/ast/mod.rs | 14 ++-- src/parser/mod.rs | 144 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+), 4 deletions(-) diff --git a/src/parser/ast/mod.rs b/src/parser/ast/mod.rs index f33f5e3..a68a417 100644 --- a/src/parser/ast/mod.rs +++ b/src/parser/ast/mod.rs @@ -645,16 +645,22 @@ impl CallExpression { None => return Some(expressions), }; - Expression::parse(parser, ntoken, ExpressionPriority::Lowest).map(|e| expressions.push(e)); - + if let Some(expr) = Expression::parse(parser, ntoken, ExpressionPriority::Lowest) { + expressions.push(expr); + } else { + return Some(expressions); + } while parser.peek_token_is(TokenType::Comma) { parser.lexer.next(); let token = match parser.lexer.next() { Some(v) => v, None => return Some(expressions), }; - Expression::parse(parser, token, ExpressionPriority::Lowest) - .map(|e| expressions.push(e)); + if let Some(expr) = Expression::parse(parser, token, ExpressionPriority::Lowest) { + expressions.push(expr); + } else { + return Some(expressions); + } } if parser.expect_peek(TokenType::RParen).is_none() { diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 5494f34..cb24111 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -793,6 +793,119 @@ mod tests { )), ))], ), + ( + "a + add(1, 2 * 3, 4 + 5) + d;", + vec![Statement::ExpressionStatement(ExpressionStatement::new( + Token::with_value(TokenType::Ident, "a"), + Expression::InfixExpression(InfixExpression::new( + TokenType::Plus, + Expression::InfixExpression(InfixExpression::new( + TokenType::Plus, + Expression::Identifier(Identifier::new(TokenType::Ident, "a")), + "+", + Expression::CallExpression(CallExpression::new( + Expression::Identifier(Identifier::new(TokenType::Ident, "add")), + vec![ + Expression::IntegerLiteral(IntegerLiteral::new(1)), + Expression::InfixExpression(InfixExpression::new( + TokenType::Asterisk, + Expression::IntegerLiteral(IntegerLiteral::new(2)), + "*", + Expression::IntegerLiteral(IntegerLiteral::new(3)), + )), + Expression::InfixExpression(InfixExpression::new( + TokenType::Plus, + Expression::IntegerLiteral(IntegerLiteral::new(4)), + "+", + Expression::IntegerLiteral(IntegerLiteral::new(5)), + )), + ], + )), + )), + "+", + Expression::Identifier(Identifier::new(TokenType::Ident, "d")), + )), + ))], + ), + ( + "add(a,b,1, 2 * 3, 4 + 5, add(6,7 *8));", + vec![Statement::ExpressionStatement(ExpressionStatement::new( + Token::with_value(TokenType::Ident, "add"), + Expression::CallExpression(CallExpression::new( + Expression::Identifier(Identifier::new(TokenType::Ident, "add")), + vec![ + Expression::Identifier(Identifier::new(TokenType::Ident, "a")), + Expression::Identifier(Identifier::new(TokenType::Ident, "b")), + Expression::IntegerLiteral(IntegerLiteral::new(1)), + Expression::InfixExpression(InfixExpression::new( + TokenType::Asterisk, + Expression::IntegerLiteral(IntegerLiteral::new(2)), + "*", + Expression::IntegerLiteral(IntegerLiteral::new(3)), + )), + Expression::InfixExpression(InfixExpression::new( + TokenType::Plus, + Expression::IntegerLiteral(IntegerLiteral::new(4)), + "+", + Expression::IntegerLiteral(IntegerLiteral::new(5)), + )), + Expression::CallExpression(CallExpression::new( + Expression::Identifier(Identifier::new(TokenType::Ident, "add")), + vec![ + Expression::IntegerLiteral(IntegerLiteral::new(6)), + Expression::InfixExpression(InfixExpression::new( + TokenType::Asterisk, + Expression::IntegerLiteral(IntegerLiteral::new(7)), + "*", + Expression::IntegerLiteral(IntegerLiteral::new(8)), + )), + ], + )), + ], + )), + ))], + ), + ( + "add(a + b + c * d / f + g);", + vec![Statement::ExpressionStatement(ExpressionStatement::new( + Token::with_value(TokenType::Ident, "add"), + Expression::CallExpression(CallExpression::new( + Expression::Identifier(Identifier::new(TokenType::Ident, "add")), + vec![Expression::InfixExpression(InfixExpression::new( + TokenType::Plus, + Expression::InfixExpression(InfixExpression::new( + TokenType::Plus, + Expression::InfixExpression(InfixExpression::new( + TokenType::Plus, + Expression::Identifier(Identifier::new(TokenType::Ident, "a")), + "+", + Expression::Identifier(Identifier::new(TokenType::Ident, "b")), + )), + "+", + Expression::InfixExpression(InfixExpression::new( + TokenType::Slash, + Expression::InfixExpression(InfixExpression::new( + TokenType::Asterisk, + Expression::Identifier(Identifier::new( + TokenType::Ident, + "c", + )), + "*", + Expression::Identifier(Identifier::new( + TokenType::Ident, + "d", + )), + )), + "/", + Expression::Identifier(Identifier::new(TokenType::Ident, "f")), + )), + )), + "+", + Expression::Identifier(Identifier::new(TokenType::Ident, "g")), + ))], + )), + ))], + ), ( "add();", vec![Statement::ExpressionStatement(ExpressionStatement::new( @@ -815,4 +928,35 @@ mod tests { assert_eq!(program.unwrap().statements, test.1); } } + #[test] + fn call_expression_parsing_string() { + // TODO: Figure out why are there inconsistencies in BlockStatements Token + let test_cases = [ + ("add(1, 2 * 3, 4 + 5);", "add(1, (2 * 3), (4 + 5))"), + ( + "a + add(1, 2 * 3, 4 + 5) + d;", + "((a + add(1, (2 * 3), (4 + 5))) + d)", + ), + ( + "add(a,b,1, 2 * 3, 4 + 5, add(6,7 *8));", + "add(a, b, 1, (2 * 3), (4 + 5), add(6, (7 * 8)))", + ), + ( + "add(a + b + c * d / f + g);", + "add((((a + b) + ((c * d) / f)) + g))", + ), + ("add();", "add()"), + ("a + add(b * c) + d", "((a + add((b * c))) + d)"), + ]; + + for test in test_cases.iter() { + let lexer = Lexer::new(test.0); + let mut parser = Parser::new(lexer); + let program = parser.parse_program(); + check_parser_errors(&parser); + assert_eq!(parser.errors.len(), 0); + assert!(program.is_some()); + assert_eq!(program.unwrap().to_string(), test.1); + } + } }