规则表达式文法
来源:互联网 发布:菜鸟网络天津武清园区 编辑:程序博客网 时间:2024/05/17 21:06
1、背景
想写一个groovy规则表达式引擎。已经解决了groovy的脚本部分,但是在多脚本联合执行的时候,多个表达式的计算就变成一个难点了。
2、案例
例如,编写一个订购权限校验的引擎,即满足条件的用户才能对商品进行订购。
简单用伪代码的性质表示即:
public boolean checkPermission(){ if(userId==121212L){ return false;//不能订购 } return true;//可以订购}
那么可以编写groovy脚本
if(userId==121212L){ return false;//不能订购 } return true;//可以订购
那么可以配置groovy脚本,key=checkPermission。
3、问题
问题来了,一个规则配置上去很简单,执行也非常简单。但是如果存在多个表达的时候,就变得非常复杂了。例如,存在一个规则为:
用户有购买权限,并且用户订购的时间不是周末,或者指定商品没有校验,都可以订购。
用伪代码就如下所示:
if((用户有购买权限 && 用户订购的时间不是周末) || 指定商品){ return true;}return false
这个时候就麻烦了,单独执行每个表达式很简单,但是如何执行(用户有购买权限 && 用户订购的时间不是周末) || 指定商品)这一串代码就非常复杂了。
4、解决方案
毕竟要解决问题,想了很多方案。
①使用正则表达式,将表达式组里的表达式匹配出来,再进行执行。
后面发现,这个正则写法会很难,而且没有拓展性。
②编译文法
使用编译文法很容易就能够匹配出来,折腾了一个下午,终于能够顺利的把表达式组的内容全部解析出来。
1、环境安装
OS X$ cd /usr/local/lib$ sudo curl -O http://www.antlr.org/download/antlr-4.7-complete.jar$ export CLASSPATH=".:/usr/local/lib/antlr-4.7-complete.jar:$CLASSPATH"$ alias antlr4='java -jar /usr/local/lib/antlr-4.7-complete.jar'$ alias grun='java org.antlr.v4.gui.TestRig'
2、文法编写
grammar Expr; prog: (expr NEWLINE)* ;expr: expr (' && ') expr | expr (' || ') expr | INT | '(' expr ')' ;NEWLINE : [\r\n]+ ;INT : [A-Za-z]+;
以上就是表达式组的规则
3、输出表达式
import org.antlr.v4.runtime.ANTLRInputStream;import org.antlr.v4.runtime.CommonTokenStream;import org.antlr.v4.runtime.tree.ParseTree;import org.antlr.v4.runtime.tree.Tree;/** * Created by jianghuiwen on 17/5/8. */public class MainTest { public static void main(String[] args){ ANTLRInputStream in = new ANTLRInputStream("((jiang || hui) && test) ** todo\n"); ExprLexer lexer = new ExprLexer(in); CommonTokenStream tokens = new CommonTokenStream(lexer); ExprParser parser = new ExprParser(tokens); ExprParser.ProgContext ret = parser.prog(); for(int i = 0;i<ret.getChildCount();i++){ ParseTree parseTree = ret.getChild(i); printTree(parseTree); } } public static void printTree(ParseTree root){ if(root.getText().equals(" || ") || root.getText().equals("(") || root.getText().equals(")") ||root.getText().equals(" && ") ){ return; } if(root.getChildCount()>0){ for(int i=0;i<root.getChildCount();i++){ printTree(root.getChild(i)); } }else{ System.out.println(root.getText()); } }}
4、输出结果
如上图所示,就把表达式组的表达式全部输出了。然后单独执行出结果,最后再做一个合并运算,就可以得出整个表达式组的值了。
5、拓展
上述还是有很多问题的,比如,无法传递参数,那么参数这个问题也要解决,很多规则校验都需要从外部传递参数进来的,这个后续再考虑
0 0
- 规则表达式文法
- jquery 选择器文法规则
- 编译原理-表达式的文法
- 表达式文法以及parse实现
- yacc文法规则解决运算符优先级
- yacc文法规则加入字符变量名
- 文法
- 文法
- 正则表达式和上下文无关文法
- 正则表达式与上下文无关文法
- 学编译原理,一个文法规则的实现
- yacc文法规则加入字符变量名2
- 规则引擎教程--表达式规则
- 规则引擎表达式规则学习
- 关于正则表达式、正则文法、NFA、LR(1)
- 基于文法分析的表达式计算器的实现
- 正则文法和正则表达式的相互转化
- 构造文法时表达式中算符优先级的问题
- Container架构与Hypervisor(VM)架构的对比
- 57. Insert Interval
- 打包APP时报错 linker command failed with exit code 1 (use -v to see invocation)
- 自己写的一个内存修改库CheatLibrary
- 服务优化之一(初始化数据压缩存储优化)
- 规则表达式文法
- Web AppBuilder for ArcGIS(开发版)系列教程 2
- Nginx详细安装部署教程(转)
- 第六天-2017-05-08
- jsp 乱码问题
- Oracle 11g ORA-12560错误
- 多食大蒜洋葱防感冒
- HDU 1698Just a Hook(线段树 + Lazy Tag(延迟更新))
- 数据压缩 DPCM编码