[lexer] Replace String error messages with Error type

This commit is contained in:
Eryn Wells 2018-09-03 15:30:48 -07:00
parent def35966eb
commit dc8f5a7686
7 changed files with 33 additions and 43 deletions

View file

@ -62,7 +62,7 @@ impl<T> Iterator for Lexer<T> where T: Iterator<Item=char> {
out = Some(Ok(Lex::new(token, &buffer, self.line, self.offset))); out = Some(Ok(Lex::new(token, &buffer, self.line, self.offset)));
break; break;
}, },
Err(msg) => panic!("{}", msg) Err(err) => panic!("{}:{}: {}", self.line, self.offset, err.msg())
}, },
Some(c) => { Some(c) => {
let result = state.lex(c); let result = state.lex(c);
@ -84,8 +84,8 @@ impl<T> Iterator for Lexer<T> where T: Iterator<Item=char> {
out = Some(Ok(Lex::new(token, &buffer, self.line, self.offset))); out = Some(Ok(Lex::new(token, &buffer, self.line, self.offset)));
break; break;
}, },
StateResult::Fail { msg } => { StateResult::Fail(err) => {
panic!("{}", msg); panic!("{}:{}: {}", self.line, self.offset, err.msg());
} }
} }
}, },

View file

@ -3,6 +3,7 @@
*/ */
use chars::Lexable; use chars::Lexable;
use error::Error;
use token::Token; use token::Token;
use states::{Resume, State, StateResult}; use states::{Resume, State, StateResult};
use states::id::IdSub; use states::id::IdSub;
@ -20,14 +21,11 @@ impl State for Begin {
c if c.is_whitespace() => StateResult::Continue, c if c.is_whitespace() => StateResult::Continue,
c if c.is_identifier_initial() => StateResult::Advance { to: Box::new(IdSub{}) }, c if c.is_identifier_initial() => StateResult::Advance { to: Box::new(IdSub{}) },
c if c.is_hash() => StateResult::Advance { to: Box::new(Hash::new()) }, c if c.is_hash() => StateResult::Advance { to: Box::new(Hash::new()) },
_ => { _ => StateResult::fail(Error::invalid_char(c)),
let msg = format!("Invalid character: {}", c);
StateResult::Fail { msg }
}
} }
} }
fn none(&mut self) -> Result<Option<Token>, String> { fn none(&mut self) -> Result<Option<Token>, Error> {
Ok(None) Ok(None)
} }
} }

View file

@ -2,6 +2,7 @@
* Eryn Wells <eryn@erynwells.me> * Eryn Wells <eryn@erynwells.me>
*/ */
use error::Error;
use chars::Lexable; use chars::Lexable;
use states::{Resume, State, StateResult}; use states::{Resume, State, StateResult};
use token::Token; use token::Token;
@ -34,10 +35,7 @@ impl State for Bool {
match c { match c {
c if c.is_identifier_delimiter() => match self.handle_delimiter() { c if c.is_identifier_delimiter() => match self.handle_delimiter() {
Some(token) => StateResult::Emit(token, Resume::Here), Some(token) => StateResult::Emit(token, Resume::Here),
None => { None => StateResult::fail(Error::invalid_char(c)),
let msg = format!("Invalid character: {}", c);
StateResult::fail(msg.as_str())
},
}, },
_ => { _ => {
let buf = { let buf = {
@ -48,20 +46,16 @@ impl State for Bool {
if TRUE.starts_with(&buf) || FALSE.starts_with(&buf) { if TRUE.starts_with(&buf) || FALSE.starts_with(&buf) {
StateResult::advance(Box::new(Bool(buf))) StateResult::advance(Box::new(Bool(buf)))
} else { } else {
let msg = format!("Invalid character: {}", c); StateResult::fail(Error::invalid_char(c))
StateResult::fail(msg.as_str())
} }
}, },
} }
} }
fn none(&mut self) -> Result<Option<Token>, String> { fn none(&mut self) -> Result<Option<Token>, Error> {
match self.handle_delimiter() { match self.handle_delimiter() {
Some(token) => Ok(Some(token)), Some(token) => Ok(Some(token)),
None => { None => Err(Error::new("Found EOF while trying to parse a bool".to_string()))
let msg = format!("Found EOF while trying to parse a bool");
Err(msg)
}
} }
} }
} }

View file

@ -3,6 +3,7 @@
*/ */
use chars::Lexable; use chars::Lexable;
use error::Error;
use states::{State, StateResult}; use states::{State, StateResult};
use states::bool::Bool; use states::bool::Bool;
use states::number::Prefix; use states::number::Prefix;
@ -30,17 +31,14 @@ impl State for Hash {
if let Some(st) = Prefix::with_char(c) { if let Some(st) = Prefix::with_char(c) {
StateResult::advance(Box::new(st)) StateResult::advance(Box::new(st))
} else { } else {
StateResult::fail(format!("invalid numeric prefix character: {}", c).as_str()) StateResult::fail(Error::new(format!("invalid numeric prefix character: {}", c)))
} }
}, },
_ => { _ => StateResult::fail(Error::invalid_char(c)),
let msg = format!("Invalid character: {}", c);
StateResult::fail(msg.as_str())
},
} }
} }
fn none(&mut self) -> Result<Option<Token>, String> { fn none(&mut self) -> Result<Option<Token>, Error> {
Ok(None) Ok(None)
} }
} }

