php - Variables infix to prefix to postfix -


i searched on internet implementation in converting not numbers expressions variable expressions infix notation prefix , postfix. searches did weren't successful. want see if there implementation yet in php modify support more operators not (-,*,+,=).

for example convert:

a+b/c*(p/c) 

while keeping variable names, , not having enter numbers evaluate them.

i have found implementation in evalmath class provided miles kaufmann here : http://www.phpclasses.org/package/2695-php-safely-evaluate-mathematical-expressions.html

infix postfix code :

 // convert infix postfix notation     function nfx($expr) {          $index = 0;         $stack = new evalmathstack;         $output = array(); // postfix form of expression, passed pfx()         $expr = trim(strtolower($expr));          $ops   = array('+', '-', '*', '/', '^', '_');         $ops_r = array('+'=>0,'-'=>0,'*'=>0,'/'=>0,'^'=>1); // right-associative operator?           $ops_p = array('+'=>0,'-'=>0,'*'=>1,'/'=>1,'_'=>1,'^'=>2); // operator precedence          $expecting_op = false; // use in syntax-checking expression                                // , determining when - negation          if (preg_match("/[^\w\s+*^\/()\.,-]/", $expr, $matches)) { // make sure characters             return $this->trigger("illegal character '{$matches[0]}'");         }          while(1) { // 1 infinite loop ;)             $op = substr($expr, $index, 1); // first character @ current index             // find out if we're @ beginning of number/variable/function/parenthesis/operand             $ex = preg_match('/^([a-z]\w*\(?|\d+(?:\.\d*)?|\.\d+|\()/', substr($expr, $index), $match);             //===============             if ($op == '-' , !$expecting_op) { // negation instead of minus?                 $stack->push('_'); // put negation on stack                 $index++;             } elseif ($op == '_') { // have explicitly deny this, because it's legal on stack                  return $this->trigger("illegal character '_'"); // not in input expression             //===============             } elseif ((in_array($op, $ops) or $ex) , $expecting_op) { // putting operator on stack?                 if ($ex) { // expecting operator have number/variable/function/opening parethesis?                     $op = '*'; $index--; // it's implicit multiplication                 }                 // heart of algorithm:                 while($stack->count > 0 , ($o2 = $stack->last()) , in_array($o2, $ops) , ($ops_r[$op] ? $ops_p[$op] < $ops_p[$o2] : $ops_p[$op] <= $ops_p[$o2])) {                     $output[] = $stack->pop(); // pop stuff off stack output                 }                 // many thanks: http://en.wikipedia.org/wiki/reverse_polish_notation#the_algorithm_in_detail                 $stack->push($op); // put our operator onto stack                 $index++;                 $expecting_op = false;             //===============             } elseif ($op == ')' , $expecting_op) { // ready close parenthesis?                 while (($o2 = $stack->pop()) != '(') { // pop off stack last (                     if (is_null($o2)) return $this->trigger("unexpected ')'");                     else $output[] = $o2;                 }                 if (preg_match("/^([a-z]\w*)\($/", $stack->last(2), $matches)) { // did close function?                     $fnn = $matches[1]; // function name                     $arg_count = $stack->pop(); // see how many arguments there (cleverly stored on stack, thank you)                     $output[] = $stack->pop(); // pop function , push onto output                     if (in_array($fnn, $this->fb)) { // check argument count                         if($arg_count > 1)                             return $this->trigger("too many arguments ($arg_count given, 1 expected)");                     } elseif (array_key_exists($fnn, $this->f)) {                         if ($arg_count != count($this->f[$fnn]['args']))                             return $this->trigger("wrong number of arguments ($arg_count given, " . count($this->f[$fnn]['args']) . " expected)");                     } else { // did somehow push non-function on stack? should never happen                         return $this->trigger("internal error");                     }                 }                 $index++;             //===============             } elseif ($op == ',' , $expecting_op) { // did finish function argument?                 while (($o2 = $stack->pop()) != '(') {                      if (is_null($o2)) return $this->trigger("unexpected ','"); // oops, never had (                     else $output[] = $o2; // pop argument expression stuff , push onto output                 }                 // make sure there function                 if (!preg_match("/^([a-z]\w*)\($/", $stack->last(2), $matches))                     return $this->trigger("unexpected ','");                 $stack->push($stack->pop()+1); // increment argument count                 $stack->push('('); // put ( on, we'll need pop again                 $index++;                 $expecting_op = false;             //===============             } elseif ($op == '(' , !$expecting_op) {                 $stack->push('('); // easy                 $index++;                 $allow_neg = true;             //===============             } elseif ($ex , !$expecting_op) { // have function/variable/number?                 $expecting_op = true;                 $val = $match[1];                 if (preg_match("/^([a-z]\w*)\($/", $val, $matches)) { // may func, or variable w/ implicit multiplication against parentheses...                     if (in_array($matches[1], $this->fb) or array_key_exists($matches[1], $this->f)) { // it's func                         $stack->push($val);                         $stack->push(1);                         $stack->push('(');                         $expecting_op = false;                     } else { // it's var w/ implicit multiplication                         $val = $matches[1];                         $output[] = $val;                     }                 } else { // it's plain old var or num                     $output[] = $val;                 }                 $index += strlen($val);             //===============             } elseif ($op == ')') { // miscellaneous error checking                 return $this->trigger("unexpected ')'");             } elseif (in_array($op, $ops) , !$expecting_op) {                 return $this->trigger("unexpected operator '$op'");             } else { // don't want know did here                 return $this->trigger("an unexpected error occured");             }             if ($index == strlen($expr)) {                 if (in_array($op, $ops)) { // did end operator? bad.                     return $this->trigger("operator '$op' lacks operand");                 } else {                     break;                 }             }             while (substr($expr, $index, 1) == ' ') { // step index past whitespace (pretty turns whitespace                  $index++;                             // implicit multiplication if no operator there)             }          }          while (!is_null($op = $stack->pop())) { // pop off stack , push onto output             if ($op == '(') return $this->trigger("expecting ')'"); // if there (s on stack, ()s unbalanced             $output[] = $op;         }         return $output;     } 

Comments

Popular posts from this blog

html5 - What is breaking my page when printing? -

c# - must be a non-abstract type with a public parameterless constructor in redis -

ajax - PHP/JSON Login script (Twitter style) not setting sessions -