mirror of
https://github.com/Noratrieb/dilaria.git
synced 2026-01-16 10:25:02 +01:00
error tokens instead of result
This commit is contained in:
parent
5ae747d513
commit
11b735d728
3 changed files with 49 additions and 36 deletions
|
|
@ -62,7 +62,7 @@ mod span {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct CompilerError {
|
pub struct CompilerError {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub message: String,
|
pub message: String,
|
||||||
|
|
|
||||||
75
src/lex.rs
75
src/lex.rs
|
|
@ -95,6 +95,9 @@ pub enum TokenType<'code> {
|
||||||
GreaterEqual,
|
GreaterEqual,
|
||||||
/// <=
|
/// <=
|
||||||
LessEqual,
|
LessEqual,
|
||||||
|
|
||||||
|
/// An error occurred
|
||||||
|
Error(CompilerError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -141,7 +144,7 @@ impl<'code> Lexer<'code> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'code> Iterator for Lexer<'code> {
|
impl<'code> Iterator for Lexer<'code> {
|
||||||
type Item = Result<Token<'code>, CompilerError>;
|
type Item = Token<'code>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let token = loop {
|
let token = loop {
|
||||||
|
|
@ -190,18 +193,18 @@ impl<'code> Iterator for Lexer<'code> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
'!' => {
|
'!' => {
|
||||||
if self.expect('=') {
|
break if self.expect('=') {
|
||||||
let _ = self.code.next(); // consume =;
|
let _ = self.code.next(); // consume =;
|
||||||
break Token {
|
Token::new(Span::start_len(start, start + 2), TokenType::BangEqual)
|
||||||
span: Span::start_len(start, start + 2),
|
|
||||||
kind: TokenType::BangEqual,
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
return Some(Err(CompilerError::with_note(
|
Token::new(
|
||||||
Span::single(start),
|
Span::single(start),
|
||||||
"Expected '=' after '!'".to_string(),
|
TokenType::Error(CompilerError::with_note(
|
||||||
"If you meant to use it for negation, use `not`".to_string(),
|
Span::single(start),
|
||||||
)));
|
"Expected '=' after '!'".to_string(),
|
||||||
|
"If you meant to use it for negation, use `not`".to_string(),
|
||||||
|
)),
|
||||||
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
'>' => {
|
'>' => {
|
||||||
|
|
@ -227,11 +230,14 @@ impl<'code> Iterator for Lexer<'code> {
|
||||||
buffer.push(char);
|
buffer.push(char);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return Some(Err(CompilerError::with_note(
|
return Some(Token::new(
|
||||||
Span::single(start), // no not show the whole literal, this does not make sense
|
Span::single(start),
|
||||||
"String literal not closed".to_string(),
|
TokenType::Error(CompilerError::with_note(
|
||||||
"Close the literal using '\"'".to_string(),
|
Span::single(start), // no not show the whole literal, this does not make sense
|
||||||
)));
|
"String literal not closed".to_string(),
|
||||||
|
"Close the literal using '\"'".to_string(),
|
||||||
|
)),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -256,25 +262,23 @@ 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.parse::<f64>().map_err(|err| {
|
let number = number_str.parse::<f64>();
|
||||||
CompilerError::with_note(
|
break match number {
|
||||||
span,
|
|
||||||
"Invalid number".to_string(),
|
|
||||||
err.to_string(),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
match number {
|
|
||||||
Ok(number) if number.is_infinite() => {
|
Ok(number) if number.is_infinite() => {
|
||||||
return Some(Err(CompilerError::with_note(
|
Token::new(span, TokenType::Error(CompilerError::with_note(
|
||||||
span,
|
span,
|
||||||
"Number literal too long".to_string(),
|
"Number literal too long".to_string(),
|
||||||
"A number literal cannot be larger than a 64 bit float can represent"
|
"A number literal cannot be larger than a 64 bit float can represent"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
Ok(number) => break Token::new(span, TokenType::Number(number)),
|
Ok(number) => Token::new(span, TokenType::Number(number)),
|
||||||
Err(err) => return Some(Err(err)),
|
Err(err) => Token::new(span, TokenType::Error(CompilerError::with_note(
|
||||||
}
|
span,
|
||||||
|
"Invalid number".to_string(),
|
||||||
|
err.to_string(),
|
||||||
|
))),
|
||||||
|
};
|
||||||
} else if is_valid_ident_start(char) {
|
} else if is_valid_ident_start(char) {
|
||||||
// it must be an identifier
|
// it must be an identifier
|
||||||
let end = loop {
|
let end = loop {
|
||||||
|
|
@ -291,18 +295,21 @@ 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(CompilerError::with_note(
|
break Token::new(
|
||||||
Span::single(start),
|
Span::single(start),
|
||||||
format!("Unexpected character: '{}'", char),
|
TokenType::Error(CompilerError::with_note(
|
||||||
"Character is not allowed outside of string literals and comments"
|
Span::single(start),
|
||||||
.to_string(),
|
format!("Unexpected character: '{}'", char),
|
||||||
)));
|
"Character is not allowed outside of string literals and comments"
|
||||||
|
.to_string(),
|
||||||
|
)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(Ok(token))
|
Some(token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -345,7 +352,7 @@ mod test {
|
||||||
|
|
||||||
fn lex_types(str: &str) -> Vec<TokenType> {
|
fn lex_types(str: &str) -> Vec<TokenType> {
|
||||||
let lexer = Lexer::new(str);
|
let lexer = Lexer::new(str);
|
||||||
lexer.map(|token| token.unwrap().kind).collect::<Vec<_>>()
|
lexer.map(|token| token.kind).collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lex_test(code: &str, expected: Vec<TokenType>) {
|
fn lex_test(code: &str, expected: Vec<TokenType>) {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,13 @@ pub fn run_program(program: &str) {
|
||||||
let ast_alloc = Bump::new();
|
let ast_alloc = Bump::new();
|
||||||
|
|
||||||
let lexer = lex::Lexer::new(program);
|
let lexer = lex::Lexer::new(program);
|
||||||
let ast = parse::parse(lexer, &ast_alloc);
|
let ast = parse::parse(
|
||||||
|
lexer.map(|token| match &token.kind {
|
||||||
|
TokenType::Error(err) => Err(err.clone()),
|
||||||
|
_ => Ok(token),
|
||||||
|
}),
|
||||||
|
&ast_alloc,
|
||||||
|
);
|
||||||
|
|
||||||
match ast {
|
match ast {
|
||||||
Ok(ast) => process_ast(program, ast),
|
Ok(ast) => process_ast(program, ast),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue