parse grouped expressions
This commit is contained in:
parent
4b32a4fd27
commit
ec989535aa
202
src/parser.rs
202
src/parser.rs
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue