foliage-rs/src/format.rs

320 lines
8.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

struct TermDisplay<'parent>
{
parent: Option<&'parent crate::Term>,
term: &'parent crate::Term,
}
struct FormulaDisplay<'parent>
{
parent: Option<&'parent crate::Formula>,
formula: &'parent crate::Formula,
}
fn display_term<'parent>(term: &'parent crate::Term, parent: Option<&'parent crate::Term>) -> TermDisplay<'parent>
{
TermDisplay
{
parent,
term,
}
}
fn display_formula<'parent>(formula: &'parent crate::Formula, parent: Option<&'parent crate::Formula>)
-> FormulaDisplay<'parent>
{
FormulaDisplay
{
parent,
formula,
}
}
fn term_precedence(term: &crate::Term) -> u64
{
match term
{
crate::Term::Infimum | crate::Term::Supremum | crate::Term::Integer(_) | crate::Term::Symbolic(_) | crate::Term::String(_) | crate::Term::Variable(_) => 0,
crate::Term::Negative(_) => 1,
crate::Term::Multiply(_, _) => 2,
crate::Term::Add(_, _) | crate::Term::Subtract(_, _) => 3,
}
}
fn term_requires_parentheses(child: &crate::Term, parent: Option<&crate::Term>) -> bool
{
match parent
{
None => false,
Some(parent) =>
{
let child_precedence = term_precedence(child);
let parent_precedence = term_precedence(parent);
if child_precedence != parent_precedence
{
return child_precedence > parent_precedence;
}
// Subtraction isnt associative, so handle them separately
// TODO: only do this for right-hand side of subtractions
match parent
{
crate::Term::Subtract(_, _) => true,
_ => false,
}
},
}
}
fn formula_precedence(formula: &crate::Formula) -> u64
{
match formula
{
crate::Formula::Predicate(_) | crate::Formula::Boolean(_) | crate::Formula::Less(_, _) | crate::Formula::LessOrEqual(_, _) | crate::Formula::Greater(_, _) | crate::Formula::GreaterOrEqual(_, _) | crate::Formula::Equal(_, _) | crate::Formula::NotEqual(_, _) => 0,
crate::Formula::Exists(_) | crate::Formula::ForAll(_) => 1,
crate::Formula::Not(_) => 2,
crate::Formula::And(_) => 3,
crate::Formula::Or(_) => 4,
crate::Formula::Implies(_, _, _) => 5,
crate::Formula::Biconditional(_, _) => 6,
}
}
fn formula_requires_parentheses(child: &crate::Formula, parent: Option<&crate::Formula>) -> bool
{
match parent
{
None => false,
Some(parent) =>
{
let child_precedence = formula_precedence(child);
let parent_precedence = formula_precedence(parent);
if child_precedence != parent_precedence
{
return child_precedence > parent_precedence;
}
// Implications arent associative, so handle them separately
match parent
{
crate::Formula::Implies(_, _, _) => true,
_ => false,
}
},
}
}
impl std::fmt::Debug for crate::VariableDeclaration
{
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{
write!(format, "{}", &self.name)
}
}
impl std::fmt::Display for crate::VariableDeclaration
{
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{
write!(format, "{:?}", &self)
}
}
impl<'term> std::fmt::Debug for TermDisplay<'term>
{
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{
let requires_parentheses = term_requires_parentheses(self.term, self.parent);
if requires_parentheses
{
write!(format, "(")?;
}
match self.term
{
crate::Term::Infimum => write!(format, "#inf"),
crate::Term::Supremum => write!(format, "#sup"),
crate::Term::Integer(value) => write!(format, "{}", value),
crate::Term::Symbolic(ref value) => write!(format, "{}", value),
crate::Term::String(ref value) => write!(format, "\"{}\"", value),
crate::Term::Variable(ref declaration) => write!(format, "{:?}", declaration),
crate::Term::Add(ref left, ref right) => write!(format, "{:?} + {:?}", display_term(left, Some(self.term)), display_term(right, Some(self.term))),
crate::Term::Subtract(ref left, ref right) => write!(format, "{:?} - {:?}", display_term(left, Some(self.term)), display_term(right, Some(self.term))),
crate::Term::Multiply(ref left, ref right) => write!(format, "{:?} * {:?}", display_term(left, Some(self.term)), display_term(right, Some(self.term))),
crate::Term::Negative(ref argument) => write!(format, "-{:?}", display_term(argument, Some(self.term))),
}?;
if requires_parentheses
{
write!(format, ")")?;
}
Ok(())
}
}
impl<'term> std::fmt::Display for TermDisplay<'term>
{
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{
write!(format, "{:?}", self)
}
}
impl<'formula> std::fmt::Debug for FormulaDisplay<'formula>
{
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{
let requires_parentheses = formula_requires_parentheses(self.formula, self.parent);
if requires_parentheses
{
write!(format, "(")?;
}
match self.formula
{
crate::Formula::Exists(ref exists) =>
{
write!(format, "exists")?;
let mut separator = " ";
for parameter in &exists.parameters
{
write!(format, "{}{:?}", separator, parameter)?;
separator = ", "
}
write!(format, " {:?}", display_formula(&exists.argument, Some(self.formula)))?;
},
crate::Formula::ForAll(ref for_all) =>
{
write!(format, "forall")?;
let mut separator = " ";
for parameter in &for_all.parameters
{
write!(format, "{}{:?}", separator, parameter)?;
separator = ", "
}
write!(format, " {:?}", display_formula(&for_all.argument, Some(self.formula)))?;
},
crate::Formula::Not(ref argument) => write!(format, "not {:?}", display_formula(argument, Some(self.formula)))?,
crate::Formula::And(ref arguments) =>
{
let mut separator = "";
for argument in arguments
{
write!(format, "{}{:?}", separator, display_formula(argument, Some(self.formula)))?;
separator = " and "
}
},
crate::Formula::Or(ref arguments) =>
{
let mut separator = "";
for argument in arguments
{
write!(format, "{}{:?}", separator, display_formula(argument, Some(self.formula)))?;
separator = " or "
}
},
crate::Formula::Implies(ref left, ref right, implication_direction) => match implication_direction
{
crate::ImplicationDirection::LeftToRight => write!(format, "{:?} -> {:?}", display_formula(left, Some(self.formula)), display_formula(right, Some(self.formula)))?,
crate::ImplicationDirection::RightToLeft => write!(format, "{:?} <- {:?}", display_formula(left, Some(self.formula)), display_formula(right, Some(self.formula)))?,
},
crate::Formula::Biconditional(ref left, ref right) => write!(format, "{:?} <-> {:?}", display_formula(left, Some(self.formula)), display_formula(right, Some(self.formula)))?,
crate::Formula::Less(ref left, ref right) => write!(format, "{:?} < {:?}", display_term(left, None), display_term(right, None))?,
crate::Formula::LessOrEqual(ref left, ref right) => write!(format, "{:?} <= {:?}", display_term(left, None), display_term(right, None))?,
crate::Formula::Greater(ref left, ref right) => write!(format, "{:?} > {:?}", display_term(left, None), display_term(right, None))?,
crate::Formula::GreaterOrEqual(ref left, ref right) => write!(format, "{:?} >= {:?}", display_term(left, None), display_term(right, None))?,
crate::Formula::Equal(ref left, ref right) => write!(format, "{:?} = {:?}", display_term(left, None), display_term(right, None))?,
crate::Formula::NotEqual(ref left, ref right) => write!(format, "{:?} != {:?}", display_term(left, None), display_term(right, None))?,
crate::Formula::Boolean(value) =>
match value
{
true => write!(format, "#true")?,
false => write!(format, "#false")?,
},
crate::Formula::Predicate(ref predicate) =>
{
write!(format, "{}", predicate.declaration.name)?;
if !predicate.arguments.is_empty()
{
write!(format, "(")?;
let mut separator = "";
for argument in &predicate.arguments
{
write!(format, "{}{:?}", separator, display_term(argument, None))?;
separator = ", "
}
write!(format, ")")?;
}
},
}
if requires_parentheses
{
write!(format, ")")?;
}
Ok(())
}
}
impl<'formula> std::fmt::Display for FormulaDisplay<'formula>
{
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{
write!(format, "{:?}", self)
}
}
impl std::fmt::Debug for crate::Formula
{
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{
write!(format, "{:?}", display_formula(&self, None))
}
}
impl std::fmt::Display for crate::Formula
{
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{
write!(format, "{}", display_formula(&self, None))
}
}
impl std::fmt::Debug for crate::Term
{
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{
write!(format, "{:?}", display_term(&self, None))
}
}
impl std::fmt::Display for crate::Term
{
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
{
write!(format, "{}", display_term(&self, None))
}
}