clippy pedantic refactoring
This commit is contained in:
parent
94837aad7c
commit
2762361968
@ -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![
|
||||||
|
Loading…
Reference in New Issue
Block a user