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>> {
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<dyn Expression> {
Rc::new(Identifier {
value,
})
Rc::new(Identifier { value })
}
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 {
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 {