Improve lexer errors a little
This commit is contained in:
parent
2bba8dc429
commit
0fd1af9c8d
@ -20,7 +20,8 @@ mod parser;
|
|||||||
// * Overloading
|
// * Overloading
|
||||||
// * How it works
|
// * How it works
|
||||||
// * Arity to 10?
|
// * Arity to 10?
|
||||||
// * Better error handling in lexer
|
// * Vectors
|
||||||
|
// * Errors with positions?
|
||||||
// * Remove empty box values?
|
// * Remove empty box values?
|
||||||
|
|
||||||
fn showit<T: Display>(x: &mut T) -> () {
|
fn showit<T: Display>(x: &mut T) -> () {
|
||||||
|
@ -5,6 +5,34 @@ use std::iter::Peekable;
|
|||||||
use std::str::Chars;
|
use std::str::Chars;
|
||||||
use std::char;
|
use std::char;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum LexError {
|
||||||
|
UnexpectedChar,
|
||||||
|
MalformedEscapeSequence,
|
||||||
|
MalformedNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for LexError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
LexError::UnexpectedChar => "Unexpected character in input",
|
||||||
|
LexError::MalformedEscapeSequence => "Unexpected values in escape sequence",
|
||||||
|
LexError::MalformedNumber => "Unexpected characters in number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cause(&self) -> Option<&Error> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for LexError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.description())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
BadInput,
|
BadInput,
|
||||||
@ -66,7 +94,8 @@ pub enum Expr { IntConst(i32), Identifier(String), StringConst(String), FnCall(S
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Token { IntConst(i32), Identifier(String), StringConst(String), LCurly, RCurly, LParen, RParen, LSquare, RSquare,
|
pub enum Token { IntConst(i32), Identifier(String), StringConst(String), LCurly, RCurly, LParen, RParen, LSquare, RSquare,
|
||||||
Plus, Minus, Multiply, Divide, Semicolon, Colon, Comma, Period, Equals, True, False, Var, If, While,
|
Plus, Minus, Multiply, Divide, Semicolon, Colon, Comma, Period, Equals, True, False, Var, If, While,
|
||||||
LessThan, GreaterThan, Bang, LessThanEqual, GreaterThanEqual, EqualTo, NotEqualTo, Pipe, Or, Ampersand, And, Fn }
|
LessThan, GreaterThan, Bang, LessThanEqual, GreaterThanEqual, EqualTo, NotEqualTo, Pipe, Or, Ampersand, And, Fn,
|
||||||
|
LexErr(LexError) }
|
||||||
|
|
||||||
pub struct TokenIterator<'a> {
|
pub struct TokenIterator<'a> {
|
||||||
char_stream: Peekable<Chars<'a>>
|
char_stream: Peekable<Chars<'a>>
|
||||||
@ -94,7 +123,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
if let Ok(val) = out.parse::<i32>() {
|
if let Ok(val) = out.parse::<i32>() {
|
||||||
return Some(Token::IntConst(val));
|
return Some(Token::IntConst(val));
|
||||||
}
|
}
|
||||||
return None;
|
return Some(Token::LexErr(LexError::MalformedNumber));
|
||||||
},
|
},
|
||||||
'A'...'Z' | 'a'...'z' | '_' => {
|
'A'...'Z' | 'a'...'z' | '_' => {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
@ -140,6 +169,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
match nxt {
|
match nxt {
|
||||||
'"' if !escape => break,
|
'"' if !escape => break,
|
||||||
'\\' if !escape => escape = true,
|
'\\' if !escape => escape = true,
|
||||||
|
'\\' if escape => {escape = false; result.push('\\'); },
|
||||||
't' if escape => {escape = false; result.push('\t'); },
|
't' if escape => {escape = false; result.push('\t'); },
|
||||||
'n' if escape => {escape = false; result.push('\n'); },
|
'n' if escape => {escape = false; result.push('\n'); },
|
||||||
'r' if escape => {escape = false; result.push('\r'); },
|
'r' if escape => {escape = false; result.push('\r'); },
|
||||||
@ -153,11 +183,11 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
out_val += d1;
|
out_val += d1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println!("Warning: unexpected character in escaped value")
|
return Some(Token::LexErr(LexError::MalformedEscapeSequence));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println!("Warning: unexpected character in escaped value")
|
return Some(Token::LexErr(LexError::MalformedEscapeSequence));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +195,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
result.push(r);
|
result.push(r);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println!("Warning: unexpected character in escaped value")
|
return Some(Token::LexErr(LexError::MalformedEscapeSequence));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'u' if escape => {
|
'u' if escape => {
|
||||||
@ -178,11 +208,11 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
out_val += d1;
|
out_val += d1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println!("Warning: unexpected character in escaped value")
|
return Some(Token::LexErr(LexError::MalformedEscapeSequence));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println!("Warning: unexpected character in escaped value")
|
return Some(Token::LexErr(LexError::MalformedEscapeSequence));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +220,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
result.push(r);
|
result.push(r);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println!("Warning: unexpected character in escaped value")
|
return Some(Token::LexErr(LexError::MalformedEscapeSequence));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'U' if escape => {
|
'U' if escape => {
|
||||||
@ -203,11 +233,11 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
out_val += d1;
|
out_val += d1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println!("Warning: unexpected character in escaped value")
|
return Some(Token::LexErr(LexError::MalformedEscapeSequence));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println!("Warning: unexpected character in escaped value")
|
return Some(Token::LexErr(LexError::MalformedEscapeSequence));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,9 +245,10 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
result.push(r);
|
result.push(r);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println!("Warning: unexpected character in escaped value")
|
return Some(Token::LexErr(LexError::MalformedEscapeSequence));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ if escape => return Some(Token::LexErr(LexError::MalformedEscapeSequence)),
|
||||||
_ => { escape = false; result.push(nxt); },
|
_ => { escape = false; result.push(nxt); },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,7 +307,7 @@ impl<'a> Iterator for TokenIterator<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
' ' | '\n' | '\r' => (),
|
' ' | '\n' | '\r' => (),
|
||||||
_ => return None
|
_ => return Some(Token::LexErr(LexError::UnexpectedChar))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,6 +414,7 @@ fn parse_primary<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Expr, Pa
|
|||||||
Token::LParen => {parse_paren_expr(input)},
|
Token::LParen => {parse_paren_expr(input)},
|
||||||
Token::True => {Ok(Expr::True)},
|
Token::True => {Ok(Expr::True)},
|
||||||
Token::False => {Ok(Expr::False)},
|
Token::False => {Ok(Expr::False)},
|
||||||
|
Token::LexErr(le) => {println!("Error: {}", le); Err(ParseError::BadInput)}
|
||||||
_ => {println!("Can't parse: {:?}", token); Err(ParseError::BadInput)}
|
_ => {println!("Can't parse: {:?}", token); Err(ParseError::BadInput)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user