Parser refactoring for Option<Expression>.

This commit is contained in:
Jesse Brault 2026-08-20 20:01:47 -05:00
parent a4b9b958e9
commit 05a1f5d091

View File

@ -62,7 +62,7 @@ pub fn parse_statement(input: &str) -> ParseResult<Option<Statement>> {
(statement, diagnostics) (statement, diagnostics)
} }
pub fn parse_expression(input: &str) -> ParseResult<Expression> { pub fn parse_expression(input: &str) -> ParseResult<Option<Expression>> {
let mut parser = Parser::new(input); let mut parser = Parser::new(input);
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
diagnostics.append(&mut parser.advance()); diagnostics.append(&mut parser.advance());
@ -918,9 +918,9 @@ impl<'a> Parser<'a> {
let initializer = if self.current.is_some() && self.peek_current(TokenKind::Equals) { let initializer = if self.current.is_some() && self.peek_current(TokenKind::Equals) {
diagnostics.append(&mut self.advance()); // equals diagnostics.append(&mut self.advance()); // equals
let (expression, mut ds) = self.expression(); let (maybe_expression, mut ds) = self.expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
Some(expression) maybe_expression
} else { } else {
None None
}; };
@ -961,10 +961,7 @@ impl<'a> Parser<'a> {
Some(let_statement) => (Some(Statement::Let(let_statement)), diagnostics), Some(let_statement) => (Some(Statement::Let(let_statement)), diagnostics),
} }
} }
_ => { _ => self.expression_statement_or_assign_statement(),
let (statement, diagnostics) = self.expression_statement_or_assign_statement();
(Some(statement), diagnostics)
}
} }
} }
@ -987,10 +984,22 @@ impl<'a> Parser<'a> {
let (_, mut ds) = self.expect_advance(TokenKind::Equals); let (_, mut ds) = self.expect_advance(TokenKind::Equals);
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let (expression, mut ds) = self.expression(); let (maybe_expression, mut ds) = self.expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
if let Some(identifier) = maybe_identifier { let identifier = match maybe_identifier {
Some(identifier) => identifier,
None => {
return (None, diagnostics);
}
};
let expression = match maybe_expression {
Some(expression) => expression,
None => {
return (None, diagnostics);
}
};
let let_statement = LetStatement::new( let let_statement = LetStatement::new(
self.next_node_id(), self.next_node_id(),
self.token_text(&identifier), self.token_text(&identifier),
@ -999,53 +1008,76 @@ impl<'a> Parser<'a> {
expression, expression,
); );
(Some(let_statement), diagnostics) (Some(let_statement), diagnostics)
}
fn expression_statement_or_assign_statement(&mut self) -> ParseResult<Option<Statement>> {
let mut diagnostics = Vec::new();
let (maybe_base, mut ds) = self.expression();
diagnostics.append(&mut ds);
let base = match maybe_base {
Some(base) => base,
None => {
return (None, diagnostics);
}
};
if self.current.is_some() && self.peek_current(TokenKind::Equals) {
let (maybe_assign_statement, mut ds) = self.assign_rhs(base);
diagnostics.append(&mut ds);
if let Some(assign_statement) = maybe_assign_statement {
(Some(Statement::Assign(assign_statement)), diagnostics)
} else { } else {
(None, diagnostics) (None, diagnostics)
} }
}
fn expression_statement_or_assign_statement(&mut self) -> ParseResult<Statement> {
let mut diagnostics = Vec::new();
let (base, mut ds) = self.expression();
diagnostics.append(&mut ds);
if self.current.is_some() && self.peek_current(TokenKind::Equals) {
let (assign_statement, mut ds) = self.assign_rhs(base);
diagnostics.append(&mut ds);
(Statement::Assign(assign_statement), diagnostics)
} else { } else {
( (
Statement::Expression(ExpressionStatement::new(base)), Some(Statement::Expression(ExpressionStatement::new(base))),
diagnostics, diagnostics,
) )
} }
} }
fn assign_rhs(&mut self, destination: Expression) -> ParseResult<AssignStatement> { fn assign_rhs(&mut self, destination: Expression) -> ParseResult<Option<AssignStatement>> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let (_, mut ds) = self.expect_advance(TokenKind::Equals); let (_, mut ds) = self.expect_advance(TokenKind::Equals);
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let (value, mut ds) = self.expression(); let (maybe_value, mut ds) = self.expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
if let Some(value) = maybe_value {
(AssignStatement::new(destination, value), diagnostics) (Some(AssignStatement::new(destination, value)), diagnostics)
} else {
(None, diagnostics)
}
} }
fn expression(&mut self) -> ParseResult<Expression> { fn expression(&mut self) -> ParseResult<Option<Expression>> {
self.bitwise_or_expression() self.bitwise_or_expression()
} }
fn bitwise_or_expression(&mut self) -> ParseResult<Expression> { fn bitwise_or_expression(&mut self) -> ParseResult<Option<Expression>> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let (mut base, mut ds) = self.bitwise_xor_expression(); let (maybe_base, mut ds) = self.bitwise_xor_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let mut base = match maybe_base {
Some(base) => base,
None => {
return (None, diagnostics);
}
};
while self.current.is_some() && self.peek_current(TokenKind::Bar) { while self.current.is_some() && self.peek_current(TokenKind::Bar) {
diagnostics.append(&mut self.advance()); // | diagnostics.append(&mut self.advance()); // |
let (rhs, mut ds) = self.bitwise_xor_expression(); let (maybe_rhs, mut ds) = self.bitwise_xor_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let rhs = match maybe_rhs {
Some(rhs) => rhs,
None => {
return (None, diagnostics);
}
};
let source_range = let source_range =
SourceRange::new(base.source_range().start(), rhs.source_range().end()); SourceRange::new(base.source_range().start(), rhs.source_range().end());
base = Expression::Binary(BinaryExpression::new( base = Expression::Binary(BinaryExpression::new(
@ -1056,19 +1088,32 @@ impl<'a> Parser<'a> {
source_range, source_range,
)); ));
} }
(base, diagnostics) (Some(base), diagnostics)
} }
fn bitwise_xor_expression(&mut self) -> ParseResult<Expression> { fn bitwise_xor_expression(&mut self) -> ParseResult<Option<Expression>> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let (mut base, mut ds) = self.bitwise_and_expression(); let (maybe_base, mut ds) = self.bitwise_and_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let mut base = match maybe_base {
Some(base) => base,
None => {
return (None, diagnostics);
}
};
while self.current.is_some() && self.peek_current(TokenKind::Caret) { while self.current.is_some() && self.peek_current(TokenKind::Caret) {
diagnostics.append(&mut self.advance()); // ^ diagnostics.append(&mut self.advance()); // ^
let (rhs, mut ds) = self.bitwise_and_expression(); let (maybe_rhs, mut ds) = self.bitwise_and_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let rhs = match maybe_rhs {
Some(rhs) => rhs,
None => {
return (None, diagnostics);
}
};
let source_range = let source_range =
SourceRange::new(base.source_range().start(), rhs.source_range().end()); SourceRange::new(base.source_range().start(), rhs.source_range().end());
base = Expression::Binary(BinaryExpression::new( base = Expression::Binary(BinaryExpression::new(
@ -1079,19 +1124,31 @@ impl<'a> Parser<'a> {
source_range, source_range,
)); ));
} }
(base, diagnostics) (Some(base), diagnostics)
} }
fn bitwise_and_expression(&mut self) -> ParseResult<Expression> { fn bitwise_and_expression(&mut self) -> ParseResult<Option<Expression>> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let (mut base, mut ds) = self.shift_expression(); let (maybe_base, mut ds) = self.shift_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let mut base = match maybe_base {
Some(base) => base,
None => {
return (None, diagnostics);
}
};
while self.current.is_some() && self.peek_current(TokenKind::Ampersand) { while self.current.is_some() && self.peek_current(TokenKind::Ampersand) {
diagnostics.append(&mut self.advance()); // & diagnostics.append(&mut self.advance()); // &
let (rhs, mut ds) = self.shift_expression(); let (maybe_rhs, mut ds) = self.shift_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let rhs = match maybe_rhs {
Some(rhs) => rhs,
None => {
return (None, diagnostics);
}
};
let source_range = let source_range =
SourceRange::new(base.source_range().start(), rhs.source_range().end()); SourceRange::new(base.source_range().start(), rhs.source_range().end());
@ -1103,14 +1160,20 @@ impl<'a> Parser<'a> {
source_range, source_range,
)); ));
} }
(base, diagnostics) (Some(base), diagnostics)
} }
fn shift_expression(&mut self) -> ParseResult<Expression> { fn shift_expression(&mut self) -> ParseResult<Option<Expression>> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let (mut base, mut ds) = self.additive_expression(); let (maybe_base, mut ds) = self.additive_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let mut base = match maybe_base {
Some(base) => base,
None => {
return (None, diagnostics);
}
};
while self.current.is_some() { while self.current.is_some() {
let current = self.current.as_ref().unwrap(); let current = self.current.as_ref().unwrap();
@ -1122,8 +1185,14 @@ impl<'a> Parser<'a> {
self.expect_immediately_after_advance(TokenKind::Lt, &previous_cloned); // second < self.expect_immediately_after_advance(TokenKind::Lt, &previous_cloned); // second <
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let (rhs, mut ds) = self.additive_expression(); let (maybe_rhs, mut ds) = self.additive_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let rhs = match maybe_rhs {
Some(rhs) => rhs,
None => {
return (None, diagnostics);
}
};
let source_range = let source_range =
SourceRange::new(base.source_range().start(), rhs.source_range().end()); SourceRange::new(base.source_range().start(), rhs.source_range().end());
@ -1142,8 +1211,14 @@ impl<'a> Parser<'a> {
self.expect_immediately_after_advance(TokenKind::Gt, &previous_cloned); // second > self.expect_immediately_after_advance(TokenKind::Gt, &previous_cloned); // second >
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let (rhs, mut ds) = self.additive_expression(); let (maybe_rhs, mut ds) = self.additive_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let rhs = match maybe_rhs {
Some(rhs) => rhs,
None => {
return (None, diagnostics);
}
};
let source_range = let source_range =
SourceRange::new(base.source_range().start(), rhs.source_range().end()); SourceRange::new(base.source_range().start(), rhs.source_range().end());
@ -1159,22 +1234,34 @@ impl<'a> Parser<'a> {
} }
} }
(base, diagnostics) (Some(base), diagnostics)
} }
fn additive_expression(&mut self) -> ParseResult<Expression> { fn additive_expression(&mut self) -> ParseResult<Option<Expression>> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let (mut base, mut ds) = self.multiplicative_expression(); let (maybe_base, mut ds) = self.multiplicative_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let mut base = match maybe_base {
Some(base) => base,
None => {
return (None, diagnostics);
}
};
while self.current.is_some() { while self.current.is_some() {
let current = self.current.as_ref().unwrap(); let current = self.current.as_ref().unwrap();
match current.kind() { match current.kind() {
TokenKind::Plus => { TokenKind::Plus => {
diagnostics.append(&mut self.advance()); // plus diagnostics.append(&mut self.advance()); // plus
let (rhs, mut ds) = self.multiplicative_expression(); let (maybe_rhs, mut ds) = self.multiplicative_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let rhs = match maybe_rhs {
Some(rhs) => rhs,
None => {
return (None, diagnostics);
}
};
let source_range = let source_range =
SourceRange::new(base.source_range().start(), rhs.source_range().end()); SourceRange::new(base.source_range().start(), rhs.source_range().end());
@ -1188,8 +1275,14 @@ impl<'a> Parser<'a> {
} }
TokenKind::Minus => { TokenKind::Minus => {
diagnostics.append(&mut self.advance()); // minus diagnostics.append(&mut self.advance()); // minus
let (rhs, mut ds) = self.multiplicative_expression(); let (maybe_rhs, mut ds) = self.multiplicative_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let rhs = match maybe_rhs {
Some(rhs) => rhs,
None => {
return (None, diagnostics);
}
};
let source_range = let source_range =
SourceRange::new(base.source_range().start(), rhs.source_range().end()); SourceRange::new(base.source_range().start(), rhs.source_range().end());
@ -1204,22 +1297,34 @@ impl<'a> Parser<'a> {
_ => break, _ => break,
} }
} }
(base, diagnostics) (Some(base), diagnostics)
} }
fn multiplicative_expression(&mut self) -> ParseResult<Expression> { fn multiplicative_expression(&mut self) -> ParseResult<Option<Expression>> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let (mut base, mut ds) = self.prefix_expression(); let (maybe_base, mut ds) = self.prefix_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let mut base = match maybe_base {
Some(base) => base,
None => {
return (None, diagnostics);
}
};
while self.current.is_some() { while self.current.is_some() {
let current = self.current.as_ref().unwrap(); let current = self.current.as_ref().unwrap();
match current.kind() { match current.kind() {
TokenKind::Star => { TokenKind::Star => {
diagnostics.append(&mut self.advance()); // multiply diagnostics.append(&mut self.advance()); // multiply
let (rhs, mut ds) = self.prefix_expression(); let (maybe_rhs, mut ds) = self.prefix_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let rhs = match maybe_rhs {
Some(rhs) => rhs,
None => {
return (None, diagnostics);
}
};
let source_range = let source_range =
SourceRange::new(base.source_range().start(), rhs.source_range().end()); SourceRange::new(base.source_range().start(), rhs.source_range().end());
@ -1233,8 +1338,14 @@ impl<'a> Parser<'a> {
} }
TokenKind::Slash => { TokenKind::Slash => {
diagnostics.append(&mut self.advance()); // slash diagnostics.append(&mut self.advance()); // slash
let (rhs, mut ds) = self.prefix_expression(); let (maybe_rhs, mut ds) = self.prefix_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let rhs = match maybe_rhs {
Some(rhs) => rhs,
None => {
return (None, diagnostics);
}
};
let source_range = let source_range =
SourceRange::new(base.source_range().start(), rhs.source_range().end()); SourceRange::new(base.source_range().start(), rhs.source_range().end());
@ -1248,8 +1359,14 @@ impl<'a> Parser<'a> {
} }
TokenKind::Modulo => { TokenKind::Modulo => {
diagnostics.append(&mut self.advance()); // modulo diagnostics.append(&mut self.advance()); // modulo
let (rhs, mut ds) = self.prefix_expression(); let (maybe_rhs, mut ds) = self.prefix_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let rhs = match maybe_rhs {
Some(rhs) => rhs,
None => {
return (None, diagnostics);
}
};
let source_range = let source_range =
SourceRange::new(base.source_range().start(), rhs.source_range().end()); SourceRange::new(base.source_range().start(), rhs.source_range().end());
@ -1264,10 +1381,10 @@ impl<'a> Parser<'a> {
_ => break, _ => break,
} }
} }
(base, diagnostics) (Some(base), diagnostics)
} }
fn prefix_expression(&mut self) -> ParseResult<Expression> { fn prefix_expression(&mut self) -> ParseResult<Option<Expression>> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
// first, collect all consecutive operators // first, collect all consecutive operators
@ -1286,8 +1403,14 @@ impl<'a> Parser<'a> {
// now go in reverse and build up expressions // now go in reverse and build up expressions
// the parser is currently just after the prefix operators, so we need a suffix expression // the parser is currently just after the prefix operators, so we need a suffix expression
// as a base // as a base
let (mut base, mut ds) = self.suffix_expression(); let (maybe_base, mut ds) = self.suffix_expression();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let mut base = match maybe_base {
Some(base) => base,
None => {
return (None, diagnostics);
}
};
while let Some(operator_token) = operator_tokens.pop() { while let Some(operator_token) = operator_tokens.pop() {
let source_range = SourceRange::new(operator_token.start(), base.source_range().end()); let source_range = SourceRange::new(operator_token.start(), base.source_range().end());
@ -1302,14 +1425,20 @@ impl<'a> Parser<'a> {
_ => unreachable!(), _ => unreachable!(),
} }
} }
(base, diagnostics) (Some(base), diagnostics)
} }
fn suffix_expression(&mut self) -> ParseResult<Expression> { fn suffix_expression(&mut self) -> ParseResult<Option<Expression>> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let (mut base, mut ds) = self.expression_base(); let (maybe_base, mut ds) = self.expression_base();
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
let mut base = match maybe_base {
Some(base) => base,
None => {
return (None, diagnostics);
}
};
while self.current.is_some() { while self.current.is_some() {
let current = self.current.as_ref().unwrap(); let current = self.current.as_ref().unwrap();
@ -1323,10 +1452,10 @@ impl<'a> Parser<'a> {
} }
} }
(base, diagnostics) (Some(base), diagnostics)
} }
fn expression_base(&mut self) -> ParseResult<Expression> { fn expression_base(&mut self) -> ParseResult<Option<Expression>> {
let current = match self.current.as_ref() { let current = match self.current.as_ref() {
None => { None => {
let mut ds = Diagnostics::new(); let mut ds = Diagnostics::new();
@ -1334,7 +1463,7 @@ impl<'a> Parser<'a> {
&EXPRESSION_FIRSTS, &EXPRESSION_FIRSTS,
self.input.len(), self.input.len(),
)); ));
return (todo!(), ds); return (None, ds);
} }
Some(current) => current, Some(current) => current,
}; };
@ -1345,11 +1474,11 @@ impl<'a> Parser<'a> {
let source_range = SourceRange::new(current.start(), current.end()); let source_range = SourceRange::new(current.start(), current.end());
diagnostics.append(&mut self.advance()); diagnostics.append(&mut self.advance());
( (
Expression::Integer(IntegerLiteral::new( Some(Expression::Integer(IntegerLiteral::new(
self.next_node_id(), self.next_node_id(),
i32::from_str(raw).unwrap(), i32::from_str(raw).unwrap(),
source_range, source_range,
)), ))),
diagnostics, diagnostics,
) )
} }
@ -1358,11 +1487,11 @@ impl<'a> Parser<'a> {
let source_range = SourceRange::new(current.start(), current.end()); let source_range = SourceRange::new(current.start(), current.end());
diagnostics.append(&mut self.advance()); diagnostics.append(&mut self.advance());
( (
Expression::Double(DoubleLiteral::new( Some(Expression::Double(DoubleLiteral::new(
self.next_node_id(), self.next_node_id(),
f64::from_str(raw).unwrap(), f64::from_str(raw).unwrap(),
source_range, source_range,
)), ))),
diagnostics, diagnostics,
) )
} }
@ -1371,11 +1500,11 @@ impl<'a> Parser<'a> {
let source_range = SourceRange::new(current.start(), current.end()); let source_range = SourceRange::new(current.start(), current.end());
diagnostics.append(&mut self.advance()); diagnostics.append(&mut self.advance());
( (
Expression::String(StringLiteral::new( Some(Expression::String(StringLiteral::new(
self.next_node_id(), self.next_node_id(),
&with_quotes[1..with_quotes.len() - 1], &with_quotes[1..with_quotes.len() - 1],
source_range, source_range,
)), ))),
diagnostics, diagnostics,
) )
} }
@ -1384,11 +1513,11 @@ impl<'a> Parser<'a> {
let source_range = SourceRange::new(current.start(), current.end()); let source_range = SourceRange::new(current.start(), current.end());
diagnostics.append(&mut self.advance()); diagnostics.append(&mut self.advance());
( (
Expression::Identifier(Identifier::new( Some(Expression::Identifier(Identifier::new(
self.next_node_id(), self.next_node_id(),
declared_name, declared_name,
source_range, source_range,
)), ))),
diagnostics, diagnostics,
) )
} }
@ -1430,14 +1559,18 @@ impl<'a> Parser<'a> {
let mut expressions = vec![]; let mut expressions = vec![];
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let (expression, mut ds) = self.expression(); let (maybe_expression, mut ds) = self.expression();
if let Some(expression) = maybe_expression {
expressions.push(expression); expressions.push(expression);
}
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
while self.current.is_some() && self.peek_current(TokenKind::Comma) { while self.current.is_some() && self.peek_current(TokenKind::Comma) {
diagnostics.append(&mut self.advance()); // comma diagnostics.append(&mut self.advance()); // comma
let (expression, mut ds) = self.expression(); let (maybe_expression, mut ds) = self.expression();
if let Some(expression) = maybe_expression {
expressions.push(expression); expressions.push(expression);
}
diagnostics.append(&mut ds); diagnostics.append(&mut ds);
} }
@ -1677,11 +1810,15 @@ mod concrete_tests {
} }
fn assert_expression(input: &str) -> Expression { fn assert_expression(input: &str) -> Expression {
let (expression, diagnostics) = parse_expression(input); let (maybe_expression, diagnostics) = parse_expression(input);
if !diagnostics.is_empty() { if !diagnostics.is_empty() {
report_diagnostics(&diagnostics); report_diagnostics(&diagnostics);
} }
if let Some(expression) = maybe_expression {
expression expression
} else {
panic!("parse_expression produced a None")
}
} }
fn assert_function_in<'a>( fn assert_function_in<'a>(