improve error system

There is a generic error interface now that will
be used throughout the codebase.
This commit is contained in:
anna 2022-07-14 13:01:39 +02:00
parent 73d1e8aede
commit ba5c561c0e
Signed by: fef
GPG key ID: EC22E476DC2D3D84
3 changed files with 80 additions and 27 deletions

66
src/error.rs Normal file
View file

@ -0,0 +1,66 @@
use std::fmt;
use std::fmt::Formatter;
/// Anything that can go wrong while compiling and executing the build script.
pub trait Error {
/// Name of the file that the error originated from.
fn file(&self) -> &String;
/// Line (starting from 1) of the first erroneous character.
fn line(&self) -> usize;
/// Column (starting from 1) of the first erroneous character.
fn col(&self) -> usize;
/// Human readable error message.
fn msg(&self) -> &String;
/// Human readable error name (mostly for internal use; see the `fmt::Display` impl).
fn name(&self) -> &str;
}
#[derive(Debug)]
struct Position {
file: String,
line: usize,
col: usize,
}
#[derive(Debug)]
pub struct SyntaxError {
pos: Position,
msg: String,
}
impl fmt::Display for dyn Error {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{} in {}:{}:{}: {}", self.name(), self.file(), self.line(), self.col(), self.msg())
}
}
impl SyntaxError {
pub fn new(file: String, line: usize, col: usize, msg: String) -> SyntaxError {
SyntaxError {
pos: Position { file, line, col },
msg,
}
}
}
impl Error for SyntaxError {
fn file(&self) -> &String {
&self.pos.file
}
fn line(&self) -> usize {
self.pos.line
}
fn col(&self) -> usize {
self.pos.col
}
fn msg(&self) -> &String {
&self.msg
}
fn name(&self) -> &str {
"SyntaxError"
}
}

View file

@ -1,4 +1,3 @@
use std::fmt;
use std::str::Chars;
mod cursor;
@ -7,7 +6,10 @@ use cursor::Cursor;
pub(crate) mod token;
use token::Token;
use crate::error::SyntaxError;
pub struct Lexer<'a> {
file: String,
cursor: Cursor<'a>,
history: Vec<Token>,
offset: usize,
@ -89,8 +91,9 @@ impl Iterator for Lexer<'_> {
}
impl<'a> Lexer<'a> {
pub fn new(stream: Chars<'a>) -> Lexer<'a> {
pub fn new(file: String, stream: Chars<'a>) -> Lexer<'a> {
Lexer {
file,
cursor: Cursor::new(stream),
history: Vec::new(),
offset: 0,
@ -244,29 +247,11 @@ impl<'a> Lexer<'a> {
}
fn syntax_error<T>(&mut self, msg: String) -> Result<T, SyntaxError> {
Err(SyntaxError {
line: self.cursor.line(),
col: self.cursor.col(),
msg,
})
}
}
#[derive(Debug)]
pub struct SyntaxError {
pub line: usize,
pub col: usize,
pub msg: String,
}
impl fmt::Display for SyntaxError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"SyntaxError in {}:{}: {}",
self.line,
self.col,
self.msg.as_str()
)
Err(SyntaxError::new(
self.file.clone(),
self.cursor.line(),
self.cursor.col(),
msg
))
}
}

View file

@ -3,9 +3,11 @@ use std::fs;
mod lex;
use lex::Lexer;
mod error;
fn main() {
let s = fs::read_to_string("test.gaybuild").unwrap();
let lexer = Lexer::new(s.chars());
let lexer = Lexer::new(String::from("test.gaybuild"), s.chars());
for token in lexer {
println!("{}", token.unwrap());
}