Created
April 2, 2023 15:53
-
-
Save kamenchunathan/ddfcb43b751a4d95f5bd111be701ec8b to your computer and use it in GitHub Desktop.
A parser for arithmetic operations in rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[derive(Debug)] | |
| pub enum Tree<T, U> { | |
| Leaf(T), | |
| Node(Box<Tree<T, U>>, U, Box<Tree<T, U>>), | |
| } | |
| pub trait Op<T> { | |
| fn apply(&self, x: T, y: T) -> T; | |
| } | |
| impl<T, U> Tree<T, U> { | |
| pub fn singleton(item: T) -> Tree<T, U> { | |
| Tree::Leaf(item) | |
| } | |
| } | |
| impl<T, U> Tree<T, U> | |
| where | |
| U: Ord, | |
| { | |
| pub fn insert(self, op: U, val: T) -> Self { | |
| use Tree::*; | |
| match self { | |
| Leaf(curr) => Node(Box::new(Leaf(curr)), op, Box::new(Leaf(val))), | |
| Node(lhs, curr_op, rhs) => { | |
| if op <= curr_op { | |
| Node(Box::new(Node(lhs, curr_op, rhs)), op, Box::new(Leaf(val))) | |
| } else { | |
| Node(lhs, curr_op, Box::new(Node(rhs, op, Box::new(Leaf(val))))) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| impl<T, U> Tree<T, U> | |
| where | |
| U: Ord + Op<T>, | |
| T: Clone, | |
| { | |
| pub fn eval(&self) -> T { | |
| match self { | |
| Tree::Leaf(val) => (*val).clone(), | |
| Tree::Node(lhs, op, rhs) => (*op).apply(lhs.eval(), rhs.eval()), | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #![allow(unused)] | |
| use std::{cmp::Ordering, ops::Div}; | |
| use ast::{Op, Tree}; | |
| mod ast; | |
| #[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy)] | |
| enum ArithmeticOp { | |
| Add, | |
| Sub, | |
| Mul, | |
| Div, | |
| } | |
| impl Ord for ArithmeticOp { | |
| fn cmp(&self, other: &Self) -> std::cmp::Ordering { | |
| use ArithmeticOp::*; | |
| match (*self, *other) { | |
| (_, Div) => Ordering::Less, | |
| (_, Mul) => Ordering::Less, | |
| _ => Ordering::Equal, | |
| } | |
| } | |
| } | |
| impl Op<f32> for ArithmeticOp { | |
| fn apply(&self, x: f32, y: f32) -> f32 { | |
| match *self { | |
| ArithmeticOp::Add => x + y, | |
| ArithmeticOp::Sub => x - y, | |
| ArithmeticOp::Mul => x * y, | |
| ArithmeticOp::Div => x / y, | |
| } | |
| } | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use crate::{ast::Tree, ArithmeticOp}; | |
| #[test] | |
| fn eval_test_2() { | |
| use ArithmeticOp::*; | |
| use Tree::*; | |
| let tree = Leaf(3.0).insert(Add, 4.0).insert(Mul, 3.0); | |
| dbg!(&tree); | |
| assert_eq!(tree.eval(), 15.0); | |
| } | |
| #[test] | |
| fn eval_test_5() { | |
| use ArithmeticOp::*; | |
| use Tree::*; | |
| let tree = Leaf(3.0).insert(Mul, 3.0).insert(Mul, 3.0); | |
| dbg!(&tree); | |
| assert_eq!(tree.eval(), 27.0); | |
| } | |
| #[test] | |
| fn eval_test_4() { | |
| use ArithmeticOp::*; | |
| use Tree::*; | |
| let tree = Leaf(3.0).insert(Div, 3.0).insert(Div, 3.0); | |
| dbg!(&tree); | |
| assert_eq!(tree.eval(), 0.33333334); | |
| } | |
| #[test] | |
| fn eval_test_3() { | |
| use ArithmeticOp::*; | |
| use Tree::*; | |
| let tree = Leaf(3.0).insert(Mul, 3.0).insert(Add, 3.0).insert(Div, 3.0); | |
| assert_eq!(tree.eval(), 10.0); | |
| } | |
| #[test] | |
| fn eval_test_1() { | |
| use ArithmeticOp::*; | |
| use Tree::*; | |
| let tree = Leaf(3.0).insert(Add, 3.0); | |
| assert_eq!(tree.eval(), 6.0); | |
| } | |
| #[test] | |
| fn eval_test() { | |
| use Tree::*; | |
| let tree: Tree<f32, ArithmeticOp> = Leaf(3f32); | |
| assert_eq!(tree.eval(), 3f32); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment