Refactor parenthesis rules for terms
This commit is contained in:
parent
9754f933ef
commit
6c326ddb70
@ -295,28 +295,28 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula>
|
|||||||
},
|
},
|
||||||
crate::Formula::Compare(
|
crate::Formula::Compare(
|
||||||
crate::Compare{operator: crate::ComparisonOperator::Less, left, right})
|
crate::Compare{operator: crate::ComparisonOperator::Less, left, right})
|
||||||
=> write!(format, "{:?} < {:?}", display_term(left, Parentheses::None),
|
=> write!(format, "{:?} < {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any),
|
||||||
display_term(right, Parentheses::None))?,
|
display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?,
|
||||||
crate::Formula::Compare(
|
crate::Formula::Compare(
|
||||||
crate::Compare{operator: crate::ComparisonOperator::LessOrEqual, left, right})
|
crate::Compare{operator: crate::ComparisonOperator::LessOrEqual, left, right})
|
||||||
=> write!(format, "{:?} <= {:?}", display_term(left, Parentheses::None),
|
=> write!(format, "{:?} <= {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any),
|
||||||
display_term(right, Parentheses::None))?,
|
display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?,
|
||||||
crate::Formula::Compare(
|
crate::Formula::Compare(
|
||||||
crate::Compare{operator: crate::ComparisonOperator::Greater, left, right})
|
crate::Compare{operator: crate::ComparisonOperator::Greater, left, right})
|
||||||
=> write!(format, "{:?} > {:?}", display_term(left, Parentheses::None),
|
=> write!(format, "{:?} > {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any),
|
||||||
display_term(right, Parentheses::None))?,
|
display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?,
|
||||||
crate::Formula::Compare(
|
crate::Formula::Compare(
|
||||||
crate::Compare{operator: crate::ComparisonOperator::GreaterOrEqual, left, right})
|
crate::Compare{operator: crate::ComparisonOperator::GreaterOrEqual, left, right})
|
||||||
=> write!(format, "{:?} >= {:?}", display_term(left, Parentheses::None),
|
=> write!(format, "{:?} >= {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any),
|
||||||
display_term(right, Parentheses::None))?,
|
display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?,
|
||||||
crate::Formula::Compare(
|
crate::Formula::Compare(
|
||||||
crate::Compare{operator: crate::ComparisonOperator::Equal, left, right})
|
crate::Compare{operator: crate::ComparisonOperator::Equal, left, right})
|
||||||
=> write!(format, "{:?} = {:?}", display_term(left, Parentheses::None),
|
=> write!(format, "{:?} = {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any),
|
||||||
display_term(right, Parentheses::None))?,
|
display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?,
|
||||||
crate::Formula::Compare(
|
crate::Formula::Compare(
|
||||||
crate::Compare{operator: crate::ComparisonOperator::NotEqual, left, right})
|
crate::Compare{operator: crate::ComparisonOperator::NotEqual, left, right})
|
||||||
=> write!(format, "{:?} != {:?}", display_term(left, Parentheses::None),
|
=> write!(format, "{:?} != {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any),
|
||||||
display_term(right, Parentheses::None))?,
|
display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?,
|
||||||
crate::Formula::Boolean(true) => write!(format, "true")?,
|
crate::Formula::Boolean(true) => write!(format, "true")?,
|
||||||
crate::Formula::Boolean(false) => write!(format, "false")?,
|
crate::Formula::Boolean(false) => write!(format, "false")?,
|
||||||
crate::Formula::Predicate(predicate) =>
|
crate::Formula::Predicate(predicate) =>
|
||||||
@ -332,7 +332,7 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula>
|
|||||||
for argument in &predicate.arguments
|
for argument in &predicate.arguments
|
||||||
{
|
{
|
||||||
write!(format, "{}{:?}", separator,
|
write!(format, "{}{:?}", separator,
|
||||||
display_term(argument, Parentheses::None))?;
|
display_term(argument, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?;
|
||||||
|
|
||||||
separator = ", "
|
separator = ", "
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
|
pub(crate) enum ChildPosition
|
||||||
|
{
|
||||||
|
Any,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
impl super::Precedence for crate::Term
|
impl super::Precedence for crate::Term
|
||||||
{
|
{
|
||||||
fn precedence_level(&self) -> i32
|
fn precedence_level(&self) -> i32
|
||||||
@ -92,14 +100,103 @@ pub(crate) struct TermDisplay<'term>
|
|||||||
{
|
{
|
||||||
parentheses: Parentheses,
|
parentheses: Parentheses,
|
||||||
term: &'term crate::Term,
|
term: &'term crate::Term,
|
||||||
|
parent_term: Option<&'term crate::Term>,
|
||||||
|
position: ChildPosition,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn display_term(term: &crate::Term, parentheses: Parentheses) -> TermDisplay
|
impl<'term> TermDisplay<'term>
|
||||||
|
{
|
||||||
|
fn requires_parentheses(&self) -> bool
|
||||||
|
{
|
||||||
|
use crate::Term;
|
||||||
|
|
||||||
|
let parent_term = match self.parent_term
|
||||||
|
{
|
||||||
|
Some(parent_term) => parent_term,
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// The absolute value operation never requires parentheses, as it has its own parentheses
|
||||||
|
if let Term::UnaryOperation(
|
||||||
|
crate::UnaryOperation{operator: crate::UnaryOperator::AbsoluteValue, ..}) = parent_term
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.term
|
||||||
|
{
|
||||||
|
Term::Boolean(_)
|
||||||
|
| Term::SpecialInteger(_)
|
||||||
|
| Term::Integer(_)
|
||||||
|
| Term::String(_)
|
||||||
|
| Term::Variable(_)
|
||||||
|
| Term::Function(_)
|
||||||
|
| Term::UnaryOperation(_)
|
||||||
|
=> false,
|
||||||
|
Term::BinaryOperation(binary_operation) =>
|
||||||
|
{
|
||||||
|
let parent_binary_operation = match parent_term
|
||||||
|
{
|
||||||
|
Term::BinaryOperation(parent_binary_operation) => parent_binary_operation,
|
||||||
|
// Binary operations nested in the negative operation always require parentheses
|
||||||
|
Term::UnaryOperation(
|
||||||
|
crate::UnaryOperation{operator: crate::UnaryOperator::Negative, ..})
|
||||||
|
=> return true,
|
||||||
|
_ => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
match binary_operation.operator
|
||||||
|
{
|
||||||
|
crate::BinaryOperator::Exponentiate =>
|
||||||
|
parent_binary_operation.operator == crate::BinaryOperator::Exponentiate
|
||||||
|
&& self.position == ChildPosition::Left,
|
||||||
|
crate::BinaryOperator::Multiply
|
||||||
|
| crate::BinaryOperator::Divide
|
||||||
|
=> match parent_binary_operation.operator
|
||||||
|
{
|
||||||
|
crate::BinaryOperator::Exponentiate => true,
|
||||||
|
crate::BinaryOperator::Divide
|
||||||
|
| crate::BinaryOperator::Modulo
|
||||||
|
=> self.position == ChildPosition::Right,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
crate::BinaryOperator::Modulo => match parent_binary_operation.operator
|
||||||
|
{
|
||||||
|
crate::BinaryOperator::Exponentiate => true,
|
||||||
|
crate::BinaryOperator::Multiply
|
||||||
|
| crate::BinaryOperator::Divide
|
||||||
|
| crate::BinaryOperator::Modulo
|
||||||
|
=> self.position == ChildPosition::Right,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
crate::BinaryOperator::Add
|
||||||
|
| crate::BinaryOperator::Subtract
|
||||||
|
=> match parent_binary_operation.operator
|
||||||
|
{
|
||||||
|
crate::BinaryOperator::Exponentiate
|
||||||
|
| crate::BinaryOperator::Multiply
|
||||||
|
| crate::BinaryOperator::Divide
|
||||||
|
| crate::BinaryOperator::Modulo
|
||||||
|
=> true,
|
||||||
|
crate::BinaryOperator::Subtract
|
||||||
|
=> self.position == ChildPosition::Right,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn display_term<'term>(term: &'term crate::Term, parentheses: Parentheses,
|
||||||
|
parent_term: Option<&'term crate::Term>, position: ChildPosition) -> TermDisplay<'term>
|
||||||
{
|
{
|
||||||
TermDisplay
|
TermDisplay
|
||||||
{
|
{
|
||||||
parentheses,
|
parentheses,
|
||||||
term,
|
term,
|
||||||
|
parent_term,
|
||||||
|
position,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,15 +204,7 @@ impl<'term> std::fmt::Debug for TermDisplay<'term>
|
|||||||
{
|
{
|
||||||
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
|
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
|
||||||
{
|
{
|
||||||
let precedence_level = self.term.precedence_level();
|
let requires_parentheses = self.requires_parentheses();
|
||||||
let requires_parentheses = match self.parentheses
|
|
||||||
{
|
|
||||||
Parentheses::Required => true,
|
|
||||||
Parentheses::PrecedenceBased(parent_precedence_level)
|
|
||||||
=> precedence_level > parent_precedence_level,
|
|
||||||
Parentheses::None => false,
|
|
||||||
};
|
|
||||||
let parentheses = Parentheses::PrecedenceBased(precedence_level);
|
|
||||||
|
|
||||||
if requires_parentheses
|
if requires_parentheses
|
||||||
{
|
{
|
||||||
@ -148,7 +237,7 @@ impl<'term> std::fmt::Debug for TermDisplay<'term>
|
|||||||
for argument in &function.arguments
|
for argument in &function.arguments
|
||||||
{
|
{
|
||||||
write!(format, "{}{:?}", separator,
|
write!(format, "{}{:?}", separator,
|
||||||
display_term(&argument, Parentheses::None))?;
|
display_term(&argument, Parentheses::None, Some(self.term), ChildPosition::Any))?;
|
||||||
|
|
||||||
separator = ", ";
|
separator = ", ";
|
||||||
}
|
}
|
||||||
@ -170,55 +259,17 @@ impl<'term> std::fmt::Debug for TermDisplay<'term>
|
|||||||
crate::BinaryOperator::Exponentiate => "**",
|
crate::BinaryOperator::Exponentiate => "**",
|
||||||
};
|
};
|
||||||
|
|
||||||
let left_parentheses = match
|
|
||||||
binary_operation.left.precedence_level() == precedence_level
|
|
||||||
// Exponentiation is right-associative and thus requires parentheses when
|
|
||||||
// nested on the left side
|
|
||||||
&& binary_operation.operator == crate::BinaryOperator::Exponentiate
|
|
||||||
{
|
|
||||||
true => Parentheses::Required,
|
|
||||||
false => parentheses,
|
|
||||||
};
|
|
||||||
|
|
||||||
// The subtraction, division, and modulo operators require parentheses around the
|
|
||||||
// right argument even if it has the same precedence
|
|
||||||
let operator_requires_right_priority = match binary_operation.operator
|
|
||||||
{
|
|
||||||
crate::BinaryOperator::Subtract
|
|
||||||
| crate::BinaryOperator::Divide
|
|
||||||
| crate::BinaryOperator::Modulo
|
|
||||||
=> true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Additionally, modulo operations nested to the right of another multiplicative
|
|
||||||
// operation always require parentheses
|
|
||||||
let right_requires_priority = match *binary_operation.right
|
|
||||||
{
|
|
||||||
crate::Term::BinaryOperation(
|
|
||||||
crate::BinaryOperation{operator: crate::BinaryOperator::Modulo, ..})
|
|
||||||
=> true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let right_parentheses = match
|
|
||||||
binary_operation.right.precedence_level() == precedence_level
|
|
||||||
&& (operator_requires_right_priority || right_requires_priority)
|
|
||||||
{
|
|
||||||
true => Parentheses::Required,
|
|
||||||
false => parentheses,
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(format, "{:?} {} {:?}",
|
write!(format, "{:?} {} {:?}",
|
||||||
display_term(&binary_operation.left, left_parentheses),
|
display_term(&binary_operation.left, Parentheses::None, Some(self.term), ChildPosition::Left),
|
||||||
operator_string, display_term(&binary_operation.right, right_parentheses))
|
operator_string,
|
||||||
|
display_term(&binary_operation.right, Parentheses::None, Some(self.term), ChildPosition::Right))
|
||||||
},
|
},
|
||||||
crate::Term::UnaryOperation(
|
crate::Term::UnaryOperation(
|
||||||
crate::UnaryOperation{operator: crate::UnaryOperator::Negative, argument})
|
crate::UnaryOperation{operator: crate::UnaryOperator::Negative, argument})
|
||||||
=> write!(format, "-{:?}", display_term(argument, parentheses)),
|
=> write!(format, "-{:?}", display_term(argument, Parentheses::None, Some(self.term), ChildPosition::Any)),
|
||||||
crate::Term::UnaryOperation(
|
crate::Term::UnaryOperation(
|
||||||
crate::UnaryOperation{operator: crate::UnaryOperator::AbsoluteValue, argument})
|
crate::UnaryOperation{operator: crate::UnaryOperator::AbsoluteValue, argument})
|
||||||
=> write!(format, "|{:?}|", display_term(argument, Parentheses::None)),
|
=> write!(format, "|{:?}|", display_term(argument, Parentheses::None, Some(self.term), ChildPosition::Any)),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
if requires_parentheses
|
if requires_parentheses
|
||||||
@ -242,7 +293,7 @@ impl std::fmt::Debug for crate::Term
|
|||||||
{
|
{
|
||||||
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
|
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
|
||||||
{
|
{
|
||||||
write!(format, "{:?}", display_term(&self, Parentheses::None))
|
write!(format, "{:?}", display_term(&self, Parentheses::None, None, ChildPosition::Any))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +301,7 @@ impl std::fmt::Display for crate::Term
|
|||||||
{
|
{
|
||||||
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
|
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
|
||||||
{
|
{
|
||||||
write!(format, "{}", display_term(&self, Parentheses::None))
|
write!(format, "{}", display_term(&self, Parentheses::None, None, ChildPosition::Any))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user