Решение на Логически изрази от Александър Иванов

Обратно към всички решения

Към профила на Александър Иванов

Резултати

  • 20 точки от тестове
  • 2 бонус точки
  • 22 точки общо
  • 20 успешни тест(а)
  • 0 неуспешни тест(а)

Код

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr {
Atom(char),
Not(Box<Expr>),
And(Vec<Expr>),
Or(Vec<Expr>),
}
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
UnexpectedExpr,
UnexpectedUnaryOp,
UnexpectedBinOp,
UnexpectedParen,
UnexpectedEnd,
}
/// Парсър за прост израз, който не съдържа скоби
#[derive(Clone)]
pub struct SimpleExprParser {
expect_atom: bool,
st: Vec<Expr>,
operations: Vec<char>,
}
impl SimpleExprParser {
pub fn new() -> SimpleExprParser {
SimpleExprParser {
expect_atom: true,
st: Vec::new(),
operations: Vec::new(),
}
}
pub fn add_expr(&mut self, expr: Expr) -> Result<(), ParseError> {
if !self.expect_atom {
return Err(ParseError::UnexpectedExpr);
}
self.expect_atom = false;
self.st.push(expr);
let mut r: Expr;
while !self.operations.is_empty() && *self.operations.last().unwrap() == '!' {
r = self.st.pop().unwrap();
self.st.push(Expr::Not(Box::new(r)));
self.operations.pop();
}
if self.st.len() == 2 {
r = self.st.pop().unwrap();
let l = self.st.pop().unwrap();
match self.operations.pop().unwrap() {
'&' => match l {
Expr::And(mut list) => {
list.push(r);
self.st.push(Expr::And(list))
}
_ => self.st.push(Expr::And(vec![l, r])),
},
'|' => match l {
Expr::Or(mut list) => {
list.push(r);
self.st.push(Expr::Or(list))
}
_ => self.st.push(Expr::Or(vec![l, r])),
},
_ => return Err(ParseError::UnexpectedExpr),
}
}
Ok(())
}
/// Приема атом.
///
/// `c` ще бъде валиден символ за атом.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if !self.expect_atom {
return Err(ParseError::UnexpectedExpr);
}
self.expect_atom = false;
self.st.push(Expr::Atom(c));
let mut r: Expr;
while !self.operations.is_empty() && *self.operations.last().unwrap() == '!' {
r = self.st.pop().unwrap();
self.st.push(Expr::Not(Box::new(r)));
self.operations.pop();
}
if self.st.len() == 2 {
r = self.st.pop().unwrap();
let l = self.st.pop().unwrap();
match self.operations.pop().unwrap() {
'&' => match l {
Expr::And(mut list) => {
list.push(r);
self.st.push(Expr::And(list))
}
_ => self.st.push(Expr::And(vec![l, r])),
},
'|' => match l {
Expr::Or(mut list) => {
list.push(r);
self.st.push(Expr::Or(list))
}
_ => self.st.push(Expr::Or(vec![l, r])),
},
_ => return Err(ParseError::UnexpectedExpr),
}
}
Ok(())
}
/// Приема символ за операция.
///
/// `op` ще бъде едно от '&', '|', '!'.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
match op {
'!' => {
if !self.expect_atom {
return Err(ParseError::UnexpectedUnaryOp);
}
}
'&' | '|' => {
if self.expect_atom {
return Err(ParseError::UnexpectedBinOp);
}
self.expect_atom = true;
}
_ => panic!("Error on : {}", op),
}
self.operations.push(op);
Ok(())
}
/// Завършва парсването и връща построения израз.
pub fn finish(self) -> Result<Expr, ParseError> {
if !self.operations.is_empty() || self.st.is_empty() {
return Err(ParseError::UnexpectedEnd);
}
Ok(self.st.last().unwrap().clone())
}
}
impl Default for SimpleExprParser {
fn default() -> Self {
Self::new()
}
}
//////////// ! ExprParser ! ////////////
/// Парсър за пълния израз
pub struct ExprParser {
stack_frame: Vec<SimpleExprParser>,
expect_paren: bool,
}
impl ExprParser {
pub fn new() -> ExprParser {
ExprParser {
stack_frame: vec![SimpleExprParser::new()],
expect_paren: true,
}
}
/// Приема атом.
///
/// `c` ще бъде валиден символ за атом.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
self.expect_paren = false;
self.stack_frame.last_mut().unwrap().push_atom(c)
}
/// Приема символ за операция.
///
/// `op` ще бъде едно от '&', '|', '!'.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
self.expect_paren = true;
self.stack_frame.last_mut().unwrap().push_op(op)
}
/// Приема отваряща скоба.
pub fn open_paren(&mut self) -> Result<(), ParseError> {
if !self.expect_paren {
return Err(ParseError::UnexpectedParen);
}
self.stack_frame.push(SimpleExprParser::new());
Ok(())
}
/// Приема затваряща скоба.
pub fn close_paren(&mut self) -> Result<(), ParseError> {
if self.stack_frame.is_empty() || self.stack_frame.last().unwrap().st.is_empty() {
return Err(ParseError::UnexpectedParen);
}
let top = self.stack_frame.pop().unwrap();
let expr = match top.finish() {
Err(err) => return Err(err),
Ok(ex) => ex,
};
self.stack_frame.last_mut().unwrap().add_expr(expr)?;
Ok(())
}
/// Завършва парсването и връща построения израз.
pub fn finish(self) -> Result<Expr, ParseError> {
if self.stack_frame.len() != 1 {
return Err(ParseError::UnexpectedEnd);
}
match self.stack_frame.last().unwrap().clone().finish() {
Err(err) => Err(err),
Ok(expr) => Ok(expr),
}
}
}
impl Default for ExprParser {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Value {
True,
False,
Expr(Expr),
}
pub fn eval(expr: &Expr, truthy: &[char], falsy: &[char]) -> Value {
let mut rest = Vec::new();
match expr {
Expr::Atom(x) => {
if truthy.contains(x) {
return Value::True;
}
if falsy.contains(x) {
return Value::False;
}
Value::Expr(Expr::Atom(*x))
}
Expr::Not(ss) => match eval(ss, truthy, falsy) {
Value::True => Value::False,
Value::False => Value::True,
Value::Expr(ex) => Value::Expr(Expr::Not(Box::new(ex))),
},
Expr::And(ss) => {
for e in ss {
match eval(e, truthy, falsy) {
Value::True => continue,
Value::False => return Value::False,
Value::Expr(ex) => rest.push(ex),
}
}
if rest.is_empty() {
Value::True
} else if rest.len() == 1 {
Value::Expr(rest[0].clone())
} else {
Value::Expr(Expr::And(rest))
}
}
Expr::Or(ss) => {
for e in ss {
match eval(e, truthy, falsy) {
Value::True => return Value::True,
Value::False => continue,
Value::Expr(ex) => rest.push(ex),
}
}
if rest.is_empty() {
Value::False
} else if rest.len() == 1 {
Value::Expr(rest[0].clone())
} else {
Value::Expr(Expr::Or(rest))
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// ! Tests ! /////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
// #[test]
// fn test_simple_basic_simple_parser() {
// // A & B
// let mut simple_parser = SimpleExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// let _ = simple_parser.push_atom('B');
// let expr = simple_parser.finish().unwrap();
// eval(&expr, &['A'], &['B']);
// }
// #[test]
// fn test_simple_basic_errors() {
// let mut simple_parser = SimpleExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// assert_eq!(simple_parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
// let mut simple_parser = SimpleExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// let _ = simple_parser.push_atom('B');
// assert_eq!(
// simple_parser.push_atom('B'),
// Err(ParseError::UnexpectedExpr)
// );
// }
// #[test]
// fn test_simple_push_atom_valid() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// }
// #[test]
// fn test_simple_push_atom_unexpected_expr() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert_eq!(parser.push_atom('b'), Err(ParseError::UnexpectedExpr));
// }
// #[test]
// fn test_simple_push_op_not_valid() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_op('!').is_ok()); // Valid unary operator
// }
// #[test]
// fn test_simple_push_op_and_valid() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// }
// #[test]
// fn test_simple_push_op_unexpected_unary_op() {
// let mut parser = SimpleExprParser::new();
// assert_eq!(parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
// assert_eq!(parser.push_op('|'), Err(ParseError::UnexpectedBinOp));
// }
// #[test]
// fn test_simple_push_op_unexpected_bin_op() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert_eq!(parser.push_op('!'), Err(ParseError::UnexpectedUnaryOp));
// }
// #[test]
// fn test_simple_finish_valid_and_expression() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('b').is_ok());
// let result = parser.finish();
// assert_eq!(
// result,
// Ok(Expr::And(vec![Expr::Atom('a'), Expr::Atom('b')]))
// );
// }
// #[test]
// fn test_simple_finish_valid_or_expression() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &['y']), Value::True);
// assert_eq!(eval(&result, &['x', 'y'], &['y']), Value::True);
// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
// }
// #[test]
// fn test_simple_finish_valid_not_expression() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('z').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['a', 'z'], &[]), Value::False);
// }
// #[test]
// fn test_simple_finish_unexpected_end() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// let result = parser.finish();
// assert_eq!(result, Err(ParseError::UnexpectedEnd));
// }
// #[test]
// fn test_simple_finish_empty_parser() {
// let parser = SimpleExprParser::new();
// let result = parser.finish();
// // Empty parser should panic on unwrap
// assert!(result.is_err());
// }
// #[test]
// fn test_simple_nested_operations() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('b').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('c').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['a', 'b'], &['c']), Value::True);
// assert_eq!(eval(&result, &['a', 'c'], &['b']), Value::True);
// assert_eq!(eval(&result, &['c'], &['a', 'b']), Value::True);
// assert_eq!(eval(&result, &['a'], &['b', 'c']), Value::False);
// }
// #[test]
// fn test_simple_multiple_nots() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::True);
// assert_eq!(eval(&result, &[], &['x']), Value::False);
// }
// #[test]
// fn test_simple_value_expr() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &[]), Value::Expr(Expr::Atom('x')));
// }
// #[test]
// fn test_simple_value_expr_not() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::Not(Box::new(Expr::Atom('x'))))
// );
// }
// #[test]
// fn test_simple_value_expr_and() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::And(vec![Expr::Atom('x'), Expr::Atom('y')]))
// );
// }
// #[test]
// fn test_simple_value_expr_or() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::Or(vec![Expr::Atom('x'), Expr::Atom('y')]))
// );
// }
// #[test]
// fn test_simple_value_expr_or_false() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['y']), Value::Expr(Expr::Atom('x')));
// }
// #[test]
// fn test_simple_value_expr_and_true() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::Expr(Expr::Atom('y')));
// }
// #[test]
// fn test_simple_value_expr_or_true() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::True);
// }
// #[test]
// fn test_simple_value_expr_and_false() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['x']), Value::False);
// }
// #[test]
// fn test_value_expr_no_epression() {
// assert_eq!(
// SimpleExprParser::new().finish(),
// Err(ParseError::UnexpectedEnd)
// );
// }
// #[test]
// fn test_basic_expr_parser() {
// // A & (B | !C)
// let mut full_parser = ExprParser::new();
// let _ = full_parser.push_atom('A');
// let _ = full_parser.push_op('&');
// let _ = full_parser.open_paren();
// let _ = full_parser.push_atom('B');
// let _ = full_parser.push_op('|');
// let _ = full_parser.push_op('!');
// let _ = full_parser.push_atom('C');
// let _ = full_parser.close_paren();
// let expr = full_parser.finish().unwrap();
// eval(&expr, &['A'], &['B']);
// }
// #[test]
// fn test_basic_simple_parser() {
// // A & B
// let mut simple_parser = ExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// let _ = simple_parser.push_atom('B');
// let expr = simple_parser.finish().unwrap();
// eval(&expr, &['A'], &['B']);
// }
// #[test]
// fn test_basic_errors() {
// let mut simple_parser = ExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// assert_eq!(simple_parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
// let mut simple_parser = ExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// let _ = simple_parser.push_atom('B');
// assert_eq!(
// simple_parser.push_atom('B'),
// Err(ParseError::UnexpectedExpr)
// );
// }
// #[test]
// fn test_push_atom_valid() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// }
// #[test]
// fn test_push_atom_unexpected_expr() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert_eq!(parser.push_atom('b'), Err(ParseError::UnexpectedExpr));
// }
// #[test]
// fn test_push_op_not_valid() {
// let mut parser = ExprParser::new();
// assert!(parser.push_op('!').is_ok()); // Valid unary operator
// }
// #[test]
// fn test_push_op_and_valid() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// }
// #[test]
// fn test_push_op_unexpected_unary_op() {
// let mut parser = ExprParser::new();
// assert_eq!(parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
// assert_eq!(parser.push_op('|'), Err(ParseError::UnexpectedBinOp));
// }
// #[test]
// fn test_push_op_unexpected_bin_op() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert_eq!(parser.push_op('!'), Err(ParseError::UnexpectedUnaryOp));
// }
// #[test]
// fn test_finish_valid_and_expression() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('b').is_ok());
// let result = parser.finish();
// assert_eq!(
// result,
// Ok(Expr::And(vec![Expr::Atom('a'), Expr::Atom('b')]))
// );
// }
// #[test]
// fn test_finish_valid_or_expression() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &['y']), Value::True);
// assert_eq!(eval(&result, &['x', 'y'], &['y']), Value::True);
// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
// }
// #[test]
// fn test_finish_valid_not_expression() {
// let mut parser = ExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('z').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['a', 'z'], &[]), Value::False);
// }
// #[test]
// fn test_finish_unexpected_end() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// let result = parser.finish();
// assert_eq!(result, Err(ParseError::UnexpectedEnd));
// }
// #[test]
// fn test_finish_empty_parser() {
// let parser = ExprParser::new();
// let result = parser.finish();
// // Empty parser should panic on unwrap
// assert!(result.is_err());
// }
// #[test]
// fn test_nested_operations() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('b').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('c').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['a', 'b'], &['c']), Value::True);
// assert_eq!(eval(&result, &['a', 'c'], &['b']), Value::True);
// assert_eq!(eval(&result, &['c'], &['a', 'b']), Value::True);
// assert_eq!(eval(&result, &['a'], &['b', 'c']), Value::False);
// }
// #[test]
// fn test_multiple_nots() {
// let mut parser = ExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::True);
// assert_eq!(eval(&result, &[], &['x']), Value::False);
// }
// #[test]
// fn test_value_expr() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &[]), Value::Expr(Expr::Atom('x')));
// }
// #[test]
// fn test_value_expr_not() {
// let mut parser = ExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::Not(Box::new(Expr::Atom('x'))))
// );
// }
// #[test]
// fn test_value_expr_and() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::And(vec![Expr::Atom('x'), Expr::Atom('y')]))
// );
// }
// #[test]
// fn test_value_expr_or() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::Or(vec![Expr::Atom('x'), Expr::Atom('y')]))
// );
// }
// #[test]
// fn test_value_expr_or_false() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['y']), Value::Expr(Expr::Atom('x')));
// }
// #[test]
// fn test_value_expr_and_true() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::Expr(Expr::Atom('y')));
// }
// #[test]
// fn test_value_expr_or_true() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::True);
// }
// #[test]
// fn test_value_expr_and_false() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['x']), Value::False);
// }
// // start with (
// #[test]
// fn test_value_expr_starts_with_paren() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['x']), Value::Expr(Expr::Atom('y')));
// }
// // nested ()
// #[test]
// fn test_value_expr_nested_paren() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// assert!(parser.close_paren().is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['y']), Value::False);
// }
// // nested ()
// #[test]
// fn test_value_expr_nested_paren_big() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// assert!(parser.close_paren().is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x', 'y'], &[]), Value::True);
// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
// assert_eq!(eval(&result, &['x'], &['y']), Value::False);
// assert_eq!(eval(&result, &['y'], &['x']), Value::True);
// }
// // nested ()
// #[test]
// fn test_value_expr_nested_paren_biggggg() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// assert!(parser.close_paren().is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x', 'y'], &[]), Value::True);
// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
// assert_eq!(eval(&result, &['x'], &['y']), Value::False);
// assert_eq!(eval(&result, &['y'], &['x']), Value::True);
// }
// // no opening )
// #[test]
// fn test_value_expr_no_open_paren() {
// let mut parser = ExprParser::new();
// assert!(parser.close_paren().is_err());
// }
// // no closing )
// #[test]
// fn test_value_expr_no_close_paren() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert_eq!(parser.finish(), Err(ParseError::UnexpectedEnd));
// }
// #[test]
// fn test_value_expr_no_expression() {
// assert_eq!(ExprParser::new().finish(), Err(ParseError::UnexpectedEnd));
// }
// #[test]
// fn test_value_expr_no_expression_nested() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.close_paren().is_err());
// }
// combined expr
// #[test]
// fn test_value_expr_combined() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('A').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('B').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('C').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('D').is_ok());
// assert!(parser.close_paren().is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['A', 'C'], &['B', 'D']), Value::True);
// assert_eq!(eval(&result, &['A', 'D'], &['B', 'C']), Value::True);
// assert_eq!(eval(&result, &[], &['A']), Value::False);
// assert_eq!(eval(&result, &['B'], &[]), Value::False);
// assert_eq!(eval(&result, &[], &['C', 'D']), Value::False);
// assert_eq!(
// eval(&result, &['C'], &[]),
// Value::Expr(Expr::And(vec![
// Expr::Atom('A'),
// Expr::Not(Box::new(Expr::Atom('B'))),
// ]))
// );
// assert_eq!(
// eval(&result, &[], &['C']),
// Value::Expr(Expr::And(vec![
// Expr::Atom('A'),
// Expr::Not(Box::new(Expr::Atom('B'))),
// Expr::Atom('D')
// ]))
// );
// assert_eq!(
// eval(&result, &['A'], &['B']),
// Value::Expr(Expr::Or(vec![Expr::Atom('C'), Expr::Atom('D')]))
// );
// }
// add paren after atom err
// #[test]
// fn test_value_expr_add_paren_after_atom_err() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.open_paren().is_err());
// }
// add op paren after (
// #[test]
// fn test_value_expr_add_op_after_paren() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_op('|').is_err());
// }

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20241224-258381-14vhtj0/solution)
warning: variable does not need to be mutable
   --> tests/solution_test.rs:306:13
    |
306 |         let mut parser = SimpleExprParser::new();
    |             ----^^^^^^
    |             |
    |             help: remove this `mut`
    |
    = note: `#[warn(unused_mut)]` on by default

warning: `solution` (test "solution_test") generated 1 warning
    Finished test [unoptimized + debuginfo] target(s) in 2.08s
     Running tests/solution_test.rs (target/debug/deps/solution_test-1428e1090729d165)

running 20 tests
test solution_test::test_eval_full ... ok
test solution_test::test_error_paren_mismatched ... ok
test solution_test::test_eval_not_and_or ... ok
test solution_test::test_eval_partial ... ok
test solution_test::test_eval_unwrap_nested ... ok
test solution_test::test_eval_unwrap_and_or ... ok
test solution_test::test_paren_around_expr ... ok
test solution_test::test_paren_expr_priority ... ok
test solution_test::test_paren_nested ... ok
test solution_test::test_paren_not ... ok
test solution_test::test_paren_surrounded ... ok
test solution_test::test_parser_alternating_ops ... ok
test solution_test::test_parser_and_or ... ok
test solution_test::test_parser_atom ... ok
test solution_test::test_parser_error_unexpected_end ... ok
test solution_test::test_parser_errors_basic ... ok
test solution_test::test_parser_expr_and_not ... ok
test solution_test::test_parser_multiple_atoms_same_op ... ok
test solution_test::test_parser_not ... ok
test solution_test::test_parser_multiple_not ... ok

test result: ok. 20 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

История (3 версии и 0 коментара)

Александър качи първо решение на 21.12.2024 15:42 (преди 9 месеца)

Александър качи решение на 21.12.2024 15:46 (преди 9 месеца)

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr {
Atom(char),
Not(Box<Expr>),
And(Vec<Expr>),
Or(Vec<Expr>),
}
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
UnexpectedExpr,
UnexpectedUnaryOp,
UnexpectedBinOp,
UnexpectedParen,
UnexpectedEnd,
}
/// Парсър за прост израз, който не съдържа скоби
#[derive(Clone)]
pub struct SimpleExprParser {
expect_atom: bool,
st: Vec<Expr>,
operations: Vec<char>,
}
impl SimpleExprParser {
pub fn new() -> SimpleExprParser {
SimpleExprParser {
expect_atom: true,
st: Vec::new(),
operations: Vec::new(),
}
}
pub fn add_expr(&mut self, expr: Expr) -> Result<(), ParseError> {
if !self.expect_atom {
return Err(ParseError::UnexpectedExpr);
}
self.expect_atom = false;
self.st.push(expr);
let mut r: Expr;
while !self.operations.is_empty() && *self.operations.last().unwrap() == '!' {
r = self.st.pop().unwrap();
self.st.push(Expr::Not(Box::new(r)));
self.operations.pop();
}
if self.st.len() == 2 {
r = self.st.pop().unwrap();
let l = self.st.pop().unwrap();
match self.operations.pop().unwrap() {
'&' => match l {
Expr::And(mut list) => {
list.push(r);
self.st.push(Expr::And(list))
}
_ => self.st.push(Expr::And(vec![l, r])),
},
'|' => match l {
Expr::Or(mut list) => {
list.push(r);
self.st.push(Expr::Or(list))
}
_ => self.st.push(Expr::Or(vec![l, r])),
},
_ => return Err(ParseError::UnexpectedExpr),
}
}
Ok(())
}
/// Приема атом.
///
/// `c` ще бъде валиден символ за атом.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if !self.expect_atom {
return Err(ParseError::UnexpectedExpr);
}
self.expect_atom = false;
self.st.push(Expr::Atom(c));
let mut r: Expr;
while !self.operations.is_empty() && *self.operations.last().unwrap() == '!' {
r = self.st.pop().unwrap();
self.st.push(Expr::Not(Box::new(r)));
self.operations.pop();
}
if self.st.len() == 2 {
r = self.st.pop().unwrap();
let l = self.st.pop().unwrap();
match self.operations.pop().unwrap() {
'&' => match l {
Expr::And(mut list) => {
list.push(r);
self.st.push(Expr::And(list))
}
_ => self.st.push(Expr::And(vec![l, r])),
},
'|' => match l {
Expr::Or(mut list) => {
list.push(r);
self.st.push(Expr::Or(list))
}
_ => self.st.push(Expr::Or(vec![l, r])),
},
_ => return Err(ParseError::UnexpectedExpr),
}
}
Ok(())
}
/// Приема символ за операция.
///
/// `op` ще бъде едно от '&', '|', '!'.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
match op {
'!' => {
if !self.expect_atom {
return Err(ParseError::UnexpectedUnaryOp);
}
}
'&' | '|' => {
if self.expect_atom {
return Err(ParseError::UnexpectedBinOp);
}
self.expect_atom = true;
}
_ => panic!("Error on : {}", op),
}
self.operations.push(op);
Ok(())
}
/// Завършва парсването и връща построения израз.
pub fn finish(self) -> Result<Expr, ParseError> {
if !self.operations.is_empty() || self.st.is_empty() {
return Err(ParseError::UnexpectedEnd);
}
Ok(self.st.last().unwrap().clone())
}
}
impl Default for SimpleExprParser {
fn default() -> Self {
Self::new()
}
}
//////////// ! ExprParser ! ////////////
/// Парсър за пълния израз
pub struct ExprParser {
stack_frame: Vec<SimpleExprParser>,
expect_paren: bool,
}
impl ExprParser {
pub fn new() -> ExprParser {
ExprParser {
stack_frame: vec![SimpleExprParser::new()],
expect_paren: true,
}
}
/// Приема атом.
///
/// `c` ще бъде валиден символ за атом.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
self.expect_paren = false;
self.stack_frame.last_mut().unwrap().push_atom(c)
}
/// Приема символ за операция.
///
/// `op` ще бъде едно от '&', '|', '!'.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
self.expect_paren = true;
self.stack_frame.last_mut().unwrap().push_op(op)
}
/// Приема отваряща скоба.
pub fn open_paren(&mut self) -> Result<(), ParseError> {
if !self.expect_paren {
return Err(ParseError::UnexpectedParen);
}
self.stack_frame.push(SimpleExprParser::new());
Ok(())
}
/// Приема затваряща скоба.
pub fn close_paren(&mut self) -> Result<(), ParseError> {
if self.stack_frame.is_empty() || self.stack_frame.last().unwrap().st.is_empty() {
return Err(ParseError::UnexpectedParen);
}
let top = self.stack_frame.pop().unwrap();
let expr = match top.finish() {
Err(err) => return Err(err),
Ok(ex) => ex,
};
self.stack_frame.last_mut().unwrap().add_expr(expr)?;
Ok(())
}
/// Завършва парсването и връща построения израз.
pub fn finish(self) -> Result<Expr, ParseError> {
if self.stack_frame.len() != 1 {
return Err(ParseError::UnexpectedEnd);
}
match self.stack_frame.last().unwrap().clone().finish() {
Err(err) => Err(err),
Ok(expr) => Ok(expr),
}
}
}
impl Default for ExprParser {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Value {
True,
False,
Expr(Expr),
}
pub fn eval(expr: &Expr, truthy: &[char], falsy: &[char]) -> Value {
let mut rest = Vec::new();
match expr {
Expr::Atom(x) => {
if truthy.contains(x) {
return Value::True;
}
if falsy.contains(x) {
return Value::False;
}
Value::Expr(Expr::Atom(*x))
}
Expr::Not(ss) => match eval(ss, truthy, falsy) {
Value::True => Value::False,
Value::False => Value::True,
Value::Expr(ex) => Value::Expr(Expr::Not(Box::new(ex))),
},
Expr::And(ss) => {
for e in ss {
match eval(e, truthy, falsy) {
Value::True => continue,
Value::False => return Value::False,
Value::Expr(ex) => rest.push(ex),
}
}
if rest.is_empty() {
Value::True
} else if rest.len() == 1 {
Value::Expr(rest[0].clone())
} else {
Value::Expr(Expr::And(rest))
}
}
Expr::Or(ss) => {
for e in ss {
match eval(e, truthy, falsy) {
Value::True => return Value::True,
Value::False => continue,
Value::Expr(ex) => rest.push(ex),
}
}
if rest.is_empty() {
Value::False
} else if rest.len() == 1 {
Value::Expr(rest[0].clone())
} else {
Value::Expr(Expr::Or(rest))
}
}
}
}
+
+////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////// ! Tests ! /////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////
+
+// #[test]
+// fn test_simple_basic_simple_parser() {
+// // A & B
+// let mut simple_parser = SimpleExprParser::new();
+// let _ = simple_parser.push_atom('A');
+// let _ = simple_parser.push_op('&');
+// let _ = simple_parser.push_atom('B');
+// let expr = simple_parser.finish().unwrap();
+
+// eval(&expr, &['A'], &['B']);
+// }
+
+// #[test]
+// fn test_simple_basic_errors() {
+// let mut simple_parser = SimpleExprParser::new();
+// let _ = simple_parser.push_atom('A');
+// let _ = simple_parser.push_op('&');
+// assert_eq!(simple_parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
+
+// let mut simple_parser = SimpleExprParser::new();
+// let _ = simple_parser.push_atom('A');
+// let _ = simple_parser.push_op('&');
+// let _ = simple_parser.push_atom('B');
+// assert_eq!(
+// simple_parser.push_atom('B'),
+// Err(ParseError::UnexpectedExpr)
+// );
+// }
+
+// #[test]
+// fn test_simple_push_atom_valid() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// }
+
+// #[test]
+// fn test_simple_push_atom_unexpected_expr() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert_eq!(parser.push_atom('b'), Err(ParseError::UnexpectedExpr));
+// }
+
+// #[test]
+// fn test_simple_push_op_not_valid() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_op('!').is_ok()); // Valid unary operator
+// }
+
+// #[test]
+// fn test_simple_push_op_and_valid() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// }
+
+// #[test]
+// fn test_simple_push_op_unexpected_unary_op() {
+// let mut parser = SimpleExprParser::new();
+// assert_eq!(parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
+// assert_eq!(parser.push_op('|'), Err(ParseError::UnexpectedBinOp));
+// }
+
+// #[test]
+// fn test_simple_push_op_unexpected_bin_op() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert_eq!(parser.push_op('!'), Err(ParseError::UnexpectedUnaryOp));
+// }
+
+// #[test]
+// fn test_simple_finish_valid_and_expression() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('b').is_ok());
+// let result = parser.finish();
+// assert_eq!(
+// result,
+// Ok(Expr::And(vec![Expr::Atom('a'), Expr::Atom('b')]))
+// );
+// }
+
+// #[test]
+// fn test_simple_finish_valid_or_expression() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['x'], &['y']), Value::True);
+// assert_eq!(eval(&result, &['x', 'y'], &['y']), Value::True);
+// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
+// }
+
+// #[test]
+// fn test_simple_finish_valid_not_expression() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_atom('z').is_ok());
+// let result = parser.finish().unwrap();
+// assert_eq!(eval(&result, &['a', 'z'], &[]), Value::False);
+// }
+
+// #[test]
+// fn test_simple_finish_unexpected_end() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// let result = parser.finish();
+// assert_eq!(result, Err(ParseError::UnexpectedEnd));
+// }
+
+// #[test]
+// fn test_simple_finish_empty_parser() {
+// let parser = SimpleExprParser::new();
+// let result = parser.finish();
+// // Empty parser should panic on unwrap
+// assert!(result.is_err());
+// }
+
+// #[test]
+// fn test_simple_nested_operations() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('b').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('c').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['a', 'b'], &['c']), Value::True);
+// assert_eq!(eval(&result, &['a', 'c'], &['b']), Value::True);
+// assert_eq!(eval(&result, &['c'], &['a', 'b']), Value::True);
+// assert_eq!(eval(&result, &['a'], &['b', 'c']), Value::False);
+// }
+
+// #[test]
+// fn test_simple_multiple_nots() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_atom('x').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['x'], &[]), Value::True);
+// assert_eq!(eval(&result, &[], &['x']), Value::False);
+// }
+
+// #[test]
+// fn test_simple_value_expr() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &[], &[]), Value::Expr(Expr::Atom('x')));
+// }
+
+// #[test]
+// fn test_simple_value_expr_not() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_atom('x').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(
+// eval(&result, &[], &[]),
+// Value::Expr(Expr::Not(Box::new(Expr::Atom('x'))))
+// );
+// }
+
+// #[test]
+// fn test_simple_value_expr_and() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(
+// eval(&result, &[], &[]),
+// Value::Expr(Expr::And(vec![Expr::Atom('x'), Expr::Atom('y')]))
+// );
+// }
+
+// #[test]
+// fn test_simple_value_expr_or() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(
+// eval(&result, &[], &[]),
+// Value::Expr(Expr::Or(vec![Expr::Atom('x'), Expr::Atom('y')]))
+// );
+// }
+
+// #[test]
+// fn test_simple_value_expr_or_false() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &[], &['y']), Value::Expr(Expr::Atom('x')));
+// }
+
+// #[test]
+// fn test_simple_value_expr_and_true() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['x'], &[]), Value::Expr(Expr::Atom('y')));
+// }
+
+// #[test]
+// fn test_simple_value_expr_or_true() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['x'], &[]), Value::True);
+// }
+
+// #[test]
+// fn test_simple_value_expr_and_false() {
+// let mut parser = SimpleExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &[], &['x']), Value::False);
+// }
+
+// #[test]
+// fn test_value_expr_no_epression() {
+// assert_eq!(
+// SimpleExprParser::new().finish(),
+// Err(ParseError::UnexpectedEnd)
+// );
+// }
+
+// #[test]
+// fn test_basic_expr_parser() {
+// // A & (B | !C)
+// let mut full_parser = ExprParser::new();
+// let _ = full_parser.push_atom('A');
+// let _ = full_parser.push_op('&');
+// let _ = full_parser.open_paren();
+// let _ = full_parser.push_atom('B');
+// let _ = full_parser.push_op('|');
+// let _ = full_parser.push_op('!');
+// let _ = full_parser.push_atom('C');
+// let _ = full_parser.close_paren();
+// let expr = full_parser.finish().unwrap();
+
+// eval(&expr, &['A'], &['B']);
+// }
+
+// #[test]
+// fn test_basic_simple_parser() {
+// // A & B
+// let mut simple_parser = ExprParser::new();
+// let _ = simple_parser.push_atom('A');
+// let _ = simple_parser.push_op('&');
+// let _ = simple_parser.push_atom('B');
+// let expr = simple_parser.finish().unwrap();
+
+// eval(&expr, &['A'], &['B']);
+// }
+
+// #[test]
+// fn test_basic_errors() {
+// let mut simple_parser = ExprParser::new();
+// let _ = simple_parser.push_atom('A');
+// let _ = simple_parser.push_op('&');
+// assert_eq!(simple_parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
+
+// let mut simple_parser = ExprParser::new();
+// let _ = simple_parser.push_atom('A');
+// let _ = simple_parser.push_op('&');
+// let _ = simple_parser.push_atom('B');
+// assert_eq!(
+// simple_parser.push_atom('B'),
+// Err(ParseError::UnexpectedExpr)
+// );
+// }
+
+// #[test]
+// fn test_push_atom_valid() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// }
+
+// #[test]
+// fn test_push_atom_unexpected_expr() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert_eq!(parser.push_atom('b'), Err(ParseError::UnexpectedExpr));
+// }
+
+// #[test]
+// fn test_push_op_not_valid() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_op('!').is_ok()); // Valid unary operator
+// }
+
+// #[test]
+// fn test_push_op_and_valid() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// }
+
+// #[test]
+// fn test_push_op_unexpected_unary_op() {
+// let mut parser = ExprParser::new();
+// assert_eq!(parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
+// assert_eq!(parser.push_op('|'), Err(ParseError::UnexpectedBinOp));
+// }
+
+// #[test]
+// fn test_push_op_unexpected_bin_op() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert_eq!(parser.push_op('!'), Err(ParseError::UnexpectedUnaryOp));
+// }
+
+// #[test]
+// fn test_finish_valid_and_expression() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('b').is_ok());
+// let result = parser.finish();
+// assert_eq!(
+// result,
+// Ok(Expr::And(vec![Expr::Atom('a'), Expr::Atom('b')]))
+// );
+// }
+
+// #[test]
+// fn test_finish_valid_or_expression() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['x'], &['y']), Value::True);
+// assert_eq!(eval(&result, &['x', 'y'], &['y']), Value::True);
+// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
+// }
+
+// #[test]
+// fn test_finish_valid_not_expression() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_atom('z').is_ok());
+// let result = parser.finish().unwrap();
+// assert_eq!(eval(&result, &['a', 'z'], &[]), Value::False);
+// }
+
+// #[test]
+// fn test_finish_unexpected_end() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// let result = parser.finish();
+// assert_eq!(result, Err(ParseError::UnexpectedEnd));
+// }
+
+// #[test]
+// fn test_finish_empty_parser() {
+// let parser = ExprParser::new();
+// let result = parser.finish();
+// // Empty parser should panic on unwrap
+// assert!(result.is_err());
+// }
+
+// #[test]
+// fn test_nested_operations() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('a').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('b').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('c').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['a', 'b'], &['c']), Value::True);
+// assert_eq!(eval(&result, &['a', 'c'], &['b']), Value::True);
+// assert_eq!(eval(&result, &['c'], &['a', 'b']), Value::True);
+// assert_eq!(eval(&result, &['a'], &['b', 'c']), Value::False);
+// }
+
+// #[test]
+// fn test_multiple_nots() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_atom('x').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['x'], &[]), Value::True);
+// assert_eq!(eval(&result, &[], &['x']), Value::False);
+// }
+
+// #[test]
+// fn test_value_expr() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &[], &[]), Value::Expr(Expr::Atom('x')));
+// }
+
+// #[test]
+// fn test_value_expr_not() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_atom('x').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(
+// eval(&result, &[], &[]),
+// Value::Expr(Expr::Not(Box::new(Expr::Atom('x'))))
+// );
+// }
+
+// #[test]
+// fn test_value_expr_and() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(
+// eval(&result, &[], &[]),
+// Value::Expr(Expr::And(vec![Expr::Atom('x'), Expr::Atom('y')]))
+// );
+// }
+
+// #[test]
+// fn test_value_expr_or() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(
+// eval(&result, &[], &[]),
+// Value::Expr(Expr::Or(vec![Expr::Atom('x'), Expr::Atom('y')]))
+// );
+// }
+
+// #[test]
+// fn test_value_expr_or_false() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &[], &['y']), Value::Expr(Expr::Atom('x')));
+// }
+
+// #[test]
+// fn test_value_expr_and_true() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['x'], &[]), Value::Expr(Expr::Atom('y')));
+// }
+
+// #[test]
+// fn test_value_expr_or_true() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['x'], &[]), Value::True);
+// }
+
+// #[test]
+// fn test_value_expr_and_false() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &[], &['x']), Value::False);
+// }
+
+// // start with (
+// #[test]
+// fn test_value_expr_starts_with_paren() {
+// let mut parser = ExprParser::new();
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.push_atom('y').is_ok());
+// assert!(parser.close_paren().is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &[], &['x']), Value::Expr(Expr::Atom('y')));
+// }
+
+// // nested ()
+// #[test]
+// fn test_value_expr_nested_paren() {
+// let mut parser = ExprParser::new();
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.push_atom('y').is_ok());
+// assert!(parser.close_paren().is_ok());
+// assert!(parser.close_paren().is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &[], &['y']), Value::False);
+// }
+
+// // nested ()
+// #[test]
+// fn test_value_expr_nested_paren_big() {
+// let mut parser = ExprParser::new();
+// assert!(parser.open_paren().is_ok());
+
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+// assert!(parser.close_paren().is_ok());
+
+// assert!(parser.push_op('|').is_ok());
+
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+// assert!(parser.close_paren().is_ok());
+
+// assert!(parser.close_paren().is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['x', 'y'], &[]), Value::True);
+// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
+// assert_eq!(eval(&result, &['x'], &['y']), Value::False);
+// assert_eq!(eval(&result, &['y'], &['x']), Value::True);
+// }
+
+// // nested ()
+// #[test]
+// fn test_value_expr_nested_paren_biggggg() {
+// let mut parser = ExprParser::new();
+// assert!(parser.open_paren().is_ok());
+
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+// assert!(parser.close_paren().is_ok());
+
+// assert!(parser.push_op('|').is_ok());
+
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_atom('y').is_ok());
+// assert!(parser.close_paren().is_ok());
+
+// assert!(parser.close_paren().is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['x', 'y'], &[]), Value::True);
+// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
+// assert_eq!(eval(&result, &['x'], &['y']), Value::False);
+// assert_eq!(eval(&result, &['y'], &['x']), Value::True);
+// }
+
+// // no opening )
+
+// #[test]
+// fn test_value_expr_no_open_paren() {
+// let mut parser = ExprParser::new();
+// assert!(parser.close_paren().is_err());
+// }
+
+// // no closing )
+// #[test]
+// fn test_value_expr_no_close_paren() {
+// let mut parser = ExprParser::new();
+// assert!(parser.open_paren().is_ok());
+
+// assert_eq!(parser.finish(), Err(ParseError::UnexpectedEnd));
+// }
+
+// #[test]
+// fn test_value_expr_no_expression() {
+// assert_eq!(ExprParser::new().finish(), Err(ParseError::UnexpectedEnd));
+// }
+
+// #[test]
+// fn test_value_expr_no_expression_nested() {
+// let mut parser = ExprParser::new();
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.close_paren().is_err());
+// }

