解析数学表达式 代码解析AST语法树
2019年2月20日09:18:22
AST语法树自己写代码解析的话就比较麻烦,有现成的库可以解析PHP,就像webpack就是自己解析js的语法代码,编译成各种版本的可用代码
github https://github.com/josdejong/mathjs
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 |
没有办法,自己去实现 前缀,中缀,后缀表达式来实现解析字符串,对于简单的加减乘除都是比较容易的,但是需要支持一些复杂一点逻辑的计算就比较麻烦,比如开方,乘方等
其他一些解析工具基本都是java ,c,cpp的
又尝试找了一些工具,发现JavaScript里面有一些,但是不符合我的个人需求,但是可以满足大部分,简单数学字符数解析和计算
PHP可用的库
composer require nikic/php-parser
一直在更新可以使用
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);
结果
我是使用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
这个微软的库
解析数学表达式 代码解析AST语法树的更多相关文章
- Vue源码解析:AST语法树转render函数
开始 今天要说的代码全在codegen文件夹中,在说实现原理前,还是先看个简单的例子! <div class="container"> <span>{{ms ...
- 机器学习完整过程案例分布解析,python代码解析
所谓学习问题,是指观察由n个样本组成的集合,并依据这些数据来预測未知数据的性质. 学习任务(一个二分类问题): 区分一个普通的互联网检索Query是否具有某个垂直领域的意图.如果如今有一个O2O领域的 ...
- C++实现对数学基本运算表达式的解析
代码地址如下:http://www.demodashi.com/demo/11078.html 前段时间在LeetCode上刷题,遇到了很多涉及对字符串进行解析的题目.可能是出于这个原因,最近迷恋上了 ...
- Babel(抽象语法树,又称AST)
文章:https://juejin.im/post/5a9315e46fb9a0633a711f25 https://github.com/jamiebuilds/babel-handbook/blo ...
- 笔记-爬虫-js代码解析
笔记-爬虫-js代码解析 1. js代码解析 1.1. 前言 在爬取网站时经常会有js生成关键信息,而且js代码是混淆过的. 以瓜子二手车为例,直接请求https://www.guaz ...
- 基于语法分析器GOLD Parser开发的数学表达式计算器
最近发现一款文法分析神器,看完官网(http://goldparser.org/)的介绍后感觉很犀利的样子,于是就拿来测试了一番,写了一个数学表达式分析的小程序,支持的数学运算符如下所示:常规运算:+ ...
- 抽象语法树 Abstract syntax tree
什么是抽象语法树? 在计算机科学中,抽象语法和抽象语法树其实是源代码的抽象语法结构的树状表现形式 在线编辑器 我们常用的浏览器就是通过将js代码转化为抽象语法树来进行下一步的分析等其他操作.所以将js ...
- WHY数学表达式的3D可视化
WHY数学表达式的3D可视化 很早之前我就有这种想法,将数学表达式的图形显示出来.最近终于实现了这套较为完善的版本,将其代码公布,也为开源做点贡献.首先系统中定义一套脚本语言格式,用于描述数学表达式. ...
- JavaScript的工作原理:解析、抽象语法树(AST)+ 提升编译速度5个技巧
这是专门探索 JavaScript 及其所构建的组件的系列文章的第 14 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...
随机推荐
- Linux负载查询定位工具
1 uptime命令,负载查询命令 02:34:03 // 当前时间up 2 days, 20:14 // 系统运行时间1 user // 正在登录用户数 而最后三个数字呢,依次则是过去 1 分钟.5 ...
- css和css3弹性盒模型实现元素宽度(高度)自适应
一.css实现左侧宽度固定右侧宽度自适应 1.定位 <!DOCTYPE html> <html lang="en"> <head> <me ...
- perl 之 正则表达式 (简)
正则表达式,简单介绍: 元字符 匹配项 字符类:单字符与数字 . 匹配除换行符之外的任意字符 [a-z0-9] 匹配集中任意单字符 [^a-z0-9] 匹配不在集合中的任意单字符 \d 匹配单个数 ...
- 逆元知识普及(进阶篇) ——from Judge
关于一些逆元知识的拓展 刚艹完一道 提高- 的黄题(曹冲养猪) ,于是又来混一波讲解了 ——承接上文扫盲篇 四.Lucas定理(求大组合数取模) 题外话 这里Lucas定理的证明需要用到很多关 ...
- GitHub界面初识
现在很多 HR 在招聘程序员的需求都会提到「有 Github 项目者优先」,大部分求职者也会在简历中附上 Github 链接. 作为一个专业的 HR,即便不懂代码,也不能被一个链接唬住.今天我就手 ...
- centos7.6编译安装php7.2.11及redis/memcached/rabbitmq/openssl/curl等常见扩展
centos7.6编译安装php7..11及redis/memcached/rabbitmq/openssl/curl等常见扩展 获取Php的编译参数方法: [root@eus-api-cms-bac ...
- iOS app内打开safari完成google的OAuth2认证
最近使用google的oauth认证,发现不再允许使用UIWebview进行认证了,必须使用系统游览器,使用游览器也不一定要在app之间跳转,ios使用SFSafariViewController就可 ...
- Git使用八:创建和切换分支
git的分支 与svn对比 克隆一份全新的目录以同样拥有 5 个分支来说,SVN 是同时复制 5 个版本的文件,也就是说重复 5 次同样的动作.而 Git 只是获取文件的每个版本的元素,然后只载入主要 ...
- Ubuntu18.04安装Python虚拟环境
仅为使用Ubuntu18.04的Python开发人员作参考 1.安装Ubuntu18.04虚拟环境 sudo apt install virtualenv sudo apt install virtu ...
- mysql根据分组和条件查询以后如何统计记录的条数
1.子查询,查询出的数据随便起一个别名,然后根据分组和条件查询出的数据,作为一个具有一列的一个表,然后外面的查询查询这个数据表的这一列的总数,即可. SELECT COUNT( * ) FROM ( ...