ANTLR解析(一)

来源:互联网 发布:颜宁对韩春雨评价 知乎 编辑:程序博客网 时间:2024/05/29 15:48

ANTLR是一个开源的词法分析器,包含了词法分析和语法分析,可以按照自定义规则去解析文件,得到一个树,下面主要结束使用ANTLR解析简单的HQL(此HQL只包含简单的select和from语句),大概介绍了解析的方法,提供一种大概步骤,有关hibernate对于字符串HQL的详细解析可以参照hibernate的hql.g文件

首先我们需要借助一个ANTLR的图形化编辑工具antlrworks-1.5.jar,这个jar可以使我们图形化编辑.g文件(本人理解.g文件为文法),可以实时验证语法、生成java语法解析类和此法解析类

下面是.g文法文件的主要代码:

grammar CustomHQL;options{output = AST;ASTLabelType = CommonTree;}tokens{SELECT = 'select';DISTINCT='distinct';FROM = 'from';AS = 'as';HQL;FROMCLAUSE;FROMRANGE;TABLENAME;TABLEALIAS;TABLEFIELD;SELECTCLAUSE;SELECTRANGE;CHILDTABLENAME;SORTWAY;}@header {package mtpackage;}@lexer::header{package mypackage;}hql:selectClause* fromClause* ->^(HQL selectClause* fromClause*) ;selectClause:SELECT DISTINCT? selectRange? (',' selectRange)* -> ^(SELECTCLAUSE SELECT DISTINCT? selectRange*);selectRange:(tableAlias '.' (childTableName '.')?)? tableField  -> ^(SELECTRANGE tableAlias? childTableName? tableField);fromClause :FROM fromRange? (',' fromRange)* -> ^(FROMCLAUSE FROM fromRange*);fromRange :tableName (AS? tableAlias)? -> ^(FROMRANGE tableName (AS? tableAlias)?);tableName:ID -> ^(TABLENAME ID);tableAlias:ID -> ^(TABLEALIAS ID);tableField:ID -> ^(TABLEFIELD ID);childTableName:ID -> ^(CHILDTABLENAME ID);sort:SORT ->^(SORTWAY SORT);SORT:('asc' | 'desc')+;ID : ('a'..'z' |'A'..'Z')+ ;INT : '0'..'9' + ;NEWLINE:'\r' ? '\n' ;WS : (' ' |'\t' |'\n' |'\r' )+ {skip();} ;

开头的单词grammar关键字,用来定义文法的名字

option定义一些操作:输出为一个AST树,类型为CommonTree

tokens是我们自定义的一些标记,这里主要是一些关键字和占位符然后下面的是一个文法结构:这里hql节点后面只能有selectClause或fromClause 语句后面的箭头->是重写树规则,前面的文法结构式不会出现在树里面的,树的结构需要重新定义,关于树结构有两种写法,一种是直接在文法结构里面嵌套写,另外一种是在语句后面重写规则,这里采用第二种,这样有利于维护以上文法写好之后可以进行语法验证,看有没有错误:Gramat->Check Gramar 还可以在antlrworks-1.5.jar工作界面的interpreter界面写一些语句进行验证,如果执行可以生成树接表示文件正确,然后直接生成语法解析文件、文法解析文件和一个标记文件,生成这三个文件之后就可以在java里面使用了

使用主要代码如下

String hql = "select u.name, b.name.child from ConfigTable   as  eedc, InventTable as i, BatchTable";CharStream charStream = new ANTLRStringStream(hql);CustomHQL Lexer lexer = new CustomHQLLexer(charStream);TokenStream tokenStream = new CommonTokenStream(lexer);CustomHQLParser parser = new CustomHQLParser(tokenStream);CustomHQLParser.hql_return ret = parser.hql();CommonTree tree = ret.getTree();

到这里我们就已经得到一棵HQL树了


最后推荐一遍有关ANTLR入门文章http://www.oschina.net/question/12_16797

原创粉丝点击