背景antlr4定义语法文件查看生成的语法树生成代码测试结果
背景开发es查询程序,每次都要进行编码,大部分代码都是重复代码,实际上最后生成的就是json,简单樂下,有没有开发人员都会的一种表达语言,将表达语言转换成json,
很明显sql可以,开发人员都会,然后生成项目时,只需用sql来描述,你想要的查询,然后把日期等参数在json中完成替换即可,即可生成查询结果。
es json 如下
{
"query":{
"term":{
"city":{
"value":"chengdou",
"boost":1
}
}
},
"_source":{
"includes":[
"name"
],
"excludes":[
]
}
}
antlr4
ANTLR 能够根据用户定义的语法文件自动生成词法分析器和语法分析器,并将输入文本处理为语法分析树。ANTLR 自动生成的编译器高效,能够将开发者从繁杂的编译理论中解放出来,集中精力处理自己的业务逻辑。
ANTRL 4 引入的自动语法分析树创建与遍历机制,极大地提高了语言识别程序的开发效率。我们广为熟知的大数据计算框架的 SQL 解析就是基于 ANTLR,比如 Hive(ANTLR 3)、Spark 2.x(ANTLR 4)、presto(ANTLR 4)等。
定义语法文件grammar Es; // 定义一个名为ES的语法,名字与文件名一致
//语法结构
sql: selectoperation; //定义sql是一个查询操作
selectoperation:
'select' field 'from' table where ? ; //定义查询语句
field: ANYTHING # ANYTHING //子规则 *
| ID # id //子规则 匹配字母
;
table:ID;
where: 'where' expression ;
expression: ID '=' ID ;
//词法结构
ID : [a-zA-Z]+ ; // 匹配字母
ANYTHING : '*' ; // 查询 任务字符
查看生成的语法树
测试SQL
select name from a where city='chengdou'
idea中可以用插件来生成, 只需定义好语法文件即可
最后生成的结构如下
测试// Generated from ANTLR 4.9.2 package com.example.spring.estest; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; import org.antlr.v4.runtime.tree.TerminalNode; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.TermQueryBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder; import java.util.Arrays; import java.util.List; public class EsbaseVisitor结果extends AbstractParseTreeVisitor implements EsVisitor { @Override public T visitSql(EsParser.SqlContext ctx) { return visitChildren(ctx); } @Override public T visitSelectoperation(EsParser.SelectoperationContext ctx) { return visitChildren(ctx); } @Override public T visitANYTHING(EsParser.ANYTHINGContext ctx) { return visitChildren(ctx); } @Override public T visitId(EsParser.IdContext ctx) { return visitChildren(ctx); } @Override public T visitTable(EsParser.TableContext ctx) { return visitChildren(ctx); } @Override public T visitWhere(EsParser.WhereContext ctx) { return visitChildren(ctx); } @Override public T visitexpression(EsParser.expressionContext ctx) { return visitChildren(ctx); } public static void main(String[] args) { // 对每一个输入的字符串,构造一个 ANTLRStringStream 流 in ANTLRInputStream input = new ANTLRInputStream("select name from a where city='chengdou'"); // 用 in 构造词法分析器 lexer,词法分析的作用是将字符聚集成单词或者符号 EsLexer lexer = new EsLexer(input); // 用词法分析器 lexer 构造一个记号流 tokens CommonTokenStream tokens = new CommonTokenStream(lexer); // 再使用 tokens 构造语法分析器 parser,至此已经完成词法分析和语法分析的准备工作 EsParser parser = new EsParser(tokens); EsParser.SqlContext sql = parser.sql(); //找到查询子规则 EsParser.SelectoperationContext selectOperation = sql.selectoperation(); //找到查询列 String[] queryField = (String[]) Arrays.asList(selectOperation.field().getText()).toArray(); //查看where 表达式 List id = selectOperation.where().expression().ID(); //查看where 表达式里的内容 System.out.println(id.get(0).getText()); System.out.println(id.get(1).getText()); //生成es的查询语句 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.fetchSource(queryField, new String[0]); TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(id.get(0).getText(), id.get(1).getText()); searchSourceBuilder.query(termQueryBuilder); SearchRequest searchRequest = new SearchRequest(); searchRequest.source(searchSourceBuilder); System.out.println(searchRequest.source()); } }
{
"query":{
"term":{
"city":{
"value":"chengdou",
"boost":1
}
}
},
"_source":{
"includes":[
"name"
],
"excludes":[
]
}
}



