Refactoring
This commit is contained in:
parent
5b0263c89f
commit
8b967efda7
3 changed files with 41 additions and 25 deletions
|
@ -4,17 +4,34 @@ use std::error::Error;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LexingError {
|
pub struct LexingError {
|
||||||
pub line: usize,
|
pub line: usize,
|
||||||
pub msg: String,
|
pub kind: LexingErrorKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for LexingError {
|
impl fmt::Display for LexingError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "Error on line: {}", self.line)
|
write!(f, "Error: {}\n on line: {}", self.kind, self.line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for LexingError {
|
impl Error for LexingError {
|
||||||
fn description(&self) -> &str {
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
&self.msg
|
Some(&self.kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum LexingErrorKind {
|
||||||
|
UnmatchedQuote,
|
||||||
|
UnexpectedCharacter(char),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for LexingErrorKind {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
LexingErrorKind::UnmatchedQuote => write!(f, "Unmatched \" character"),
|
||||||
|
LexingErrorKind::UnexpectedCharacter(c) => write!(f, "Unexpected character {c}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for LexingErrorKind {}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::str::Chars;
|
||||||
|
|
||||||
pub use error::LexingError;
|
pub use error::LexingError;
|
||||||
|
|
||||||
|
use self::error::LexingErrorKind;
|
||||||
use self::token::Token;
|
use self::token::Token;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -101,14 +102,18 @@ impl<'a> Lexer<'a> {
|
||||||
token::TokenType::Greater,
|
token::TokenType::Greater,
|
||||||
),
|
),
|
||||||
'"' => {
|
'"' => {
|
||||||
let mut string = String::with_capacity(128);
|
let mut string = String::new();
|
||||||
let unmatched_char_error = Some(Err(LexingError {
|
let unmatched_char_error = Some(Err(LexingError {
|
||||||
line: self.line,
|
line: self.line,
|
||||||
msg: "Unmatched \" character".to_string(),
|
kind: LexingErrorKind::UnmatchedQuote,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.source_iter.next() {
|
let next_char = self.source_iter.next();
|
||||||
|
if let Some('\n') = next_char {
|
||||||
|
self.line+=1;
|
||||||
|
}
|
||||||
|
match next_char {
|
||||||
Some('"') => break,
|
Some('"') => break,
|
||||||
Some('\\') => match self.source_iter.next() {
|
Some('\\') => match self.source_iter.next() {
|
||||||
Some(c) => string.push(c),
|
Some(c) => string.push(c),
|
||||||
|
@ -120,21 +125,16 @@ impl<'a> Lexer<'a> {
|
||||||
}
|
}
|
||||||
self.get_token(token::TokenType::String(string))
|
self.get_token(token::TokenType::String(string))
|
||||||
}
|
}
|
||||||
c@'0'..='9' => {
|
c @ '0'..='9' => {
|
||||||
let mut num: i64 = c.to_digit(10).unwrap() as i64;
|
let mut num: i64 = c.to_digit(10).unwrap() as i64;
|
||||||
while let Some(c) = self.source_iter.peek() {
|
while let Some(c) = self.source_iter.next_if(|c| c.is_digit(10)) {
|
||||||
match c {
|
num *= 10;
|
||||||
c@'0'..='9' => {
|
num += c.to_digit(10).unwrap() as i64;
|
||||||
num *= 10;
|
|
||||||
num += c.to_digit(10).unwrap() as i64;
|
|
||||||
},
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.get_token(token::TokenType::Int(num))
|
self.get_token(token::TokenType::Int(num))
|
||||||
},
|
}
|
||||||
c@'a'..='z' | c@'A'..='Z' => {
|
c @ 'a'..='z' | c @ 'A'..='Z' => {
|
||||||
let mut identifier = String::with_capacity(128);
|
let mut identifier = String::new();
|
||||||
identifier.push(c);
|
identifier.push(c);
|
||||||
while let Some(c) = self.source_iter.next_if(|c| c.is_alphanumeric()) {
|
while let Some(c) = self.source_iter.next_if(|c| c.is_alphanumeric()) {
|
||||||
identifier.push(c);
|
identifier.push(c);
|
||||||
|
@ -154,10 +154,9 @@ impl<'a> Lexer<'a> {
|
||||||
"let" => token::TokenType::Let,
|
"let" => token::TokenType::Let,
|
||||||
"While" => token::TokenType::While,
|
"While" => token::TokenType::While,
|
||||||
"or" => token::TokenType::Or,
|
"or" => token::TokenType::Or,
|
||||||
_ => token::TokenType::Identifier(identifier)
|
_ => token::TokenType::Identifier(identifier),
|
||||||
|
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
// Ignore whitespace
|
// Ignore whitespace
|
||||||
' ' | '\r' | '\t' => return None,
|
' ' | '\r' | '\t' => return None,
|
||||||
'\n' => {
|
'\n' => {
|
||||||
|
@ -167,7 +166,7 @@ impl<'a> Lexer<'a> {
|
||||||
c => {
|
c => {
|
||||||
return Some(Err(LexingError {
|
return Some(Err(LexingError {
|
||||||
line: self.line,
|
line: self.line,
|
||||||
msg: format!("Unexpected character: {c}"),
|
kind: LexingErrorKind::UnexpectedCharacter(c),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -12,7 +12,7 @@ fn run_file(file: &path::Path) -> Result<(), io::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_repl() {
|
fn run_repl() {
|
||||||
let mut line_buf = String::with_capacity(1024);
|
let mut line_buf = String::new();
|
||||||
loop {
|
loop {
|
||||||
match io::stdin().read_line(&mut line_buf) {
|
match io::stdin().read_line(&mut line_buf) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
|
Loading…
Reference in a new issue