AST構文木を用いた数学式解析の実装方法

PHPにおける数学式の解析を行う場合、自前で構文解析器を実装するのは非常に複雑です。JavaScriptエコシステムではwebpackがJavaScriptコードをAST形式に変換して処理するように、既存のライブラリを活用するのが効率的です。

PHPにおけるAST解析の実装例

PHPではnikic/php-parserライブラリが広く使用されています。以下に基本的な使用方法を示します。

composer require nikic/php-parser

AST構文木の生成

数式文字列をASTに変換する処理の実装例:

namespace App\Http\Controllers\Math; use PhpParser\ParserFactory; use PhpParser\NodeDumper; class AstController { public function parseExpression(string $expression) { $code = <<<PHP_CODE \$result = $expression; PHP_CODE; $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); try { $ast = $parser->parse($code); } catch (\Exception $e) { throw new \RuntimeException("構文解析失敗: " . $e->getMessage()); } $dumper = new NodeDumper; return $dumper->dump($ast); } }

ASTトラバーサーによるノード操作

ASTの各ノードを巡回して演算子と数値を分離するカスタムビジター:

namespace App\Visitor; use PhpParser\NodeVisitorAbstract; use PhpParser\Node; class AstVisitor extends NodeVisitorAbstract { private $values = []; private $operators = []; public function leaveNode(Node $node) { if ($node instanceof Node\Scalar\LNumber) { $this->values[] = $node->value; } if ($node instanceof Node\Expr\BinaryOp) { $this->operators[] = $node->getType(); } } public function getValues(): array { return $this->values; } public function getOperators(): array { return $this->operators; } }

使用例

$parser = new AstController(); $astDump = $parser->parseExpression("((99 + 1)*4-1)"); // ビジターによるノード処理 $traverser = new NodeTraverser(); $visitor = new AstVisitor(); $traverser->addVisitor($visitor); $processed = $traverser->traverse($parser->getAst()); print_r($visitor->getValues()); // [99, 1, 4, 1] print_r($visitor->getOperators()); // ['BinaryOp_Plus', 'BinaryOp_Mul', 'BinaryOp_Minus']

このようにしてASTを解析することで、数式の要素を分解して処理することが可能になります。複雑な演算子やカスタム関数のサポートには、ノードタイプの判定処理を追加する必要があります。

その他の関連ツール

  • mathjs: JavaScriptベースの数学ライブラリ
  • postcss-math: CSSにおける数式計算を可能にするPostCSSプラグイン
  • Microsoft/tolerant-php-parser: PHPの代替パーサー実装

タグ: PHP-Parser Math.js AST Visitorパターン

6月1日 06:40 投稿