From 5b03990d389ad564db37dc927556370186e0ba77 Mon Sep 17 00:00:00 2001 From: Charlie Root Date: Tue, 1 Apr 2025 17:34:02 +0200 Subject: [PATCH] refactor --- src/main.rs | 183 ++++++++++++++++++++++++++++------------------------ 1 file changed, 97 insertions(+), 86 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6afd714..67ed171 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ use std::io; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq)] enum Symbol { - Number { value: u64 }, + Number(f64), LeftBracket, RightBracket, Add, @@ -17,32 +17,32 @@ enum Node { Add { left: Box, right: Box }, Sub { left: Box, right: Box }, Mul { left: Box, right: Box }, - Number { value: u64 }, + Div { left: Box, right: Box }, + Number(f64), } #[test] fn test_eval() { let node_to_eval = Node::Add { left: Box::new(Node::Add { - left: Box::new(Node::Number { value: 1 }), - right: Box::new(Node::Number { value: 1 }), + left: Box::new(Node::Number(1.0)), + right: Box::new(Node::Number(1.0)), }), - right: Box::new(Node::Number { value: 3 }), + right: Box::new(Node::Number(3.0)), }; - let result = eval(&node_to_eval); - - assert!(result == 5_i64); + assert!((result - 5.0_f64).abs() < 0.00000000000000000001); } -fn eval(expr: &Node) -> i64 { +fn eval(expr: &Node) -> f64 { 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 } => { + Node::Div { left, right } => eval(left) / eval(right), + Node::Number(value) => { // println!("Evaling number {value}"); - *value as i64 + *value } } } @@ -50,6 +50,7 @@ fn eval(expr: &Node) -> i64 { #[derive(Debug)] enum ParseError { WrongTokenError { pos: usize }, + WrongNumberError { pos: usize }, } fn main() { @@ -58,16 +59,17 @@ fn main() { match tokenize(&user_input) { Ok(tokenized_input) => { // for el in &tokenized_input { - // println!("lol {:?}", el); + // println!("lol {:?}", el); // } let ast = ast(tokenized_input); - // println!("{:?}", ast); + // println!(" test {:?}", ast); match ast { Ok(ast) => { let evaled = eval(&ast); - println!("{}", evaled); + println!("{}\n", evaled); } _ => { + // println!("lol"); continue; } } @@ -79,6 +81,13 @@ fn main() { println!("^"); println!("Syntax Error\n"); } + Err(ParseError::WrongNumberError { pos }) => { + for _ in 0..pos { + print!("-"); + } + println!("^"); + println!("Your Number is invalid HERE\n"); + } } } } @@ -96,31 +105,11 @@ fn try_tokenizing() { let tokenized_input: Vec> = input.iter().map(|s| tokenize(s).unwrap()).collect(); let result: Vec> = vec![ - 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 }, - ], + vec![Symbol::Number(1.0), Symbol::Add, Symbol::Number(2.0)], + vec![Symbol::Number(3.0), Symbol::Sub, Symbol::Number(4.0)], + vec![Symbol::Number(5.0), Symbol::Mul, Symbol::Number(6.0)], + vec![Symbol::Number(7.0), Symbol::Div, Symbol::Number(8.0)], + vec![Symbol::Number(8.0), Symbol::Exp, Symbol::Number(9.0)], ]; assert!(tokenized_input == result); } @@ -131,17 +120,16 @@ fn tokenize(input: &str) -> Result, ParseError> { for (i, c) in input.chars().enumerate() { if !c.is_ascii_digit() && !acc.is_empty() { - tokens.push(Symbol::Number { - value: acc - .parse() - .map_err(|_| ParseError::WrongTokenError { pos: 1 })?, - }); - acc.clear(); + if let Ok(num) = acc.parse() { + tokens.push(Symbol::Number(num)); + acc.clear(); + } else { + return Err(ParseError::WrongNumberError { pos: i }); + } }; match c { '0'..='9' => { acc.push(c); - continue; } ' ' => continue, '(' => tokens.push(Symbol::LeftBracket), @@ -156,63 +144,86 @@ fn tokenize(input: &str) -> Result, ParseError> { } } if !acc.is_empty() { - tokens.push(Symbol::Number { - value: acc - .parse() - .map_err(|_| ParseError::WrongTokenError { pos: 1 })?, - }); - } + if let Ok(num) = acc.parse() { + tokens.push(Symbol::Number(num)); + } else { + return Err(ParseError::WrongNumberError { pos: 0 }); + } + }; Ok(tokens) } -fn ast(input: Vec) -> Result { +fn ast(mut input: Vec) -> Result { let mut stack = Vec::::new(); // println!("{}", input.len()); let length = input.len(); let mut i = 0; + if length == 1 { + if let Symbol::Number(num) = input[0] { + return Ok(Node::Number(num)); + } else { + return Err(ParseError::WrongTokenError { pos: 0 }); + } + } + while i < length { let s = &input[i]; match s { - Symbol::Number { value } => { - stack.push(Node::Number { value: *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::Add | Symbol::Sub | Symbol::Mul | Symbol::Div => { + if let Ok(n) = push_to_ast(&mut input, &mut i) { + stack.push(n); + } else { + return Err(ParseError::WrongTokenError { pos: i }); } } - Symbol::Sub => {} - Symbol::Mul => {} - Symbol::Div => {} - _ => { - continue; - } + _ => {} } - i += 1; + i += 1 } if stack.len() != 1 { return Err(ParseError::WrongTokenError { pos: 1 }); } Ok(stack[0].clone()) } + +fn push_to_ast(input: &mut [Symbol], index: &mut usize) -> Result { + let left = input.get(*index - 1); + let op = input.get(*index); + let right = input.get(*index + 1); + *index += 1; + + if let (Some(op), Some(l), Some(r)) = (op, left, right) { + if let (Symbol::Number(le), Symbol::Number(ri)) = (l, r) { + match op { + Symbol::Add => { + return Ok(Node::Add { + left: Box::new(Node::Number(*le)), + right: Box::new(Node::Number(*ri)), + }); + } + Symbol::Sub => { + return Ok(Node::Sub { + left: Box::new(Node::Number(*le)), + right: Box::new(Node::Number(*ri)), + }); + } + Symbol::Mul => { + return Ok(Node::Mul { + left: Box::new(Node::Number(*le)), + right: Box::new(Node::Number(*ri)), + }); + } + Symbol::Div => { + return Ok(Node::Div { + left: Box::new(Node::Number(*le)), + right: Box::new(Node::Number(*ri)), + }); + } + _ => return Err(ParseError::WrongTokenError { pos: 16 }), + } + } + } + Err(ParseError::WrongTokenError { pos: 1 }) +}