This commit is contained in:
Charlie Root 2025-03-29 00:57:25 +01:00
commit 2601dcd274
Signed by: faukah
SSH key fingerprint: SHA256:Uj2AXqvtdCA4hn5Hq0ZonhIAyUqI1q4w2sMG3Z1TH7E

View file

@ -1,9 +1,8 @@
use std::io;
use std::{error::Error, io};
#[derive(Debug, PartialEq, Eq)]
enum Symbol {
Number(i32),
Number { value: u64 },
LeftBracket,
RightBracket,
Add,
@ -13,6 +12,26 @@ enum Symbol {
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)]
enum ParseError {
WrongTokenError { pos: usize },
@ -23,8 +42,19 @@ fn main() {
let user_input = get_user_input().expect("No input");
match tokenize(&user_input) {
Ok(tokenized_input) => {
for el in &tokenized_input {
println!("{:?}", el);
// for el in &tokenized_input {
// 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 }) => {
@ -51,11 +81,31 @@ fn try_tokenizing() {
let tokenized_input: Vec<Vec<Symbol>> = input.iter().map(|s| tokenize(s).unwrap()).collect();
let result: Vec<Vec<Symbol>> = vec![
vec![Symbol::Number(1), Symbol::Add, Symbol::Number(2)],
vec![Symbol::Number(3), Symbol::Sub, Symbol::Number(4)],
vec![Symbol::Number(5), Symbol::Mul, Symbol::Number(6)],
vec![Symbol::Number(7), Symbol::Div, Symbol::Number(8)],
vec![Symbol::Number(8), Symbol::Exp, Symbol::Number(9)],
vec![
Symbol::Number { value: 1 },
Symbol::Add,
Symbol::Number { value: 2 },
],
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);
}
@ -66,7 +116,11 @@ fn tokenize(input: &str) -> Result<Vec<Symbol>, ParseError> {
for (i, c) in input.chars().enumerate() {
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();
};
match c {
@ -87,8 +141,68 @@ fn tokenize(input: &str) -> Result<Vec<Symbol>, ParseError> {
}
}
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)
}
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())
}