private PoHeader::parseArithmetic($string)
Parses and sanitizes an arithmetic formula into a plural element stack.
While parsing, we ensure, that the operators have the right precedence and associativity.
Parameters
string $string: A string containing the arithmetic formula.
Return value
A stack of values and operations to be evaluated.
File
- core/lib/Drupal/Component/Gettext/PoHeader.php, line 276
Class
- PoHeader
- Gettext PO header handler.
Namespace
Drupal\Component\Gettext
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | private function parseArithmetic( $string ) { // Operator precedence table. $precedence = array ( "(" => -1, ")" => -1, "?" => 1, ":" => 1, "||" => 3, "&&" => 4, "==" => 5, "!=" => 5, "<" => 6, ">" => 6, "<=" => 6, ">=" => 6, "+" => 7, "-" => 7, "*" => 8, "/" => 8, "%" => 8); // Right associativity. $right_associativity = array ( "?" => 1, ":" => 1); $tokens = $this ->tokenizeFormula( $string ); // Parse by converting into infix notation then back into postfix // Operator stack - holds math operators and symbols. $operator_stack = array (); // Element Stack - holds data to be operated on. $element_stack = array (); foreach ( $tokens as $token ) { $current_token = $token ; // Numbers and the $n variable are simply pushed into $element_stack. if ( is_numeric ( $token )) { $element_stack [] = $current_token ; } elseif ( $current_token == "n" ) { $element_stack [] = '$n' ; } elseif ( $current_token == "(" ) { $operator_stack [] = $current_token ; } elseif ( $current_token == ")" ) { $topop = array_pop ( $operator_stack ); while (isset( $topop ) && ( $topop != "(" )) { $element_stack [] = $topop ; $topop = array_pop ( $operator_stack ); } } elseif (! empty ( $precedence [ $current_token ])) { // If it's an operator, then pop from $operator_stack into // $element_stack until the precedence in $operator_stack is less // than current, then push into $operator_stack. $topop = array_pop ( $operator_stack ); while (isset( $topop ) && ( $precedence [ $topop ] >= $precedence [ $current_token ]) && !(( $precedence [ $topop ] == $precedence [ $current_token ]) && ! empty ( $right_associativity [ $topop ]) && ! empty ( $right_associativity [ $current_token ]))) { $element_stack [] = $topop ; $topop = array_pop ( $operator_stack ); } if ( $topop ) { // Return element to top. $operator_stack [] = $topop ; } // Parentheses are not needed. $operator_stack [] = $current_token ; } else { return FALSE; } } // Flush operator stack. $topop = array_pop ( $operator_stack ); while ( $topop != NULL) { $element_stack [] = $topop ; $topop = array_pop ( $operator_stack ); } $return = $element_stack ; // Now validate stack. $previous_size = count ( $element_stack ) + 1; while ( count ( $element_stack ) < $previous_size ) { $previous_size = count ( $element_stack ); for ( $i = 2; $i < count ( $element_stack ); $i ++) { $op = $element_stack [ $i ]; if (! empty ( $precedence [ $op ])) { if ( $op == ":" ) { $f = $element_stack [ $i - 2] . "):" . $element_stack [ $i - 1] . ")" ; } elseif ( $op == "?" ) { $f = "(" . $element_stack [ $i - 2] . "?(" . $element_stack [ $i - 1]; } else { $f = "(" . $element_stack [ $i - 2] . $op . $element_stack [ $i - 1] . ")" ; } array_splice ( $element_stack , $i - 2, 3, $f ); break ; } } } // If only one element is left, the number of operators is appropriate. return count ( $element_stack ) == 1 ? $return : FALSE; } |
Please login to continue.