use prexel::context::{Context, DefaultContext};
use prexel::evaluator::Evaluator;
use prexel::function::{Associativity, BinaryFunction, Precedence};
use prexel::Result;
fn main() {
const USE_U8: bool = true;
if USE_U8 {
let mut context: DefaultContext<u8> = DefaultContext::new();
context.add_constant("true", 1).unwrap();
context.add_constant("false", 0).unwrap();
context.add_binary_function(AndOperator).unwrap();
context.add_binary_function(OrOperator).unwrap();
context.add_binary_function(XorOperator).unwrap();
let evaluator = Evaluator::with_context(context);
let expression1 = "(1 or 0) and (1 xor 0)";
let expression2 = "(0 and 1)";
assert_eq!(evaluator.eval(expression1).unwrap(), 1);
assert_eq!(evaluator.eval(expression2).unwrap(), 0);
println!("{} = {}", expression1, evaluator.eval(expression1).unwrap());
println!("{} = {}", expression2, evaluator.eval(expression2).unwrap());
} else {
let mut context: DefaultContext<bool> = DefaultContext::new();
context.add_constant("true", true).unwrap();
context.add_constant("false", false).unwrap();
context.add_binary_function(AndOperator).unwrap();
context.add_binary_function(OrOperator).unwrap();
context.add_binary_function(XorOperator).unwrap();
let evaluator = Evaluator::with_context(context);
let expression1 = "(true or false) and (true xor false)";
let expression2 = "(false and true)";
assert_eq!(evaluator.eval(expression1).unwrap(), true);
assert_eq!(evaluator.eval(expression2).unwrap(), false);
println!("{} = {}", expression1, evaluator.eval(expression1).unwrap());
println!("{} = {}", expression2, evaluator.eval(expression2).unwrap());
}
}
struct AndOperator;
struct XorOperator;
struct OrOperator;
impl BinaryFunction<bool> for AndOperator {
fn name(&self) -> &str {
"and"
}
fn precedence(&self) -> Precedence {
Precedence::VERY_LOW
}
fn associativity(&self) -> Associativity {
Associativity::Left
}
fn call(&self, left: bool, right: bool) -> Result<bool> {
Ok(left && right)
}
}
impl BinaryFunction<bool> for XorOperator {
fn name(&self) -> &str {
"xor"
}
fn precedence(&self) -> Precedence {
Precedence::LOW
}
fn associativity(&self) -> Associativity {
Associativity::Left
}
fn call(&self, left: bool, right: bool) -> Result<bool> {
Ok(left ^ right)
}
}
impl BinaryFunction<bool> for OrOperator {
fn name(&self) -> &str {
"or"
}
fn precedence(&self) -> Precedence {
Precedence::MEDIUM
}
fn associativity(&self) -> Associativity {
Associativity::Left
}
fn call(&self, left: bool, right: bool) -> Result<bool> {
Ok(left || right)
}
}
impl BinaryFunction<u8> for AndOperator {
fn name(&self) -> &str {
"and"
}
fn precedence(&self) -> Precedence {
Precedence::VERY_LOW
}
fn associativity(&self) -> Associativity {
Associativity::Left
}
fn call(&self, left: u8, right: u8) -> Result<u8> {
Ok(left & right)
}
}
impl BinaryFunction<u8> for XorOperator {
fn name(&self) -> &str {
"xor"
}
fn precedence(&self) -> Precedence {
Precedence::LOW
}
fn associativity(&self) -> Associativity {
Associativity::Left
}
fn call(&self, left: u8, right: u8) -> Result<u8> {
Ok(left ^ right)
}
}
impl BinaryFunction<u8> for OrOperator {
fn name(&self) -> &str {
"or"
}
fn precedence(&self) -> Precedence {
Precedence::MEDIUM
}
fn associativity(&self) -> Associativity {
Associativity::Left
}
fn call(&self, left: u8, right: u8) -> Result<u8> {
Ok(left | right)
}
}