mirror of
https://github.com/Noratrieb/dilaria.git
synced 2026-01-17 02:45:02 +01:00
remove lexer error
This commit is contained in:
parent
219a7b7e37
commit
d3125945eb
3 changed files with 33 additions and 87 deletions
90
src/lex.rs
90
src/lex.rs
|
|
@ -141,7 +141,7 @@ impl<'code> Lexer<'code> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'code> Iterator for Lexer<'code> {
|
impl<'code> Iterator for Lexer<'code> {
|
||||||
type Item = Result<Token<'code>, LexError>;
|
type Item = Result<Token<'code>, CompilerError>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let token = loop {
|
let token = loop {
|
||||||
|
|
@ -197,9 +197,10 @@ impl<'code> Iterator for Lexer<'code> {
|
||||||
kind: TokenType::BangEqual,
|
kind: TokenType::BangEqual,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return Some(Err(LexError::new(
|
return Some(Err(CompilerError::with_note(
|
||||||
Span::single(start),
|
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);
|
buffer.push(char);
|
||||||
}
|
}
|
||||||
None => {
|
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
|
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 number_str = &self.src[start..end];
|
||||||
let span = Span::start_end(start, end);
|
let span = Span::start_end(start, end);
|
||||||
let number = number_str
|
let number = number_str.parse::<f64>().map_err(|err| {
|
||||||
.parse::<f64>()
|
CompilerError::with_note(
|
||||||
.map_err(|err| LexError::new(span, LexErrorKind::InvalidFloat(err)));
|
span,
|
||||||
|
"Invalid number".to_string(),
|
||||||
|
err.to_string(),
|
||||||
|
)
|
||||||
|
});
|
||||||
match number {
|
match number {
|
||||||
Ok(number) if number.is_infinite() => {
|
Ok(number) if number.is_infinite() => {
|
||||||
return Some(Err(LexError::new(
|
return Some(Err(CompilerError::with_note(
|
||||||
span,
|
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)),
|
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]),
|
keyword_or_ident(&self.src[start..end]),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Some(Err(LexError::new(
|
return Some(Err(CompilerError::with_note(
|
||||||
Span::single(start),
|
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 == '_'
|
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<LexError> 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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::lex::Lexer;
|
use crate::lex::Lexer;
|
||||||
|
|
|
||||||
23
src/parse.rs
23
src/parse.rs
|
|
@ -4,7 +4,6 @@ mod test;
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::errors::{CompilerError, Span};
|
use crate::errors::{CompilerError, Span};
|
||||||
use crate::lex::{Token, TokenType};
|
use crate::lex::{Token, TokenType};
|
||||||
use crate::LexError;
|
|
||||||
use bumpalo::boxed::Box;
|
use bumpalo::boxed::Box;
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
|
@ -13,7 +12,7 @@ use std::iter::Peekable;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Parser<'code, 'ast, I>
|
struct Parser<'code, 'ast, I>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = Result<Token<'code>, LexError>>,
|
I: Iterator<Item = Result<Token<'code>, CompilerError>>,
|
||||||
I: 'code,
|
I: 'code,
|
||||||
{
|
{
|
||||||
tokens: Peekable<I>,
|
tokens: Peekable<I>,
|
||||||
|
|
@ -24,7 +23,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse<'ast, 'code>(
|
pub fn parse<'ast, 'code>(
|
||||||
tokens: impl Iterator<Item = Result<Token<'code>, LexError>> + 'code,
|
tokens: impl Iterator<Item = Result<Token<'code>, CompilerError>> + 'code,
|
||||||
ast_bump: &'ast Bump,
|
ast_bump: &'ast Bump,
|
||||||
) -> Result<Program<'ast>, CompilerError> {
|
) -> Result<Program<'ast>, CompilerError> {
|
||||||
let mut parser = Parser {
|
let mut parser = Parser {
|
||||||
|
|
@ -74,7 +73,7 @@ macro_rules! enter_parse {
|
||||||
|
|
||||||
impl<'code, 'ast, I> Parser<'code, 'ast, I>
|
impl<'code, 'ast, I> Parser<'code, 'ast, I>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = Result<Token<'code>, LexError>>,
|
I: Iterator<Item = Result<Token<'code>, CompilerError>>,
|
||||||
I: 'code,
|
I: 'code,
|
||||||
{
|
{
|
||||||
const MAX_DEPTH: usize = 100;
|
const MAX_DEPTH: usize = 100;
|
||||||
|
|
@ -642,7 +641,7 @@ where
|
||||||
fn next(&mut self) -> ParseResult<'code, Option<Token<'code>>> {
|
fn next(&mut self) -> ParseResult<'code, Option<Token<'code>>> {
|
||||||
match self.tokens.next() {
|
match self.tokens.next() {
|
||||||
Some(Ok(t)) => Ok(Some(t)),
|
Some(Ok(t)) => Ok(Some(t)),
|
||||||
Some(Err(t)) => Err(t.into()),
|
Some(Err(comp_err)) => Err(ParseErr::LexError(comp_err)),
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -650,7 +649,7 @@ where
|
||||||
fn peek(&mut self) -> ParseResult<'code, Option<&Token<'code>>> {
|
fn peek(&mut self) -> ParseResult<'code, Option<&Token<'code>>> {
|
||||||
match self.tokens.peek() {
|
match self.tokens.peek() {
|
||||||
Some(Ok(t)) => Ok(Some(t)),
|
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),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -687,13 +686,7 @@ pub enum ParseErr<'code> {
|
||||||
InvalidTokenPrimary(Token<'code>),
|
InvalidTokenPrimary(Token<'code>),
|
||||||
EofExpecting(TokenType<'code>),
|
EofExpecting(TokenType<'code>),
|
||||||
Eof(&'static str),
|
Eof(&'static str),
|
||||||
LexError(LexError),
|
LexError(CompilerError),
|
||||||
}
|
|
||||||
|
|
||||||
impl From<LexError> for ParseErr<'_> {
|
|
||||||
fn from(err: LexError) -> Self {
|
|
||||||
Self::LexError(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: remove this and ParseErr
|
// todo: remove this and ParseErr
|
||||||
|
|
@ -729,10 +722,10 @@ impl From<ParseErr<'_>> for CompilerError {
|
||||||
ParseErr::BreakOutsideLoop(_) => "break used outside of loop".to_string(),
|
ParseErr::BreakOutsideLoop(_) => "break used outside of loop".to_string(),
|
||||||
ParseErr::ReturnOutsideFunction(_) => "return used outside of function".to_string(),
|
ParseErr::ReturnOutsideFunction(_) => "return used outside of function".to_string(),
|
||||||
ParseErr::MaxDepth(_) => "reached maximal nesting depth".to_string(),
|
ParseErr::MaxDepth(_) => "reached maximal nesting depth".to_string(),
|
||||||
ParseErr::LexError(err) => err.message(),
|
ParseErr::LexError(err) => err.message.clone(),
|
||||||
},
|
},
|
||||||
note: match error {
|
note: match error {
|
||||||
ParseErr::LexError(err) => err.note(),
|
ParseErr::LexError(err) => err.note.clone(),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::errors::Span;
|
use crate::errors::{CompilerError, Span};
|
||||||
use crate::parse::Parser;
|
use crate::parse::Parser;
|
||||||
use crate::LexError;
|
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
|
|
||||||
|
|
@ -23,12 +22,12 @@ fn token(kind: TokenType) -> Token {
|
||||||
fn parser<'ast>(
|
fn parser<'ast>(
|
||||||
tokens: std::vec::Vec<Token>,
|
tokens: std::vec::Vec<Token>,
|
||||||
alloc: &'ast Bump,
|
alloc: &'ast Bump,
|
||||||
) -> Parser<'static, 'ast, std::vec::IntoIter<Result<Token, LexError>>>
|
) -> Parser<'static, 'ast, std::vec::IntoIter<Result<Token, CompilerError>>>
|
||||||
where {
|
where {
|
||||||
let tokens = tokens
|
let tokens = tokens
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(Ok)
|
.map(Ok)
|
||||||
.collect::<Vec<Result<Token, LexError>>>();
|
.collect::<Vec<Result<Token, CompilerError>>>();
|
||||||
|
|
||||||
Parser {
|
Parser {
|
||||||
tokens: tokens.into_iter().peekable(),
|
tokens: tokens.into_iter().peekable(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue