Example #1
0
 public function parenthesize(Node $node, ExpressionNode $cutoff, $prepend = '', $conservative = false)
 {
     $text = $node->accept($this);
     if ($node instanceof ExpressionNode) {
         // Second term is a unary minus
         if ($node->getOperator() == '-' && $node->getRight() == null) {
             return "({$text})";
         }
         if ($cutoff->getOperator() == '-' && $node->lowerPrecedenceThan($cutoff)) {
             return "({$text})";
         }
         if ($conservative) {
             // Add parentheses more liberally for / and ^ operators,
             // so that e.g. x/(y*z) is printed correctly
             if ($cutoff->getOperator() == '/' && $node->lowerPrecedenceThan($cutoff)) {
                 return "({$text})";
             }
             if ($cutoff->getOperator() == '^' && $node->getOperator() == '^') {
                 return "({$text})";
             }
         }
         if ($node->strictlyLowerPrecedenceThan($cutoff)) {
             return "({$text})";
         }
     }
     if (($node instanceof NumberNode || $node instanceof IntegerNode || $node instanceof RationalNode) && $node->getValue() < 0) {
         return "({$text})";
     }
     // Treat rational numbers as divisions on printing
     if ($node instanceof RationalNode && $node->getDenominator() != 1) {
         $fakeNode = new ExpressionNode($node->getNumerator(), '/', $node->getDenominator());
         if ($fakeNode->lowerPrecedenceThan($cutoff)) {
             return "({$text})";
         }
     }
     return "{$prepend}{$text}";
 }
Example #2
0
 /**
  * Returns true if the current Node has lower precedence than the one
  * we compare with.
  *
  * In case of a tie, we also consider the associativity.
  * (Left associative operators are lower precedence in this context.)
  *
  * @param Node $other Node to compare to.
  * @retval boolean
  */
 public function lowerPrecedenceThan($other)
 {
     if (!$other instanceof ExpressionNode) {
         return false;
     }
     if ($this->getPrecedence() < $other->getPrecedence()) {
         return true;
     }
     if ($this->getPrecedence() > $other->getPrecedence()) {
         return false;
     }
     if ($this->associativity == self::LEFT_ASSOC) {
         return true;
     }
     return false;
 }
 /** Simplify (x^a)^b when a and b are both numeric.
  * @param Node $leftOperand
  * @param Node $rightOperand
  * @retval Node|null
  */
 private function doubleExponentiation($leftOperand, $rightOperand)
 {
     // (x^a)^b -> x^(ab) for a, b numbers
     if ($leftOperand instanceof ExpressionNode && $leftOperand->getOperator() == '^') {
         $factory = new MultiplicationNodeFactory();
         $power = $factory->makeNode($leftOperand->getRight(), $rightOperand);
         $base = $leftOperand->getLeft();
         return self::makeNode($base, $power);
     }
     // No simplification found
     return null;
 }
Example #4
0
 /**
  * Determine if $node is in fact a unary operator.
  *
  * If $node can be a unary operator (i.e. is a '+' or '-' node),
  * **and** this is the first node we parse or the previous node
  * was a SubExpressionNode, i.e. an opening parenthesis, or the
  * previous node was already a unary minus, this means that the
  * current node is in fact a unary '+' or '-' and we return true,
  * otherwise we return false.
  *
  * @param Node $node Current node
  * @param Node|null $lastNode Previous node handled by the Parser
  * @retval boolean
  */
 protected function isUnary($node, $lastNode)
 {
     if (!$node->canBeUnary()) {
         return false;
     }
     // Unary if it is the first token
     if ($this->operatorStack->isEmpty() && $this->operandStack->isEmpty()) {
         return true;
     }
     // or if the previous token was '('
     if ($lastNode instanceof SubExpressionNode) {
         return true;
     }
     // or last node was already a unary minus
     if ($lastNode instanceof ExpressionNode && $lastNode->getOperator() == '~') {
         return true;
     }
     return false;
 }
Example #5
0
 /**
  * Add curly braces around the LaTex representation of $node if needed.
  *
  * Nodes representing a single ConstantNode, VariableNode or NumberNodes (0--9)
  * are returned as-is. Other Nodes get curly braces around their LaTeX code.
  *
  * @param Node $node    AST to parse
  * @retval string
  */
 public function bracesNeeded(Node $node)
 {
     if ($node instanceof VariableNode || $node instanceof ConstantNode) {
         return $node->accept($this);
     } elseif ($node instanceof IntegerNode && $node->getValue() >= 0 && $node->getValue() <= 9) {
         return $node->accept($this);
     } else {
         return '{' . $node->accept($this) . '}';
     }
 }