1
0
Fork 0

Added Call Expressions

1. Added Call Expressions
2. Refactored Boolean/Prefix/Infix parse functions
3. Added tests to support Call Expressions parser
This commit is contained in:
Ishan Jain 2020-01-20 16:14:26 +05:30
parent 8536d0defa
commit 8ec7ec1ba1
2 changed files with 244 additions and 147 deletions

View File

@ -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<Self> {
Some(Self::BooleanExpression(BooleanExpression::new(token.name)))
}
pub fn parse_grouped_expression(parser: &mut Parser, _token: Token) -> Option<Self> {
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<Self> {
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<Expression> {
let n = match token.literal?.parse::<i64>() {
@ -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<Expression>,
}
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<Expression>,
operator: String,
right: Box<Expression>,
}
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<Expression> {
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<Expression>,
consequence: BlockStatement,
alternative: Option<BlockStatement>,
@ -474,18 +428,54 @@ pub struct IfExpression {
impl IfExpression {
pub fn new(
token: TokenType,
condition: Expression,
consequence: BlockStatement,
alternative: Option<BlockStatement>,
) -> Self {
Self {
token,
condition: Box::new(condition),
consequence,
alternative,
}
}
pub fn parse(parser: &mut Parser, _ctoken: Token) -> Option<Expression> {
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<Statement>,
}
impl BlockStatement {
pub fn new(token: Token, stmt: Vec<Statement>) -> Self {
Self {
token,
statements: stmt,
}
pub fn new(stmt: Vec<Statement>) -> Self {
Self { statements: stmt }
}
pub fn parse(parser: &mut Parser, ogtoken: Token) -> Option<Self> {
pub fn parse(parser: &mut Parser, _ogtoken: Token) -> Option<Self> {
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<Vec<Identifier>> {
fn parse_function_parameters(parser: &mut Parser, _ctoken: Token) -> Option<Vec<Identifier>> {
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<Expression>,
arguments: Vec<Expression>,
}
impl CallExpression {
pub fn new(f: Expression, arguments: Vec<Expression>) -> Self {
Self {
function: Box::new(f),
arguments,
}
}
pub fn parse(parser: &mut Parser, ctoken: Token, expr: Expression) -> Option<Expression> {
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<Vec<Expression>> {
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::{

View File

@ -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 <ident>(<args>).
// 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![],
)),
))],
),