j84reginato/my-eval

PHP parser for mathematical expressions.

1.0.0 2022-02-17 18:45 UTC

This package is auto-updated.

Last update: 2024-04-24 13:15:53 UTC


README

Latest Stable Version Total Downloads License Code Climate

DESCRIPTION

PHP parser and evaluator library for mathematical and logical expressions.

Intended use: safe and reasonably efficient evaluation of user submitted formulas and/or logical expressions. The library supports basic arithmetic and elementary functions, as well as variables and extra functions, ternary ( if/then/else) expressions and conditional, logical (conjunction and disjunction) and relational operations.

The lexer and parser produces an abstract syntax tree (AST) that can be traversed using a tree interpreter. The math-parser library ships with three interpreters:

  • an evaluator computing the value of the given expression.
  • a differentiator transforming the AST into a (somewhat) simplied AST representing the derivative of the supplied expression.
  • a rudimentary LaTeX output generator, useful for pretty printing expressions using MathJax

EXAMPLES

It is possible to fine-tune the lexer and parser, but the library ships with a StdMathParser class, capable of tokenizing and parsing standard mathematical expressions, including arithmetical operations as well as elementary functions.

Use MyEval\Lexing\StdMathLexer;
use MyEval\Parsing\Parser;
use MyEval\Solving\StdMathEvaluator;

// Tokenize
$lexer = new StdMathLexer();
$tokens = $lexer->tokenize('1+2');

// Parse
// Generate an abstract syntax tree
$parser = new Parser();
$ast = $parser->parse($tokens);

// Do something with the AST, e.g. evaluate the expression:
$evaluator = new StdMathEvaluator();
$value = $ast->accept($evaluator);
echo $value;

More interesting example, containing variables:

Use MyEval\Lexing\StdMathLexer;
use MyEval\Parsing\Parser;
use MyEval\Solving\StdMathEvaluator;

// Tokenize
$lexer = new StdMathLexer();
$tokens = $lexer->tokenize('x+sqrt(y)');

// Parse
// Generate an abstract syntax tree
$parser = new Parser();
$ast = $parser->parse($tokens);

// Evaluate
$evaluator = new StdMathEvaluator([ 'x' => 2, 'y' => 3 ]);
$value = $ast->accept($evaluator);

We can do other things with the AST. The library ships with a differentiator, computing the (symbolic) derivative with respect to a given variable.

use MyEval\Lexing\StdMathLexer;
use MyEval\Parsing\Parser;
use MyEval\Solving\Differentiator;
use MyEval\Solving\StdMathEvaluator;

// Tokenize
$lexer = new StdMathLexer();
$tokens = $lexer->tokenize('exp(2*x)-x*y');

// Parse
// Generate an abstract syntax tree
$parser = new Parser();
$ast = $parser->parse($tokens);

// Differentiate
$differentiator = new Differentiator('x');
$derivative = $ast->accept($differentiator);
$df = $derivative->accept($differentiator);

// Evaluate
// $df now contains the AST of '2*exp(x)-y' and can be evaluated further
$evaluator = new StdMathEvaluator([ 'x' => 1, 'y' => 2 ]);
$value = $df->accept($evaluator);

Implicit multiplication

Another helpful feature is that the parser understands implicit multiplication. An expression as 2x is parsed the same as 2*x and xsin(x)cos(x)^2 is parsed as x*sin(x)*cos(x)^2.

Note that implicit multiplication has the same precedence as explicit multiplication. In particular, xy^2z is parsed as x*y^2*z and not as x*y^(2*z).

To make full use of implicit multiplication, the standard lexer only allows one-letter variables. (Otherwise, we wouldn't know if xy should be parsed as x*y or as the single variable xy).

DOCUMENTATION

For complete documentation, see the TODO

THANKS

The Lexer is based on the lexer described by Marc-Oliver Fiset in his blog.

The parser is a version of the "Shunting yard" algorithm, described for example by Theodore Norvell.