View file

@ -3,6 +3,7 @@
*/ */
use chars::Lexable; use chars::Lexable;
use error::Error;
use states::{Resume, State, StateResult}; use states::{Resume, State, StateResult};
use token::Token; use token::Token;
@ -14,14 +15,11 @@ impl State for IdSub {
match c { match c {
c if c.is_identifier_subsequent() => StateResult::Continue, c if c.is_identifier_subsequent() => StateResult::Continue,
c if c.is_identifier_delimiter() => StateResult::Emit(Token::Id, Resume::Here), c if c.is_identifier_delimiter() => StateResult::Emit(Token::Id, Resume::Here),
_ => { _ => StateResult::fail(Error::invalid_char(c)),
let msg = format!("Invalid character: {}", c);
StateResult::Fail { msg }
}
} }
} }
fn none(&mut self) -> Result<Option<Token>, String> { fn none(&mut self) -> Result<Option<Token>, Error> {
Ok(Some(Token::Id)) Ok(Some(Token::Id))
} }
} }

View file

@ -3,6 +3,7 @@
*/ */
use std::fmt::Debug; use std::fmt::Debug;
use error::Error;
use token::Token; use token::Token;
mod begin; mod begin;
@ -22,7 +23,7 @@ pub enum StateResult {
/// Emit a Lex with the provided Token and the accumulated buffer. The Resume value indicates /// Emit a Lex with the provided Token and the accumulated buffer. The Resume value indicates
/// whether to revisit the current input character or advance to the next one. /// whether to revisit the current input character or advance to the next one.
Emit(Token, Resume), Emit(Token, Resume),
Fail { msg: String } Fail(Error)
} }
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
@ -35,7 +36,7 @@ pub enum Resume {
pub trait State: Debug { pub trait State: Debug {
fn lex(&mut self, c: char) -> StateResult; fn lex(&mut self, c: char) -> StateResult;
fn none(&mut self) -> Result<Option<Token>, String>; fn none(&mut self) -> Result<Option<Token>, Error>;
} }
impl StateResult { impl StateResult {
@ -47,7 +48,7 @@ impl StateResult {
StateResult::Emit(token, at) StateResult::Emit(token, at)
} }
pub fn fail(msg: &str) -> StateResult { pub fn fail(err: Error) -> StateResult {
StateResult::Fail { msg: msg.to_string() } StateResult::Fail(err)
} }
} }

View file

@ -2,8 +2,9 @@
* Eryn Wells <eryn@erynwells.me> * Eryn Wells <eryn@erynwells.me>
*/ */
use super::{Radix, Exact}; use error::Error;
use states::{State, StateResult}; use states::{State, StateResult};
use states::number::{Radix, Exact};
use states::number::Builder; use states::number::Builder;
use token::Token; use token::Token;
@ -32,12 +33,12 @@ impl State for Prefix {
fn lex(&mut self, c: char) -> StateResult { fn lex(&mut self, c: char) -> StateResult {
match c { match c {
'#' => StateResult::advance(Box::new(Hash(self.0))), '#' => StateResult::advance(Box::new(Hash(self.0))),
_ => StateResult::fail(format!("invalid char: {}", c).as_str()) _ => StateResult::fail(Error::invalid_char(c))
} }
} }
fn none(&mut self) -> Result<Option<Token>, String> { fn none(&mut self) -> Result<Option<Token>, Error> {
Err("blah".to_string()) Err(Error::new("blah".to_string()))
} }
} }
@ -48,21 +49,21 @@ impl State for Hash {
self.0.push_exact(ex); self.0.push_exact(ex);
StateResult::advance(Box::new(Prefix::new(self.0))) StateResult::advance(Box::new(Prefix::new(self.0)))
} else { } else {
StateResult::fail(format!("invalid char: {}", c).as_str()) StateResult::fail(Error::invalid_char(c))
} }
} else if let Some(rx) = Radix::from(c) { } else if let Some(rx) = Radix::from(c) {
if !self.0.seen_radix() { if !self.0.seen_radix() {
self.0.push_radix(rx); self.0.push_radix(rx);
StateResult::advance(Box::new(Prefix::new(self.0))) StateResult::advance(Box::new(Prefix::new(self.0)))
} else { } else {
StateResult::fail(format!("invalid char: {}", c).as_str()) StateResult::fail(Error::invalid_char(c))
} }
} else { } else {
StateResult::fail(format!("invalid char: {}", c).as_str()) StateResult::fail(Error::invalid_char(c))
} }
} }
fn none(&mut self) -> Result<Option<Token>, String> { fn none(&mut self) -> Result<Option<Token>, Error> {
Err("blah".to_string()) Err(Error::new("blah".to_string()))
} }
} }