Александър качи решение на 21.12.2024 16:38 (преди 9 месеца)

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr {
Atom(char),
Not(Box<Expr>),
And(Vec<Expr>),
Or(Vec<Expr>),
}
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
UnexpectedExpr,
UnexpectedUnaryOp,
UnexpectedBinOp,
UnexpectedParen,
UnexpectedEnd,
}
/// Парсър за прост израз, който не съдържа скоби
#[derive(Clone)]
pub struct SimpleExprParser {
expect_atom: bool,
st: Vec<Expr>,
operations: Vec<char>,
}
impl SimpleExprParser {
pub fn new() -> SimpleExprParser {
SimpleExprParser {
expect_atom: true,
st: Vec::new(),
operations: Vec::new(),
}
}
pub fn add_expr(&mut self, expr: Expr) -> Result<(), ParseError> {
if !self.expect_atom {
return Err(ParseError::UnexpectedExpr);
}
self.expect_atom = false;
self.st.push(expr);
let mut r: Expr;
while !self.operations.is_empty() && *self.operations.last().unwrap() == '!' {
r = self.st.pop().unwrap();
self.st.push(Expr::Not(Box::new(r)));
self.operations.pop();
}
if self.st.len() == 2 {
r = self.st.pop().unwrap();
let l = self.st.pop().unwrap();
match self.operations.pop().unwrap() {
'&' => match l {
Expr::And(mut list) => {
list.push(r);
self.st.push(Expr::And(list))
}
_ => self.st.push(Expr::And(vec![l, r])),
},
'|' => match l {
Expr::Or(mut list) => {
list.push(r);
self.st.push(Expr::Or(list))
}
_ => self.st.push(Expr::Or(vec![l, r])),
},
_ => return Err(ParseError::UnexpectedExpr),
}
}
Ok(())
}
/// Приема атом.
///
/// `c` ще бъде валиден символ за атом.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
if !self.expect_atom {
return Err(ParseError::UnexpectedExpr);
}
self.expect_atom = false;
self.st.push(Expr::Atom(c));
let mut r: Expr;
while !self.operations.is_empty() && *self.operations.last().unwrap() == '!' {
r = self.st.pop().unwrap();
self.st.push(Expr::Not(Box::new(r)));
self.operations.pop();
}
if self.st.len() == 2 {
r = self.st.pop().unwrap();
let l = self.st.pop().unwrap();
match self.operations.pop().unwrap() {
'&' => match l {
Expr::And(mut list) => {
list.push(r);
self.st.push(Expr::And(list))
}
_ => self.st.push(Expr::And(vec![l, r])),
},
'|' => match l {
Expr::Or(mut list) => {
list.push(r);
self.st.push(Expr::Or(list))
}
_ => self.st.push(Expr::Or(vec![l, r])),
},
_ => return Err(ParseError::UnexpectedExpr),
}
}
Ok(())
}
/// Приема символ за операция.
///
/// `op` ще бъде едно от '&', '|', '!'.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
match op {
'!' => {
if !self.expect_atom {
return Err(ParseError::UnexpectedUnaryOp);
}
}
'&' | '|' => {
if self.expect_atom {
return Err(ParseError::UnexpectedBinOp);
}
self.expect_atom = true;
}
_ => panic!("Error on : {}", op),
}
self.operations.push(op);
Ok(())
}
/// Завършва парсването и връща построения израз.
pub fn finish(self) -> Result<Expr, ParseError> {
if !self.operations.is_empty() || self.st.is_empty() {
return Err(ParseError::UnexpectedEnd);
}
Ok(self.st.last().unwrap().clone())
}
}
impl Default for SimpleExprParser {
fn default() -> Self {
Self::new()
}
}
//////////// ! ExprParser ! ////////////
/// Парсър за пълния израз
pub struct ExprParser {
stack_frame: Vec<SimpleExprParser>,
expect_paren: bool,
}
impl ExprParser {
pub fn new() -> ExprParser {
ExprParser {
stack_frame: vec![SimpleExprParser::new()],
expect_paren: true,
}
}
/// Приема атом.
///
/// `c` ще бъде валиден символ за атом.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_atom(&mut self, c: char) -> Result<(), ParseError> {
self.expect_paren = false;
self.stack_frame.last_mut().unwrap().push_atom(c)
}
/// Приема символ за операция.
///
/// `op` ще бъде едно от '&', '|', '!'.
/// В противен случай можете да panic-нете (няма да се тества)
pub fn push_op(&mut self, op: char) -> Result<(), ParseError> {
self.expect_paren = true;
self.stack_frame.last_mut().unwrap().push_op(op)
}
/// Приема отваряща скоба.
pub fn open_paren(&mut self) -> Result<(), ParseError> {
if !self.expect_paren {
return Err(ParseError::UnexpectedParen);
}
self.stack_frame.push(SimpleExprParser::new());
Ok(())
}
/// Приема затваряща скоба.
pub fn close_paren(&mut self) -> Result<(), ParseError> {
if self.stack_frame.is_empty() || self.stack_frame.last().unwrap().st.is_empty() {
return Err(ParseError::UnexpectedParen);
}
let top = self.stack_frame.pop().unwrap();
let expr = match top.finish() {
Err(err) => return Err(err),
Ok(ex) => ex,
};
self.stack_frame.last_mut().unwrap().add_expr(expr)?;
Ok(())
}
/// Завършва парсването и връща построения израз.
pub fn finish(self) -> Result<Expr, ParseError> {
if self.stack_frame.len() != 1 {
return Err(ParseError::UnexpectedEnd);
}
match self.stack_frame.last().unwrap().clone().finish() {
Err(err) => Err(err),
Ok(expr) => Ok(expr),
}
}
}
impl Default for ExprParser {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Value {
True,
False,
Expr(Expr),
}
pub fn eval(expr: &Expr, truthy: &[char], falsy: &[char]) -> Value {
let mut rest = Vec::new();
match expr {
Expr::Atom(x) => {
if truthy.contains(x) {
return Value::True;
}
if falsy.contains(x) {
return Value::False;
}
Value::Expr(Expr::Atom(*x))
}
Expr::Not(ss) => match eval(ss, truthy, falsy) {
Value::True => Value::False,
Value::False => Value::True,
Value::Expr(ex) => Value::Expr(Expr::Not(Box::new(ex))),
},
Expr::And(ss) => {
for e in ss {
match eval(e, truthy, falsy) {
Value::True => continue,
Value::False => return Value::False,
Value::Expr(ex) => rest.push(ex),
}
}
if rest.is_empty() {
Value::True
} else if rest.len() == 1 {
Value::Expr(rest[0].clone())
} else {
Value::Expr(Expr::And(rest))
}
}
Expr::Or(ss) => {
for e in ss {
match eval(e, truthy, falsy) {
Value::True => return Value::True,
Value::False => continue,
Value::Expr(ex) => rest.push(ex),
}
}
if rest.is_empty() {
Value::False
} else if rest.len() == 1 {
Value::Expr(rest[0].clone())
} else {
Value::Expr(Expr::Or(rest))
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// ! Tests ! /////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
// #[test]
// fn test_simple_basic_simple_parser() {
// // A & B
// let mut simple_parser = SimpleExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// let _ = simple_parser.push_atom('B');
// let expr = simple_parser.finish().unwrap();
// eval(&expr, &['A'], &['B']);
// }
// #[test]
// fn test_simple_basic_errors() {
// let mut simple_parser = SimpleExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// assert_eq!(simple_parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
// let mut simple_parser = SimpleExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// let _ = simple_parser.push_atom('B');
// assert_eq!(
// simple_parser.push_atom('B'),
// Err(ParseError::UnexpectedExpr)
// );
// }
// #[test]
// fn test_simple_push_atom_valid() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// }
// #[test]
// fn test_simple_push_atom_unexpected_expr() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert_eq!(parser.push_atom('b'), Err(ParseError::UnexpectedExpr));
// }
// #[test]
// fn test_simple_push_op_not_valid() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_op('!').is_ok()); // Valid unary operator
// }
// #[test]
// fn test_simple_push_op_and_valid() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// }
// #[test]
// fn test_simple_push_op_unexpected_unary_op() {
// let mut parser = SimpleExprParser::new();
// assert_eq!(parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
// assert_eq!(parser.push_op('|'), Err(ParseError::UnexpectedBinOp));
// }
// #[test]
// fn test_simple_push_op_unexpected_bin_op() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert_eq!(parser.push_op('!'), Err(ParseError::UnexpectedUnaryOp));
// }
// #[test]
// fn test_simple_finish_valid_and_expression() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('b').is_ok());
// let result = parser.finish();
// assert_eq!(
// result,
// Ok(Expr::And(vec![Expr::Atom('a'), Expr::Atom('b')]))
// );
// }
// #[test]
// fn test_simple_finish_valid_or_expression() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &['y']), Value::True);
// assert_eq!(eval(&result, &['x', 'y'], &['y']), Value::True);
// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
// }
// #[test]
// fn test_simple_finish_valid_not_expression() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('z').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['a', 'z'], &[]), Value::False);
// }
// #[test]
// fn test_simple_finish_unexpected_end() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// let result = parser.finish();
// assert_eq!(result, Err(ParseError::UnexpectedEnd));
// }
// #[test]
// fn test_simple_finish_empty_parser() {
// let parser = SimpleExprParser::new();
// let result = parser.finish();
// // Empty parser should panic on unwrap
// assert!(result.is_err());
// }
// #[test]
// fn test_simple_nested_operations() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('b').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('c').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['a', 'b'], &['c']), Value::True);
// assert_eq!(eval(&result, &['a', 'c'], &['b']), Value::True);
// assert_eq!(eval(&result, &['c'], &['a', 'b']), Value::True);
// assert_eq!(eval(&result, &['a'], &['b', 'c']), Value::False);
// }
// #[test]
// fn test_simple_multiple_nots() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::True);
// assert_eq!(eval(&result, &[], &['x']), Value::False);
// }
// #[test]
// fn test_simple_value_expr() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &[]), Value::Expr(Expr::Atom('x')));
// }
// #[test]
// fn test_simple_value_expr_not() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::Not(Box::new(Expr::Atom('x'))))
// );
// }
// #[test]
// fn test_simple_value_expr_and() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::And(vec![Expr::Atom('x'), Expr::Atom('y')]))
// );
// }
// #[test]
// fn test_simple_value_expr_or() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::Or(vec![Expr::Atom('x'), Expr::Atom('y')]))
// );
// }
// #[test]
// fn test_simple_value_expr_or_false() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['y']), Value::Expr(Expr::Atom('x')));
// }
// #[test]
// fn test_simple_value_expr_and_true() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::Expr(Expr::Atom('y')));
// }
// #[test]
// fn test_simple_value_expr_or_true() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::True);
// }
// #[test]
// fn test_simple_value_expr_and_false() {
// let mut parser = SimpleExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['x']), Value::False);
// }
// #[test]
// fn test_value_expr_no_epression() {
// assert_eq!(
// SimpleExprParser::new().finish(),
// Err(ParseError::UnexpectedEnd)
// );
// }
// #[test]
// fn test_basic_expr_parser() {
// // A & (B | !C)
// let mut full_parser = ExprParser::new();
// let _ = full_parser.push_atom('A');
// let _ = full_parser.push_op('&');
// let _ = full_parser.open_paren();
// let _ = full_parser.push_atom('B');
// let _ = full_parser.push_op('|');
// let _ = full_parser.push_op('!');
// let _ = full_parser.push_atom('C');
// let _ = full_parser.close_paren();
// let expr = full_parser.finish().unwrap();
// eval(&expr, &['A'], &['B']);
// }
// #[test]
// fn test_basic_simple_parser() {
// // A & B
// let mut simple_parser = ExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// let _ = simple_parser.push_atom('B');
// let expr = simple_parser.finish().unwrap();
// eval(&expr, &['A'], &['B']);
// }
// #[test]
// fn test_basic_errors() {
// let mut simple_parser = ExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// assert_eq!(simple_parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
// let mut simple_parser = ExprParser::new();
// let _ = simple_parser.push_atom('A');
// let _ = simple_parser.push_op('&');
// let _ = simple_parser.push_atom('B');
// assert_eq!(
// simple_parser.push_atom('B'),
// Err(ParseError::UnexpectedExpr)
// );
// }
// #[test]
// fn test_push_atom_valid() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// }
// #[test]
// fn test_push_atom_unexpected_expr() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert_eq!(parser.push_atom('b'), Err(ParseError::UnexpectedExpr));
// }
// #[test]
// fn test_push_op_not_valid() {
// let mut parser = ExprParser::new();
// assert!(parser.push_op('!').is_ok()); // Valid unary operator
// }
// #[test]
// fn test_push_op_and_valid() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// }
// #[test]
// fn test_push_op_unexpected_unary_op() {
// let mut parser = ExprParser::new();
// assert_eq!(parser.push_op('&'), Err(ParseError::UnexpectedBinOp));
// assert_eq!(parser.push_op('|'), Err(ParseError::UnexpectedBinOp));
// }
// #[test]
// fn test_push_op_unexpected_bin_op() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert_eq!(parser.push_op('!'), Err(ParseError::UnexpectedUnaryOp));
// }
// #[test]
// fn test_finish_valid_and_expression() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('b').is_ok());
// let result = parser.finish();
// assert_eq!(
// result,
// Ok(Expr::And(vec![Expr::Atom('a'), Expr::Atom('b')]))
// );
// }
// #[test]
// fn test_finish_valid_or_expression() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &['y']), Value::True);
// assert_eq!(eval(&result, &['x', 'y'], &['y']), Value::True);
// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
// }
// #[test]
// fn test_finish_valid_not_expression() {
// let mut parser = ExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('z').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['a', 'z'], &[]), Value::False);
// }
// #[test]
// fn test_finish_unexpected_end() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// let result = parser.finish();
// assert_eq!(result, Err(ParseError::UnexpectedEnd));
// }
// #[test]
// fn test_finish_empty_parser() {
// let parser = ExprParser::new();
// let result = parser.finish();
// // Empty parser should panic on unwrap
// assert!(result.is_err());
// }
// #[test]
// fn test_nested_operations() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('a').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('b').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('c').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['a', 'b'], &['c']), Value::True);
// assert_eq!(eval(&result, &['a', 'c'], &['b']), Value::True);
// assert_eq!(eval(&result, &['c'], &['a', 'b']), Value::True);
// assert_eq!(eval(&result, &['a'], &['b', 'c']), Value::False);
// }
// #[test]
// fn test_multiple_nots() {
// let mut parser = ExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::True);
// assert_eq!(eval(&result, &[], &['x']), Value::False);
// }
// #[test]
// fn test_value_expr() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &[]), Value::Expr(Expr::Atom('x')));
// }
// #[test]
// fn test_value_expr_not() {
// let mut parser = ExprParser::new();
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('x').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::Not(Box::new(Expr::Atom('x'))))
// );
// }
// #[test]
// fn test_value_expr_and() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::And(vec![Expr::Atom('x'), Expr::Atom('y')]))
// );
// }
// #[test]
// fn test_value_expr_or() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(
// eval(&result, &[], &[]),
// Value::Expr(Expr::Or(vec![Expr::Atom('x'), Expr::Atom('y')]))
// );
// }
// #[test]
// fn test_value_expr_or_false() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['y']), Value::Expr(Expr::Atom('x')));
// }
// #[test]
// fn test_value_expr_and_true() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::Expr(Expr::Atom('y')));
// }
// #[test]
// fn test_value_expr_or_true() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x'], &[]), Value::True);
// }
// #[test]
// fn test_value_expr_and_false() {
// let mut parser = ExprParser::new();
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['x']), Value::False);
// }
// // start with (
// #[test]
// fn test_value_expr_starts_with_paren() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['x']), Value::Expr(Expr::Atom('y')));
// }
// // nested ()
// #[test]
// fn test_value_expr_nested_paren() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// assert!(parser.close_paren().is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &[], &['y']), Value::False);
// }
// // nested ()
// #[test]
// fn test_value_expr_nested_paren_big() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// assert!(parser.close_paren().is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x', 'y'], &[]), Value::True);
// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
// assert_eq!(eval(&result, &['x'], &['y']), Value::False);
// assert_eq!(eval(&result, &['y'], &['x']), Value::True);
// }
// // nested ()
// #[test]
// fn test_value_expr_nested_paren_biggggg() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('&').is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.push_atom('x').is_ok());
// assert!(parser.push_op('|').is_ok());
// assert!(parser.push_op('!').is_ok());
// assert!(parser.push_atom('y').is_ok());
// assert!(parser.close_paren().is_ok());
// assert!(parser.close_paren().is_ok());
// let result = parser.finish().unwrap();
// assert_eq!(eval(&result, &['x', 'y'], &[]), Value::True);
// assert_eq!(eval(&result, &[], &['x', 'y']), Value::False);
// assert_eq!(eval(&result, &['x'], &['y']), Value::False);
// assert_eq!(eval(&result, &['y'], &['x']), Value::True);
// }
// // no opening )
// #[test]
// fn test_value_expr_no_open_paren() {
// let mut parser = ExprParser::new();
// assert!(parser.close_paren().is_err());
// }
// // no closing )
// #[test]
// fn test_value_expr_no_close_paren() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert_eq!(parser.finish(), Err(ParseError::UnexpectedEnd));
// }
// #[test]
// fn test_value_expr_no_expression() {
// assert_eq!(ExprParser::new().finish(), Err(ParseError::UnexpectedEnd));
// }
// #[test]
// fn test_value_expr_no_expression_nested() {
// let mut parser = ExprParser::new();
// assert!(parser.open_paren().is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.open_paren().is_ok());
// assert!(parser.close_paren().is_err());
// }
+
+// combined expr
+// #[test]
+// fn test_value_expr_combined() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('A').is_ok());
+// assert!(parser.push_op('&').is_ok());
+// assert!(parser.push_op('!').is_ok());
+// assert!(parser.push_atom('B').is_ok());
+// assert!(parser.push_op('&').is_ok());
+
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.push_atom('C').is_ok());
+// assert!(parser.push_op('|').is_ok());
+// assert!(parser.push_atom('D').is_ok());
+// assert!(parser.close_paren().is_ok());
+
+// let result = parser.finish().unwrap();
+
+// assert_eq!(eval(&result, &['A', 'C'], &['B', 'D']), Value::True);
+// assert_eq!(eval(&result, &['A', 'D'], &['B', 'C']), Value::True);
+// assert_eq!(eval(&result, &[], &['A']), Value::False);
+// assert_eq!(eval(&result, &['B'], &[]), Value::False);
+// assert_eq!(eval(&result, &[], &['C', 'D']), Value::False);
+// assert_eq!(
+// eval(&result, &['C'], &[]),
+// Value::Expr(Expr::And(vec![
+// Expr::Atom('A'),
+// Expr::Not(Box::new(Expr::Atom('B'))),
+// ]))
+// );
+// assert_eq!(
+// eval(&result, &[], &['C']),
+// Value::Expr(Expr::And(vec![
+// Expr::Atom('A'),
+// Expr::Not(Box::new(Expr::Atom('B'))),
+// Expr::Atom('D')
+// ]))
+// );
+
+// assert_eq!(
+// eval(&result, &['A'], &['B']),
+// Value::Expr(Expr::Or(vec![Expr::Atom('C'), Expr::Atom('D')]))
+// );
+// }
+
+// add paren after atom err
+// #[test]
+// fn test_value_expr_add_paren_after_atom_err() {
+// let mut parser = ExprParser::new();
+// assert!(parser.push_atom('x').is_ok());
+// assert!(parser.open_paren().is_err());
+// }
+// add op paren after (
+// #[test]
+// fn test_value_expr_add_op_after_paren() {
+// let mut parser = ExprParser::new();
+// assert!(parser.open_paren().is_ok());
+// assert!(parser.push_op('|').is_err());
+// }