rendered paste bodyfunction _locale_import_parse_arithmetic($string, $n) {
// 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 = _locale_import_tokenize_formula($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) {
$operator_stack[] = $topop; // Return element to top
}
$operator_stack[] = $current_token; // Parentheses are not needed
}
else {
return FALSE;
}
}
// Flush operator stack
$topop = array_pop($operator_stack);
while ($topop != NULL) {
$element_stack[] = $topop;
$topop = array_pop($operator_stack);
}
// Now extract formula from 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])) {
$length = 3;
$delta = 2;
switch ($op) {
case '==':
$f = $element_stack[$i - 2] == $element_stack[$i - 1];
break;
case '!=':
$f = $element_stack[$i - 2] != $element_stack[$i - 1];
break;
case '<=':
$f = $element_stack[$i - 2] <= $element_stack[$i - 1];
break;
case '>=':
$f = $element_stack[$i - 2] >= $element_stack[$i - 1];
break;
case '<':
$f = $element_stack[$i - 2] < $element_stack[$i - 1];
break;
case '>':
$f = $element_stack[$i - 2] > $element_stack[$i - 1];
break;
case '+':
$f = $element_stack[$i - 2] + $element_stack[$i - 1];
break;
case '-':
$f = $element_stack[$i - 2] - $element_stack[$i - 1];
break;
case '*':
$f = $element_stack[$i - 2] * $element_stack[$i - 1];
break;
case '/':
$f = $element_stack[$i - 2] / $element_stack[$i - 1];
break;
case '%':
$f = $element_stack[$i - 2] % $element_stack[$i - 1];
break;
case '&&':
$f = $element_stack[$i - 2] && $element_stack[$i - 1];
break;
case '||':
$f = $element_stack[$i - 2] || $element_stack[$i - 1];
break;
case ':':
$f = $element_stack[$i - 3] ? $element_stack[$i - 2] : $element_stack[$i - 1];
// Remove bool, left, right, :, ?
$length = 5;
$delta = 3;
break;
}
array_splice($element_stack, $i - $delta, $length, $f);
break;
}
}
}
var_dump($element_stack);
}