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"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# logos = "0.9.7"
|
|
||||||
# num-traits = "0.2"
|
|
||||||
# num-rational = "0.2"
|
|
||||||
nom = "5.0"
|
nom = "5.0"
|
||||||
decimal = "2.0.4"
|
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 std::time::{Instant};
|
||||||
use decimal::d128;
|
use decimal::d128;
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Operator {
|
pub enum Operator {
|
||||||
Plus,
|
Plus,
|
||||||
Minus,
|
Minus,
|
||||||
Multiply,
|
Multiply,
|
||||||
@ -14,71 +13,16 @@ enum Operator {
|
|||||||
LeftParen,
|
LeftParen,
|
||||||
RightParen,
|
RightParen,
|
||||||
}
|
}
|
||||||
use Operator::*;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Token {
|
pub enum Token {
|
||||||
Operator(Operator),
|
Operator(Operator),
|
||||||
Number(d128),
|
Number(d128),
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenVector = Vec<Token>;
|
pub type TokenVector = Vec<Token>;
|
||||||
|
|
||||||
fn lex(input: &str) -> Result<TokenVector, String> {
|
mod lexer;
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
@ -87,7 +31,7 @@ fn main() {
|
|||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
let s = if args.len() == 2 { &args[1] } else { "0.1" };
|
let s = if args.len() == 2 { &args[1] } else { "0.1" };
|
||||||
|
|
||||||
match lex(s) {
|
match lexer::lex(s) {
|
||||||
Ok(vector) => println!("{:?}", vector),
|
Ok(vector) => println!("{:?}", vector),
|
||||||
Err(e) => println!("lexing error: {}", e),
|
Err(e) => println!("lexing error: {}", e),
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user