From 0fd1af9c8d565a21e6105e4e10eaa3566ce13919 Mon Sep 17 00:00:00 2001 From: jonathandturner Date: Wed, 2 Mar 2016 09:16:36 -0500 Subject: [PATCH] Improve lexer errors a little --- src/main.rs | 3 ++- src/parser.rs | 56 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index 174257db..80fa76af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,8 @@ mod parser; // * Overloading // * How it works // * Arity to 10? -// * Better error handling in lexer +// * Vectors +// * Errors with positions? // * Remove empty box values? fn showit(x: &mut T) -> () { diff --git a/src/parser.rs b/src/parser.rs index 32194411..9e3e5d84 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -5,6 +5,34 @@ use std::iter::Peekable; use std::str::Chars; 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)] pub enum ParseError { BadInput, @@ -66,7 +94,8 @@ pub enum Expr { IntConst(i32), Identifier(String), StringConst(String), FnCall(S #[derive(Debug)] 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, - 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> { char_stream: Peekable> @@ -94,7 +123,7 @@ impl<'a> Iterator for TokenIterator<'a> { if let Ok(val) = out.parse::() { return Some(Token::IntConst(val)); } - return None; + return Some(Token::LexErr(LexError::MalformedNumber)); }, 'A'...'Z' | 'a'...'z' | '_' => { let mut result = Vec::new(); @@ -140,6 +169,7 @@ impl<'a> Iterator for TokenIterator<'a> { match nxt { '"' if !escape => break, '\\' if !escape => escape = true, + '\\' if escape => {escape = false; result.push('\\'); }, 't' if escape => {escape = false; result.push('\t'); }, 'n' if escape => {escape = false; result.push('\n'); }, 'r' if escape => {escape = false; result.push('\r'); }, @@ -153,11 +183,11 @@ impl<'a> Iterator for TokenIterator<'a> { out_val += d1; } else { - println!("Warning: unexpected character in escaped value") + return Some(Token::LexErr(LexError::MalformedEscapeSequence)); } } 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); } else { - println!("Warning: unexpected character in escaped value") + return Some(Token::LexErr(LexError::MalformedEscapeSequence)); } } 'u' if escape => { @@ -178,11 +208,11 @@ impl<'a> Iterator for TokenIterator<'a> { out_val += d1; } else { - println!("Warning: unexpected character in escaped value") + return Some(Token::LexErr(LexError::MalformedEscapeSequence)); } } 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); } else { - println!("Warning: unexpected character in escaped value") + return Some(Token::LexErr(LexError::MalformedEscapeSequence)); } } 'U' if escape => { @@ -203,11 +233,11 @@ impl<'a> Iterator for TokenIterator<'a> { out_val += d1; } else { - println!("Warning: unexpected character in escaped value") + return Some(Token::LexErr(LexError::MalformedEscapeSequence)); } } 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); } 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); }, } } @@ -276,7 +307,7 @@ impl<'a> Iterator for TokenIterator<'a> { } }, ' ' | '\n' | '\r' => (), - _ => return None + _ => return Some(Token::LexErr(LexError::UnexpectedChar)) } } @@ -383,6 +414,7 @@ fn parse_primary<'a>(input: &mut Peekable>) -> Result {parse_paren_expr(input)}, Token::True => {Ok(Expr::True)}, Token::False => {Ok(Expr::False)}, + Token::LexErr(le) => {println!("Error: {}", le); Err(ParseError::BadInput)} _ => {println!("Can't parse: {:?}", token); Err(ParseError::BadInput)} } }