安装antlr4插件
创建一个后缀是g4的文件
grammar Expr;
expression :
'(' expression ')' # parens
| expression 'and' expression # andOp
| expression 'or' expression # orOp
| '@' VARNAME comparison_op NUMBER # comparison
| '@' VARNAME comparison_op STRING # comparison
| '@' NUMBER comparison_op NUMBER # comparison
| '@' STRING comparison_op STRING # comparison
| '@' VARNAME comparison_op VARNAME # comparison
| '@' VARNAME contains_op VARNAME # comparison
| '@' VARNAME contains_op NUMBER # comparison
| '@' VARNAME contains_op STRING # comparison
| '@' STRING contains_op STRING # comparison
| VARNAME comparison_op NUMBER # comparison
| VARNAME comparison_op STRING # comparison
| NUMBER comparison_op NUMBER # comparison
| STRING comparison_op STRING # comparison
| VARNAME comparison_op VARNAME # comparison
| VARNAME contains_op VARNAME # comparison
| VARNAME contains_op NUMBER # comparison
| VARNAME contains_op STRING # comparison
| STRING contains_op STRING # comparison
;
comparison_op : '<' | '<=' | '>' | '>=' | '==' | '!=';
contains_op: 'contains' | 'notcontains';
STRING : '\'' ( '\\' . | '\\\'' | ~[\\'] )* '\'';
NUMBER : '-'? [0-9]+ ('.' [0-9]+)?;
VARNAME : [a-zA-Z_][a-zA-Z_0-9]*;
WS : [ \t\r\n]+ -> skip; // 忽略空白字符
fragment Letter: [a-zA-Z];
fragment Digit: [0-9];
fragment ChineseCharacter: [\u4e00-\u9fa5];
上面的文件可以直接解析如下格式的表达式:
@prices == 1 and (@val >=1 or @name<=4) and 1==1 and '2'=='3' and '1123' contains '1' and '23455' notcontains '5'
右键生成代码
引入POM
<!--动态表达式-->
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.10.1</version>
</dependency>
测试表达式结构
@Test
public void Test00(){
// 构建字符流
CodePointCharStream charStream = CharStreams.fromString("@prices == 1 and (@val >=1 or @name<=4) and 1==1 and '2'=='3' and '1123' contains '1' and '23455' notcontains '5'");
// 从字符流分析词法, 解析为token
ExprLexer lexer = new ExprLexer(charStream);
// 从token进行分析
ExprParser parser = new ExprParser(new CommonTokenStream( lexer) );
// 使用监听器,遍历语法树,根据语法定义,prog为语法树的根节点
ParseTree prog = parser.expression();
// 创建监听器
CustomerExprListener listener = new CustomerExprListener();
// 遍历AST并使用监听器处理
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(listener, prog);
// 打印生成的语法树
//System.out.println( prog.toStringTree(parser));
}
拿到表达式以后,就可以把结果处理成实际业务想要的对象了
package com.java.core.web.antlr4;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.TerminalNode;
public class CustomerExprListener extends ExprBaseListener{
@Override
public void enterEveryRule(ParserRuleContext ctx) {
//System.out.println("Entering rule: " + ctx.getText());
}
@Override
public void exitEveryRule(ParserRuleContext ctx) {
//System.out.println("Exiting rule: " + ctx.getText());
}
@Override
public void visitTerminal(TerminalNode node) {
System.out.println("Visiting terminal: " + node.getText());
}
@Override
public void visitErrorNode(ErrorNode node) {
//System.out.println("Visiting error: " + node.getText());
}
}
监听输出的内容
Visiting terminal: @
Visiting terminal: prices
Visiting terminal: ==
Visiting terminal: 1
Visiting terminal: and
Visiting terminal: (
Visiting terminal: @
Visiting terminal: val
Visiting terminal: >=
Visiting terminal: 1
Visiting terminal: or
Visiting terminal: @
Visiting terminal: name
Visiting terminal: <=
Visiting terminal: 4
Visiting terminal: )
Visiting terminal: and
Visiting terminal: 1
Visiting terminal: ==
Visiting terminal: 1
Visiting terminal: and
Visiting terminal: '2'
Visiting terminal: ==
Visiting terminal: '3'
Visiting terminal: and
Visiting terminal: '1123'
Visiting terminal: contains
Visiting terminal: '1'
Visiting terminal: and
Visiting terminal: '23455'
Visiting terminal: notcontains
Visiting terminal: '5'
可以把监控的类提取出来
/**
* 遍历语法树节点
* @param tree
*/
public static RuleTest traverseTree(ParseTree tree, String name, RuleTest ruleTest) {
//自定义变量
// public String type; //类型 1-属性 2-值 (由比较操作符决定)
// public String group; //组 0-不用添加组 1-需要添加组 (由连续小括号的数量决定,如果两个符号连续都是小括号,那么系统会认为是一个组)
// public String bracket;//括号 判断是否是组 (小括号的数量记录)
// public String isObject;//是否new object (条件对象 0-不创建 1-创建 由逻辑运算符决定 如 and/or)
if (tree instanceof TerminalNode) {
TerminalNode terminalNode = (TerminalNode) tree;
//得到树节点
String text = terminalNode.getText();
//获取条件组
List<Condition> list = ruleTest.getConditionList();
//判断节点类型 (比较操作符/逻辑运算符号/小括号/中括号/@符)
int res = CheckSymbolOptions.getNameOrValue(text);
if (res == 1){ //比较操作符
ruleTest.setType("2");
ruleTest.setEndBracket("0");
if (ruleTest.getGroup() == null || ruleTest.getGroup().equals("0")){
if (list.size()>0){
Condition condition = list.get(list.size()-1);
String symbolOptions = SymbolOptions.getNameOrValue(text);
condition.setCompareOperation(symbolOptions);//比较操作(操作符)
}
}else{
Condition cond = list.get(list.size()-1);
List<Condition> conditionList = cond.getConditionList();
if (conditionList.size()>0){
Condition condition = conditionList.get(conditionList.size()-1);
String symbolOptions = SymbolOptions.getNameOrValue(text);
condition.setCompareOperation(symbolOptions);//比较操作(操作符)
}
}
}else if (res ==2){ //逻辑运算符
if (ruleTest.getGroup() == null || ruleTest.getGroup().equals("0")){
//添加条件对象
Condition condition = addCondition(name,"symbol",text);
list.add(condition);
ruleTest.setIsObject("1");//需要添加条件对象 0-不添加 1-添加
}else{
Condition cond = list.get(list.size()-1);
List<Condition> conditionList = cond.getConditionList();
//添加条件对象
Condition condition = addCondition(name,"symbol",text);
conditionList.add(condition);
ruleTest.setIsObject("1");//需要添加条件对象 0-不添加 1-添加
}
}else if (res==3){ //括号标识符
if (text.equals("(")){
ruleTest.setType("1");
if (ruleTest.getBracket()==null || ruleTest.getBracket().equals("0")){
ruleTest.setBracket("1");
}else{
int va = Integer.valueOf(ruleTest.getBracket())+1;
ruleTest.setBracket(String.valueOf(va));
if (va==2){
if (list== null){
list = new ArrayList<>();
}
ruleTest.setGroup("1");
// if (list.size()==0){
// Condition condition = addCondition(name,"group",null);
// int endva = Integer.valueOf(ruleTest.getSubscript())+1;
// ruleTest.setSubscript(String.valueOf(endva));//记录下标
// condition.setTierIndex(String.valueOf(endva));
// list.add(condition);
// ruleTest.setConditionList(list);
// }
//创建对象
Condition condition = addCondition(name,"group",null);
condition.setDescribe(null);
int endva = Integer.valueOf(ruleTest.getSubscript())+1;
ruleTest.setSubscript(String.valueOf(endva));//记录下标
condition.setTierIndex(String.valueOf(endva));
list.add(condition);
ruleTest.setConditionList(list);
ruleTest.setIsObject("0");//添加对象后回复初始状态
}
ruleTest.setBracket("0");
}
if (ruleTest.getId()==null){
//设置rule属性
ruleTest.setId(generateId("rule"));//id需要自动生成 rule_xxxxxxxxxx(10位数)
ruleTest.setName(name);
ruleTest.setSubscript("1");//记录索引
ruleTest.setTierIndex("1");//层级索引 需要确定来源
}
}
if (text.equals(")")){
if (ruleTest.getEndBracket()==null || ruleTest.getEndBracket().equals("0")){
ruleTest.setEndBracket("1");
}else{
int endva = Integer.valueOf(ruleTest.getEndBracket())+1;
ruleTest.setEndBracket(String.valueOf(endva));
}
if (ruleTest.getEndBracket().equals("2")){
ruleTest.setGroup("0");
}
}
}else if (res ==4){ //@ 参数标识
ruleTest.setType("1");
}else {
//初始化对象与集合
if (list== null || list.size()==0){
list = new ArrayList<>();
Condition condition = addCondition(name,"single",null);
list.add(condition);
ruleTest.setConditionList(list);
}
if (ruleTest.getGroup() == null || ruleTest.getGroup().equals("0")){
if (ruleTest.getIsObject()!=null){
if (ruleTest.getIsObject().equals("1")){
//创建对象
// Condition condition = new Condition();
Condition condition = addCondition(name,"single",null);
list.add(condition);
ruleTest.setIsObject("0");//添加对象后回复初始状态
}
}
}else{
if (ruleTest.getIsObject()!=null){
if (ruleTest.getIsObject().equals("1")) {
Condition cond = list.get(list.size()-1);
List<Condition> conditionList = cond.getConditionList();
//创建对象
Condition addCondition = addCondition(name,"single",null);
conditionList.add(addCondition);
ruleTest.setIsObject("0");//添加对象后回复初始状态
}
}
}
if (list.size()>0){
if (ruleTest.getGroup()== null || ruleTest.getGroup().equals("0") ){
//获取属性详情,判断属性是否存在,如果存在拿到属性名称、类型等信息
String type = DataType.getDataType("5000"); //此处需要替换
Condition condition = list.get(list.size()-1);
if (condition.getLeftOperatorExpression()==null || condition.getRightOperatorExpression()==null ){
if (ruleTest.getType().equals("1")){
//创建左边运算符表达式
LeftOperatorExpression left = addLeftOperatorExpression(type,text);
condition.setLeftOperatorExpression(left);
ruleTest.setType("0");
}
if (ruleTest.getType().equals("2")){
//创建右边运算符表达式
RightOperatorExpression right = addRightOperatorExpression(type,text);
condition.setRightOperatorExpression(right);
ruleTest.setType("0");
ruleTest.setBracket("0");
}
}
}else{
if (ruleTest.getGroup().equals("1")){
String type = DataType.getDataType("5000"); //此处需要替换
Condition cond = list.get(list.size()-1);
// Rule rule = cond.getRule();
List<Condition> conditionList = cond.getConditionList();
//初始化对象与集合
if (conditionList== null || conditionList.size()==0){
conditionList = new ArrayList<>();
Condition condition = addCondition(name,"single",null);
if (condition.getLeftOperatorExpression() == null || condition.getRightOperatorExpression() == null) {
if (ruleTest.getType().equals("1")) {
//创建左边运算符表达式
LeftOperatorExpression left = addLeftOperatorExpression(type, text);
condition.setLeftOperatorExpression(left);
ruleTest.setType("0");
}
if (ruleTest.getType().equals("2")) {
//创建右边运算符表达式
RightOperatorExpression right = addRightOperatorExpression(type, text);
condition.setRightOperatorExpression(right);
ruleTest.setType("0");
ruleTest.setBracket("0");
}
}
conditionList.add(condition);
cond.setConditionList(conditionList);
}else{
Condition condition = conditionList.get(conditionList.size()-1);
if (condition.getLeftOperatorExpression() == null || condition.getRightOperatorExpression() == null) {
if (ruleTest.getType().equals("1")) {
//创建左边运算符表达式
LeftOperatorExpression left = addLeftOperatorExpression(type, text);
condition.setLeftOperatorExpression(left);
ruleTest.setType("0");
}
if (ruleTest.getType().equals("2")) {
//创建右边运算符表达式
RightOperatorExpression right = addRightOperatorExpression(type, text);
condition.setRightOperatorExpression(right);
ruleTest.setType("0");
ruleTest.setBracket("0");
}
}
}
}
}
}
}
}
//递归 循环遍历
for (int i = 0; i < tree.getChildCount(); i++) {
traverseTree(tree.getChild(i),name,ruleTest);
}
return ruleTest;
}