diff --git a/src/lex.rs b/src/lex.rs index 78af59b..bc1608e 100644 --- a/src/lex.rs +++ b/src/lex.rs @@ -141,7 +141,7 @@ impl<'code> Lexer<'code> { } impl<'code> Iterator for Lexer<'code> { - type Item = Result, LexError>; + type Item = Result, CompilerError>; fn next(&mut self) -> Option { let token = loop { @@ -197,9 +197,10 @@ impl<'code> Iterator for Lexer<'code> { kind: TokenType::BangEqual, }; } else { - return Some(Err(LexError::new( + return Some(Err(CompilerError::with_note( Span::single(start), - LexErrorKind::SingleBang, + "Expected '=' after '!'".to_string(), + "If you meant to use it for negation, use `not`".to_string(), ))); }; } @@ -226,9 +227,10 @@ impl<'code> Iterator for Lexer<'code> { buffer.push(char); } None => { - return Some(Err(LexError::new( + return Some(Err(CompilerError::with_note( Span::single(start), // no not show the whole literal, this does not make sense - LexErrorKind::UnclosedStringLiteral, + "String literal not closed".to_string(), + "Close the literal using '\"'".to_string(), ))); } } @@ -254,14 +256,20 @@ impl<'code> Iterator for Lexer<'code> { }; let number_str = &self.src[start..end]; let span = Span::start_end(start, end); - let number = number_str - .parse::() - .map_err(|err| LexError::new(span, LexErrorKind::InvalidFloat(err))); + let number = number_str.parse::().map_err(|err| { + CompilerError::with_note( + span, + "Invalid number".to_string(), + err.to_string(), + ) + }); match number { Ok(number) if number.is_infinite() => { - return Some(Err(LexError::new( + return Some(Err(CompilerError::with_note( span, - LexErrorKind::FloatInfiniteLiteral, + "Number literal too long".to_string(), + "A number literal cannot be larger than a 64 bit float can represent" + .to_string(), ))) } Ok(number) => break Token::new(span, TokenType::Number(number)), @@ -283,9 +291,11 @@ impl<'code> Iterator for Lexer<'code> { keyword_or_ident(&self.src[start..end]), ); } else { - return Some(Err(LexError::new( + return Some(Err(CompilerError::with_note( Span::single(start), - LexErrorKind::InvalidCharacter(char), + format!("Unexpected character: '{}'", char), + "Character is not allowed outside of string literals and comments" + .to_string(), ))); } } @@ -355,62 +365,6 @@ fn is_valid_ident_start(char: char) -> bool { char.is_alphabetic() || char == '_' } -#[derive(Debug, Clone)] -pub struct LexError { - pub span: Span, - pub kind: LexErrorKind, -} - -impl LexError { - fn new(span: Span, kind: LexErrorKind) -> Self { - Self { span, kind } - } -} - -impl From for CompilerError { - fn from(error: LexError) -> Self { - Self { - span: { error.span }, - message: { - match &error.kind { - LexErrorKind::InvalidCharacter(char) => { - format!("Unexpected character: '{}'", char) - } - LexErrorKind::InvalidFloat(_) => "Invalid number".to_string(), - LexErrorKind::FloatInfiniteLiteral => "Number literal too long".to_string(), - LexErrorKind::UnclosedStringLiteral => "String literal not closed".to_string(), - LexErrorKind::SingleBang => "Expected '=' after '!'".to_string(), - } - }, - note: match &error.kind { - LexErrorKind::InvalidCharacter(_) => Some( - "Character is not allowed outside of string literals and comments".to_string(), - ), - LexErrorKind::InvalidFloat(err) => Some(err.to_string()), - LexErrorKind::FloatInfiniteLiteral => Some( - "A number literal cannot be larger than a 64 bit float can represent" - .to_string(), - ), - LexErrorKind::UnclosedStringLiteral => { - Some("Close the literal using '\"'".to_string()) - } - LexErrorKind::SingleBang => { - Some("If you meant to use it for negation, use `not`".to_string()) - } - }, - } - } -} - -#[derive(Debug, Clone)] -pub enum LexErrorKind { - InvalidCharacter(char), - InvalidFloat(std::num::ParseFloatError), - FloatInfiniteLiteral, - UnclosedStringLiteral, - SingleBang, -} - #[cfg(test)] mod test { use crate::lex::Lexer; diff --git a/src/parse.rs b/src/parse.rs index e8aeeb8..4f8d986 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -4,7 +4,6 @@ mod test; use crate::ast::*; use crate::errors::{CompilerError, Span}; use crate::lex::{Token, TokenType}; -use crate::LexError; use bumpalo::boxed::Box; use bumpalo::collections::Vec; use bumpalo::Bump; @@ -13,7 +12,7 @@ use std::iter::Peekable; #[derive(Debug)] struct Parser<'code, 'ast, I> where - I: Iterator, LexError>>, + I: Iterator, CompilerError>>, I: 'code, { tokens: Peekable, @@ -24,7 +23,7 @@ where } pub fn parse<'ast, 'code>( - tokens: impl Iterator, LexError>> + 'code, + tokens: impl Iterator, CompilerError>> + 'code, ast_bump: &'ast Bump, ) -> Result, CompilerError> { let mut parser = Parser { @@ -74,7 +73,7 @@ macro_rules! enter_parse { impl<'code, 'ast, I> Parser<'code, 'ast, I> where - I: Iterator, LexError>>, + I: Iterator, CompilerError>>, I: 'code, { const MAX_DEPTH: usize = 100; @@ -642,7 +641,7 @@ where fn next(&mut self) -> ParseResult<'code, Option>> { match self.tokens.next() { Some(Ok(t)) => Ok(Some(t)), - Some(Err(t)) => Err(t.into()), + Some(Err(comp_err)) => Err(ParseErr::LexError(comp_err)), None => Ok(None), } } @@ -650,7 +649,7 @@ where fn peek(&mut self) -> ParseResult<'code, Option<&Token<'code>>> { match self.tokens.peek() { Some(Ok(t)) => Ok(Some(t)), - Some(Err(t)) => Err(t.clone().into()), + Some(Err(comp_err)) => Err(ParseErr::LexError(comp_err.clone())), None => Ok(None), } } @@ -687,13 +686,7 @@ pub enum ParseErr<'code> { InvalidTokenPrimary(Token<'code>), EofExpecting(TokenType<'code>), Eof(&'static str), - LexError(LexError), -} - -impl From for ParseErr<'_> { - fn from(err: LexError) -> Self { - Self::LexError(err) - } + LexError(CompilerError), } // todo: remove this and ParseErr @@ -729,10 +722,10 @@ impl From> for CompilerError { ParseErr::BreakOutsideLoop(_) => "break used outside of loop".to_string(), ParseErr::ReturnOutsideFunction(_) => "return used outside of function".to_string(), ParseErr::MaxDepth(_) => "reached maximal nesting depth".to_string(), - ParseErr::LexError(err) => err.message(), + ParseErr::LexError(err) => err.message.clone(), }, note: match error { - ParseErr::LexError(err) => err.note(), + ParseErr::LexError(err) => err.note.clone(), _ => None, }, } diff --git a/src/parse/test.rs b/src/parse/test.rs index e296bb2..eda013a 100644 --- a/src/parse/test.rs +++ b/src/parse/test.rs @@ -1,6 +1,5 @@ -use crate::errors::Span; +use crate::errors::{CompilerError, Span}; use crate::parse::Parser; -use crate::LexError; use bumpalo::Bump; use prelude::*; @@ -23,12 +22,12 @@ fn token(kind: TokenType) -> Token { fn parser<'ast>( tokens: std::vec::Vec, alloc: &'ast Bump, -) -> Parser<'static, 'ast, std::vec::IntoIter>> +) -> Parser<'static, 'ast, std::vec::IntoIter>> where { let tokens = tokens .into_iter() .map(Ok) - .collect::>>(); + .collect::>>(); Parser { tokens: tokens.into_iter().peekable(),