parse grouped expressions

This commit is contained in:
Victor Timofei 2023-09-11 01:49:20 +03:00
parent 4b32a4fd27
commit ec989535aa
Signed by: vtimofei
GPG Key ID: B790DCEBE281403A
1 changed files with 112 additions and 90 deletions

View File

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