j84reginato/my-eval

数学表达式解析器。

1.0.0 2022-02-17 18:45 UTC

This package is auto-updated.

Last update: 2024-09-24 14:14:01 UTC


README

Latest Stable Version Total Downloads License Code Climate

描述

PHP 数学表达式和逻辑表达式解析器库。

预期用途:安全且合理高效的评估用户提交的公式和/或逻辑表达式。该库支持基本算术和初等函数,以及变量和额外函数,三元(if/then/else)表达式和条件、逻辑(合取和析取)以及关系运算。

词法分析和解析器生成一个抽象语法树(AST),可以使用树解释器遍历。数学解析器库附带三个解释器

  • 一个计算给定表达式值的评估器。
  • 一个将AST转换为(某种程度上)简化的AST的微分器,表示给定表达式的导数。
  • 一个基本的LaTeX输出生成器,用于使用MathJax进行表达式美观打印。

示例

可以微调词法分析和解析器,但库附带了一个StdMathParser类,能够对标准数学表达式进行标记化和解析,包括算术运算以及初等函数。

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;

包含变量的更有趣的示例

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);

我们可以使用AST做其他事情。该库附带了一个微分器,可以计算相对于给定变量的(符号)导数。

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);

隐式乘法

另一个有用的特性是解析器理解隐式乘法。表达式2x被解析为2*x2*x,以及xsin(x)cos(x)^2被解析为x*sin(x)*cos(x)^2

注意隐式乘法与显式乘法的优先级相同。特别是,xy^2z被解析为x*y^2*z,而不是x*y^(2*z)

为了充分利用隐式乘法,标准词法分析器仅允许单字母变量。(否则,我们就不知道xy应该被解析为x*y还是作为一个单独的变量xy)。

文档

对于完整的文档,请参阅TODO

感谢

词法分析器基于Marc-Oliver Fiset在其博客中描述的词法分析器。

解析器是“Shunting yard”算法的一个版本,例如由Theodore Norvell描述。