werks
This commit is contained in:
parent
be663876a4
commit
2601dcd274
1 changed files with 126 additions and 12 deletions
138
src/main.rs
138
src/main.rs
|
@ -1,9 +1,8 @@
|
||||||
use std::io;
|
use std::{error::Error, io};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
enum Symbol {
|
enum Symbol {
|
||||||
Number(i32),
|
Number { value: u64 },
|
||||||
|
|
||||||
LeftBracket,
|
LeftBracket,
|
||||||
RightBracket,
|
RightBracket,
|
||||||
Add,
|
Add,
|
||||||
|
@ -13,6 +12,26 @@ enum Symbol {
|
||||||
Exp,
|
Exp,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
enum Node {
|
||||||
|
Add { left: Box<Node>, right: Box<Node> },
|
||||||
|
Sub { left: Box<Node>, right: Box<Node> },
|
||||||
|
Mul { left: Box<Node>, right: Box<Node> },
|
||||||
|
Number { value: u64 },
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval(expr: &Node) -> i64 {
|
||||||
|
match expr {
|
||||||
|
Node::Add { left, right } => eval(left) + eval(right),
|
||||||
|
Node::Sub { left, right } => eval(left) - eval(right),
|
||||||
|
Node::Mul { left, right } => eval(left) * eval(right),
|
||||||
|
Node::Number { value } => {
|
||||||
|
// println!("Evaling number {value}");
|
||||||
|
*value as i64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum ParseError {
|
enum ParseError {
|
||||||
WrongTokenError { pos: usize },
|
WrongTokenError { pos: usize },
|
||||||
|
@ -23,8 +42,19 @@ fn main() {
|
||||||
let user_input = get_user_input().expect("No input");
|
let user_input = get_user_input().expect("No input");
|
||||||
match tokenize(&user_input) {
|
match tokenize(&user_input) {
|
||||||
Ok(tokenized_input) => {
|
Ok(tokenized_input) => {
|
||||||
for el in &tokenized_input {
|
// for el in &tokenized_input {
|
||||||
println!("{:?}", el);
|
// println!("lol {:?}", el);
|
||||||
|
// }
|
||||||
|
let ast = ast(tokenized_input);
|
||||||
|
// println!("{:?}", ast);
|
||||||
|
match ast {
|
||||||
|
Ok(ast) => {
|
||||||
|
let evaled = eval(&ast);
|
||||||
|
println!("{}", evaled);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(ParseError::WrongTokenError { pos }) => {
|
Err(ParseError::WrongTokenError { pos }) => {
|
||||||
|
@ -51,11 +81,31 @@ fn try_tokenizing() {
|
||||||
let tokenized_input: Vec<Vec<Symbol>> = input.iter().map(|s| tokenize(s).unwrap()).collect();
|
let tokenized_input: Vec<Vec<Symbol>> = input.iter().map(|s| tokenize(s).unwrap()).collect();
|
||||||
|
|
||||||
let result: Vec<Vec<Symbol>> = vec![
|
let result: Vec<Vec<Symbol>> = vec![
|
||||||
vec![Symbol::Number(1), Symbol::Add, Symbol::Number(2)],
|
vec![
|
||||||
vec![Symbol::Number(3), Symbol::Sub, Symbol::Number(4)],
|
Symbol::Number { value: 1 },
|
||||||
vec![Symbol::Number(5), Symbol::Mul, Symbol::Number(6)],
|
Symbol::Add,
|
||||||
vec![Symbol::Number(7), Symbol::Div, Symbol::Number(8)],
|
Symbol::Number { value: 2 },
|
||||||
vec![Symbol::Number(8), Symbol::Exp, Symbol::Number(9)],
|
],
|
||||||
|
vec![
|
||||||
|
Symbol::Number { value: 3 },
|
||||||
|
Symbol::Sub,
|
||||||
|
Symbol::Number { value: 4 },
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
Symbol::Number { value: 5 },
|
||||||
|
Symbol::Mul,
|
||||||
|
Symbol::Number { value: 6 },
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
Symbol::Number { value: 7 },
|
||||||
|
Symbol::Div,
|
||||||
|
Symbol::Number { value: 8 },
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
Symbol::Number { value: 8 },
|
||||||
|
Symbol::Exp,
|
||||||
|
Symbol::Number { value: 9 },
|
||||||
|
],
|
||||||
];
|
];
|
||||||
assert!(tokenized_input == result);
|
assert!(tokenized_input == result);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +116,11 @@ fn tokenize(input: &str) -> Result<Vec<Symbol>, ParseError> {
|
||||||
|
|
||||||
for (i, c) in input.chars().enumerate() {
|
for (i, c) in input.chars().enumerate() {
|
||||||
if !c.is_ascii_digit() && !acc.is_empty() {
|
if !c.is_ascii_digit() && !acc.is_empty() {
|
||||||
tokens.push(Symbol::Number(acc.parse().unwrap_or(0)));
|
tokens.push(Symbol::Number {
|
||||||
|
value: acc
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| ParseError::WrongTokenError { pos: 1 })?,
|
||||||
|
});
|
||||||
acc.clear();
|
acc.clear();
|
||||||
};
|
};
|
||||||
match c {
|
match c {
|
||||||
|
@ -87,8 +141,68 @@ fn tokenize(input: &str) -> Result<Vec<Symbol>, ParseError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !acc.is_empty() {
|
if !acc.is_empty() {
|
||||||
tokens.push(Symbol::Number(acc.parse().unwrap_or(0)));
|
tokens.push(Symbol::Number {
|
||||||
|
value: acc
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| ParseError::WrongTokenError { pos: 1 })?,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(tokens)
|
Ok(tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ast(input: Vec<Symbol>) -> Result<Node, ParseError> {
|
||||||
|
let mut stack = Vec::<Node>::new();
|
||||||
|
// println!("{}", input.len());
|
||||||
|
let length = input.len();
|
||||||
|
let mut i = 0;
|
||||||
|
|
||||||
|
while i < length {
|
||||||
|
// println!("Count: {}", i);
|
||||||
|
let s = &input[i];
|
||||||
|
// println!("Symbol: {:?}", s);
|
||||||
|
match s {
|
||||||
|
Symbol::Number { value } => {
|
||||||
|
stack.push(Node::Number { value: *value });
|
||||||
|
// println!("pushed {value}")
|
||||||
|
}
|
||||||
|
Symbol::Add => {
|
||||||
|
let left = stack.pop();
|
||||||
|
// increment
|
||||||
|
let right = input.get(i + 1);
|
||||||
|
i += 1;
|
||||||
|
|
||||||
|
match (left, right) {
|
||||||
|
(Some(left), Some(right)) => {
|
||||||
|
match right {
|
||||||
|
Symbol::Number { value } => {
|
||||||
|
stack.push(Node::Add {
|
||||||
|
left: (Box::new(left)),
|
||||||
|
right: (Box::new(Node::Number { value: *value })),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => return Err(ParseError::WrongTokenError { pos: 1 }),
|
||||||
|
}
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(ParseError::WrongTokenError { pos: 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Symbol::Sub => {}
|
||||||
|
Symbol::Mul => {}
|
||||||
|
Symbol::Div => {}
|
||||||
|
_ => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
// println!("Stack length: {}", stack.len());
|
||||||
|
// println!("Stack: {:?}", stack);
|
||||||
|
if stack.len() != 1 {
|
||||||
|
return Err(ParseError::WrongTokenError { pos: 1 });
|
||||||
|
}
|
||||||
|
Ok(stack[0].clone())
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue