ready_set_boole/src/ast.rs

137 lines
4.1 KiB
Rust

mod tests;
#[derive(Debug, Clone, PartialEq)]
pub enum Token {
Negation,
Conjunction,
Disjunction,
ExclusiveDisjunction,
MaterialCondition,
LogicalEquivalence
}
#[derive(Debug, Clone, PartialEq)]
pub enum Node<T> {
Leaf(T),
Unary {
operator: Token,
operand: Box<Node<T>>
},
Binary {
operator: Token,
lhs: Box<Node<T>>,
rhs: Box<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) {
let operand = Box::new(stack.pop().unwrap());
stack.push(Node::Unary {
operator: token,
operand,
});
}
pub fn add_binary_node<T>(stack: &mut Vec<Node<T>>, token: Token) {
let rhs = Box::new(stack.pop().unwrap());
let lhs = Box::new(stack.pop().unwrap());
stack.push(Node::Binary {
operator: token,
lhs,
rhs
});
}
fn bool_to_char(b: bool) -> char {
match b {
false => '0',
true => '1'
}
}
fn token_to_char(token: Token) -> char {
match token {
Token::Negation => '!',
Token::Conjunction =>'&',
Token::Disjunction => '|',
Token::ExclusiveDisjunction => '^',
Token::MaterialCondition => '>',
Token::LogicalEquivalence => '=',
}
}