From 8ec7ec1ba159dc34168df281c7bc092ce16272cd Mon Sep 17 00:00:00 2001 From: ishanjain28 Date: Mon, 20 Jan 2020 16:14:26 +0530 Subject: [PATCH] Added Call Expressions 1. Added Call Expressions 2. Refactored Boolean/Prefix/Infix parse functions 3. Added tests to support Call Expressions parser --- src/parser/ast/mod.rs | 203 ++++++++++++++++++++++++++---------------- src/parser/mod.rs | 188 +++++++++++++++++++++++--------------- 2 files changed, 244 insertions(+), 147 deletions(-) diff --git a/src/parser/ast/mod.rs b/src/parser/ast/mod.rs index 323c685..f33f5e3 100644 --- a/src/parser/ast/mod.rs +++ b/src/parser/ast/mod.rs @@ -192,6 +192,7 @@ pub enum Expression { BooleanExpression(BooleanExpression), IfExpression(IfExpression), FunctionExpression(FunctionLiteral), + CallExpression(CallExpression), // TODO: Temporary placeholder value. Should be removed once this section is done None, } @@ -225,10 +226,6 @@ impl Expression { } } - pub fn parse_boolean(_parser: &mut Parser, token: Token) -> Option { - Some(Self::BooleanExpression(BooleanExpression::new(token.name))) - } - pub fn parse_grouped_expression(parser: &mut Parser, _token: Token) -> Option { let next_token = parser.lexer.next()?; let expr = Expression::parse(parser, next_token, ExpressionPriority::Lowest); @@ -239,47 +236,6 @@ impl Expression { expr } } - - pub fn parse_if_expression(parser: &mut Parser, ctoken: Token) -> Option { - if parser.expect_peek(TokenType::LParen).is_none() { - return None; - } - let next_token = parser.lexer.next()?; - let condition = Expression::parse(parser, next_token.clone(), ExpressionPriority::Lowest)?; - - if parser.expect_peek(TokenType::RParen).is_none() { - return None; - } - if parser.expect_peek(TokenType::LBrace).is_none() { - return None; - } - - let consequence = BlockStatement::parse(parser, next_token)?; - - if parser.peek_token_is(TokenType::Else) { - let token = parser.lexer.next()?; - - if parser.expect_peek(TokenType::LBrace).is_none() { - return None; - } - - let alternative = BlockStatement::parse(parser, token); - - Some(Expression::IfExpression(IfExpression::new( - ctoken.name, - condition, - consequence, - alternative, - ))) - } else { - Some(Expression::IfExpression(IfExpression::new( - ctoken.name, - condition, - consequence, - None, - ))) - } - } } impl Display for Expression { @@ -292,6 +248,7 @@ impl Display for Expression { Expression::BooleanExpression(v) => v.to_string(), Expression::IfExpression(v) => v.to_string(), Expression::FunctionExpression(v) => v.to_string(), + Expression::CallExpression(v) => v.to_string(), Expression::None => "None".into(), }; @@ -337,16 +294,12 @@ impl Display for Identifier { #[derive(Debug, PartialEq)] pub struct IntegerLiteral { - token: TokenType, value: i64, } impl IntegerLiteral { - pub fn new(token: TokenType, v: i64) -> Self { - Self { - token: token, - value: v, - } + pub fn new(v: i64) -> Self { + Self { value: v } } pub fn parse(parser: &mut Parser, token: Token) -> Option { let n = match token.literal?.parse::() { @@ -358,24 +311,21 @@ impl IntegerLiteral { return None; } }; - Some(Expression::IntegerLiteral(IntegerLiteral::new( - TokenType::Int, - n, - ))) + Some(Expression::IntegerLiteral(IntegerLiteral::new(n))) } } #[derive(Debug, PartialEq)] pub struct PrefixExpression { - token: Token, + token: TokenType, operator: String, right: Box, } impl PrefixExpression { - pub fn new(token: Token, operator: &str, right: Expression) -> Self { + pub fn new(token: TokenType, operator: &str, right: Expression) -> Self { Self { - token: token, + token, operator: operator.to_string(), right: Box::new(right), } @@ -385,7 +335,7 @@ impl PrefixExpression { let next_token = parser.lexer.next()?; let right_expr = Expression::parse(parser, next_token.clone(), ExpressionPriority::Prefix)?; Some(Expression::PrefixExpression(PrefixExpression { - token: ctoken.clone(), + token: ctoken.name, operator: ctoken.to_string().into(), right: Box::new(right_expr), })) @@ -404,16 +354,16 @@ impl Display for PrefixExpression { #[derive(Debug, PartialEq)] pub struct InfixExpression { - token: Token, + token: TokenType, left: Box, operator: String, right: Box, } impl InfixExpression { - pub fn new(token: Token, left: Expression, operator: &str, right: Expression) -> Self { + pub fn new(token: TokenType, left: Expression, operator: &str, right: Expression) -> Self { Self { - token: token, + token, left: Box::new(left), operator: operator.to_string(), right: Box::new(right), @@ -424,7 +374,7 @@ impl InfixExpression { let next_token = parser.lexer.next()?; let right_expr = Expression::parse(parser, next_token, cprecedence)?; Some(Expression::InfixExpression(InfixExpression::new( - token.clone(), + token.name, left_expr, &token.to_string(), right_expr, @@ -456,6 +406,11 @@ impl BooleanExpression { value: token == TokenType::True, } } + pub fn parse(_parser: &mut Parser, token: Token) -> Option { + Some(Expression::BooleanExpression(BooleanExpression::new( + token.name, + ))) + } } impl Display for BooleanExpression { @@ -466,7 +421,6 @@ impl Display for BooleanExpression { #[derive(Debug, PartialEq)] pub struct IfExpression { - token: TokenType, condition: Box, consequence: BlockStatement, alternative: Option, @@ -474,18 +428,54 @@ pub struct IfExpression { impl IfExpression { pub fn new( - token: TokenType, condition: Expression, consequence: BlockStatement, alternative: Option, ) -> Self { Self { - token, condition: Box::new(condition), consequence, alternative, } } + pub fn parse(parser: &mut Parser, _ctoken: Token) -> Option { + if parser.expect_peek(TokenType::LParen).is_none() { + return None; + } + let next_token = parser.lexer.next()?; + let condition = Expression::parse(parser, next_token.clone(), ExpressionPriority::Lowest)?; + + if parser.expect_peek(TokenType::RParen).is_none() { + return None; + } + if parser.expect_peek(TokenType::LBrace).is_none() { + return None; + } + + let consequence = BlockStatement::parse(parser, next_token)?; + + if parser.peek_token_is(TokenType::Else) { + let token = parser.lexer.next()?; + + if parser.expect_peek(TokenType::LBrace).is_none() { + return None; + } + + let alternative = BlockStatement::parse(parser, token); + + Some(Expression::IfExpression(IfExpression::new( + condition, + consequence, + alternative, + ))) + } else { + Some(Expression::IfExpression(IfExpression::new( + condition, + consequence, + None, + ))) + } + } } impl Display for IfExpression { @@ -504,19 +494,15 @@ impl Display for IfExpression { #[derive(Debug, PartialEq)] pub struct BlockStatement { - token: Token, statements: Vec, } impl BlockStatement { - pub fn new(token: Token, stmt: Vec) -> Self { - Self { - token, - statements: stmt, - } + pub fn new(stmt: Vec) -> Self { + Self { statements: stmt } } - pub fn parse(parser: &mut Parser, ogtoken: Token) -> Option { + pub fn parse(parser: &mut Parser, _ogtoken: Token) -> Option { let mut stmts = vec![]; let mut ctoken = parser.lexer.next(); @@ -533,7 +519,7 @@ impl BlockStatement { ctoken = parser.lexer.next(); } - Some(BlockStatement::new(ogtoken, stmts)) + Some(BlockStatement::new(stmts)) } } @@ -585,7 +571,7 @@ impl FunctionLiteral { })) } - fn parse_function_parameters(parser: &mut Parser, ctoken: Token) -> Option> { + fn parse_function_parameters(parser: &mut Parser, _ctoken: Token) -> Option> { let mut out = vec![]; if parser.peek_token_is(TokenType::RParen) { @@ -617,12 +603,77 @@ impl Display for FunctionLiteral { "{} {}({}) {}", self.token.name.to_string(), self.token.literal.as_ref().unwrap(), - self.parameters.iter().map(|x| x.to_string()).join(","), + self.parameters.iter().join(","), "" )) } } +#[derive(Debug, PartialEq)] +pub struct CallExpression { + function: Box, + arguments: Vec, +} + +impl CallExpression { + pub fn new(f: Expression, arguments: Vec) -> Self { + Self { + function: Box::new(f), + arguments, + } + } + + pub fn parse(parser: &mut Parser, ctoken: Token, expr: Expression) -> Option { + let args = Self::parse_call_arguments(parser, ctoken); + + Some(Expression::CallExpression(Self { + function: Box::new(expr), + arguments: args?, + })) + } + + fn parse_call_arguments(parser: &mut Parser, _ctoken: Token) -> Option> { + let mut expressions = vec![]; + if let Some(token) = parser.lexer.peek() { + if token.name == TokenType::RParen { + parser.lexer.next(); + return Some(expressions); + } + } + let ntoken = match parser.lexer.next() { + Some(token) => token, + None => return Some(expressions), + }; + + Expression::parse(parser, ntoken, ExpressionPriority::Lowest).map(|e| expressions.push(e)); + + 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 parser.expect_peek(TokenType::RParen).is_none() { + return None; + } + Some(expressions) + } +} + +impl Display for CallExpression { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + f.write_fmt(format_args!( + "{}({})", + self.function, + self.arguments.iter().join(", ") + )) + } +} + #[cfg(test)] mod tests { use crate::{ diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 6ca8f12..5494f34 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -27,6 +27,7 @@ lazy_static! { m.insert(TokenType::Minus, ExpressionPriority::Sum); m.insert(TokenType::Slash, ExpressionPriority::Product); m.insert(TokenType::Asterisk, ExpressionPriority::Product); + m.insert(TokenType::LParen, ExpressionPriority::Call); m }; } @@ -51,12 +52,16 @@ impl<'a> Parser<'a> { parser.register_prefix(TokenType::Int, IntegerLiteral::parse); parser.register_prefix(TokenType::Bang, PrefixExpression::parse); parser.register_prefix(TokenType::Minus, PrefixExpression::parse); - parser.register_prefix(TokenType::True, Expression::parse_boolean); - parser.register_prefix(TokenType::False, Expression::parse_boolean); + parser.register_prefix(TokenType::True, BooleanExpression::parse); + parser.register_prefix(TokenType::False, BooleanExpression::parse); parser.register_prefix(TokenType::LParen, Expression::parse_grouped_expression); - parser.register_prefix(TokenType::If, Expression::parse_if_expression); + parser.register_prefix(TokenType::If, IfExpression::parse); parser.register_prefix(TokenType::Function, FunctionLiteral::parse); + // Neat trick! + // Call expressions looks like (). + // We can easily parse those by registering a infix on '('/LParen + parser.register_infix(TokenType::LParen, CallExpression::parse); parser.register_infix(TokenType::Plus, InfixExpression::parse); parser.register_infix(TokenType::Minus, InfixExpression::parse); parser.register_infix(TokenType::Slash, InfixExpression::parse); @@ -254,7 +259,7 @@ mod tests { program.unwrap().statements, vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::with_value(TokenType::Int, "5"), - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 5)) + Expression::IntegerLiteral(IntegerLiteral::new(5)) ))] ); } @@ -267,9 +272,9 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::new(TokenType::Bang), Expression::PrefixExpression(PrefixExpression::new( - Token::new(TokenType::Bang), + TokenType::Bang, "!", - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 5)), + Expression::IntegerLiteral(IntegerLiteral::new(5)), )), ))], ), @@ -278,9 +283,9 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::new(TokenType::Minus), Expression::PrefixExpression(PrefixExpression::new( - Token::new(TokenType::Minus), + TokenType::Minus, "-", - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 15)), + Expression::IntegerLiteral(IntegerLiteral::new(15)), )), ))], ), @@ -289,7 +294,7 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::new(TokenType::Bang), Expression::PrefixExpression(PrefixExpression::new( - Token::new(TokenType::Bang), + TokenType::Bang, "!", Expression::Identifier(Identifier::new(TokenType::Ident, "foobar")), )), @@ -300,7 +305,7 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::new(TokenType::Bang), Expression::PrefixExpression(PrefixExpression::new( - Token::new(TokenType::Bang), + TokenType::Bang, "!", Expression::BooleanExpression(BooleanExpression::new(TokenType::True)), )), @@ -311,7 +316,7 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::new(TokenType::Bang), Expression::PrefixExpression(PrefixExpression::new( - Token::new(TokenType::Bang), + TokenType::Bang, "!", Expression::BooleanExpression(BooleanExpression::new(TokenType::False)), )), @@ -352,10 +357,10 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::with_value(TokenType::Int, "5"), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Plus), - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 5)), + TokenType::Plus, + Expression::IntegerLiteral(IntegerLiteral::new(5)), "+", - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 10)), + Expression::IntegerLiteral(IntegerLiteral::new(10)), )), ))], ), @@ -364,10 +369,10 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::with_value(TokenType::Int, "5"), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Minus), - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 5)), + TokenType::Minus, + Expression::IntegerLiteral(IntegerLiteral::new(5)), "-", - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 10)), + Expression::IntegerLiteral(IntegerLiteral::new(10)), )), ))], ), @@ -376,10 +381,10 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::with_value(TokenType::Int, "5"), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Asterisk), - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 5)), + TokenType::Asterisk, + Expression::IntegerLiteral(IntegerLiteral::new(5)), "*", - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 15)), + Expression::IntegerLiteral(IntegerLiteral::new(15)), )), ))], ), @@ -388,10 +393,10 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::with_value(TokenType::Int, "15"), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Slash), - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 15)), + TokenType::Slash, + Expression::IntegerLiteral(IntegerLiteral::new(15)), "/", - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 3)), + Expression::IntegerLiteral(IntegerLiteral::new(3)), )), ))], ), @@ -400,10 +405,10 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::with_value(TokenType::Int, "5"), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::GreaterThan), - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 5)), + TokenType::GreaterThan, + Expression::IntegerLiteral(IntegerLiteral::new(5)), ">", - Expression::IntegerLiteral(IntegerLiteral::new(TokenType::Int, 15)), + Expression::IntegerLiteral(IntegerLiteral::new(15)), )), ))], ), @@ -412,9 +417,9 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::with_value(TokenType::Ident, "a"), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Plus), + TokenType::Plus, Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Plus), + TokenType::Plus, Expression::Identifier(Identifier::new(TokenType::Ident, "a")), "+", Expression::Identifier(Identifier::new(TokenType::Ident, "b")), @@ -429,7 +434,7 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::new(TokenType::True), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Equals), + TokenType::Equals, Expression::BooleanExpression(BooleanExpression::new(TokenType::True)), "==", Expression::BooleanExpression(BooleanExpression::new(TokenType::True)), @@ -441,7 +446,7 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::new(TokenType::True), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::NotEquals), + TokenType::NotEquals, Expression::BooleanExpression(BooleanExpression::new(TokenType::True)), "!=", Expression::BooleanExpression(BooleanExpression::new(TokenType::False)), @@ -453,7 +458,7 @@ mod tests { vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::new(TokenType::False), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Equals), + TokenType::Equals, Expression::BooleanExpression(BooleanExpression::new(TokenType::False)), "==", Expression::BooleanExpression(BooleanExpression::new(TokenType::False)), @@ -566,20 +571,18 @@ mod tests { statements: vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::new(TokenType::If), Expression::IfExpression(IfExpression::new( - TokenType::If, Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::GreaterThan), + TokenType::GreaterThan, Expression::Identifier(Identifier::new(TokenType::Ident, "x")), ">", Expression::Identifier(Identifier::new(TokenType::Ident, "y")), )), - BlockStatement::new( - Token::with_value(TokenType::Ident, "x"), - vec![Statement::ExpressionStatement(ExpressionStatement::new( + BlockStatement::new(vec![Statement::ExpressionStatement( + ExpressionStatement::new( Token::with_value(TokenType::Ident, "x"), Expression::Identifier(Identifier::new(TokenType::Ident, "x")), - ))], - ), + ), + )]), None, )), ))], @@ -604,30 +607,24 @@ mod tests { statements: vec![Statement::ExpressionStatement(ExpressionStatement::new( Token::new(TokenType::If), Expression::IfExpression(IfExpression::new( - TokenType::If, Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::GreaterThan), + TokenType::GreaterThan, Expression::Identifier(Identifier::new(TokenType::Ident, "x")), ">", Expression::Identifier(Identifier::new(TokenType::Ident, "y")), )), - BlockStatement::new( - Token::with_value(TokenType::Ident, "x"), - vec![Statement::ExpressionStatement(ExpressionStatement::new( + BlockStatement::new(vec![Statement::ExpressionStatement( + ExpressionStatement::new( Token::with_value(TokenType::Ident, "x"), Expression::Identifier(Identifier::new(TokenType::Ident, "x")), - ))], - ), - Some(BlockStatement::new( - // TODO: Not sure if this is the right token to have here. - // Since, It's a block statement parser, I believe it *should* have the first token it encounters in the block - // Else is dealt with before the block starts so, maybe this is not the right token to have here. Will revisit later - Token::new(TokenType::Else), - vec![Statement::ExpressionStatement(ExpressionStatement::new( + ), + )]), + Some(BlockStatement::new(vec![Statement::ExpressionStatement( + ExpressionStatement::new( Token::with_value(TokenType::Ident, "y"), Expression::Identifier(Identifier::new(TokenType::Ident, "y")), - ))], - )), + ), + )])), )), ))], }, @@ -645,7 +642,8 @@ mod tests { } #[test] - fn function_literal_expression() { + fn function_literal_parsing() { + // TODO: Figure out why are there inconsistencies in BlockStatements Token let test_cases = [ ( "fn(a,b) {x + y;}", @@ -657,18 +655,17 @@ mod tests { Identifier::new(TokenType::Ident, "a"), Identifier::new(TokenType::Ident, "b"), ], - BlockStatement::new( - Token::with_value(TokenType::Ident, "x"), - vec![Statement::ExpressionStatement(ExpressionStatement::new( + BlockStatement::new(vec![Statement::ExpressionStatement( + ExpressionStatement::new( Token::with_value(TokenType::Ident, "x"), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Plus), + TokenType::Plus, Expression::Identifier(Identifier::new(TokenType::Ident, "x")), "+", Expression::Identifier(Identifier::new(TokenType::Ident, "y")), )), - ))], - ), + ), + )]), )), ))], ), @@ -679,7 +676,7 @@ mod tests { Expression::FunctionExpression(FunctionLiteral::new( Token::new(TokenType::Function), vec![], - BlockStatement::new(Token::new(TokenType::RBrace), vec![]), + BlockStatement::new(vec![]), )), ))], ), @@ -694,7 +691,7 @@ mod tests { Identifier::new(TokenType::Ident, "ya"), Identifier::new(TokenType::Ident, "z"), ], - BlockStatement::new(Token::new(TokenType::RBrace), vec![]), + BlockStatement::new(vec![]), )), ))], ), @@ -705,7 +702,7 @@ mod tests { Expression::FunctionExpression(FunctionLiteral::new( Token::new(TokenType::Function), vec![Identifier::new(TokenType::Ident, "a")], - BlockStatement::new(Token::new(TokenType::RBrace), vec![]), + BlockStatement::new(vec![]), )), ))], ), @@ -720,14 +717,13 @@ mod tests { Identifier::new(TokenType::Ident, "b"), Identifier::new(TokenType::Ident, "abc"), ], - BlockStatement::new( - Token::new(TokenType::LParen), - vec![Statement::ExpressionStatement(ExpressionStatement::new( + BlockStatement::new(vec![Statement::ExpressionStatement( + ExpressionStatement::new( Token::new(TokenType::LParen), Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Asterisk), + TokenType::Asterisk, Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Plus), + TokenType::Plus, Expression::Identifier(Identifier::new( TokenType::Ident, "x", @@ -740,7 +736,7 @@ mod tests { )), "*", Expression::InfixExpression(InfixExpression::new( - Token::new(TokenType::Minus), + TokenType::Minus, Expression::Identifier(Identifier::new( TokenType::Ident, "a", @@ -752,8 +748,58 @@ mod tests { )), )), )), - ))], - ), + ), + )]), + )), + ))], + ), + ]; + + 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().statements, test.1); + } + } + #[test] + fn call_expression_parsing() { + // TODO: Figure out why are there inconsistencies in BlockStatements Token + let test_cases = [ + ( + "add(1, 2 * 3, 4 + 5);", + vec![Statement::ExpressionStatement(ExpressionStatement::new( + Token::with_value(TokenType::Ident, "add"), + 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)), + )), + ], + )), + ))], + ), + ( + "add();", + vec![Statement::ExpressionStatement(ExpressionStatement::new( + Token::with_value(TokenType::Ident, "add"), + Expression::CallExpression(CallExpression::new( + Expression::Identifier(Identifier::new(TokenType::Ident, "add")), + vec![], )), ))], ),