From 600a6a1b4b371e475db6d29b6f5aeb379f3d6209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Mon, 30 Mar 2020 08:04:09 +0200 Subject: [PATCH] Refactor precedence rules --- src/format.rs | 10 +++- src/format/formulas.rs | 105 +++++++++++++++++------------------------ src/format/terms.rs | 76 +++++++++++++---------------- src/parse/formulas.rs | 5 +- 4 files changed, 86 insertions(+), 110 deletions(-) diff --git a/src/format.rs b/src/format.rs index d1094f3..acb192c 100644 --- a/src/format.rs +++ b/src/format.rs @@ -5,5 +5,13 @@ pub(crate) use terms::*; trait Precedence { - fn precedence(&self) -> i32; + fn precedence_level(&self) -> i32; +} + +#[derive(Clone, Copy, Eq, PartialEq)] +pub(crate) enum Parentheses +{ + None, + PrecedenceBased(i32), + Required, } diff --git a/src/format/formulas.rs b/src/format/formulas.rs index 81ef924..b1a5e1f 100644 --- a/src/format/formulas.rs +++ b/src/format/formulas.rs @@ -2,7 +2,7 @@ use super::*; impl super::Precedence for crate::Formula { - fn precedence(&self) -> i32 + fn precedence_level(&self) -> i32 { match &self { @@ -57,15 +57,15 @@ impl std::fmt::Display for crate::PredicateDeclaration struct FormulaDisplay<'formula> { - parent_precedence: Option, + parentheses: Parentheses, formula: &'formula crate::Formula, } -fn display_formula(formula: &crate::Formula, parent_precedence: Option) -> FormulaDisplay +fn display_formula(formula: &crate::Formula, parentheses: Parentheses) -> FormulaDisplay { FormulaDisplay { - parent_precedence, + parentheses, formula, } } @@ -74,13 +74,15 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula> { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { - let precedence = self.formula.precedence(); - let requires_parentheses = match self.parent_precedence + let precedence_level = self.formula.precedence_level(); + let requires_parentheses = match self.parentheses { - Some(parent_precedence) => precedence > parent_precedence, - None => false, + Parentheses::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 { @@ -104,7 +106,7 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula> separator = ", " } - write!(format, " {:?}", display_formula(&exists.argument, precedence))?; + write!(format, " {:?}", display_formula(&exists.argument, parentheses))?; }, crate::Formula::ForAll(for_all) => { @@ -121,10 +123,10 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula> separator = ", " } - write!(format, " {:?}", display_formula(&for_all.argument, precedence))?; + write!(format, " {:?}", display_formula(&for_all.argument, parentheses))?; }, crate::Formula::Not(argument) => write!(format, "not {:?}", - display_formula(argument, precedence))?, + display_formula(argument, parentheses))?, crate::Formula::And(arguments) => { let mut separator = ""; @@ -133,7 +135,7 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula> for argument in arguments { - write!(format, "{}{:?}", separator, display_formula(argument, precedence))?; + write!(format, "{}{:?}", separator, display_formula(argument, parentheses))?; separator = " and " } @@ -146,64 +148,40 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula> for argument in arguments { - write!(format, "{}{:?}", separator, display_formula(argument, precedence))?; + write!(format, "{}{:?}", separator, display_formula(argument, parentheses))?; separator = " or " } }, 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 // the antecedent side - crate::Formula::Implies(_) => true, - _ => false, + crate::Formula::Implies(_) => Parentheses::Required, + _ => parentheses, }; - let implication_requires_parentheses = match **antecedent + let implication_parentheses = match **antecedent { // Implication is right-associative and thus doesn’t require parentheses when // nested on the implication side with the same implication 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 - crate::Formula::Implies(_) => true, - _ => false, + crate::Formula::Implies(_) => Parentheses::Required, + _ => parentheses, }; let format_antecedent = |format: &mut std::fmt::Formatter| -> Result<_, _> { - if antecedent_requires_parentheses - { - write!(format, "(")?; - } - - write!(format, "{:?}", display_formula(antecedent, precedence))?; - - if antecedent_requires_parentheses - { - write!(format, ")")?; - } - - Ok(()) + write!(format, "{:?}", display_formula(antecedent, antecedent_parentheses)) }; let format_implication = |format: &mut std::fmt::Formatter| -> Result<_, _> { - if implication_requires_parentheses - { - write!(format, "(")?; - } - - write!(format, "{:?}", display_formula(implication, precedence))?; - - if implication_requires_parentheses - { - write!(format, ")")?; - } - - Ok(()) + write!(format, "{:?}", display_formula(implication, implication_parentheses)) }; match direction @@ -228,35 +206,35 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula> for argument in arguments { - write!(format, "{}{:?}", separator, display_formula(argument, precedence))?; + write!(format, "{}{:?}", separator, display_formula(argument, parentheses))?; separator = " <-> "; } }, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::Less, left, right}) - => write!(format, "{:?} < {:?}", display_term(left, None), - display_term(right, None))?, + => write!(format, "{:?} < {:?}", display_term(left, Parentheses::None), + display_term(right, Parentheses::None))?, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::LessOrEqual, left, right}) - => write!(format, "{:?} <= {:?}", display_term(left, None), - display_term(right, None))?, + => write!(format, "{:?} <= {:?}", display_term(left, Parentheses::None), + display_term(right, Parentheses::None))?, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::Greater, left, right}) - => write!(format, "{:?} > {:?}", display_term(left, None), - display_term(right, None))?, + => write!(format, "{:?} > {:?}", display_term(left, Parentheses::None), + display_term(right, Parentheses::None))?, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::GreaterOrEqual, left, right}) - => write!(format, "{:?} >= {:?}", display_term(left, None), - display_term(right, None))?, + => write!(format, "{:?} >= {:?}", display_term(left, Parentheses::None), + display_term(right, Parentheses::None))?, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::Equal, left, right}) - => write!(format, "{:?} = {:?}", display_term(left, None), - display_term(right, None))?, + => write!(format, "{:?} = {:?}", display_term(left, Parentheses::None), + display_term(right, Parentheses::None))?, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::NotEqual, left, right}) - => write!(format, "{:?} != {:?}", display_term(left, None), - display_term(right, None))?, + => write!(format, "{:?} != {:?}", display_term(left, Parentheses::None), + display_term(right, Parentheses::None))?, crate::Formula::Boolean(true) => write!(format, "true")?, crate::Formula::Boolean(false) => write!(format, "false")?, crate::Formula::Predicate(predicate) => @@ -271,7 +249,8 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula> for argument in &predicate.arguments { - write!(format, "{}{:?}", separator, display_term(argument, None))?; + write!(format, "{}{:?}", separator, + display_term(argument, Parentheses::None))?; separator = ", " } @@ -302,7 +281,7 @@ impl std::fmt::Debug for crate::Formula { 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 { - write!(format, "{}", display_formula(&self, None)) + write!(format, "{}", display_formula(&self, Parentheses::None)) } } diff --git a/src/format/terms.rs b/src/format/terms.rs index a42073e..60f0c57 100644 --- a/src/format/terms.rs +++ b/src/format/terms.rs @@ -2,7 +2,7 @@ use super::*; impl super::Precedence for crate::Term { - fn precedence(&self) -> i32 + fn precedence_level(&self) -> i32 { match &self { @@ -90,15 +90,15 @@ impl std::fmt::Display for crate::VariableDeclaration pub(crate) struct TermDisplay<'term> { - parent_precedence: Option, + parentheses: Parentheses, term: &'term crate::Term, } -pub(crate) fn display_term(term: &crate::Term, parent_precedence: Option) -> TermDisplay +pub(crate) fn display_term(term: &crate::Term, parentheses: Parentheses) -> TermDisplay { TermDisplay { - parent_precedence, + parentheses, term, } } @@ -107,12 +107,15 @@ impl<'term> std::fmt::Debug for TermDisplay<'term> { fn fmt(&self, format: &mut std::fmt::Formatter) -> std::fmt::Result { - let precedence = self.term.precedence(); - let requires_parentheses = match self.parent_precedence + let precedence_level = self.term.precedence_level(); + let requires_parentheses = match self.parentheses { - Some(parent_precedence) => precedence > parent_precedence, - None => false, + 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 { @@ -144,7 +147,8 @@ impl<'term> std::fmt::Debug for TermDisplay<'term> for argument in &function.arguments { - write!(format, "{}{:?}", separator, display_term(&argument, None))?; + write!(format, "{}{:?}", separator, + display_term(&argument, Parentheses::None))?; separator = ", "; } @@ -166,10 +170,15 @@ impl<'term> std::fmt::Debug for TermDisplay<'term> 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 // 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 // right argument even if it has the same precedence @@ -192,43 +201,24 @@ impl<'term> std::fmt::Debug for TermDisplay<'term> _ => false, }; - let right_requires_parentheses = binary_operation.right.precedence() == precedence - && (operator_requires_right_priority || right_requires_priority); - - if left_requires_parentheses + let right_parentheses = match + binary_operation.right.precedence_level() == precedence_level + && (operator_requires_right_priority || right_requires_priority) { - write!(format, "(")?; - } + true => Parentheses::Required, + false => parentheses, + }; - write!(format, "{:?}", display_term(&binary_operation.left, Some(precedence)))?; - - if left_requires_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(()) + write!(format, "{:?} {} {:?}", + display_term(&binary_operation.left, left_parentheses), + operator_string, display_term(&binary_operation.right, right_parentheses)) }, crate::Term::UnaryOperation( crate::UnaryOperation{operator: crate::UnaryOperator::Negative, argument}) - => write!(format, "-{:?}", display_term(argument, Some(precedence))), + => write!(format, "-{:?}", display_term(argument, parentheses)), crate::Term::UnaryOperation( crate::UnaryOperation{operator: crate::UnaryOperator::AbsoluteValue, argument}) - => write!(format, "|{:?}|", display_term(argument, None)), + => write!(format, "|{:?}|", display_term(argument, Parentheses::None)), }?; 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 { - 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 { - write!(format, "{}", display_term(&self, None)) + write!(format, "{}", display_term(&self, Parentheses::None)) } } diff --git a/src/parse/formulas.rs b/src/parse/formulas.rs index 2be8679..65e0927 100644 --- a/src/parse/formulas.rs +++ b/src/parse/formulas.rs @@ -627,9 +627,8 @@ mod tests crate::ImplicationDirection::RightToLeft); 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]