Refactor precedence rules
This commit is contained in:
parent
8bf9d4bd45
commit
600a6a1b4b
@ -5,5 +5,13 @@ pub(crate) use terms::*;
|
|||||||
|
|
||||||
trait Precedence
|
trait Precedence
|
||||||
{
|
{
|
||||||
fn precedence(&self) -> i32;
|
fn precedence_level(&self) -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
|
pub(crate) enum Parentheses
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
PrecedenceBased(i32),
|
||||||
|
Required,
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use super::*;
|
|||||||
|
|
||||||
impl super::Precedence for crate::Formula
|
impl super::Precedence for crate::Formula
|
||||||
{
|
{
|
||||||
fn precedence(&self) -> i32
|
fn precedence_level(&self) -> i32
|
||||||
{
|
{
|
||||||
match &self
|
match &self
|
||||||
{
|
{
|
||||||
@ -57,15 +57,15 @@ impl std::fmt::Display for crate::PredicateDeclaration
|
|||||||
|
|
||||||
struct FormulaDisplay<'formula>
|
struct FormulaDisplay<'formula>
|
||||||
{
|
{
|
||||||
parent_precedence: Option<i32>,
|
parentheses: Parentheses,
|
||||||
formula: &'formula crate::Formula,
|
formula: &'formula crate::Formula,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_formula(formula: &crate::Formula, parent_precedence: Option<i32>) -> FormulaDisplay
|
fn display_formula(formula: &crate::Formula, parentheses: Parentheses) -> FormulaDisplay
|
||||||
{
|
{
|
||||||
FormulaDisplay
|
FormulaDisplay
|
||||||
{
|
{
|
||||||
parent_precedence,
|
parentheses,
|
||||||
formula,
|
formula,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,13 +74,15 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula>
|
|||||||
{
|
{
|
||||||
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
|
fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result
|
||||||
{
|
{
|
||||||
let precedence = self.formula.precedence();
|
let precedence_level = self.formula.precedence_level();
|
||||||
let requires_parentheses = match self.parent_precedence
|
let requires_parentheses = match self.parentheses
|
||||||
{
|
{
|
||||||
Some(parent_precedence) => precedence > parent_precedence,
|
Parentheses::None => false,
|
||||||
None => false,
|
Parentheses::PrecedenceBased(parent_precedence_level)
|
||||||
|
=> precedence_level > parent_precedence_level,
|
||||||
|
Parentheses::Required => true,
|
||||||
};
|
};
|
||||||
let precedence = Some(precedence);
|
let parentheses = Parentheses::PrecedenceBased(precedence_level);
|
||||||
|
|
||||||
if requires_parentheses
|
if requires_parentheses
|
||||||
{
|
{
|
||||||
@ -104,7 +106,7 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula>
|
|||||||
separator = ", "
|
separator = ", "
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(format, " {:?}", display_formula(&exists.argument, precedence))?;
|
write!(format, " {:?}", display_formula(&exists.argument, parentheses))?;
|
||||||
},
|
},
|
||||||
crate::Formula::ForAll(for_all) =>
|
crate::Formula::ForAll(for_all) =>
|
||||||
{
|
{
|
||||||
@ -121,10 +123,10 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula>
|
|||||||
separator = ", "
|
separator = ", "
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(format, " {:?}", display_formula(&for_all.argument, precedence))?;
|
write!(format, " {:?}", display_formula(&for_all.argument, parentheses))?;
|
||||||
},
|
},
|
||||||
crate::Formula::Not(argument) => write!(format, "not {:?}",
|
crate::Formula::Not(argument) => write!(format, "not {:?}",
|
||||||
display_formula(argument, precedence))?,
|
display_formula(argument, parentheses))?,
|
||||||
crate::Formula::And(arguments) =>
|
crate::Formula::And(arguments) =>
|
||||||
{
|
{
|
||||||
let mut separator = "";
|
let mut separator = "";
|
||||||
@ -133,7 +135,7 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula>
|
|||||||
|
|
||||||
for argument in arguments
|
for argument in arguments
|
||||||
{
|
{
|
||||||
write!(format, "{}{:?}", separator, display_formula(argument, precedence))?;
|
write!(format, "{}{:?}", separator, display_formula(argument, parentheses))?;
|
||||||
|
|
||||||
separator = " and "
|
separator = " and "
|
||||||
}
|
}
|
||||||
@ -146,64 +148,40 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula>
|
|||||||
|
|
||||||
for argument in arguments
|
for argument in arguments
|
||||||
{
|
{
|
||||||
write!(format, "{}{:?}", separator, display_formula(argument, precedence))?;
|
write!(format, "{}{:?}", separator, display_formula(argument, parentheses))?;
|
||||||
|
|
||||||
separator = " or "
|
separator = " or "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
crate::Formula::Implies(crate::Implies{direction, antecedent, implication}) =>
|
crate::Formula::Implies(crate::Implies{direction, antecedent, implication}) =>
|
||||||
{
|
{
|
||||||
let antecedent_requires_parentheses = match **antecedent
|
let antecedent_parentheses = match **antecedent
|
||||||
{
|
{
|
||||||
// Implication is right-associative and thus requires parentheses when nested on
|
// Implication is right-associative and thus requires parentheses when nested on
|
||||||
// the antecedent side
|
// the antecedent side
|
||||||
crate::Formula::Implies(_) => true,
|
crate::Formula::Implies(_) => Parentheses::Required,
|
||||||
_ => false,
|
_ => parentheses,
|
||||||
};
|
};
|
||||||
|
|
||||||
let implication_requires_parentheses = match **antecedent
|
let implication_parentheses = match **antecedent
|
||||||
{
|
{
|
||||||
// Implication is right-associative and thus doesn’t require parentheses when
|
// Implication is right-associative and thus doesn’t require parentheses when
|
||||||
// nested on the implication side with the same implication direction
|
// nested on the implication side with the same implication direction
|
||||||
crate::Formula::Implies(crate::Implies{direction: nested_direction, ..})
|
crate::Formula::Implies(crate::Implies{direction: nested_direction, ..})
|
||||||
if nested_direction == *direction => false,
|
if nested_direction == *direction => Parentheses::None,
|
||||||
// If the nested implication is in the other direction, parentheses are needed
|
// If the nested implication is in the other direction, parentheses are needed
|
||||||
crate::Formula::Implies(_) => true,
|
crate::Formula::Implies(_) => Parentheses::Required,
|
||||||
_ => false,
|
_ => parentheses,
|
||||||
};
|
};
|
||||||
|
|
||||||
let format_antecedent = |format: &mut std::fmt::Formatter| -> Result<_, _>
|
let format_antecedent = |format: &mut std::fmt::Formatter| -> Result<_, _>
|
||||||
{
|
{
|
||||||
if antecedent_requires_parentheses
|
write!(format, "{:?}", display_formula(antecedent, antecedent_parentheses))
|
||||||
{
|
|
||||||
write!(format, "(")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(format, "{:?}", display_formula(antecedent, precedence))?;
|
|
||||||
|
|
||||||
if antecedent_requires_parentheses
|
|
||||||
{
|
|
||||||
write!(format, ")")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let format_implication = |format: &mut std::fmt::Formatter| -> Result<_, _>
|
let format_implication = |format: &mut std::fmt::Formatter| -> Result<_, _>
|
||||||
{
|
{
|
||||||
if implication_requires_parentheses
|
write!(format, "{:?}", display_formula(implication, implication_parentheses))
|
||||||
{
|
|
||||||
write!(format, "(")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(format, "{:?}", display_formula(implication, precedence))?;
|
|
||||||
|
|
||||||
if implication_requires_parentheses
|
|
||||||
{
|
|
||||||
write!(format, ")")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match direction
|
match direction
|
||||||
@ -228,35 +206,35 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula>
|
|||||||
|
|
||||||
for argument in arguments
|
for argument in arguments
|
||||||
{
|
{
|
||||||
write!(format, "{}{:?}", separator, display_formula(argument, precedence))?;
|
write!(format, "{}{:?}", separator, display_formula(argument, parentheses))?;
|
||||||
|
|
||||||
separator = " <-> ";
|
separator = " <-> ";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
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, None),
|
=> write!(format, "{:?} < {:?}", display_term(left, Parentheses::None),
|
||||||
display_term(right, None))?,
|
display_term(right, Parentheses::None))?,
|
||||||
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, None),
|
=> write!(format, "{:?} <= {:?}", display_term(left, Parentheses::None),
|
||||||
display_term(right, None))?,
|
display_term(right, Parentheses::None))?,
|
||||||
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, None),
|
=> write!(format, "{:?} > {:?}", display_term(left, Parentheses::None),
|
||||||
display_term(right, None))?,
|
display_term(right, Parentheses::None))?,
|
||||||
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, None),
|
=> write!(format, "{:?} >= {:?}", display_term(left, Parentheses::None),
|
||||||
display_term(right, None))?,
|
display_term(right, Parentheses::None))?,
|
||||||
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, None),
|
=> write!(format, "{:?} = {:?}", display_term(left, Parentheses::None),
|
||||||
display_term(right, None))?,
|
display_term(right, Parentheses::None))?,
|
||||||
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, None),
|
=> write!(format, "{:?} != {:?}", display_term(left, Parentheses::None),
|
||||||
display_term(right, None))?,
|
display_term(right, Parentheses::None))?,
|
||||||
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) =>
|
||||||
@ -271,7 +249,8 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula>
|
|||||||
|
|
||||||
for argument in &predicate.arguments
|
for argument in &predicate.arguments
|
||||||
{
|
{
|
||||||
write!(format, "{}{:?}", separator, display_term(argument, None))?;
|
write!(format, "{}{:?}", separator,
|
||||||
|
display_term(argument, Parentheses::None))?;
|
||||||
|
|
||||||
separator = ", "
|
separator = ", "
|
||||||
}
|
}
|
||||||
@ -302,7 +281,7 @@ impl std::fmt::Debug for crate::Formula
|
|||||||
{
|
{
|
||||||
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_formula(&self, None))
|
write!(format, "{:?}", display_formula(&self, Parentheses::None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,7 +289,7 @@ impl std::fmt::Display for crate::Formula
|
|||||||
{
|
{
|
||||||
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_formula(&self, None))
|
write!(format, "{}", display_formula(&self, Parentheses::None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use super::*;
|
|||||||
|
|
||||||
impl super::Precedence for crate::Term
|
impl super::Precedence for crate::Term
|
||||||
{
|
{
|
||||||
fn precedence(&self) -> i32
|
fn precedence_level(&self) -> i32
|
||||||
{
|
{
|
||||||
match &self
|
match &self
|
||||||
{
|
{
|
||||||
@ -90,15 +90,15 @@ impl std::fmt::Display for crate::VariableDeclaration
|
|||||||
|
|
||||||
pub(crate) struct TermDisplay<'term>
|
pub(crate) struct TermDisplay<'term>
|
||||||
{
|
{
|
||||||
parent_precedence: Option<i32>,
|
parentheses: Parentheses,
|
||||||
term: &'term crate::Term,
|
term: &'term crate::Term,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn display_term(term: &crate::Term, parent_precedence: Option<i32>) -> TermDisplay
|
pub(crate) fn display_term(term: &crate::Term, parentheses: Parentheses) -> TermDisplay
|
||||||
{
|
{
|
||||||
TermDisplay
|
TermDisplay
|
||||||
{
|
{
|
||||||
parent_precedence,
|
parentheses,
|
||||||
term,
|
term,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,12 +107,15 @@ 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 = self.term.precedence();
|
let precedence_level = self.term.precedence_level();
|
||||||
let requires_parentheses = match self.parent_precedence
|
let requires_parentheses = match self.parentheses
|
||||||
{
|
{
|
||||||
Some(parent_precedence) => precedence > parent_precedence,
|
Parentheses::Required => true,
|
||||||
None => false,
|
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
|
||||||
{
|
{
|
||||||
@ -144,7 +147,8 @@ impl<'term> std::fmt::Debug for TermDisplay<'term>
|
|||||||
|
|
||||||
for argument in &function.arguments
|
for argument in &function.arguments
|
||||||
{
|
{
|
||||||
write!(format, "{}{:?}", separator, display_term(&argument, None))?;
|
write!(format, "{}{:?}", separator,
|
||||||
|
display_term(&argument, Parentheses::None))?;
|
||||||
|
|
||||||
separator = ", ";
|
separator = ", ";
|
||||||
}
|
}
|
||||||
@ -166,10 +170,15 @@ impl<'term> std::fmt::Debug for TermDisplay<'term>
|
|||||||
crate::BinaryOperator::Exponentiate => "**",
|
crate::BinaryOperator::Exponentiate => "**",
|
||||||
};
|
};
|
||||||
|
|
||||||
let left_requires_parentheses = binary_operation.left.precedence() == precedence
|
let left_parentheses = match
|
||||||
|
binary_operation.left.precedence_level() == precedence_level
|
||||||
// Exponentiation is right-associative and thus requires parentheses when
|
// Exponentiation is right-associative and thus requires parentheses when
|
||||||
// nested on the left side
|
// nested on the left side
|
||||||
&& binary_operation.operator == crate::BinaryOperator::Exponentiate;
|
&& binary_operation.operator == crate::BinaryOperator::Exponentiate
|
||||||
|
{
|
||||||
|
true => Parentheses::Required,
|
||||||
|
false => parentheses,
|
||||||
|
};
|
||||||
|
|
||||||
// The subtraction, division, and modulo operators require parentheses around the
|
// The subtraction, division, and modulo operators require parentheses around the
|
||||||
// right argument even if it has the same precedence
|
// right argument even if it has the same precedence
|
||||||
@ -192,43 +201,24 @@ impl<'term> std::fmt::Debug for TermDisplay<'term>
|
|||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let right_requires_parentheses = binary_operation.right.precedence() == precedence
|
let right_parentheses = match
|
||||||
&& (operator_requires_right_priority || right_requires_priority);
|
binary_operation.right.precedence_level() == precedence_level
|
||||||
|
&& (operator_requires_right_priority || right_requires_priority)
|
||||||
if left_requires_parentheses
|
|
||||||
{
|
{
|
||||||
write!(format, "(")?;
|
true => Parentheses::Required,
|
||||||
}
|
false => parentheses,
|
||||||
|
};
|
||||||
|
|
||||||
write!(format, "{:?}", display_term(&binary_operation.left, Some(precedence)))?;
|
write!(format, "{:?} {} {:?}",
|
||||||
|
display_term(&binary_operation.left, left_parentheses),
|
||||||
if left_requires_parentheses
|
operator_string, display_term(&binary_operation.right, right_parentheses))
|
||||||
{
|
|
||||||
write!(format, ")")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(format, " {} ", operator_string)?;
|
|
||||||
|
|
||||||
if right_requires_parentheses
|
|
||||||
{
|
|
||||||
write!(format, "(")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(format, "{:?}", display_term(&binary_operation.right, Some(precedence)))?;
|
|
||||||
|
|
||||||
if right_requires_parentheses
|
|
||||||
{
|
|
||||||
write!(format, ")")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
},
|
},
|
||||||
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, Some(precedence))),
|
=> write!(format, "-{:?}", display_term(argument, parentheses)),
|
||||||
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, None)),
|
=> write!(format, "|{:?}|", display_term(argument, Parentheses::None)),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
if requires_parentheses
|
if requires_parentheses
|
||||||
@ -252,7 +242,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, None))
|
write!(format, "{:?}", display_term(&self, Parentheses::None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +250,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, None))
|
write!(format, "{}", display_term(&self, Parentheses::None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,9 +627,8 @@ mod tests
|
|||||||
crate::ImplicationDirection::RightToLeft);
|
crate::ImplicationDirection::RightToLeft);
|
||||||
|
|
||||||
assert_eq!(format_formula("(a -> b -> c)"), "a -> b -> c");
|
assert_eq!(format_formula("(a -> b -> c)"), "a -> b -> c");
|
||||||
// TODO: fix
|
assert_eq!(format_formula("(a -> (b -> c))"), "a -> b -> c");
|
||||||
//assert_eq!(format_formula("(a -> (b -> c))"), "a -> b -> c");
|
assert_eq!(format_formula("((a -> b) -> c)"), "(a -> b) -> c");
|
||||||
//assert_eq!(format_formula("((a -> b) -> c)"), "(a -> b) -> c");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user