Skip to content

Commit

Permalink
refactor: structuring of Expression
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukáš Chudíček committed Nov 14, 2023
1 parent edb796f commit 5703371
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 4 deletions.
3 changes: 0 additions & 3 deletions src/expression.rs

This file was deleted.

66 changes: 66 additions & 0 deletions src/expression_components/expression.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#![allow(dead_code)]

// todo this should likely be only inside the xml parser
enum LogicOp {
Not,
And,
Or,
Xor,
Implies,
}

use std::{io::BufRead, str::FromStr};

use crate::xml_parsing::xml_reader::XmlReader;

use super::proposition::Proposition;

/// Represents a recursive expression. Leaf nodes are propositions. Join `Expression::Terminal`s
/// into more complex expressions using other `Expression` variants.
///
/// Available variants:
///
/// - `Expression::Terminal` - a leaf node, containing a proposition
/// - `Expression::Not` - a negation of the inner expression
/// - `Expression::And` - a conjunction of the inner expressions. The inner expressions are
/// stored inside a `Vec<_>`, to allow for an arbitrary number of conjuncts useful for
/// creating CNF formulas. `Expression::And` with an empty `Vec<_>` is equivalent to
/// constant `true`.
/// - `Expression::Or` - a disjunction of the inner expressions. The inner expressions are
/// stored inside a `Vec<_>`, to allow for an arbitrary number of disjuncts useful for
/// creating DNF formulas. `Expression::Or` with an empty `Vec<_>` is equivalent to
/// constant `false`.
/// - `Expression::Xor` - an exclusive disjunction of the inner expressions.
/// - `Expression::Implies` - an implication of the inner expressions. The order of the
/// operands follows conventional notation, i.e. `Expression::Implies(lhs, rhs)` is
/// equivalent to `lhs => rhs`.
pub enum Expression<T> {
Terminal(Proposition<T>),
Not(Box<Expression<T>>),
And(Vec<Expression<T>>),
Or(Vec<Expression<T>>),
Xor(Box<Expression<T>>, Box<Expression<T>>),
Implies(Box<Expression<T>>, Box<Expression<T>>),
}

impl<T: PartialOrd> Expression<T> {
// todo
// this will likely be removed. Think it is only used to find the highest
// value *for each* of the variables, which is `O(n^2)` with this method.
pub fn highest_value_used_with_variable(&self, _variable: &str) -> Option<T> {
unimplemented!()
}
}

// todo
// really torn apart between keeping this here, moving it to a separate file within
// this module, and moving it into the `xml_parsing` module
impl<T: FromStr> Expression<T> {
pub fn try_from_xml<XR, BR>(_xml: &mut XR)
where
XR: XmlReader<BR>,
BR: BufRead,
{
unimplemented!()
}
}
2 changes: 2 additions & 0 deletions src/expression_components/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod expression;
pub mod proposition;
82 changes: 82 additions & 0 deletions src/expression_components/proposition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#![allow(dead_code)]

use std::str::FromStr;

pub enum ComparisonOperator {
Eq,
Neq,
Lt,
Gt,
Leq,
Geq,
}

impl ComparisonOperator {
pub fn flip(&self) -> Self {
match self {
Self::Eq => Self::Eq,
Self::Neq => Self::Neq,
Self::Lt => Self::Gt,
Self::Gt => Self::Lt,
Self::Leq => Self::Geq,
Self::Geq => Self::Leq,
}
}
}

impl FromStr for ComparisonOperator {
type Err = (); // todo maybe better error

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"eq" => Ok(Self::Eq),
"neq" => Ok(Self::Neq),
"lt" => Ok(Self::Lt),
"gt" => Ok(Self::Gt),
"leq" => Ok(Self::Leq),
"geq" => Ok(Self::Geq),
_ => Err(()),
}
}
}

impl ToString for ComparisonOperator {
fn to_string(&self) -> String {
match self {
Self::Eq => "eq",
Self::Neq => "neq",
Self::Lt => "lt",
Self::Gt => "gt",
Self::Leq => "leq",
Self::Geq => "geq",
}
.to_string()
}
}

/// Represents a formula in the form of `variable comparison_operator value`.
///
/// This order is fixed. To represent a formula of form `value comparison_operator variable`,
/// use `comparison_operator.flip()`.
pub struct Proposition<T> {
pub comparison_operator: ComparisonOperator,
// ci = variable name in the xml file // todo remove this comment likely; user of this file should not care about xml
pub variable: String,
// cn = constant value in the xml file // todo remove this comment likely; user of this file should not care about xml
pub value: T,
}

impl<T> Proposition<T> {
pub fn new(comparison_operator: ComparisonOperator, variable: String, value: T) -> Self {
Self {
comparison_operator,
variable,
value,
}
}
}

pub struct Person {
/// A person must have a name, no matter how much Juliet may hate it
name: String,
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod prototype; // not public; will be replaced by legit
pub mod test_utils; // TODO:
// Once this becomes a library, this needs to become private, but for now it is convenient
// to have it accessible from outside binaries.
mod expression;
mod expression_components;
mod xml_parsing;

#[cfg(test)]
Expand Down
2 changes: 2 additions & 0 deletions src/prototype/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ pub enum CmpOp {
Geq,
}

// todo this should be impl FromStr & impl ToString
impl CmpOp {
pub fn try_from_str(s: &str) -> Result<Self, ParseCmpOpError> {
match s {
Expand Down Expand Up @@ -426,6 +427,7 @@ impl<T> Proposition<T> {
/// if the input terminal operands are flipped, the returning value will flip the operands as well
/// as the comparison operator in order to normalize the proposition
pub fn new(cmp_op: CmpOp, ops: TerminalOps<T>) -> Self {
// todo `TerminalOps` are specific for xml loading; this struct should not care about it
match ops {
TerminalOps::Standard(lhs, rhs) => Self {
cmp: cmp_op,
Expand Down

0 comments on commit 5703371

Please sign in to comment.