clippy pedantic refactoring

This commit is contained in:
Theis Pieter Hollebeek 2023-01-20 13:20:13 +01:00
parent 94837aad7c
commit 2762361968

View File

@ -1,17 +1,17 @@
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum LexerErrorType { pub enum ErrorType {
UnexpectedToken(char), UnexpectedToken(char),
InvalidConstructor, InvalidConstructor,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct LexerError { pub struct Error {
error: LexerErrorType, error: ErrorType,
line: isize, line: isize,
col: isize, col: isize,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum Token { pub enum Token {
Name(String), Name(String),
Id(String), Id(String),
@ -45,7 +45,7 @@ enum Mode {
} }
impl Mode { impl Mode {
fn token_constructor(&self) -> Result<Box<dyn Fn(String) -> Token>, LexerErrorType> { fn token_constructor(&self) -> Result<Box<dyn Fn(String) -> Token>, ErrorType> {
match self { match self {
Mode::Name => Ok(Box::new(Token::Name)), Mode::Name => Ok(Box::new(Token::Name)),
Mode::Class => Ok(Box::new(Token::Class)), Mode::Class => Ok(Box::new(Token::Class)),
@ -54,43 +54,40 @@ impl Mode {
Mode::MlWhitespace => Ok(Box::new(Token::MlWhitespace)), Mode::MlWhitespace => Ok(Box::new(Token::MlWhitespace)),
Mode::SlComment => Ok(Box::new(Token::SlComment)), Mode::SlComment => Ok(Box::new(Token::SlComment)),
Mode::Id => Ok(Box::new(Token::Id)), Mode::Id => Ok(Box::new(Token::Id)),
Mode::EscapedString => Err(LexerErrorType::InvalidConstructor), Mode::EscapedString => Err(ErrorType::InvalidConstructor),
} }
} }
} }
#[allow(dead_code)] fn collect_into_token_and_push(
pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> { constructor: &dyn Fn(String) -> Token,
let mut tokens = Vec::new();
let mut value = Vec::new();
let mut iter = code.chars();
let mut mode = Mode::SlWhitespace;
let mut line = 0;
let mut col = 0;
let position_map = move |error: LexerErrorType| LexerError { error, line, col };
let collect_into_token_and_push =
|constructor: Box<dyn Fn(String) -> Token>,
tokens: &mut Vec<Token>, tokens: &mut Vec<Token>,
value: &mut Vec<char>| { value: &mut Vec<char>,
) {
let token = constructor(value.iter().collect()); let token = constructor(value.iter().collect());
tokens.push(token); tokens.push(token);
value.clear(); value.clear();
}; }
loop {
let current_char = match iter.next() { #[allow(dead_code)]
Some(c) => c, pub fn lexer(code_to_lex: &str) -> Result<Vec<Token>, Error> {
None => break, let mut tokens = Vec::new();
}; let mut value = Vec::new();
let mut mode = Mode::SlWhitespace;
let mut line = 0;
let mut col = 0;
let position_map = move |error: ErrorType| Error { error, line, col };
for current_char in code_to_lex.chars() {
match current_char { match current_char {
v @ '.' | v @ '#' => { v @ ('.' | '#') => {
match mode { match mode {
m @ Mode::Name m @ (Mode::Name
| m @ Mode::Class | Mode::Class
| m @ Mode::Id | Mode::Id
| m @ Mode::SlWhitespace | Mode::SlWhitespace
| m @ Mode::MlWhitespace => { | Mode::MlWhitespace) => {
collect_into_token_and_push( collect_into_token_and_push(
m.token_constructor().map_err(position_map)?, &m.token_constructor().map_err(position_map)?,
&mut tokens, &mut tokens,
&mut value, &mut value,
); );
@ -102,10 +99,10 @@ pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> {
} }
Mode::String | Mode::SlComment => {} Mode::String | Mode::SlComment => {}
Mode::EscapedString => { Mode::EscapedString => {
return Err(LexerError { return Err(Error {
line, line,
col, col,
error: LexerErrorType::UnexpectedToken('.'), error: ErrorType::UnexpectedToken('.'),
}) })
} }
}; };
@ -117,10 +114,10 @@ pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> {
mode = Mode::EscapedString; mode = Mode::EscapedString;
} }
_ => { _ => {
return Err(LexerError { return Err(Error {
line, line,
col, col,
error: LexerErrorType::UnexpectedToken('\\'), error: ErrorType::UnexpectedToken('\\'),
}) })
} }
}, },
@ -131,15 +128,15 @@ pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> {
value.push('"'); value.push('"');
collect_into_token_and_push( collect_into_token_and_push(
m.token_constructor().map_err(position_map)?, &m.token_constructor().map_err(position_map)?,
&mut tokens, &mut tokens,
&mut value, &mut value,
); );
} }
m @ Mode::SlWhitespace | m @ Mode::MlWhitespace => { m @ (Mode::SlWhitespace | Mode::MlWhitespace) => {
mode = Mode::String; mode = Mode::String;
collect_into_token_and_push( collect_into_token_and_push(
m.token_constructor().map_err(position_map)?, &m.token_constructor().map_err(position_map)?,
&mut tokens, &mut tokens,
&mut value, &mut value,
); );
@ -153,23 +150,23 @@ pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> {
value.push('"'); value.push('"');
} }
_ => { _ => {
return Err(LexerError { return Err(Error {
line, line,
col, col,
error: LexerErrorType::UnexpectedToken('"'), error: ErrorType::UnexpectedToken('"'),
}) })
} }
}; };
} }
v @ '{' | v @ '}' | v @ '[' | v @ ']' => match mode { v @ ('{' | '}' | '[' | ']') => match mode {
m @ Mode::Name m @ (Mode::Name
| m @ Mode::Class | Mode::Class
| m @ Mode::Id | Mode::Id
| m @ Mode::MlWhitespace | Mode::MlWhitespace
| m @ Mode::SlWhitespace => { | Mode::SlWhitespace) => {
collect_into_token_and_push( collect_into_token_and_push(
m.token_constructor().map_err(position_map)?, &m.token_constructor().map_err(position_map)?,
&mut tokens, &mut tokens,
&mut value, &mut value,
); );
@ -184,21 +181,21 @@ pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> {
tokens.push(constructor(String::from(v))); tokens.push(constructor(String::from(v)));
} }
Mode::EscapedString => { Mode::EscapedString => {
return Err(LexerError { return Err(Error {
line, line,
col, col,
error: LexerErrorType::UnexpectedToken(v), error: ErrorType::UnexpectedToken(v),
}) })
} }
Mode::String | Mode::SlComment => { Mode::String | Mode::SlComment => {
value.push(v); value.push(v);
} }
}, },
c @ ' ' | c @ '\r' => { c @ (' ' | '\r') => {
match mode { match mode {
m @ Mode::Name | m @ Mode::Class | m @ Mode::Id => { m @ (Mode::Name | Mode::Class | Mode::Id) => {
collect_into_token_and_push( collect_into_token_and_push(
m.token_constructor().map_err(position_map)?, &m.token_constructor().map_err(position_map)?,
&mut tokens, &mut tokens,
&mut value, &mut value,
); );
@ -206,10 +203,10 @@ pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> {
} }
Mode::String | Mode::SlComment | Mode::MlWhitespace | Mode::SlWhitespace => {} Mode::String | Mode::SlComment | Mode::MlWhitespace | Mode::SlWhitespace => {}
Mode::EscapedString => { Mode::EscapedString => {
return Err(LexerError { return Err(Error {
line, line,
col, col,
error: LexerErrorType::UnexpectedToken(c), error: ErrorType::UnexpectedToken(c),
}) })
} }
}; };
@ -217,9 +214,9 @@ pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> {
} }
c @ '\n' => { c @ '\n' => {
match mode { match mode {
m @ Mode::Name | m @ Mode::Class | m @ Mode::Id | m @ Mode::SlComment => { m @ (Mode::Name | Mode::Class | Mode::Id | Mode::SlComment) => {
collect_into_token_and_push( collect_into_token_and_push(
m.token_constructor().map_err(position_map)?, &m.token_constructor().map_err(position_map)?,
&mut tokens, &mut tokens,
&mut value, &mut value,
); );
@ -230,10 +227,10 @@ pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> {
} }
Mode::String => {} Mode::String => {}
Mode::EscapedString => { Mode::EscapedString => {
return Err(LexerError { return Err(Error {
line, line,
col, col,
error: LexerErrorType::UnexpectedToken('\n'), error: ErrorType::UnexpectedToken('\n'),
}) })
} }
}; };
@ -244,55 +241,55 @@ pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> {
'/' => { '/' => {
match mode { match mode {
Mode::String | Mode::SlComment => {} Mode::String | Mode::SlComment => {}
m @ Mode::Name m @ (Mode::Name
| m @ Mode::Class | Mode::Class
| m @ Mode::Id | Mode::Id
| m @ Mode::SlWhitespace | Mode::SlWhitespace
| m @ Mode::MlWhitespace => { | Mode::MlWhitespace) => {
collect_into_token_and_push( collect_into_token_and_push(
m.token_constructor().map_err(position_map)?, &m.token_constructor().map_err(position_map)?,
&mut tokens, &mut tokens,
&mut value, &mut value,
); );
mode = Mode::SlComment; mode = Mode::SlComment;
} }
Mode::EscapedString => { Mode::EscapedString => {
return Err(LexerError { return Err(Error {
line, line,
col, col,
error: LexerErrorType::UnexpectedToken('/'), error: ErrorType::UnexpectedToken('/'),
}) })
} }
}; };
value.push('/'); value.push('/');
} }
v @ 'A'..='Z' | v @ 'a'..='z' | v @ '0'..='9' => { v @ ('A'..='Z' | 'a'..='z' | '0'..='9') => {
match mode { match mode {
Mode::Name | Mode::Class | Mode::Id => { Mode::Name | Mode::Class | Mode::Id => {
if v.is_numeric() { if v.is_numeric()
if value.len() == 0 || mode == Mode::Id && value.len() == 1 { && (value.is_empty() || mode == Mode::Id && value.len() == 1)
return Err(LexerError { {
return Err(Error {
line, line,
col, col,
error: LexerErrorType::UnexpectedToken(v), error: ErrorType::UnexpectedToken(v),
}); });
} }
} }
}
Mode::String | Mode::SlComment => {} Mode::String | Mode::SlComment => {}
m @ Mode::SlWhitespace | m @ Mode::MlWhitespace => { m @ (Mode::SlWhitespace | Mode::MlWhitespace) => {
collect_into_token_and_push( collect_into_token_and_push(
m.token_constructor().map_err(position_map)?, &m.token_constructor().map_err(position_map)?,
&mut tokens, &mut tokens,
&mut value, &mut value,
); );
mode = Mode::Name; mode = Mode::Name;
} }
Mode::EscapedString => { Mode::EscapedString => {
return Err(LexerError { return Err(Error {
line, line,
col, col,
error: LexerErrorType::UnexpectedToken(v), error: ErrorType::UnexpectedToken(v),
}) })
} }
}; };
@ -303,10 +300,10 @@ pub fn lexer(code: String) -> Result<Vec<Token>, LexerError> {
value.push(unrecognized_char); value.push(unrecognized_char);
} }
_ => { _ => {
return Err(LexerError { return Err(Error {
line, line,
col, col,
error: LexerErrorType::UnexpectedToken(unrecognized_char), error: ErrorType::UnexpectedToken(unrecognized_char),
}); });
} }
}, },
@ -323,7 +320,7 @@ fn test_example_1() {
// text { \"hello world\" } // text { \"hello world\" }
\"hello world\" \"hello world\"
}"; }";
let tokens = lexer(text.to_string()); let tokens = lexer(text);
assert_eq!( assert_eq!(
tokens, tokens,
Ok(vec![ Ok(vec![