Shunting Yard implementation in PHP needed, interp

2020-02-07 04:13发布

问题:

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

回答1:

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)



回答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)



回答3:

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)



回答4:

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