From 4e9d846fbd51cec9e8d931c4aa3f399668ac316e Mon Sep 17 00:00:00 2001 From: Mel Date: Sun, 21 Nov 2021 19:44:47 +0100 Subject: Basic errors for parsing. --- src/parse/macros.rs | 22 +++++++---- src/parse/mod.rs | 2 +- src/parse/parser.rs | 107 +++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 93 insertions(+), 38 deletions(-) (limited to 'src/parse') diff --git a/src/parse/macros.rs b/src/parse/macros.rs index 97e0104..9cf995c 100644 --- a/src/parse/macros.rs +++ b/src/parse/macros.rs @@ -16,15 +16,15 @@ macro_rules! consume { if let Token {kind: $( $kind )|+, ..} = token { Ok(token) } else { - Err(anyhow!( - // Make a better error message - "Received unexpected token: '{:?}'.", - token.kind - )) + Err(parser_error(ErrorLocation::Specific(token.location), ParserError::UnexpectedToken { + received: token.kind, + expected: merge_token_names!($($kind),+), + })) } } else { - // Here too - Err(anyhow!("Expected a token.")) + Err(parser_error(ErrorLocation::Eof, ParserError::UnexpectedEof { + expected: merge_token_names!($($kind),+), + })) } }; } @@ -49,3 +49,11 @@ macro_rules! inner { } }; } + +// TODO: Better names for the tokens. +#[macro_export] +macro_rules! merge_token_names { + ($($kind:pat_param),+) => { + vec![$( stringify!($kind) ),+].join(", ") + }; +} diff --git a/src/parse/mod.rs b/src/parse/mod.rs index e45e6fa..9ddca42 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -1,3 +1,3 @@ pub mod ast; mod macros; -pub mod parser; +pub mod parser; \ No newline at end of file diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 8b43a74..76bbab7 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1,15 +1,17 @@ +use thiserror::Error; + use super::ast::expression::Expression; use super::ast::nodes::{ArrayNode, LoopNode, StrNode, UnaryOperator}; use super::ast::statement::Statement; use super::ast::Program; +use crate::error::{ErrorLocation, RHError, RHErrorKind}; use crate::lex::lexer::Lexer; -use crate::lex::token::TokenKind::*; +use crate::lex::token::TokenKind::{self, *}; use crate::parse::ast::nodes::{ ArrayAccessNode, BinaryOperator, BlockNode, CallNode, ConditionalBlock, FnHeader, FnNode, IfNode, MemberAccessNode, SimpleLiteral, StrPart, TypedIdentifier, }; -use crate::{check, consume, consume_if, inner, lex::token::Token}; -use anyhow::{anyhow, Result}; +use crate::{check, consume, consume_if, inner, lex::token::Token, merge_token_names}; use std::iter::Peekable; pub struct Parser { @@ -23,7 +25,7 @@ impl> Parser { } } - pub fn parse(&mut self) -> Result { + pub fn parse(&mut self) -> Result { let mut statements = Vec::new(); while !check!(self, Eof) { @@ -33,7 +35,7 @@ impl> Parser { Ok(Program { statements }) } - fn statement(&mut self) -> Result { + fn statement(&mut self) -> Result { let token = self.tokens.peek().expect("Expected token."); match token.kind { KeywordPrint => self.print_statement(), @@ -44,14 +46,14 @@ impl> Parser { } } - fn return_statement(&mut self) -> Result { + fn return_statement(&mut self) -> Result { consume!(self, KeywordReturn)?; let expression = self.expression()?; consume!(self, SemiColon)?; Ok(Statement::Return(expression)) } - fn break_statement(&mut self) -> Result { + fn break_statement(&mut self) -> Result { consume!(self, KeywordBreak)?; let returned_on_break = if consume_if!(self, SemiColon).is_none() { let expression = self.expression()?; @@ -63,30 +65,30 @@ impl> Parser { Ok(Statement::Break(returned_on_break)) } - fn continue_statement(&mut self) -> Result { + fn continue_statement(&mut self) -> Result { consume!(self, KeywordContinue)?; consume!(self, SemiColon)?; Ok(Statement::Continue) } - fn print_statement(&mut self) -> Result { + fn print_statement(&mut self) -> Result { consume!(self, KeywordPrint)?; let expression = self.expression()?; consume!(self, SemiColon)?; Ok(Statement::Print(expression)) } - fn expression_statement(&mut self) -> Result { + fn expression_statement(&mut self) -> Result { let expression = self.expression()?; consume!(self, SemiColon)?; Ok(Statement::Expression(expression)) } - pub fn expression(&mut self) -> Result { + pub fn expression(&mut self) -> Result { self.assignment_expression() } - fn assignment_expression(&mut self) -> Result { + fn assignment_expression(&mut self) -> Result { // Parse any expressions as l-values for now. let left = self.or_expression()?; @@ -103,7 +105,7 @@ impl> Parser { } } - fn or_expression(&mut self) -> Result { + fn or_expression(&mut self) -> Result { let mut left = self.and_expression()?; while let Some(op) = consume_if!(self, OpAnd) { @@ -119,7 +121,7 @@ impl> Parser { Ok(left) } - fn and_expression(&mut self) -> Result { + fn and_expression(&mut self) -> Result { let mut left = self.equality_expression()?; while let Some(op) = consume_if!(self, OpOr) { @@ -135,7 +137,7 @@ impl> Parser { Ok(left) } - fn equality_expression(&mut self) -> Result { + fn equality_expression(&mut self) -> Result { let mut left = self.comparison_expression()?; while let Some(op) = consume_if!(self, OpEq | OpNeq) { @@ -151,7 +153,7 @@ impl> Parser { Ok(left) } - fn comparison_expression(&mut self) -> Result { + fn comparison_expression(&mut self) -> Result { let mut left = self.term_expression()?; while let Some(op) = consume_if!(self, OpGt | OpGte | OpLt | OpLte) { @@ -167,7 +169,7 @@ impl> Parser { Ok(left) } - fn term_expression(&mut self) -> Result { + fn term_expression(&mut self) -> Result { let mut left = self.factor_expression()?; while let Some(op) = consume_if!(self, OpPlus | OpMinus) { @@ -183,7 +185,7 @@ impl> Parser { Ok(left) } - fn factor_expression(&mut self) -> Result { + fn factor_expression(&mut self) -> Result { let mut left = self.unary_expression()?; while let Some(op) = consume_if!(self, OpSlash | OpStar) { @@ -199,7 +201,7 @@ impl> Parser { Ok(left) } - fn unary_expression(&mut self) -> Result { + fn unary_expression(&mut self) -> Result { let expression = if check!(self, OpPlus | OpMinus | OpNot) { Expression::Unary { op: UnaryOperator::from_token(self.tokens.next().unwrap()), @@ -212,7 +214,7 @@ impl> Parser { Ok(expression) } - fn postfix_expression(&mut self) -> Result { + fn postfix_expression(&mut self) -> Result { let mut left = self.unit_expression()?; while let Some(token) = consume_if!(self, GroupOpen | ArrayOpen | Dot) { @@ -255,7 +257,7 @@ impl> Parser { Ok(left) } - fn unit_expression(&mut self) -> Result { + fn unit_expression(&mut self) -> Result { if let Some(token) = self.tokens.peek() { match token.kind { Int(_) | Float(_) | Str(_) | KeywordTrue | KeywordFalse => { @@ -275,21 +277,47 @@ impl> Parser { KeywordFn => Ok(Expression::FnLiteral(Box::new(self.function()?))), KeywordIf => Ok(Expression::If(Box::new(self.conditional()?))), KeywordLoop => Ok(Expression::Loop(Box::new(self.repeating()?))), - _ => Err(anyhow!("Unexpected token: {:?}", token.kind)), + _ => Err(parser_error( + ErrorLocation::Specific(token.location), + ParserError::UnexpectedToken { + received: token.kind.clone(), + expected: merge_token_names!( + Int(_), + Float(_), + Str(_), + KeywordTrue, + KeywordFalse, + Ident(_), + StrOpen, + GroupOpen, + BlockOpen, + ArrayOpen, + KeywordFn, + KeywordIf, + KeywordLoop + ), + }, + )), } } else { - Err(anyhow!("Expected expression.")) + Err(parser_error( + ErrorLocation::Eof, + ParserError::UnexpectedEof { + // Well sure this works. + expected: "expression".into(), + }, + )) } } - fn group(&mut self) -> Result { + fn group(&mut self) -> Result { consume!(self, GroupOpen)?; let expression = self.expression()?; consume!(self, GroupClose)?; Ok(expression) } - fn array(&mut self) -> Result { + fn array(&mut self) -> Result { consume!(self, ArrayOpen)?; let mut elements = Vec::new(); @@ -305,7 +333,7 @@ impl> Parser { Ok(ArrayNode { elements }) } - fn str(&mut self) -> Result { + fn str(&mut self) -> Result { let mut parts = Vec::new(); consume!(self, StrOpen)?; @@ -333,7 +361,7 @@ impl> Parser { Ok(StrNode { parts }) } - fn function(&mut self) -> Result { + fn function(&mut self) -> Result { consume!(self, KeywordFn)?; let header = { @@ -382,7 +410,7 @@ impl> Parser { Ok(FnNode { header, body }) } - fn conditional(&mut self) -> Result { + fn conditional(&mut self) -> Result { consume!(self, KeywordIf)?; let mut conditionals = Vec::new(); @@ -418,7 +446,7 @@ impl> Parser { }) } - fn repeating(&mut self) -> Result { + fn repeating(&mut self) -> Result { consume!(self, KeywordLoop)?; let condition = if consume_if!(self, KeywordIf).is_some() { @@ -432,7 +460,7 @@ impl> Parser { Ok(LoopNode { body, condition }) } - fn generic_block(&mut self) -> Result { + fn generic_block(&mut self) -> Result { consume!(self, BlockOpen)?; let mut statements = Vec::new(); @@ -467,3 +495,22 @@ impl> Parser { }) } } + +fn parser_error(at: ErrorLocation, parse_error: ParserError) -> RHError { + RHError { + at, + kind: RHErrorKind::Parse(parse_error), + } +} + +#[derive(Error, Debug)] +pub enum ParserError { + #[error("Received unexpected '{received}', expected: {expected}.'")] + UnexpectedToken { + received: TokenKind, + // Stringified expected tokens + expected: String, + }, + #[error("Unexpected end of file, expected: {expected}")] + UnexpectedEof { expected: String }, +} -- cgit 1.4.1