refacto: use generic types
This commit is contained in:
parent
2300d91fad
commit
a13dfeaeeb
89
src/ast.rs
89
src/ast.rs
|
@ -25,6 +25,79 @@ pub enum Node<T> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Node<bool> {
|
||||||
|
pub fn parse_formula(formula: &str) -> Node<bool> {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ast_to_formula(ast: Node<bool>) -> String {
|
||||||
|
let mut str = String::from("");
|
||||||
|
match ast {
|
||||||
|
Node::Unary { operator, operand } => {
|
||||||
|
str.push_str(Self::ast_to_formula(*operand).as_str());
|
||||||
|
str.push(token_to_char(operator));
|
||||||
|
},
|
||||||
|
Node::Binary { operator, lhs, rhs } => {
|
||||||
|
str.push_str(Self::ast_to_formula(*lhs).as_str());
|
||||||
|
str.push_str(Self::ast_to_formula(*rhs).as_str());
|
||||||
|
str.push(token_to_char(operator));
|
||||||
|
},
|
||||||
|
Node::Leaf(b) => str.push(bool_to_char(b)),
|
||||||
|
};
|
||||||
|
str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Node<char> {
|
||||||
|
pub fn parse_formula(formula: &str) -> Node<char> {
|
||||||
|
let mut stack = vec![];
|
||||||
|
for c in formula.chars() {
|
||||||
|
match c {
|
||||||
|
'A'..='Z' => stack.push(Node::Leaf(c)),
|
||||||
|
'!' => 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()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ast_to_formula(ast: Node<char>) -> String {
|
||||||
|
let mut str = String::from("");
|
||||||
|
match ast {
|
||||||
|
Node::Unary { operator, operand } => {
|
||||||
|
str.push_str(Self::ast_to_formula(*operand).as_str());
|
||||||
|
str.push(token_to_char(operator));
|
||||||
|
},
|
||||||
|
Node::Binary { operator, lhs, rhs } => {
|
||||||
|
str.push_str(Self::ast_to_formula(*lhs).as_str());
|
||||||
|
str.push_str(Self::ast_to_formula(*rhs).as_str());
|
||||||
|
str.push(token_to_char(operator));
|
||||||
|
},
|
||||||
|
Node::Leaf(c) => str.push(c),
|
||||||
|
};
|
||||||
|
str
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_unary_node<T>(stack: &mut Vec<Node<T>>, token: Token) {
|
pub fn add_unary_node<T>(stack: &mut Vec<Node<T>>, token: Token) {
|
||||||
let operand = Box::new(stack.pop().unwrap());
|
let operand = Box::new(stack.pop().unwrap());
|
||||||
stack.push(Node::Unary {
|
stack.push(Node::Unary {
|
||||||
|
@ -61,19 +134,3 @@ fn token_to_char(token: Token) -> char {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ast_to_formula(ast: Node<bool>) -> String {
|
|
||||||
let mut str = String::from("");
|
|
||||||
match ast {
|
|
||||||
Node::Unary { operator, operand } => {
|
|
||||||
str.push_str(ast_to_formula(*operand).as_str());
|
|
||||||
str.push(token_to_char(operator));
|
|
||||||
},
|
|
||||||
Node::Binary { operator, lhs, rhs } => {
|
|
||||||
str.push_str(ast_to_formula(*rhs).as_str());
|
|
||||||
str.push_str(ast_to_formula(*lhs).as_str());
|
|
||||||
str.push(token_to_char(operator));
|
|
||||||
},
|
|
||||||
Node::Leaf(b) => str.push(bool_to_char(b)),
|
|
||||||
};
|
|
||||||
str
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::ast::{ add_binary_node, ast_to_formula, Node, Token };
|
use crate::ast::{ add_binary_node, Node, Token };
|
||||||
use crate::boolean_evaluation::parse_formula;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn add_nodes() {
|
fn add_nodes() {
|
||||||
|
@ -16,16 +15,30 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reverse_ast() {
|
fn ast_to_formula_bool() {
|
||||||
let formula = "01&";
|
let formula = "01&";
|
||||||
assert_eq!(ast_to_formula(parse_formula(formula)), formula);
|
assert_eq!(Node::<bool>::ast_to_formula(Node::<bool>::parse_formula(formula)), formula);
|
||||||
let formula = "01&00|&";
|
let formula = "01&00|&";
|
||||||
assert_eq!(ast_to_formula(parse_formula(formula)), formula);
|
assert_eq!(Node::<bool>::ast_to_formula(Node::<bool>::parse_formula(formula)), formula);
|
||||||
let formula = "01&00|&11^&";
|
let formula = "01&00|&11^&";
|
||||||
assert_eq!(ast_to_formula(parse_formula(formula)), formula);
|
assert_eq!(Node::<bool>::ast_to_formula(Node::<bool>::parse_formula(formula)), formula);
|
||||||
let formula = "01&00|&11=^";
|
let formula = "01&00|&11=^";
|
||||||
assert_eq!(ast_to_formula(parse_formula(formula)), formula);
|
assert_eq!(Node::<bool>::ast_to_formula(Node::<bool>::parse_formula(formula)), formula);
|
||||||
let formula = "01&00|&0!=";
|
let formula = "01&00|&0!=";
|
||||||
assert_eq!(ast_to_formula(parse_formula(formula)), formula);
|
assert_eq!(Node::<bool>::ast_to_formula(Node::<bool>::parse_formula(formula)), formula);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ast_to_formula_char() {
|
||||||
|
let formula = "AB&";
|
||||||
|
assert_eq!(Node::<char>::ast_to_formula(Node::<char>::parse_formula(formula)), formula);
|
||||||
|
let formula = "AB&CD|&";
|
||||||
|
assert_eq!(Node::<char>::ast_to_formula(Node::<char>::parse_formula(formula)), formula);
|
||||||
|
let formula = "AB&AC|&DE^&";
|
||||||
|
assert_eq!(Node::<char>::ast_to_formula(Node::<char>::parse_formula(formula)), formula);
|
||||||
|
let formula = "AB&CD|&EF=^";
|
||||||
|
assert_eq!(Node::<char>::ast_to_formula(Node::<char>::parse_formula(formula)), formula);
|
||||||
|
let formula = "AB&CD|&E!=";
|
||||||
|
assert_eq!(Node::<char>::ast_to_formula(Node::<char>::parse_formula(formula)), formula);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,24 +1,6 @@
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::ast::{ Token, Node, add_unary_node, add_binary_node };
|
use crate::ast::{ Token, Node };
|
||||||
|
|
||||||
pub fn parse_formula(formula: &str) -> Node<bool> {
|
|
||||||
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 {
|
fn compute(operator: Token, lhs: bool, rhs: bool) -> bool {
|
||||||
match operator {
|
match operator {
|
||||||
|
@ -40,6 +22,6 @@ fn evaluate(tree: Node<bool>) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval_formula(formula: &str) -> bool {
|
pub fn eval_formula(formula: &str) -> bool {
|
||||||
let tree = parse_formula(formula);
|
let tree = Node::<bool>::parse_formula(formula);
|
||||||
evaluate(tree)
|
evaluate(tree)
|
||||||
}
|
}
|
11
src/main.rs
11
src/main.rs
|
@ -4,10 +4,10 @@ mod gray_code;
|
||||||
mod boolean_evaluation;
|
mod boolean_evaluation;
|
||||||
mod truth_table;
|
mod truth_table;
|
||||||
mod ast;
|
mod ast;
|
||||||
|
mod negation_normal_form;
|
||||||
|
|
||||||
use gray_code::gray_code;
|
use gray_code::gray_code;
|
||||||
use truth_table::print_truth_table;
|
use truth_table::print_truth_table;
|
||||||
use boolean_evaluation::eval_formula;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
|
@ -21,13 +21,4 @@ fn main() {
|
||||||
println!("{}", gray_code(7));
|
println!("{}", gray_code(7));
|
||||||
println!("{}", gray_code(3));
|
println!("{}", gray_code(3));
|
||||||
print_truth_table("ABC|&");
|
print_truth_table("ABC|&");
|
||||||
//print_truth_table("ABCF&&&");
|
|
||||||
// println!("{}", eval_formula("000|&"));
|
|
||||||
// println!("{}", eval_formula("001|&"));
|
|
||||||
// println!("{}", eval_formula("010|&"));
|
|
||||||
// println!("{}", eval_formula("011|&"));
|
|
||||||
// println!("{}", eval_formula("100|&"));
|
|
||||||
// println!("{}", eval_formula("101|&"));
|
|
||||||
// println!("{}", eval_formula("110|&"));
|
|
||||||
// println!("{}", eval_formula("111|&"));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
use crate::ast::Node;
|
||||||
|
|
||||||
|
// fn cancel_double_negation(ast: Node<char>) {
|
||||||
|
// let mut new_ast = ast.clone();
|
||||||
|
|
||||||
|
// fn recursion(ast: &mut Node<char>, node_count: usize) {
|
||||||
|
// match ast {
|
||||||
|
// Node::Unary { operator: _, operand } => {
|
||||||
|
// recursion(&mut *operand, node_count + 1);
|
||||||
|
// },
|
||||||
|
// Node::Binary { operator: _, lhs, rhs } => {
|
||||||
|
// recursion(&mut *lhs, node_count + 1);
|
||||||
|
// recursion(&mut *rhs, node_count + 1);
|
||||||
|
// },
|
||||||
|
// Node::Leaf(c) => (),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// recursion(&mut new_ast, 0);
|
||||||
|
|
||||||
|
// new_ast
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn negation_normal_form(formula: &str) -> String {
|
||||||
|
let ast = Node::<char>::parse_formula(formula);
|
||||||
|
|
||||||
|
Node::<char>::ast_to_formula(ast)
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::negation_normal_form::negation_normal_form;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn double_neg() {
|
||||||
|
assert_eq!(negation_normal_form("A!!"), "A");
|
||||||
|
assert_eq!(negation_normal_form("A!!!!"), "A");
|
||||||
|
assert_eq!(negation_normal_form("A!!!"), "A!");
|
||||||
|
assert_eq!(negation_normal_form("A!!!!!!!!!!!!!!!!"), "A");
|
||||||
|
assert_eq!(negation_normal_form("A!!!!!!!!!!!!!!!"), "A!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn neg_and() {
|
||||||
|
assert_eq!(negation_normal_form("AB&!"), "A!B!|");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn neg_or() {
|
||||||
|
assert_eq!(negation_normal_form("AB|!"), "A!B!&");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue