j84reginato / my-eval
数学表达式解析器。
1.0.0
2022-02-17 18:45 UTC
Requires
- php: >=8.1
- phplucidframe/console-table: ^1.2
Requires (Dev)
- phpunit/php-code-coverage: ^9.2
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.6
This package is auto-updated.
Last update: 2024-09-24 14:14:01 UTC
README
描述
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*x
和2*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描述。