From afb5d7d10570be1e03462351c62bd7202fc37285 Mon Sep 17 00:00:00 2001 From: gbrochar Date: Fri, 5 Jan 2024 17:11:59 +0100 Subject: [PATCH] feat(ex04): boolean evaluation --- src/ast.rs | 42 ++++++++++++++++++++++++++++++ src/ast/tests.rs | 13 ++++++++++ src/boolean_evaluation.rs | 45 +++++++++++++++++++++++++++++++++ src/boolean_evaluation/tests.rs | 26 +++++++++++++++++++ src/main.rs | 2 ++ src/truth_table,rs | 0 6 files changed, 128 insertions(+) create mode 100644 src/ast.rs create mode 100644 src/ast/tests.rs create mode 100644 src/boolean_evaluation.rs create mode 100644 src/boolean_evaluation/tests.rs create mode 100644 src/truth_table,rs diff --git a/src/ast.rs b/src/ast.rs new file mode 100644 index 0000000..e0efaae --- /dev/null +++ b/src/ast.rs @@ -0,0 +1,42 @@ + +#[derive(Debug, Clone)] +pub enum Token { + Negation, + Conjunction, + Disjunction, + ExclusiveDisjunction, + MaterialCondition, + LogicalEquivalence +} + +#[derive(Debug, Clone)] +pub enum Node { + Leaf(T), + Unary { + operator: Token, + operand: Box> + }, + Binary { + operator: Token, + lhs: Box>, + rhs: Box>, + }, +} + +pub fn add_unary_node(stack: &mut Vec>, token: Token) { + let operand = Box::new(stack.pop().unwrap()); + stack.push(Node::Unary { + operator: token, + operand, + }); +} + +pub fn add_binary_node(stack: &mut Vec>, token: Token) { + let lhs = Box::new(stack.pop().unwrap()); + let rhs = Box::new(stack.pop().unwrap()); + stack.push(Node::Binary { + operator: token, + lhs, + rhs + }); +} \ No newline at end of file diff --git a/src/ast/tests.rs b/src/ast/tests.rs new file mode 100644 index 0000000..085d695 --- /dev/null +++ b/src/ast/tests.rs @@ -0,0 +1,13 @@ +#[cfg(test)] +mod tests { + #[test] + fn add_nodes() { + let stack = vec![Node::Leaf(true), Node::Leaf(false)]; + let rhs = vec![Node::Binary { + operator: Token::Conjunction, + lhs: Box::new(Node::Leaf(true)), + rhs: Box::new(Node::Leaf(false)) + }]; + assert_eq!(add_binary_node(&mut stack, Token::Conjunction), rhs); + } +} \ No newline at end of file diff --git a/src/boolean_evaluation.rs b/src/boolean_evaluation.rs new file mode 100644 index 0000000..18f89e7 --- /dev/null +++ b/src/boolean_evaluation.rs @@ -0,0 +1,45 @@ +mod tests; + +use crate::ast::{ Token, Node, add_unary_node, add_binary_node }; + +fn parse_formula(formula: &str) -> Node { + let mut stack = vec![]; + for c in formula.chars() { + match c { + '0' => stack.push(Node::Leaf(false)), + '1' => stack.push(Node::Leaf(true)), + '!' => add_unary_node(&mut stack, Token::Negation), + '&' => add_binary_node(&mut stack, Token::Conjunction), + '|' => add_binary_node(&mut stack, Token::Disjunction), + '^' => add_binary_node(&mut stack, Token::ExclusiveDisjunction), + '>' => add_binary_node(&mut stack, Token::MaterialCondition), + '=' => add_binary_node(&mut stack, Token::LogicalEquivalence), + _ => panic!("Error: {} is not a valid character", c) + } + } + stack.pop().unwrap() +} + +fn compute(operator: Token, lhs: bool, rhs: bool) -> bool { + match operator { + Token::Negation => !lhs, + Token::Conjunction => lhs & rhs, + Token::Disjunction => lhs | rhs, + Token::ExclusiveDisjunction => lhs ^ rhs, + Token::MaterialCondition => !(lhs && !rhs), + Token::LogicalEquivalence => lhs == rhs + } +} + +fn evaluate(tree: Node) -> bool { + match tree { + Node::Unary { operator, operand } => compute(operator, evaluate(*operand), false), + Node::Binary { operator, lhs, rhs } => compute(operator, evaluate(*lhs), evaluate(*rhs)), + Node::Leaf(b) => b, + } +} + +fn eval_formula(formula: &str) -> bool { + let tree = parse_formula(formula); + evaluate(tree) +} \ No newline at end of file diff --git a/src/boolean_evaluation/tests.rs b/src/boolean_evaluation/tests.rs new file mode 100644 index 0000000..3ecffe4 --- /dev/null +++ b/src/boolean_evaluation/tests.rs @@ -0,0 +1,26 @@ +#[cfg(test)] +mod tests { + use crate::boolean_evaluation::eval_formula; + + #[test] + fn only_binary() { + assert_eq!(eval_formula("10&"), false); + assert_eq!(eval_formula("10|"), true); + assert_eq!(eval_formula("11>"), true); + assert_eq!(eval_formula("10="), false); + assert_eq!(eval_formula("1011||="), true); + } + + #[test] + fn only_unary() { + assert_eq!(eval_formula("1!"), false); + assert_eq!(eval_formula("0!"), true); + + } + + #[test] + fn binary_and_uneray() { + assert_eq!(eval_formula("10&!"), true); + assert_eq!(eval_formula("11&!"), false); + } +} diff --git a/src/main.rs b/src/main.rs index bb1527a..b32469d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ mod adder; mod multiplier; mod gray_code; +mod boolean_evaluation; +mod ast; use gray_code::gray_code; diff --git a/src/truth_table,rs b/src/truth_table,rs new file mode 100644 index 0000000..e69de29