From 05a1f5d0915aa9c15d86505147c7ab4d9a34ad7e Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Thu, 20 Aug 2026 20:01:47 -0500 Subject: [PATCH] Parser refactoring for Option. --- dmc-lib/src/parser.rs | 297 ++++++++++++++++++++++++++++++------------ 1 file changed, 217 insertions(+), 80 deletions(-) diff --git a/dmc-lib/src/parser.rs b/dmc-lib/src/parser.rs index 189b96d..a44a417 100644 --- a/dmc-lib/src/parser.rs +++ b/dmc-lib/src/parser.rs @@ -62,7 +62,7 @@ pub fn parse_statement(input: &str) -> ParseResult> { (statement, diagnostics) } -pub fn parse_expression(input: &str) -> ParseResult { +pub fn parse_expression(input: &str) -> ParseResult> { let mut parser = Parser::new(input); let mut diagnostics = Vec::new(); 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) { diagnostics.append(&mut self.advance()); // equals - let (expression, mut ds) = self.expression(); + let (maybe_expression, mut ds) = self.expression(); diagnostics.append(&mut ds); - Some(expression) + maybe_expression } else { None }; @@ -961,10 +961,7 @@ impl<'a> Parser<'a> { Some(let_statement) => (Some(Statement::Let(let_statement)), diagnostics), } } - _ => { - let (statement, diagnostics) = self.expression_statement_or_assign_statement(); - (Some(statement), diagnostics) - } + _ => self.expression_statement_or_assign_statement(), } } @@ -987,65 +984,100 @@ impl<'a> Parser<'a> { let (_, mut ds) = self.expect_advance(TokenKind::Equals); diagnostics.append(&mut ds); - let (expression, mut ds) = self.expression(); + let (maybe_expression, mut ds) = self.expression(); diagnostics.append(&mut ds); - if let Some(identifier) = maybe_identifier { - let let_statement = LetStatement::new( - self.next_node_id(), - self.token_text(&identifier), - SourceRange::new(identifier.start(), identifier.end()), - is_mut, - expression, - ); - (Some(let_statement), diagnostics) - } else { - (None, diagnostics) - } + 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( + self.next_node_id(), + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), + is_mut, + expression, + ); + (Some(let_statement), diagnostics) } - fn expression_statement_or_assign_statement(&mut self) -> ParseResult { + fn expression_statement_or_assign_statement(&mut self) -> ParseResult> { let mut diagnostics = Vec::new(); - let (base, mut ds) = self.expression(); + 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 (assign_statement, mut ds) = self.assign_rhs(base); + let (maybe_assign_statement, mut ds) = self.assign_rhs(base); diagnostics.append(&mut ds); - (Statement::Assign(assign_statement), diagnostics) + if let Some(assign_statement) = maybe_assign_statement { + (Some(Statement::Assign(assign_statement)), diagnostics) + } else { + (None, diagnostics) + } } else { ( - Statement::Expression(ExpressionStatement::new(base)), + Some(Statement::Expression(ExpressionStatement::new(base))), diagnostics, ) } } - fn assign_rhs(&mut self, destination: Expression) -> ParseResult { + fn assign_rhs(&mut self, destination: Expression) -> ParseResult> { let mut diagnostics = Vec::new(); let (_, mut ds) = self.expect_advance(TokenKind::Equals); diagnostics.append(&mut ds); - let (value, mut ds) = self.expression(); + let (maybe_value, mut ds) = self.expression(); diagnostics.append(&mut ds); - - (AssignStatement::new(destination, value), diagnostics) + if let Some(value) = maybe_value { + (Some(AssignStatement::new(destination, value)), diagnostics) + } else { + (None, diagnostics) + } } - fn expression(&mut self) -> ParseResult { + fn expression(&mut self) -> ParseResult> { self.bitwise_or_expression() } - fn bitwise_or_expression(&mut self) -> ParseResult { + fn bitwise_or_expression(&mut self) -> ParseResult> { 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); + let mut base = match maybe_base { + Some(base) => base, + None => { + return (None, diagnostics); + } + }; while self.current.is_some() && self.peek_current(TokenKind::Bar) { 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); + let rhs = match maybe_rhs { + Some(rhs) => rhs, + None => { + return (None, diagnostics); + } + }; + let source_range = SourceRange::new(base.source_range().start(), rhs.source_range().end()); base = Expression::Binary(BinaryExpression::new( @@ -1056,19 +1088,32 @@ impl<'a> Parser<'a> { source_range, )); } - (base, diagnostics) + (Some(base), diagnostics) } - fn bitwise_xor_expression(&mut self) -> ParseResult { + fn bitwise_xor_expression(&mut self) -> ParseResult> { 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); + let mut base = match maybe_base { + Some(base) => base, + None => { + return (None, diagnostics); + } + }; while self.current.is_some() && self.peek_current(TokenKind::Caret) { 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); + let rhs = match maybe_rhs { + Some(rhs) => rhs, + None => { + return (None, diagnostics); + } + }; + let source_range = SourceRange::new(base.source_range().start(), rhs.source_range().end()); base = Expression::Binary(BinaryExpression::new( @@ -1079,19 +1124,31 @@ impl<'a> Parser<'a> { source_range, )); } - (base, diagnostics) + (Some(base), diagnostics) } - fn bitwise_and_expression(&mut self) -> ParseResult { + fn bitwise_and_expression(&mut self) -> ParseResult> { 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); + let mut base = match maybe_base { + Some(base) => base, + None => { + return (None, diagnostics); + } + }; while self.current.is_some() && self.peek_current(TokenKind::Ampersand) { diagnostics.append(&mut self.advance()); // & - let (rhs, mut ds) = self.shift_expression(); + let (maybe_rhs, mut ds) = self.shift_expression(); diagnostics.append(&mut ds); + let rhs = match maybe_rhs { + Some(rhs) => rhs, + None => { + return (None, diagnostics); + } + }; let source_range = SourceRange::new(base.source_range().start(), rhs.source_range().end()); @@ -1103,14 +1160,20 @@ impl<'a> Parser<'a> { source_range, )); } - (base, diagnostics) + (Some(base), diagnostics) } - fn shift_expression(&mut self) -> ParseResult { + fn shift_expression(&mut self) -> ParseResult> { 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); + let mut base = match maybe_base { + Some(base) => base, + None => { + return (None, diagnostics); + } + }; while self.current.is_some() { 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 < diagnostics.append(&mut ds); - let (rhs, mut ds) = self.additive_expression(); + let (maybe_rhs, mut ds) = self.additive_expression(); diagnostics.append(&mut ds); + let rhs = match maybe_rhs { + Some(rhs) => rhs, + None => { + return (None, diagnostics); + } + }; let source_range = 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 > diagnostics.append(&mut ds); - let (rhs, mut ds) = self.additive_expression(); + let (maybe_rhs, mut ds) = self.additive_expression(); diagnostics.append(&mut ds); + let rhs = match maybe_rhs { + Some(rhs) => rhs, + None => { + return (None, diagnostics); + } + }; let source_range = 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 { + fn additive_expression(&mut self) -> ParseResult> { 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); + let mut base = match maybe_base { + Some(base) => base, + None => { + return (None, diagnostics); + } + }; while self.current.is_some() { let current = self.current.as_ref().unwrap(); match current.kind() { TokenKind::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); + let rhs = match maybe_rhs { + Some(rhs) => rhs, + None => { + return (None, diagnostics); + } + }; let source_range = SourceRange::new(base.source_range().start(), rhs.source_range().end()); @@ -1188,8 +1275,14 @@ impl<'a> Parser<'a> { } TokenKind::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); + let rhs = match maybe_rhs { + Some(rhs) => rhs, + None => { + return (None, diagnostics); + } + }; let source_range = SourceRange::new(base.source_range().start(), rhs.source_range().end()); @@ -1204,22 +1297,34 @@ impl<'a> Parser<'a> { _ => break, } } - (base, diagnostics) + (Some(base), diagnostics) } - fn multiplicative_expression(&mut self) -> ParseResult { + fn multiplicative_expression(&mut self) -> ParseResult> { 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); + let mut base = match maybe_base { + Some(base) => base, + None => { + return (None, diagnostics); + } + }; while self.current.is_some() { let current = self.current.as_ref().unwrap(); match current.kind() { TokenKind::Star => { 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); + let rhs = match maybe_rhs { + Some(rhs) => rhs, + None => { + return (None, diagnostics); + } + }; let source_range = SourceRange::new(base.source_range().start(), rhs.source_range().end()); @@ -1233,8 +1338,14 @@ impl<'a> Parser<'a> { } TokenKind::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); + let rhs = match maybe_rhs { + Some(rhs) => rhs, + None => { + return (None, diagnostics); + } + }; let source_range = SourceRange::new(base.source_range().start(), rhs.source_range().end()); @@ -1248,8 +1359,14 @@ impl<'a> Parser<'a> { } TokenKind::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); + let rhs = match maybe_rhs { + Some(rhs) => rhs, + None => { + return (None, diagnostics); + } + }; let source_range = SourceRange::new(base.source_range().start(), rhs.source_range().end()); @@ -1264,10 +1381,10 @@ impl<'a> Parser<'a> { _ => break, } } - (base, diagnostics) + (Some(base), diagnostics) } - fn prefix_expression(&mut self) -> ParseResult { + fn prefix_expression(&mut self) -> ParseResult> { let mut diagnostics = Vec::new(); // first, collect all consecutive operators @@ -1286,8 +1403,14 @@ impl<'a> Parser<'a> { // now go in reverse and build up expressions // the parser is currently just after the prefix operators, so we need a suffix expression // as a base - let (mut base, mut ds) = self.suffix_expression(); + let (maybe_base, mut ds) = self.suffix_expression(); 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() { let source_range = SourceRange::new(operator_token.start(), base.source_range().end()); @@ -1302,14 +1425,20 @@ impl<'a> Parser<'a> { _ => unreachable!(), } } - (base, diagnostics) + (Some(base), diagnostics) } - fn suffix_expression(&mut self) -> ParseResult { + fn suffix_expression(&mut self) -> ParseResult> { 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); + let mut base = match maybe_base { + Some(base) => base, + None => { + return (None, diagnostics); + } + }; while self.current.is_some() { 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 { + fn expression_base(&mut self) -> ParseResult> { let current = match self.current.as_ref() { None => { let mut ds = Diagnostics::new(); @@ -1334,7 +1463,7 @@ impl<'a> Parser<'a> { &EXPRESSION_FIRSTS, self.input.len(), )); - return (todo!(), ds); + return (None, ds); } Some(current) => current, }; @@ -1345,11 +1474,11 @@ impl<'a> Parser<'a> { let source_range = SourceRange::new(current.start(), current.end()); diagnostics.append(&mut self.advance()); ( - Expression::Integer(IntegerLiteral::new( + Some(Expression::Integer(IntegerLiteral::new( self.next_node_id(), i32::from_str(raw).unwrap(), source_range, - )), + ))), diagnostics, ) } @@ -1358,11 +1487,11 @@ impl<'a> Parser<'a> { let source_range = SourceRange::new(current.start(), current.end()); diagnostics.append(&mut self.advance()); ( - Expression::Double(DoubleLiteral::new( + Some(Expression::Double(DoubleLiteral::new( self.next_node_id(), f64::from_str(raw).unwrap(), source_range, - )), + ))), diagnostics, ) } @@ -1371,11 +1500,11 @@ impl<'a> Parser<'a> { let source_range = SourceRange::new(current.start(), current.end()); diagnostics.append(&mut self.advance()); ( - Expression::String(StringLiteral::new( + Some(Expression::String(StringLiteral::new( self.next_node_id(), &with_quotes[1..with_quotes.len() - 1], source_range, - )), + ))), diagnostics, ) } @@ -1384,11 +1513,11 @@ impl<'a> Parser<'a> { let source_range = SourceRange::new(current.start(), current.end()); diagnostics.append(&mut self.advance()); ( - Expression::Identifier(Identifier::new( + Some(Expression::Identifier(Identifier::new( self.next_node_id(), declared_name, source_range, - )), + ))), diagnostics, ) } @@ -1430,14 +1559,18 @@ impl<'a> Parser<'a> { let mut expressions = vec![]; let mut diagnostics = Vec::new(); - let (expression, mut ds) = self.expression(); - expressions.push(expression); + let (maybe_expression, mut ds) = self.expression(); + if let Some(expression) = maybe_expression { + expressions.push(expression); + } diagnostics.append(&mut ds); while self.current.is_some() && self.peek_current(TokenKind::Comma) { diagnostics.append(&mut self.advance()); // comma - let (expression, mut ds) = self.expression(); - expressions.push(expression); + let (maybe_expression, mut ds) = self.expression(); + if let Some(expression) = maybe_expression { + expressions.push(expression); + } diagnostics.append(&mut ds); } @@ -1677,11 +1810,15 @@ mod concrete_tests { } fn assert_expression(input: &str) -> Expression { - let (expression, diagnostics) = parse_expression(input); + let (maybe_expression, diagnostics) = parse_expression(input); if !diagnostics.is_empty() { report_diagnostics(&diagnostics); } - expression + if let Some(expression) = maybe_expression { + expression + } else { + panic!("parse_expression produced a None") + } } fn assert_function_in<'a>(