Put lexer into it's own file
This commit is contained in:
parent
47768ee208
commit
1fe9214a62
@ -5,8 +5,5 @@ authors = ["Kasper <kasperkh.kh@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
# logos = "0.9.7"
|
||||
# num-traits = "0.2"
|
||||
# num-rational = "0.2"
|
||||
nom = "5.0"
|
||||
decimal = "2.0.4"
|
||||
|
||||
59
src/lexer.rs
Normal file
59
src/lexer.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use std::str::FromStr;
|
||||
use decimal::d128;
|
||||
use crate::{Token, TokenVector, Operator::*};
|
||||
|
||||
pub fn lex(input: &str) -> Result<TokenVector, String> {
|
||||
|
||||
let mut chars = input.chars().enumerate().peekable();
|
||||
let mut tokens: TokenVector = vec![];
|
||||
|
||||
while let Some((index, current_char)) = chars.next() {
|
||||
match current_char {
|
||||
'+' => tokens.push(Token::Operator(Plus)),
|
||||
'-' => tokens.push(Token::Operator(Minus)),
|
||||
'*' => tokens.push(Token::Operator(Multiply)),
|
||||
'/' => tokens.push(Token::Operator(Divide)),
|
||||
'%' => tokens.push(Token::Operator(PercentOrModulo)),
|
||||
'^' => tokens.push(Token::Operator(Caret)),
|
||||
'!' => tokens.push(Token::Operator(Factorial)),
|
||||
'(' => tokens.push(Token::Operator(LeftParen)),
|
||||
')' => tokens.push(Token::Operator(RightParen)),
|
||||
',' => continue,
|
||||
value if value.is_whitespace() => continue,
|
||||
value if value.is_alphabetic() => {
|
||||
|
||||
},
|
||||
'.' | '0'..='9' => {
|
||||
|
||||
let start_index = index;
|
||||
let mut end_index = index+1;
|
||||
while let Some((_idk, current_char)) = chars.peek() {
|
||||
if current_char == &'.' || current_char.is_digit(10) {
|
||||
chars.next();
|
||||
end_index += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
match d128::from_str(&input[start_index..end_index]) {
|
||||
Ok(number) => {
|
||||
if d128::get_status().is_empty() {
|
||||
tokens.push(Token::Number(number));
|
||||
} else {
|
||||
return Err(format!("Error parsing d128 number: {}", &input[start_index..end_index]));
|
||||
}
|
||||
},
|
||||
Err(_e) => {
|
||||
return Err("Error parsing d128 number (This should not happen because d128 does not throw errors)".to_owned());
|
||||
}
|
||||
};
|
||||
|
||||
},
|
||||
_ => {
|
||||
return Err(format!("Unknown character: {}", current_char));
|
||||
},
|
||||
}
|
||||
};
|
||||
return Ok(tokens)
|
||||
}
|
||||
66
src/main.rs
66
src/main.rs
@ -1,9 +1,8 @@
|
||||
use std::time::{Instant};
|
||||
use decimal::d128;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Operator {
|
||||
pub enum Operator {
|
||||
Plus,
|
||||
Minus,
|
||||
Multiply,
|
||||
@ -14,71 +13,16 @@ enum Operator {
|
||||
LeftParen,
|
||||
RightParen,
|
||||
}
|
||||
use Operator::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Token {
|
||||
pub enum Token {
|
||||
Operator(Operator),
|
||||
Number(d128),
|
||||
}
|
||||
|
||||
type TokenVector = Vec<Token>;
|
||||
pub type TokenVector = Vec<Token>;
|
||||
|
||||
fn lex(input: &str) -> Result<TokenVector, String> {
|
||||
|
||||
let mut chars = input.chars().enumerate().peekable();
|
||||
let mut tokens: TokenVector = vec![];
|
||||
|
||||
while let Some((index, current_char)) = chars.next() {
|
||||
match current_char {
|
||||
'+' => tokens.push(Token::Operator(Plus)),
|
||||
'-' => tokens.push(Token::Operator(Minus)),
|
||||
'*' => tokens.push(Token::Operator(Multiply)),
|
||||
'/' => tokens.push(Token::Operator(Divide)),
|
||||
'%' => tokens.push(Token::Operator(PercentOrModulo)),
|
||||
'^' => tokens.push(Token::Operator(Caret)),
|
||||
'!' => tokens.push(Token::Operator(Factorial)),
|
||||
'(' => tokens.push(Token::Operator(LeftParen)),
|
||||
')' => tokens.push(Token::Operator(RightParen)),
|
||||
',' => continue,
|
||||
value if value.is_whitespace() => continue,
|
||||
value if value.is_alphabetic() => {
|
||||
|
||||
},
|
||||
'.' | '0'..='9' => {
|
||||
|
||||
let start_index = index;
|
||||
let mut end_index = index+1;
|
||||
while let Some((_idk, current_char)) = chars.peek() {
|
||||
if current_char == &'.' || current_char.is_digit(10) {
|
||||
chars.next();
|
||||
end_index += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
match d128::from_str(&input[start_index..end_index]) {
|
||||
Ok(number) => {
|
||||
if d128::get_status().is_empty() {
|
||||
tokens.push(Token::Number(number));
|
||||
} else {
|
||||
return Err(format!("Error parsing d128 number: {}", &input[start_index..end_index]));
|
||||
}
|
||||
},
|
||||
Err(_e) => {
|
||||
return Err("Error parsing d128 number (This should not happen because d128 does not throw errors)".to_owned());
|
||||
}
|
||||
};
|
||||
|
||||
},
|
||||
_ => {
|
||||
return Err(format!("Unknown character: {}", current_char));
|
||||
},
|
||||
}
|
||||
};
|
||||
return Ok(tokens)
|
||||
}
|
||||
mod lexer;
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
@ -87,7 +31,7 @@ fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let s = if args.len() == 2 { &args[1] } else { "0.1" };
|
||||
|
||||
match lex(s) {
|
||||
match lexer::lex(s) {
|
||||
Ok(vector) => println!("{:?}", vector),
|
||||
Err(e) => println!("lexing error: {}", e),
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user