3

I'm looking for something that can interpret a string in php and perform simple math calculation, and then return a boolean result as to whether the expression is true or false.

For example:

  1. Sue types in "3*{mysalary}/9=10000"
  2. PHP splits this up into two expressions - explode('=',string);
  3. PHP takes my list of database fields, and replaces any "{}" delimited fields with the data (typecasted to int)
  4. PHP then evaluates the maths expression
  5. php then compares the left side to the right side
  6. boolean result produced.

It may sound complex but it only needs to be very simple. Here are the constraints: 1/ mathematical operators are fixed to: + - / * 2/ comparison operators are fixed to: = > < >= <= 3/ do not need floating point comparisons, everything can be done at an integer level. So any divisions can be rounded if need be or simply just round the final result

There will only ever be two expressions, with one comparison operator. If there is any sort of error at all we will just return false.

Has anyone seen something that can do this already? I know I can make something but why re-invent the wheel right?

If you haven't seen anything do you care to list some "gotcha's" or caveat's that you can think of when building this.

After reading some more I realise I could use the shunting yard algorithm. Does anyone have an implementation of this in PHP?

I am aware the eval could be an easy method to perform this, however, it concerns me that the user could very easily break something using this method or cause syntax errors. I'd rather not include it in the solution, or if i do then it'd need to tightly control how it is used.

Thanks.

Jason

Jason
  • 15,064
  • 15
  • 65
  • 105

4 Answers4

2

There is an expression parser engine (implementations for JavaScript+Node, PHP, Python and ActionScript), on github Xpresion (ps. i'm the author)

The engine is quite flexible and configurable, one can create parsers that parse any expression which also includes user-defined variables, user-defined functions, polymorphic operators and general n-ary operators (eg. ternary if-then-else)

The algorithm is quite general (one could say, a generalised variation of Shunting Yard algorithm)

Nikos M.
  • 8,033
  • 4
  • 36
  • 43
2

Take a look at the evalMath class on PHPClasses. This should do pretty much everything that you want, including variable substitution (such as setting a value for "mysalary" in your example before evaluating the expression)

Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • evalMath has severe limitations, e.g. no support for brackets – andig Dec 28 '13 at 20:05
  • @andig - What?!? evalMath works perfectly well with brackets, please explain exactly what you mean by "severe limitations" – Mark Baker Dec 28 '13 at 20:12
  • I've looked at the site, saw the comments, had to sign up. Several comments complaining about brackets. Have to admit I didn't test it. Was however entirely happy with https://github.com/andig/php-shunting-yard/tree/dev. If inappropriate feel free to delete. – andig Dec 28 '13 at 22:56
  • The code itself handles brackets without any problems, because it is a working implementation of the shunting yard algorithm. I don't use it myself these days, but it's a perfectly serviceable library, albeit rather dated these days and not PSR-0 compliant (it predates PSR-0 by several years) and not coded according to SOLID principles... but far better for people to use that than `eval` – Mark Baker Dec 28 '13 at 23:01
  • These days, I'd recommend [ircmaxell's formula evaluator](https://gist.github.com/ircmaxell/1232629)... it's good SOLID and easily extensible – Mark Baker Dec 28 '13 at 23:07
0

The approach I'd take is:

  1. Tokenize the expression
  2. Parse it into an abstract syntax tree
  3. Perform variable substitutions (see eager evaluation)
  4. Calculate the result

Now...

  • The shunting-yard algorithm is a way to do steps 1 and 2.
  • You can check if the expression is syntactically correct after the 2nd step
  • How you calculate the result will depend on how the AST is built.

The hardest step is the 2nd; you have to consider operator precedence, parentheses and other things, but there's plenty of literature on that (you can even just follow that wikipedia link)

NullUserException
  • 83,810
  • 28
  • 209
  • 234
0

why dont you simply perform variables replacements, and then do a preg_replace("/[^0-9+-*\/]/", '', $inputString), and then use either eval() or create_function()? If you use this you MUST make sure that possibly unsafe "statements" are removed, that's why i used preg_replace, so it would remove any literal string

Quamis
  • 10,924
  • 12
  • 50
  • 66