freezewarp / php-shunting-yard
灵活的Shunting Yard解析器,基于https://github.com/andig/php-shunting-yard
1.2.1
2019-07-26 05:05 UTC
Requires
- php: >=7
Requires (Dev)
- phpunit/phpunit: ^5.0|^6.0|^7.0|^8.0
README
分支更改
此分支的一般目标是采用现有的安全公式评估框架,并添加更多通用输入所需的功能(而原始版本主要侧重于数字)。
为此,进行了以下更改
-
常量可以是任何PHP值,不仅仅是数值。(内部表示为
T_NATIVE,并包含T_NULL。) -
已添加对字符串字面量的支持。
- 添加了
||运算符用于连接。 (此运算符的优先级高于相等但低于加法和减法。因此,2 + 3 || 3 + 4 = "57"。) +运算符在任一边是非数值时充当连接运算符。(因此,"2" + "3" = 5,但"2 " + "3" = "2 3"。)- 支持字符串字面量,可以是
"string"或'string'。(不支持转义。)
- 添加了
-
已添加对数组字面量的支持。
- 如果任一操作数是数组,则
||运算符将执行数组合并。 - 可以使用
in运算符检查数组成员的存在。还需要添加一个not in运算符。 - 实现了列表和关联数组。列表使用语法
[1, 2, 3],而关联数组使用语法[1 -> 2, 3 -> 4, 5 -> 6]。 - 数组键和值支持除shunting表达式外所有支持的运算——例如,
[1 + 2 -> 3 + 4, 5 + 6 -> 7 + 8]等价于[3 -> 7, 11 -> 15]。
- 如果任一操作数是数组,则
-
已扩展变量名
- 现在,任何匹配
/\p{L}\p{N}\.]+/(即只包含Unicode字母、数字和符号.)的字符串都将被视为变量名。这意味着littérature + 手紙是一个有效的公式,添加了两个变量。 - 为更复杂的变量引用分配了特殊语法,
${xyz}——这支持变量名中除}之外的任何字符。 - 未注册的变量将评估为0而不是抛出异常。可以在上下文中设置一个严格的模式标志来重新启用旧的行为。
- 现在,任何匹配
-
使用#支持行尾注释
-
进行了一些更具有主观性的更改,以使整体语法更友好
- 没有设置默认常量。在构建时,可以传递一个数组以一次性设置所有常量。
and、or和not现在是&、|和!的别名。if、coalesce、min和max函数默认注册。- 移除了xor运算符以避免可能的混淆(它曾是
><)。
为所有这些更改编写了单元测试。所有现有和新测试都通过。
最后,虽然不包括在内,但个人推荐通过以下方式重载上下文来使用此包
new class($array) extends Context
{
public function cs($name) {
return your_array_getter($this->constants, $name);
}
}
虽然默认类仅执行正常数组查找,但有许多进行更高级数组查找的机会。Laravel的array_get提供了基本的点查找,或者可以使用https://github.com/Galbar/JsonPath-PHP进行完整的JSONPath查找。
示例
简单的方程式解析
use RR\Shunt\Parser; $equation = '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3'; $result = Parser::parse($equation); echo $result; //3.0001220703125
具有常量和函数的方程式
use RR\Shunt\Parser; use RR\Shunt\Context; $ctx = new Context(); $ctx->def('abs'); // wrapper for PHP "abs" function $ctx->def('foo', 5); // constant "foo" with value "5" $ctx->def('bar', function($a, $b) { return $a * $b; }); // define function $equation = '3 + bar(4, 2) / (abs(-1) - foo) ^ 2 ^ 3'; $result = Parser::parse($equation, $ctx); echo $result; //3.0001220703125
测试条件
use RR\Shunt\Parser; use RR\Shunt\Context; $ctx = new Context(); $ctx->def('foo', 5); // constant "foo" with value "5" $equation = '(foo > 3) & (foo < 6)'; $result = Parser::parse($equation, $ctx); echo $result; //true
在多个输入上重新运行解析表达式
use RR\Shunt\Parser; use RR\Shunt\Context; $counter = 1; $ctx = new Context(); $ctx->def('data', function() { global $counter; return $counter++; }); // define function $ctx->def('bar', function($a) { return 2*$a; }); // define function $equation = 'bar(data())'; $parser = new Parser(new Scanner($equation)); $result = $parser->reduce($this->ctx); // first result echo $result; // 2 $result = $parser->reduce($this->ctx); // second result echo $result; // 4
安装
在您的composer.json文件中定义以下需求
{
"require": {
"freezewarp/php-shunting-yard": "dev-master"
}
}
作者
这是一个基于 https://github.com/andig/php-shunting-yard 的分支,它又使用了以下代码: