作者:江南白衣
ANTLR(ANother Tool for Language Recognition)风头正盛,经常可以看到用它做语法解释器的项目,比如Hibernate就在3.0换上它来解释HQL,加强了HQL的语法。
因为Antlr是EBNF-AST语法解释系的代表,而自己总是心思思想搞一下DSL(领域语言),所以从Hibernate来学习一下Antlr的应用。
Hibernate HQL translator作者Joshua Davis的两个Blog
Hibernate3 Query Translator Design - Part One : The Basics
Hibernate3 Query Translator Design - Part Two : Parsing HQL
Antlr最好的介绍文章是那篇,在《程序员》2004年3月有中文的版本。 不过,那个计算器的例子太简单了。深刻一点的有<ashley j.s="" very="" thorough="" tutorial=""></ashley>。
另外,SlickEdit 支持Antlr的语法,是一定要用的编辑器,在 ttdown.com上有破解。
一,Antlr引擎的工作过程大概是这样的:
1.Lexer类--词法分析器。
定义语言中的各种Token(单词),如 From 、Where、=、<>.......
Lexer负责把读入的普通文本流识别成Token串。
2.Parser类--语法分析器。
使用BNF语法,递归定义句子的Pattern,如whereStatement、FromStatement、SelectStatement。
Parser负责把读入的Token串匹配成句子,翻译出AST(抽象语法树)。
有些简单的应用,也可以在本层现炒现卖,完成所有动作,属于Single Pass Builder。
3.TreeParser类--抽象语法树遍历器。
根据Parser类分析出来的AST(抽象语法树)进行动作。
用Parser把AST抽取出来,再用TreeParser进行动作的Double Pass Builder模式,解耦了Parser和Generation,再配合Template 生成代码,是Antlr推荐的最佳模式。
二,开发人员的实际步骤
1.按照Antlr的简单语法定义前面讲的3个类,文件的后缀名为g。
2.使用java antlr.Tool xxx.g命令,把grammar文件编译成java文件。
3.编写应用程序,如:
看过Antlr对HQL的解释,觉得EBNF系的方法要解释Java这样的编程语言还好些,如果要解释类自然语言的DSL就比较痛苦,所以情绪不是很高涨,挑一条最容易的"Delete from goods where ....." 匆匆走过场
Joel的一句话对我的影响比较大:"如果为了证明一个微不足道的问题需要花三个小时写下几黑板的证明步骤,那么这种机制不可能用来证明任何有趣的东西" 。对于我这个层次的程序员,antlr在我手中造不出有趣的DSL来。
importantlr.*;
importantlr.collections.*;
publicclassMain
{
publicstaticvoidmain(String[]args)throwsException
{
ExprLexerlexer=newExprLexer(System.in);
ExprParserparser=newExprParser(lexer);
parser.expr();ASTast=parser.getAST();
ExprTreeParsertreeParser=newExprTreeParser();
intx=treeParser.expr(ast);
}
}
三,Hibernate对Antlr的应用
Hibernate的HQL Grammar文件一共有三个,在/grammar目录下:
1.hql.g 定义Token类和Parser类,将HQL解释成hql的抽象语法树(AST)
2.hql-sql.g 定义Tree Walker ,将HQL AST转化为SQL AST,将生成模块与Hibernate解耦。
3.sql-gen.g 定义Tree Walker,从SQL AST生成sql
下面看 DELETE FROM GOODS的翻译过程
1.HqlBaseLexer extends Lexer
定义EQ: '=';LT: '<'; GT: '>';PLUS: '+';等符号
及IDENT: ( 'a' .. 'z' | '_' ) ( 'a' .. 'z' | '0' .. '9' | '_' | '$' )*
2.HqlBaseParser extends Parser
先定义DELETE="delete"; FROM="from"; MIN="min"; 等字符串
再定义:
statement
:(updateStatement|deleteStatement|selectStatement)
;三种Statement之一
deleteStatement
:DELETE^
(optionalFromTokenFromClause)
(whereClause)?
;DELETE为叶子,(whereClause)可选
optionalFromTokenFromClause!
:(FROM!)?f:path{
AST#range=#([RANGE,"RANGE"],#f);
#optionalFromTokenFromClause=#([FROM,"FROM"],#range);
}
;不是很好懂对吧,我也这样觉得,whereClause就更加不要看了。
3. HqlSqlBaseWalker extends TreeParser
hql与sql的delete语句基本上是一样的,没什么转换。
4.SqlGeneratorBase extends TreeParser
根据SQL AST, 生成SQL语句
privateStringBufferbuf=newStringBuffer();
protectedvoidout(Strings)
{
buf.append(s);
}
statement
:selectStatement|updateStatement|deleteStatement
;
deleteStatement
:#(DELETE{out("delete");}
from
(whereClause)?
)
;输出"delete"from
:#(f:FROM{out("from");}
(fromTable)*)
fromTable
:#(a:FROM_FRAGMENT{out(a);}(tableJoin[a])*{fromFragmentSeparator(a);})
|#(b:JOIN_FRAGMENT{out(b);}(tableJoin[b])*{fromFragmentSeparator(b);})
;tableJoin[ASTparent]
:#(c:JOIN_FRAGMENT{out("");out(c);}(tableJoin[c])*)
|#(d:FROM_FRAGMENT{nestedFromFragment(d,parent);}(tableJoin[d])*)
;
.晕了吧~~~~~
whereClause
:#(WHERE{out("where");}(conditionList|booleanExpr[false]))
;
分享到:
相关推荐
项目中没有添加antlr-2.7.6.jar,hibernate不会执行hql语句
JPA标准中,面向对象的语法检查、识别: 如JPA 实现Hibernate中用到hql语句:from Person p 到数据库的时候它会转换成select * from person;
解决weblogic抛出的ClassNotFoundException: org.hibernate.hql.ast.HqlToken异常
ANTLR技术及其在HQL语言编译中的应用,徐骁栋,,本文分析了当前比较流行的编译工具ANTLR,并结合编译技术研究了ANTLR的特性和功能,最后给出了ANTLR编译器在开源框架Hibernate中的HQL查询
hibernate3.jar-核心类库 antlr-2.7.6.jar-代码扫描器,用来翻译HQL语句 commons-collections-3.1.jar-功能比java.util.*强大 dom4j-1.6.1.jar-类似于jdom,用来读写XML文件的 javassist-3.4.GA.jar- Javassist 字节...
在使用Hibernate时所必须的jar包,如果没有添加那么相关的hibernate映射不会执行hql语句并且会报NoClassDefFoundError:antlr/ANTLRException错误。
antlr-2.7.6.jar 一个语言转换工具(Hibernate利用它实现 HQL 到 SQL 的转换模板相关操作需要包) c3p0-0.9.1.jar c3p0数据源实现的jar文件 cglib.jar CGLIB 字节码解释器 commons-collections-3.1.jar collections ...
weblogic10 与hibernate冲突解决方案 错误如下:org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken linux windows 环境解决方案全解 Linux 启动脚本添加如下: export USER_...
2.antlr-2.7.2.jar(语言转换工具,hibernate利用它实现HQL到SQL的转换) 3.commons-collections-3.2.1.jar(commons项目中的子项目,是对collection集合的封装) 4.dom4j-1.6.1.jar(对dom4j的封装,是解析xml文件...
Hibernate对象-关系映射框架(ORM)使用ANTLR来处理HQL语言。 除了这些鼎鼎大名的项目之外,还可以利用ANTLR构建各种各样的实用工具,如配置文件读取器、遗留代码转换器、维基文本渲染器,以及JSON解析器。我编写...
Hibernate在解析HQL生成SQL时需要的Java文件。压缩包里三个以.g为后缀的是规则文件,以.java为后缀的文件需要拷贝到Hibernate的源码org.hibernate.hql包下,便可运行
2.antlr-2.7.2.jar(语言转换工具,hibernate利用它实现HQL到SQL的转换) 3.commons-collections-3.2.1.jar(commons项目中的子项目,是对collection集合的封装) 4.dom4j-1.6.1.jar(对dom4j的封装,是解析xml文件...
2.antlr-2.7.2.jar(语言转换工具,hibernate利用它实现HQL到SQL的转换) 3.commons-collections-3.2.1.jar(commons项目中的子项目,是对collection集合的封装) 4.dom4j-1.6.1.jar(对dom4j的封装,是解析xml文件...
一个语言转换工具, Hibernate利用它实现 HQL 到 SQL 的转换模板相关操作需要包 javassist-3.9.0.GA.jar 代码生成工具 Hibernate用它在运行时扩展 Java类和实现,同cglib包 slf4j-api-1.5.8.jar和slf4j-log4j12...
一个语言转换工具, Hibernate利用它实现 HQL 到 SQL 的转换模板相关操作需要包 javassist-3.9.0.GA.jar 代码生成工具 Hibernate用它在运行时扩展 Java类和实现,同cglib包 slf4j-api-1.5.8.jar和slf4j-log4j12-...
hibernate官网中缺失包org\hibernate\hql\antlr中的类文件