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>> {
|
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 {
|
||||||
|
|
Loading…
Reference in New Issue