2019年2月20日09:18:22php
AST語法樹本身寫代碼解析的話就比較麻煩,有現成的庫能夠解析PHP,就像webpack就是本身解析js的語法代碼,編譯成各類版本的可用代碼css
github https://github.com/josdejong/mathjsjava
Extension | Description |
---|---|
mathsteps | A step-by-step math solver library that is focused on pedagogy (how best to teach). The math problems it focuses on are pre-algebra and algebra problems involving simplifying expressions. |
mathjs‑expression‑parser | This custom build of mathjs contains just the expression parser and basic arithmetic functions for numbers. About four times as small as the full mathjs library. |
mathjs-simple-integral | Extends Math.js to be able to compute simple integrals. |
math.diff.js | Symbolic differentiation plugin for Math.js |
postcss-math | PostCSS plugin for making calculations with math.js |
沒有辦法,本身去實現 前綴,中綴,後綴表達式來實現解析字符串,對於簡單的加減乘除都是比較容易的,可是須要支持一些複雜一點邏輯的計算就比較麻煩,好比開方,乘方等node
其餘一些解析工具基本都是java ,c,cpp的webpack
又嘗試找了一些工具,發現JavaScript裏面有一些,可是不符合個人我的需求,可是能夠知足大部分,簡單數學字符數解析和計算git
http://mathjs.org github
PHP可用的庫web
composer require nikic/php-parser
一直在更新可使用express
namespace App\Http\Controllers\Data\V2; use App\Http\Controllers\Data\V2\BaseController as Base; use PhpParser\Error; use PhpParser\NodeDumper; use PhpParser\ParserFactory; class CommonController extends Base { public static function index(Request $Request) { $code = <<<CODE <?php ((99 + 1)*4-1); CODE; $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); try { $ast = $parser->parse($code); } catch (Error $error) { echo "Parse error: {$error->getMessage()}\n"; return; } $dumper = new NodeDumper; echo $dumper->dump($ast);
結果markdown
我是使用pre打印的
array( 0: Stmt_Expression( expr: Expr_BinaryOp_Minus( left: Expr_BinaryOp_Mul( left: Expr_BinaryOp_Plus( left: Scalar_LNumber( value: 99 ) right: Scalar_LNumber( value: 1 ) ) right: Scalar_LNumber( value: 4 ) ) right: Expr_BinaryOp_Plus( left: Scalar_LNumber( value: 1 ) right: Scalar_LNumber( value: 2 ) ) ) ) )
基本就能夠達到語法樹解析,元素本身解析就能夠了,可是支持的運算符只能支持官方已有的運算符,特殊的運算符或者自定義的運算符,得本身標記去解析,特別複雜的須要本身根據解析的ast去從新轉換成本身實際業務的需求
若是你須要添加一個vistor 遍歷真個ast樹 ,並獲取,修改數據
<?php namespace App\Service; use PhpParser\NodeVisitorAbstract; use PhpParser\Node; class Visitor extends NodeVisitorAbstract { public $data; public $operator; public function __construct() { $this->data = new \SplStack(); $this->operator = new \SplStack(); } public function leaveNode(Node $node) { //全部的符號 if ($node instanceof Node\Expr) { $this->operator->push($node->getType()); } //全部運算符 // if ($node instanceof Node\Expr\BinaryOp) { // $this->operator->push($node->getType()); // } // $this->operator->push($node->getType()); if ($node instanceof Node\Scalar) { $this->data->push((string) $node->value); } } public function getData() { return $this->data; } public function getOperator() { return $this->operator; } }
而後在解析ast樹的代碼添加vistor
public function TransformToAst($string = '') { try { if (empty($string)) { throw new \Exception('公式不能爲空'); } $code = <<<CODE <?php $string; CODE; $ParserFactory = new ParserFactory(); $parser = $ParserFactory->create(ParserFactory::PREFER_PHP7); $ast = $parser->parse($code); $traverser = new NodeTraverser; $Visitor = new Visitor(); $traverser->addVisitor($Visitor); $modifiedStmts = $traverser->traverse($ast); p($Visitor->getOperator()); pp($Visitor->getData()); // pp($modifiedStmts); // die; if (empty($ast_object)) { throw new \Exception('解析表達式爲空'); } $ast_new = self::ParseAstToArray($ast_object['0']); return $ast_new; } catch (\Exception $e) { throw new \Exception($e->getMessage() . $e->getFile() . $e->getLine()); } }
其餘提供的不少工具類,可是缺乏demo實例,讓處入手的人很難直接上手使用
參考 https://github.com/nikic/PHP-Parser/blob/master/doc/component/Walking_the_AST.markdown 之後有時間在翻譯一下文檔
Microsoft/tolerant-php-parser
這個微軟的庫