From 6ac075ffd0838a75c1cb031ecb0b848ceb0f756c Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Fri, 21 Aug 2026 13:18:20 -0500 Subject: [PATCH] Parser refactoring to use new (Maybe)ParseResult types, WIP. --- dm/src/repl.rs | 14 +- dmc-lib/src/parser.rs | 920 ++++++++++++++++++++++-------------------- 2 files changed, 488 insertions(+), 446 deletions(-) diff --git a/dm/src/repl.rs b/dm/src/repl.rs index 5bfde99..a4a607a 100644 --- a/dm/src/repl.rs +++ b/dm/src/repl.rs @@ -105,12 +105,14 @@ fn compile_statement( register_count: usize, constants_table: &mut ConstantsTable, ) -> Result { - let (maybe_statement, parse_diagnostics) = parse_statement(input); - if !parse_diagnostics.is_empty() { - Err(parse_diagnostics) - } else if let Some(statement) = maybe_statement { - session.compile_statement(&statement, register_count, constants_table) + let maybe_statement = parse_statement(input); + if !maybe_statement.is_ok() { + Err(maybe_statement.into_diagnostics()) } else { - panic!("Unable to unwrap statement from previous input.") + session.compile_statement( + &maybe_statement.into_inner(), + register_count, + constants_table, + ) } } diff --git a/dmc-lib/src/parser.rs b/dmc-lib/src/parser.rs index a44a417..a1aab43 100644 --- a/dmc-lib/src/parser.rs +++ b/dmc-lib/src/parser.rs @@ -27,8 +27,129 @@ use crate::source_range::SourceRange; use crate::token::{Token, TokenKind}; use std::str::FromStr; +#[deprecated] pub type ParseResult = (T, Diagnostics); +pub struct ParseResult2 { + t: T, + diagnostics: Diagnostics, +} + +impl ParseResult2 { + pub fn new(t: T, diagnostics: Diagnostics) -> Self { + Self { t, diagnostics } + } + + fn to_maybe_parse_result(self) -> MaybeParseResult { + MaybeParseResult::some(self.t, self.diagnostics) + } +} + +pub struct MaybeParseResult { + t: Option, + diagnostics: Diagnostics, +} + +impl MaybeParseResult { + fn some(t: T, diagnostics: Diagnostics) -> Self { + Self { + t: Some(t), + diagnostics, + } + } + + fn none(diagnostics: Diagnostics) -> Self { + Self { + t: None, + diagnostics, + } + } + + fn push_diagnostic(&mut self, diagnostic: Diagnostic) { + self.diagnostics.push(diagnostic); + } + + fn append_diagnostics(&mut self, diagnostics: &mut Diagnostics) { + self.diagnostics.append(diagnostics); + } + + fn with_diagnostics(mut self, mut diagnostics: Diagnostics) -> Self { + self.diagnostics.append(&mut diagnostics); + self + } + + pub fn is_ok(&self) -> bool { + self.t.is_some() && self.diagnostics.is_empty() + } + + fn map(self, f: impl FnOnce(T) -> R) -> MaybeParseResult { + if self.is_ok() { + let t = self.t.unwrap(); + MaybeParseResult::some(f(t), self.diagnostics) + } else { + MaybeParseResult::none(self.diagnostics) + } + } + + fn flat_map(mut self, f: impl FnOnce(T) -> MaybeParseResult) -> MaybeParseResult { + if self.is_ok() { + let t = self.t.unwrap(); + let mut r = f(t); + r.append_diagnostics(&mut self.diagnostics); + r + } else { + MaybeParseResult::none(self.diagnostics) + } + } + + fn zip_map(mut self, mut other: MaybeParseResult, f: impl FnOnce(T, T) -> T) -> Self { + if self.is_ok() && other.is_ok() { + let t0 = self.t.take().unwrap(); + let t1 = other.t.take().unwrap(); + MaybeParseResult::some(f(t0, t1), self.diagnostics) + } else { + let mut result = MaybeParseResult::none(self.diagnostics); + result.diagnostics.append(&mut other.diagnostics); + result + } + } + + pub fn take_inner(&mut self) -> T { + if !self.is_ok() { + panic!("Attempt to take non-Ok MaybeParseResult inner"); + } + self.t.take().unwrap() + } + + pub fn into_inner(self) -> T { + if !self.is_ok() { + panic!("Attempt to take non-Ok MaybeParseResult inner"); + } + self.t.unwrap() + } + + pub fn take_diagnostics(&mut self) -> Diagnostics { + std::mem::take(&mut self.diagnostics) + } + + pub fn into_diagnostics(self) -> Diagnostics { + self.diagnostics + } + + pub fn diagnostics(&self) -> &Diagnostics { + &self.diagnostics + } +} + +impl Default for MaybeParseResult { + fn default() -> Self { + Self { + t: None, + diagnostics: Diagnostics::new(), + } + } +} + pub fn get_compilation_unit( input: &str, file_id: Option, @@ -53,22 +174,22 @@ pub fn parse_compilation_unit( (compilation_unit, diagnostics) } -pub fn parse_statement(input: &str) -> ParseResult> { +pub fn parse_statement(input: &str) -> MaybeParseResult { let mut parser = Parser::new(input); let mut diagnostics = Diagnostics::new(); diagnostics.append(&mut parser.advance()); - let (statement, mut ds) = parser.statement(); - diagnostics.append(&mut ds); - (statement, diagnostics) + let mut maybe_statement = parser.statement(); + maybe_statement.append_diagnostics(&mut diagnostics); + maybe_statement } -pub fn parse_expression(input: &str) -> ParseResult> { +pub fn parse_expression(input: &str) -> MaybeParseResult { let mut parser = Parser::new(input); let mut diagnostics = Vec::new(); diagnostics.append(&mut parser.advance()); - let (expression, mut ds) = parser.expression(); - diagnostics.append(&mut ds); - (expression, diagnostics) + let mut maybe_expression = parser.expression(); + maybe_expression.append_diagnostics(&mut diagnostics); + maybe_expression } macro_rules! matches_expression_first { @@ -374,10 +495,11 @@ impl<'a> Parser<'a> { }; match current.kind() { TokenKind::Fn => { - let (maybe_function, mut ds) = self.function(); - diagnostics.append(&mut ds); - if let Some(function) = maybe_function { - functions.push(function); + let maybe_function = self.function(); + if maybe_function.is_ok() { + functions.push(maybe_function.into_inner()); + } else { + diagnostics.append(&mut maybe_function.into_diagnostics()); } } TokenKind::Extern => { @@ -388,10 +510,11 @@ impl<'a> Parser<'a> { } } TokenKind::Class => { - let (maybe_class, mut ds) = self.class(); - diagnostics.append(&mut ds); - if let Some(class) = maybe_class { - classes.push(class); + let maybe_class = self.class(); + if maybe_class.is_ok() { + classes.push(maybe_class.into_inner()); + } else { + diagnostics.append(&mut maybe_class.into_diagnostics()); } } _ => unreachable!(), @@ -400,7 +523,7 @@ impl<'a> Parser<'a> { ((), diagnostics) } - fn function(&mut self) -> ParseResult> { + fn function(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); let is_public = if self.current.is_some() && self.peek_current(TokenKind::Public) { @@ -435,10 +558,11 @@ impl<'a> Parser<'a> { let mut statements = vec![]; while self.current.is_some() && !self.peek_current(TokenKind::End) { - let (maybe_statement, mut ds) = self.statement(); - diagnostics.append(&mut ds); - if let Some(statement) = maybe_statement { - statements.push(statement); + let maybe_statement = self.statement(); + if maybe_statement.is_ok() { + statements.push(maybe_statement.into_inner()); + } else { + diagnostics.append(&mut maybe_statement.into_diagnostics()); } } @@ -455,9 +579,9 @@ impl<'a> Parser<'a> { return_type, statements, ); - (Some(function), diagnostics) + MaybeParseResult::some(function, diagnostics) } else { - (None, diagnostics) + MaybeParseResult::none(diagnostics) } } @@ -501,7 +625,7 @@ impl<'a> Parser<'a> { } } - fn class(&mut self) -> ParseResult> { + fn class(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); let (_, mut ds) = self.expect_advance(TokenKind::Class); @@ -521,38 +645,38 @@ impl<'a> Parser<'a> { let mut fields = vec![]; let mut functions = vec![]; - let mut maybe_constructor: Option = None; + let mut constructor: Option = None; while self.current.is_some() && !self.peek_current(TokenKind::End) { match self.current.as_ref().unwrap().kind() { // checked in loop TokenKind::Public => { - let (_, mut ds) = self.public_class_member( - &mut fields, - &mut functions, - &mut maybe_constructor, - ); + let (_, mut ds) = + self.public_class_member(&mut fields, &mut functions, &mut constructor); diagnostics.append(&mut ds); } TokenKind::Mut | TokenKind::Identifier => { - let (maybe_field, mut ds) = self.field(); - diagnostics.append(&mut ds); - if let Some(field) = maybe_field { - fields.push(field); + let maybe_field = self.field(); + if maybe_field.is_ok() { + fields.push(maybe_field.into_inner()); + } else { + diagnostics.append(&mut maybe_field.into_diagnostics()); } } TokenKind::Fn => { - let (maybe_function, mut ds) = self.function(); - diagnostics.append(&mut ds); - if let Some(function) = maybe_function { - functions.push(function); + let maybe_function = self.function(); + if maybe_function.is_ok() { + functions.push(maybe_function.into_inner()); + } else { + diagnostics.append(&mut maybe_function.into_diagnostics()); } } TokenKind::Ctor => { - let (constructor, mut ds) = self.constructor(); - diagnostics.append(&mut ds); - if let Some(constructor) = constructor { - maybe_constructor = Some(constructor); + let maybe_constructor = self.constructor(); + if maybe_constructor.is_ok() { + constructor.replace(maybe_constructor.into_inner()); + } else { + diagnostics.append(&mut maybe_constructor.into_diagnostics()); } } _ => unreachable!(), @@ -568,13 +692,13 @@ impl<'a> Parser<'a> { self.token_text(&identifier), SourceRange::new(identifier.start(), identifier.end()), generic_parameters, - maybe_constructor, + constructor, fields, functions, ); - (Some(class), diagnostics) + MaybeParseResult::some(class, diagnostics) } else { - (None, diagnostics) + MaybeParseResult::none(diagnostics) } } @@ -784,30 +908,33 @@ impl<'a> Parser<'a> { &mut self, fields: &mut Vec, functions: &mut Vec, - maybe_ctor: &mut Option, + constructor: &mut Option, ) -> ParseResult<()> { let mut diagnostics = Vec::new(); if self.lookahead.is_some() { match self.lookahead.as_ref().unwrap().kind() { TokenKind::Mut | TokenKind::Identifier => { - let (maybe_field, mut ds) = self.field(); - diagnostics.append(&mut ds); - if let Some(field) = maybe_field { - fields.push(field); + let maybe_field = self.field(); + if maybe_field.is_ok() { + fields.push(maybe_field.into_inner()); + } else { + diagnostics.append(&mut maybe_field.into_diagnostics()); } } TokenKind::Fn => { - let (maybe_function, mut ds) = self.function(); - diagnostics.append(&mut ds); - if let Some(function) = maybe_function { - functions.push(function); + let maybe_function = self.function(); + if maybe_function.is_ok() { + functions.push(maybe_function.into_inner()); + } else { + diagnostics.append(&mut maybe_function.into_diagnostics()); } } TokenKind::Ctor => { - let (ctor, mut ds) = self.constructor(); - diagnostics.append(&mut ds); - if let Some(ctor) = ctor { - maybe_ctor.replace(ctor); + let maybe_constructor = self.constructor(); + if maybe_constructor.is_ok() { + constructor.replace(maybe_constructor.into_inner()); + } else { + diagnostics.append(&mut maybe_constructor.into_diagnostics()); } } _ => { @@ -829,7 +956,7 @@ impl<'a> Parser<'a> { ((), diagnostics) } - fn constructor(&mut self) -> ParseResult> { + fn constructor(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); let is_public = if self.current.is_some() && self.peek_current(TokenKind::Public) { @@ -863,10 +990,11 @@ impl<'a> Parser<'a> { while self.current.is_some() && matches_statement_first!(self.current.as_ref().unwrap().kind()) { - let (maybe_statement, mut ds) = self.statement(); - diagnostics.append(&mut ds); - if let Some(statement) = maybe_statement { - statements.push(statement); + let maybe_statement = self.statement(); + if maybe_statement.is_ok() { + statements.push(maybe_statement.into_inner()); + } else { + diagnostics.append(&mut maybe_statement.into_diagnostics()) } } @@ -881,13 +1009,13 @@ impl<'a> Parser<'a> { parameters, statements, ); - (Some(constructor), diagnostics) + MaybeParseResult::some(constructor, diagnostics) } else { - (None, diagnostics) + MaybeParseResult::none(diagnostics) } } - fn field(&mut self) -> ParseResult> { + fn field(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); let is_public = if self.current.is_some() && self.peek_current(TokenKind::Public) { @@ -918,30 +1046,47 @@ impl<'a> Parser<'a> { let initializer = if self.current.is_some() && self.peek_current(TokenKind::Equals) { diagnostics.append(&mut self.advance()); // equals - let (maybe_expression, mut ds) = self.expression(); - diagnostics.append(&mut ds); - maybe_expression + let maybe_expression = self.expression(); + Some(maybe_expression) } else { None }; if let Some(identifier) = identifier { - let field = Field::new( - self.next_node_id(), - self.token_text(&identifier), - SourceRange::new(identifier.start(), identifier.end()), - is_public, - is_mut, - declared_type, - initializer, - ); - (Some(field), diagnostics) + if let Some(maybe_initializer) = initializer { + maybe_initializer + .map(|expression| { + Field::new( + self.next_node_id(), + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), + is_public, + is_mut, + declared_type, + Some(expression), + ) + }) + .with_diagnostics(diagnostics) + } else { + MaybeParseResult::some( + Field::new( + self.next_node_id(), + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), + is_public, + is_mut, + declared_type, + None, + ), + diagnostics, + ) + } } else { - (None, diagnostics) + MaybeParseResult::none(diagnostics) } } - fn statement(&mut self) -> ParseResult> { + fn statement(&mut self) -> MaybeParseResult { let current = match self.current.as_ref() { None => { let mut ds = Diagnostics::new(); @@ -949,23 +1094,19 @@ impl<'a> Parser<'a> { &STATEMENT_FIRSTS, self.input.len(), )); - return (None, ds); + return MaybeParseResult::none(ds); } Some(current) => current, }; match current.kind() { - TokenKind::Let => { - let (maybe_let_statement, diagnostics) = self.let_statement(); - match maybe_let_statement { - None => (None, diagnostics), - Some(let_statement) => (Some(Statement::Let(let_statement)), diagnostics), - } - } + TokenKind::Let => self + .let_statement() + .map(|let_statement| Statement::Let(let_statement)), _ => self.expression_statement_or_assign_statement(), } } - fn let_statement(&mut self) -> ParseResult> { + fn let_statement(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); let (_, mut ds) = self.expect_advance(TokenKind::Let); @@ -984,196 +1125,138 @@ impl<'a> Parser<'a> { let (_, mut ds) = self.expect_advance(TokenKind::Equals); diagnostics.append(&mut ds); - let (maybe_expression, mut ds) = self.expression(); - diagnostics.append(&mut ds); + let mut maybe_expression = self.expression(); let identifier = match maybe_identifier { + None => { + diagnostics.append(&mut maybe_expression.take_diagnostics()); + return MaybeParseResult::none(diagnostics); + } 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> { - 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 { - (None, diagnostics) - } - } else { - ( - Some(Statement::Expression(ExpressionStatement::new(base))), - diagnostics, + maybe_expression.map(|expression| { + LetStatement::new( + self.next_node_id(), + self.token_text(&identifier), + SourceRange::new(identifier.start(), identifier.end()), + is_mut, + expression, ) - } + }) } - 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 (maybe_value, mut ds) = self.expression(); - diagnostics.append(&mut ds); - if let Some(value) = maybe_value { - (Some(AssignStatement::new(destination, value)), diagnostics) + fn expression_statement_or_assign_statement(&mut self) -> MaybeParseResult { + let base = self.expression(); + if self.current.is_some() && self.peek_current(TokenKind::Equals) { + base.flat_map(|expression| { + self.assign_rhs(expression) + .map(|assign_statement| Statement::Assign(assign_statement)) + }) } else { - (None, diagnostics) + base.map(|expression| Statement::Expression(ExpressionStatement::new(expression))) } } - fn expression(&mut self) -> ParseResult> { + fn assign_rhs(&mut self, destination: Expression) -> MaybeParseResult { + let (_, mut ds) = self.expect_advance(TokenKind::Equals); + let mut expression = self.expression(); + expression.append_diagnostics(&mut ds); + expression.map(|expression| AssignStatement::new(destination, expression)) + } + + fn expression(&mut self) -> MaybeParseResult { self.bitwise_or_expression() } - fn bitwise_or_expression(&mut self) -> ParseResult> { + fn bitwise_or_expression(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); - 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); - } - }; + let mut base = self.bitwise_xor_expression(); while self.current.is_some() && self.peek_current(TokenKind::Bar) { diagnostics.append(&mut self.advance()); // | - 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 rhs = self.bitwise_xor_expression(); - let source_range = - SourceRange::new(base.source_range().start(), rhs.source_range().end()); - base = Expression::Binary(BinaryExpression::new( - self.next_node_id(), - base, - rhs, - BinaryOperation::BitwiseOr, - source_range, - )); + base = base.zip_map(rhs, |lhs, rhs| { + let source_range = + SourceRange::new(lhs.source_range().start(), rhs.source_range().end()); + + Expression::Binary(BinaryExpression::new( + self.next_node_id(), + lhs, + rhs, + BinaryOperation::BitwiseOr, + source_range, + )) + }); } - (Some(base), diagnostics) + + base.append_diagnostics(&mut diagnostics); + base } - fn bitwise_xor_expression(&mut self) -> ParseResult> { + fn bitwise_xor_expression(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); - 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); - } - }; + let mut base = self.bitwise_and_expression(); while self.current.is_some() && self.peek_current(TokenKind::Caret) { diagnostics.append(&mut self.advance()); // ^ - 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 rhs = self.bitwise_and_expression(); - let source_range = - SourceRange::new(base.source_range().start(), rhs.source_range().end()); - base = Expression::Binary(BinaryExpression::new( - self.next_node_id(), - base, - rhs, - BinaryOperation::BitwiseXor, - source_range, - )); + base = base.zip_map(rhs, |lhs, rhs| { + let source_range = + SourceRange::new(lhs.source_range().start(), rhs.source_range().end()); + + Expression::Binary(BinaryExpression::new( + self.next_node_id(), + lhs, + rhs, + BinaryOperation::BitwiseXor, + source_range, + )) + }); } - (Some(base), diagnostics) + + base.append_diagnostics(&mut diagnostics); + base } - fn bitwise_and_expression(&mut self) -> ParseResult> { + fn bitwise_and_expression(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); - 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); - } - }; + let mut base = self.shift_expression(); while self.current.is_some() && self.peek_current(TokenKind::Ampersand) { diagnostics.append(&mut self.advance()); // & - 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 rhs = self.shift_expression(); - let source_range = - SourceRange::new(base.source_range().start(), rhs.source_range().end()); - base = Expression::Binary(BinaryExpression::new( - self.next_node_id(), - base, - rhs, - BinaryOperation::BitwiseAnd, - source_range, - )); + base = base.zip_map(rhs, |lhs, rhs| { + let source_range = + SourceRange::new(lhs.source_range().start(), rhs.source_range().end()); + + Expression::Binary(BinaryExpression::new( + self.next_node_id(), + lhs, + rhs, + BinaryOperation::BitwiseAnd, + source_range, + )) + }); } - (Some(base), diagnostics) + + base.append_diagnostics(&mut diagnostics); + base } - fn shift_expression(&mut self) -> ParseResult> { + fn shift_expression(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); - 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); - } - }; + let mut base = self.additive_expression(); + if !base.is_ok() { + return base; + } while self.current.is_some() { let current = self.current.as_ref().unwrap(); @@ -1185,24 +1268,19 @@ impl<'a> Parser<'a> { self.expect_immediately_after_advance(TokenKind::Lt, &previous_cloned); // second < diagnostics.append(&mut ds); - 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 rhs = self.additive_expression(); - let source_range = - SourceRange::new(base.source_range().start(), rhs.source_range().end()); - base = Expression::Binary(BinaryExpression::new( - self.next_node_id(), - base, - rhs, - BinaryOperation::LeftShift, - source_range, - )); + base = base.zip_map(rhs, |lhs, rhs| { + let source_range = + SourceRange::new(lhs.source_range().start(), rhs.source_range().end()); + Expression::Binary(BinaryExpression::new( + self.next_node_id(), + lhs, + rhs, + BinaryOperation::LeftShift, + source_range, + )) + }); } TokenKind::Gt => { let previous_cloned = current.clone(); @@ -1211,180 +1289,148 @@ impl<'a> Parser<'a> { self.expect_immediately_after_advance(TokenKind::Gt, &previous_cloned); // second > diagnostics.append(&mut ds); - 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 rhs = self.additive_expression(); - let source_range = - SourceRange::new(base.source_range().start(), rhs.source_range().end()); - base = Expression::Binary(BinaryExpression::new( - self.next_node_id(), - base, - rhs, - BinaryOperation::RightShift, - source_range, - )); + base = base.zip_map(rhs, |lhs, rhs| { + let source_range = + SourceRange::new(lhs.source_range().start(), rhs.source_range().end()); + Expression::Binary(BinaryExpression::new( + self.next_node_id(), + lhs, + rhs, + BinaryOperation::RightShift, + source_range, + )) + }); } _ => break, } } - (Some(base), diagnostics) + base.append_diagnostics(&mut diagnostics); + base } - fn additive_expression(&mut self) -> ParseResult> { + fn additive_expression(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); - 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); - } - }; + let mut base = self.multiplicative_expression(); + if !base.is_ok() { + return base; + } while self.current.is_some() { let current = self.current.as_ref().unwrap(); match current.kind() { TokenKind::Plus => { diagnostics.append(&mut self.advance()); // plus - 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 rhs = self.multiplicative_expression(); - let source_range = - SourceRange::new(base.source_range().start(), rhs.source_range().end()); - base = Expression::Binary(BinaryExpression::new( - self.next_node_id(), - base, - rhs, - BinaryOperation::Add, - source_range, - )); + base = base.zip_map(rhs, |lhs, rhs| { + let source_range = + SourceRange::new(lhs.source_range().start(), rhs.source_range().end()); + Expression::Binary(BinaryExpression::new( + self.next_node_id(), + lhs, + rhs, + BinaryOperation::Add, + source_range, + )) + }) } TokenKind::Minus => { diagnostics.append(&mut self.advance()); // minus - 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 rhs = self.multiplicative_expression(); - let source_range = - SourceRange::new(base.source_range().start(), rhs.source_range().end()); - base = Expression::Binary(BinaryExpression::new( - self.next_node_id(), - base, - rhs, - BinaryOperation::Subtract, - source_range, - )); + base = base.zip_map(rhs, |lhs, rhs| { + let source_range = + SourceRange::new(lhs.source_range().start(), rhs.source_range().end()); + Expression::Binary(BinaryExpression::new( + self.next_node_id(), + lhs, + rhs, + BinaryOperation::Subtract, + source_range, + )) + }) } _ => break, } } - (Some(base), diagnostics) + + base.append_diagnostics(&mut diagnostics); + base } - fn multiplicative_expression(&mut self) -> ParseResult> { + fn multiplicative_expression(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); - 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); - } - }; + let mut base = self.prefix_expression(); + if !base.is_ok() { + return base; + } while self.current.is_some() { let current = self.current.as_ref().unwrap(); match current.kind() { TokenKind::Star => { diagnostics.append(&mut self.advance()); // multiply - 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 rhs = self.prefix_expression(); - let source_range = - SourceRange::new(base.source_range().start(), rhs.source_range().end()); - base = Expression::Binary(BinaryExpression::new( - self.next_node_id(), - base, - rhs, - BinaryOperation::Multiply, - source_range, - )); + base = base.zip_map(rhs, |lhs, rhs| { + let source_range = + SourceRange::new(lhs.source_range().start(), rhs.source_range().end()); + Expression::Binary(BinaryExpression::new( + self.next_node_id(), + lhs, + rhs, + BinaryOperation::Multiply, + source_range, + )) + }) } TokenKind::Slash => { diagnostics.append(&mut self.advance()); // slash - 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 rhs = self.prefix_expression(); - let source_range = - SourceRange::new(base.source_range().start(), rhs.source_range().end()); - base = Expression::Binary(BinaryExpression::new( - self.next_node_id(), - base, - rhs, - BinaryOperation::Divide, - source_range, - )) + base = base.zip_map(rhs, |lhs, rhs| { + let source_range = + SourceRange::new(lhs.source_range().start(), rhs.source_range().end()); + Expression::Binary(BinaryExpression::new( + self.next_node_id(), + lhs, + rhs, + BinaryOperation::Divide, + source_range, + )) + }) } TokenKind::Modulo => { diagnostics.append(&mut self.advance()); // modulo - 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 rhs = self.prefix_expression(); - let source_range = - SourceRange::new(base.source_range().start(), rhs.source_range().end()); - base = Expression::Binary(BinaryExpression::new( - self.next_node_id(), - base, - rhs, - BinaryOperation::Modulo, - source_range, - )); + base = base.zip_map(rhs, |lhs, rhs| { + let source_range = + SourceRange::new(lhs.source_range().start(), rhs.source_range().end()); + + Expression::Binary(BinaryExpression::new( + self.next_node_id(), + lhs, + rhs, + BinaryOperation::Modulo, + source_range, + )) + }); } _ => break, } } - (Some(base), diagnostics) + + base.append_diagnostics(&mut diagnostics); + base } - fn prefix_expression(&mut self) -> ParseResult> { + fn prefix_expression(&mut self) -> MaybeParseResult { let mut diagnostics = Vec::new(); // first, collect all consecutive operators @@ -1403,67 +1449,62 @@ 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 (maybe_base, mut ds) = self.suffix_expression(); - diagnostics.append(&mut ds); - let mut base = match maybe_base { - Some(base) => base, - None => { - return (None, diagnostics); - } - }; + let mut base = self.suffix_expression(); while let Some(operator_token) = operator_tokens.pop() { - let source_range = SourceRange::new(operator_token.start(), base.source_range().end()); match operator_token.kind() { TokenKind::Minus => { - base = Expression::Negative(NegativeExpression::new( - self.next_node_id(), - base, - source_range, - )); + base = base.map(|expression| { + let source_range = SourceRange::new( + operator_token.start(), + expression.source_range().end(), + ); + Expression::Negative(NegativeExpression::new( + self.next_node_id(), + expression, + source_range, + )) + }); } _ => unreachable!(), } } - (Some(base), diagnostics) + + base.append_diagnostics(&mut diagnostics); + base } - fn suffix_expression(&mut self) -> ParseResult> { - let mut diagnostics = Vec::new(); - - 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); - } - }; + fn suffix_expression(&mut self) -> MaybeParseResult { + let mut base = self.expression_base(); + if !base.is_ok() { + return base; + } while self.current.is_some() { let current = self.current.as_ref().unwrap(); match current.kind() { TokenKind::LeftParentheses => { - let (call, mut ds) = self.call(base); - diagnostics.append(&mut ds); - base = Expression::Call(call); + let call = self.call(base.take_inner()); + base = call + .to_maybe_parse_result() + .map(|call| Expression::Call(call)) } _ => break, } } - (Some(base), diagnostics) + base } - fn expression_base(&mut self) -> ParseResult> { + fn expression_base(&mut self) -> MaybeParseResult { let current = match self.current.as_ref() { None => { - let mut ds = Diagnostics::new(); - ds.push(Self::get_expected_but_found_eoi( + let mut result = MaybeParseResult::default(); + result.push_diagnostic(Self::get_expected_but_found_eoi( &EXPRESSION_FIRSTS, self.input.len(), )); - return (None, ds); + return result; } Some(current) => current, }; @@ -1473,12 +1514,12 @@ impl<'a> Parser<'a> { let raw = self.token_text(¤t); let source_range = SourceRange::new(current.start(), current.end()); diagnostics.append(&mut self.advance()); - ( - Some(Expression::Integer(IntegerLiteral::new( + MaybeParseResult::some( + Expression::Integer(IntegerLiteral::new( self.next_node_id(), i32::from_str(raw).unwrap(), source_range, - ))), + )), diagnostics, ) } @@ -1486,12 +1527,12 @@ impl<'a> Parser<'a> { let raw = self.token_text(¤t); let source_range = SourceRange::new(current.start(), current.end()); diagnostics.append(&mut self.advance()); - ( - Some(Expression::Double(DoubleLiteral::new( + MaybeParseResult::some( + Expression::Double(DoubleLiteral::new( self.next_node_id(), f64::from_str(raw).unwrap(), source_range, - ))), + )), diagnostics, ) } @@ -1499,12 +1540,12 @@ impl<'a> Parser<'a> { let with_quotes = self.token_text(¤t); let source_range = SourceRange::new(current.start(), current.end()); diagnostics.append(&mut self.advance()); - ( - Some(Expression::String(StringLiteral::new( + MaybeParseResult::some( + Expression::String(StringLiteral::new( self.next_node_id(), &with_quotes[1..with_quotes.len() - 1], source_range, - ))), + )), diagnostics, ) } @@ -1512,12 +1553,12 @@ impl<'a> Parser<'a> { let declared_name = self.token_text(¤t); let source_range = SourceRange::new(current.start(), current.end()); diagnostics.append(&mut self.advance()); - ( - Some(Expression::Identifier(Identifier::new( + MaybeParseResult::some( + Expression::Identifier(Identifier::new( self.next_node_id(), declared_name, source_range, - ))), + )), diagnostics, ) } @@ -1525,7 +1566,7 @@ impl<'a> Parser<'a> { } } - fn call(&mut self, callee: Expression) -> ParseResult { + fn call(&mut self, callee: Expression) -> ParseResult2 { let mut diagnostics = Vec::new(); let (_, mut ds) = self.expect_advance(TokenKind::LeftParentheses); diagnostics.append(&mut ds); @@ -1549,7 +1590,7 @@ impl<'a> Parser<'a> { SourceRange::new(callee.source_range().start(), callee.source_range().end()) }; - ( + ParseResult2::new( Call::new(self.next_node_id(), callee, arguments, source_range), diagnostics, ) @@ -1559,19 +1600,21 @@ impl<'a> Parser<'a> { let mut expressions = vec![]; let mut diagnostics = Vec::new(); - let (maybe_expression, mut ds) = self.expression(); - if let Some(expression) = maybe_expression { - expressions.push(expression); + let maybe_expression = self.expression(); + if maybe_expression.is_ok() { + expressions.push(maybe_expression.into_inner()); + } else { + diagnostics.append(&mut maybe_expression.into_diagnostics()); } - diagnostics.append(&mut ds); while self.current.is_some() && self.peek_current(TokenKind::Comma) { diagnostics.append(&mut self.advance()); // comma - let (maybe_expression, mut ds) = self.expression(); - if let Some(expression) = maybe_expression { - expressions.push(expression); + let maybe_expression = self.expression(); + if maybe_expression.is_ok() { + expressions.push(maybe_expression.into_inner()); + } else { + diagnostics.append(&mut maybe_expression.into_diagnostics()); } - diagnostics.append(&mut ds); } (expressions, diagnostics) @@ -1810,14 +1853,11 @@ mod concrete_tests { } fn assert_expression(input: &str) -> Expression { - let (maybe_expression, diagnostics) = parse_expression(input); - if !diagnostics.is_empty() { - report_diagnostics(&diagnostics); - } - if let Some(expression) = maybe_expression { - expression + let maybe_expression = parse_expression(input); + if maybe_expression.is_ok() { + maybe_expression.into_inner() } else { - panic!("parse_expression produced a None") + report_diagnostics(maybe_expression.diagnostics()); } }