improve error system
There is a generic error interface now that will be used throughout the codebase.
This commit is contained in:
parent
73d1e8aede
commit
ba5c561c0e
3 changed files with 80 additions and 27 deletions
66
src/error.rs
Normal file
66
src/error.rs
Normal 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"
|
||||
}
|
||||
}
|
|
@ -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
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue