function _locale_import_parse_arithmetic

7.x locale.inc _locale_import_parse_arithmetic($string)
6.x locale.inc _locale_import_parse_arithmetic($string)

Parses and sanitizes an arithmetic formula into a PHP expression

While parsing, we ensure, that the operators have the right precedence and associativity.

Parameters

$string: A string containing the arithmetic formula

Return value

The PHP version of the formula

Related topics

1 call to _locale_import_parse_arithmetic()
_locale_import_parse_plural_forms in drupal-6.x/includes/locale.inc
Parses a Plural-Forms entry from a Gettext Portable Object file header

File

drupal-6.x/includes/locale.inc, line 1478
Administration functions for locale.module.

Code

function _locale_import_parse_arithmetic($string) {
  // Operator precedence table
  $prec = array("(" => -1, ")" => -1, "?" => 1, ":" => 1, "||" => 3, "&&" => 4, "==" => 5, "!=" => 5, "<" => 6, ">" => 6, "<=" => 6, ">=" => 6, "+" => 7, "-" => 7, "*" => 8, "/" => 8, "%" => 8);
  // Right associativity
  $rasc = array("?" => 1, ":" => 1);

  $tokens = _locale_import_tokenize_formula($string);

  // Parse by converting into infix notation then back into postfix
  $opstk = array();
  $elstk = array();

  foreach ($tokens as $token) {
    $ctok = $token;

    // Numbers and the $n variable are simply pushed into $elarr
    if (is_numeric($token)) {
      $elstk[] = $ctok;
    }
    elseif ($ctok == "n") {
      $elstk[] = '$n';
    }
    elseif ($ctok == "(") {
      $opstk[] = $ctok;
    }
    elseif ($ctok == ")") {
      $topop = array_pop($opstk);
      while (isset($topop) && ($topop != "(")) {
        $elstk[] = $topop;
        $topop = array_pop($opstk);
      }
    }
    elseif (!empty($prec[$ctok])) {
      // If it's an operator, then pop from $oparr into $elarr until the
      // precedence in $oparr is less than current, then push into $oparr
      $topop = array_pop($opstk);
      while (isset($topop) && ($prec[$topop] >= $prec[$ctok]) && !(($prec[$topop] == $prec[$ctok]) && !empty($rasc[$topop]) && !empty($rasc[$ctok]))) {
        $elstk[] = $topop;
        $topop = array_pop($opstk);
      }
      if ($topop) {
        $opstk[] = $topop; // Return element to top
      }
      $opstk[] = $ctok; // Parentheses are not needed
    }
    else {
      return FALSE;
    }
  }

  // Flush operator stack
  $topop = array_pop($opstk);
  while ($topop != NULL) {
    $elstk[] = $topop;
    $topop = array_pop($opstk);
  }

  // Now extract formula from stack
  $prevsize = count($elstk) + 1;
  while (count($elstk) < $prevsize) {
    $prevsize = count($elstk);
    for ($i = 2; $i < count($elstk); $i++) {
      $op = $elstk[$i];
      if (!empty($prec[$op])) {
        $f = "";
        if ($op == ":") {
          $f = $elstk[$i - 2] . "):" . $elstk[$i - 1] . ")";
        }
        elseif ($op == "?") {
          $f = "(" . $elstk[$i - 2] . "?(" . $elstk[$i - 1];
        }
        else {
          $f = "(" . $elstk[$i - 2] . $op . $elstk[$i - 1] . ")";
        }
        array_splice($elstk, $i - 2, 3, $f);
        break;
      }
    }
  }

  // If only one element is left, the number of operators is appropriate
  if (count($elstk) == 1) {
    return $elstk[0];
  }
  else {
    return FALSE;
  }
}