mod tests; use crate::ast::{add_binary_node, add_unary_node, Node, Token}; use std::collections::HashSet; 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 get_hashset(formula: &str) -> HashSet { let mut hashset = HashSet::new(); for c in formula.chars() { match c { 'A'..='Z' => { hashset.insert(c); } '!' | '&' | '|' | '^' | '>' | '=' => (), _ => panic!("Error: {} is not a valid character", c), } } hashset } fn eval_formula(formula: &str) -> bool { let tree = parse_formula(formula); evaluate(tree) } fn recursive_fn(formula: &str, mut vec: Vec, format: String) { let char = vec.pop(); if let Some(c) = char { recursive_fn( formula.replace(c, "0").as_str(), vec.clone(), format!("{format} 0 |"), ); recursive_fn( formula.replace(c, "1").as_str(), vec.clone(), format!("{format} 1 |"), ); } else { match eval_formula(formula) { false => println!("{format} 0 |"), true => println!("{format} 1 |"), } } } pub fn print_truth_table(formula: &str) { let set: HashSet = get_hashset(formula); let mut vec: Vec = set.iter().cloned().collect(); vec.sort(); let mut format = String::from("|"); let mut separator = String::from("|"); for i in vec.clone() { format = format!("{format} {i} |"); separator = format!("{separator}---|"); } format = format!("{format} = |"); separator = format!("{separator}---|"); println!("{format}"); println!("{separator}"); recursive_fn(formula, vec.into_iter().rev().collect(), String::from("|")); // call eval formula a lot }