From 6c326ddb709e9b1e6fff8e0e71c24b2d5fed2f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Thu, 9 Apr 2020 15:01:51 +0200 Subject: [PATCH] Refactor parenthesis rules for terms --- src/format/formulas.rs | 26 +++---- src/format/terms.rs | 163 +++++++++++++++++++++++++++-------------- 2 files changed, 120 insertions(+), 69 deletions(-) diff --git a/src/format/formulas.rs b/src/format/formulas.rs index 010665f..fcb535d 100644 --- a/src/format/formulas.rs +++ b/src/format/formulas.rs @@ -295,28 +295,28 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula> }, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::Less, left, right}) - => write!(format, "{:?} < {:?}", display_term(left, Parentheses::None), - display_term(right, Parentheses::None))?, + => write!(format, "{:?} < {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any), + display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::LessOrEqual, left, right}) - => write!(format, "{:?} <= {:?}", display_term(left, Parentheses::None), - display_term(right, Parentheses::None))?, + => write!(format, "{:?} <= {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any), + display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::Greater, left, right}) - => write!(format, "{:?} > {:?}", display_term(left, Parentheses::None), - display_term(right, Parentheses::None))?, + => write!(format, "{:?} > {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any), + display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::GreaterOrEqual, left, right}) - => write!(format, "{:?} >= {:?}", display_term(left, Parentheses::None), - display_term(right, Parentheses::None))?, + => write!(format, "{:?} >= {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any), + display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::Equal, left, right}) - => write!(format, "{:?} = {:?}", display_term(left, Parentheses::None), - display_term(right, Parentheses::None))?, + => write!(format, "{:?} = {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any), + display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?, crate::Formula::Compare( crate::Compare{operator: crate::ComparisonOperator::NotEqual, left, right}) - => write!(format, "{:?} != {:?}", display_term(left, Parentheses::None), - display_term(right, Parentheses::None))?, + => write!(format, "{:?} != {:?}", display_term(left, Parentheses::None, None, crate::format::terms::ChildPosition::Any), + display_term(right, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?, crate::Formula::Boolean(true) => write!(format, "true")?, crate::Formula::Boolean(false) => write!(format, "false")?, crate::Formula::Predicate(predicate) => @@ -332,7 +332,7 @@ impl<'formula> std::fmt::Debug for FormulaDisplay<'formula> for argument in &predicate.arguments { write!(format, "{}{:?}", separator, - display_term(argument, Parentheses::None))?; + display_term(argument, Parentheses::None, None, crate::format::terms::ChildPosition::Any))?; separator = ", " } diff --git a/src/format/terms.rs b/src/format/terms.rs index e1a3cdc..5f568fb 100644 --- a/src/format/terms.rs +++ b/src/format/terms.rs @@ -1,5 +1,13 @@ use super::*; +#[derive(Clone, Copy, Eq, PartialEq)] +pub(crate) enum ChildPosition +{ + Any, + Left, + Right, +} + impl super::Precedence for crate::Term { fn precedence_level(&self) -> i32 @@ -92,14 +100,103 @@ pub(crate) struct TermDisplay<'term> { parentheses: Parentheses, 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 { parentheses, 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 { - let precedence_level = self.term.precedence_level(); - 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); + let requires_parentheses = self.requires_parentheses(); if requires_parentheses { @@ -148,7 +237,7 @@ impl<'term> std::fmt::Debug for TermDisplay<'term> for argument in &function.arguments { write!(format, "{}{:?}", separator, - display_term(&argument, Parentheses::None))?; + display_term(&argument, Parentheses::None, Some(self.term), ChildPosition::Any))?; separator = ", "; } @@ -170,55 +259,17 @@ impl<'term> std::fmt::Debug for TermDisplay<'term> 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, "{:?} {} {:?}", - display_term(&binary_operation.left, left_parentheses), - operator_string, display_term(&binary_operation.right, right_parentheses)) + display_term(&binary_operation.left, Parentheses::None, Some(self.term), ChildPosition::Left), + operator_string, + display_term(&binary_operation.right, Parentheses::None, Some(self.term), ChildPosition::Right)) }, crate::Term::UnaryOperation( 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::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 @@ -242,7 +293,7 @@ impl std::fmt::Debug for crate::Term { 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 { - write!(format, "{}", display_term(&self, Parentheses::None)) + write!(format, "{}", display_term(&self, Parentheses::None, None, ChildPosition::Any)) } }