版本:v1.0
摘要
本文主要介绍了ANTLR方面的内容,包括ANTLR是什么,如何进行ANTLR的开发,总结了ANTLR的语法知识,整理了ANTLR的相关的开发工具,总结了ANTLR常见问题及解决办法,然后总结了ANTLR的一些内容等等
2013-12-15
修订历史 | ||
---|---|---|
修订 1.0 | 2013-12-15 | crl |
|
版权 © 2013 Crifan, http://crifan.com
目录
需要了解一些相关背景概念和知识:
【整理】与antlr相关的背景知识:LL(k) vs LR(k), lexer vs parser, NFA vs DFA, computing lookahead
然后后续再去学习ANTLR,才会更加清楚相关的原理和概念。
ANTLR==ANother Tool for Language Recognition
折腾ANTLR之前,需要对于和ANTLR相关的一些概念,有所了解:
【整理】与antlr开发相关的一些东西:StringTemplate,antlr的IDE(antlrworks,Eclipse的antlr插件)
关于ANTLR v4的环境搭建,可参考:
期间,可能会出现一些问题,详见:
【已解决】antlr v4中运行grun Hello r -tree,结果无输出
【已解决】运行grun Hello r -tree出错:Can’t load Hello as lexer or parser
对于搞清楚了基本的ANTLR开发流程后,
写好了ANTLR的.g的语法文件,生成了对应的lexer和parser的代码
比如xxxLexer.java和xxxParser.java
接下来,就是要搞清楚,如何去将对应的代码,集成到自己的程序中,为程序所用了:
这方面,可以参考:
目录
ANTLR的语法,虽然有ANTLR作者写的书,其中有解释,但是感觉还是解释的不够详细。
其中,很多内容,还是需要经过自己的实践,才能更好的理解的。
下面,总结一下,目前对ANTLR中部分的语法的理解:
这个是看了作者的书籍后,总结出来的,相对比较全面的语法的解释:
【整理】antlr中的各种语法:集合元素(Element Sets),标签元素(Element Labels),构造树操作符(Tree construction operators)
另外关于header方面的含义,总结如下:
详见:
【已解决】用antlrworks-1.2.2.jar编译代码出错:error: cannot find symbol,g.NEWLINE();,symbol: method NEWLINE()
至今,对于fragment,没有真正透彻的了解,所以可能会导致一些问题:
其他的,还有一些心得:
目录
总结ANTLR的相关开发工具或环境:
目前已知有几种常见方式:
下面分别介绍:
基于命令行下去开发ANTLR
自己使用对应的命令,去从antlr的.g的文件,生成对应的lexer和parser等相关的代码
然后再继续去用对应的代码,写测试代码去测试。
ANTLRWorks是IDE,是用Java写的。
是官网提供的,官方推荐的ANTLR的开发环境。
相关总结:
【总结】使用ANTLR和ANTLRWorks的开发心得和注意事项
【记录】将当前的ANTLRWorks 1.4.3,升级到ANTLRWorks 1.5.rc1,实际上是ANTLRWorks 1.5.rc2
ANTLRWorks v2,截至目前,感觉是:真心不好用。
详见:
【记录】尝试使用ANTLRWorks 2.0去进行ANTLR开发
【已解决】ANTLRWorks 2.0编译Hello.g4文件结果出错:line 1:0 token recognition error at: ‘W’
基于成熟的Eclipse这个通用的IDE框架,加上对应的ANTLR插件,也是可以用来开发ANTLR的。
只是效果貌似不是那么好而已。
详见:
【记录】使用Eclipse开发Antlr:创建antlr项目并编译
【已解决】Eclipse中对于antlr去Debug(Java)时出错:execution was cancelled reason code generation fails
【未解决】Eclipse中用Debug(Java)调试Antlr出错:unable to connect to ANTLR Debugger,Connection refused: connect
目录
ANTLR开发期间,常常会遇到各种错误,现在总结如下:
在写ANTLR的grammar时,经常会遇到:
The following token definitions can never be matched because prior tokens match the same input
对于这样的问题,之前遇到过很多。
后来,算是有点明白了,所以专门整理出来其原因和一般的解决思路:
另外,之前遇到过很多次,有需要的可以去参考:
在写ANTLR的grammar时,经常会遇到,多重匹配的问题:
一般的小问题,都可以自己慢慢修改代码,而搞定的。
比如:
【已解决】antrl代码编译出错:Decision can match input such as "’#include’" using multiple alternatives: 1, 2
其他的,也有之前不够熟悉antlr时,没有解决的问题:
【未解决】antlr语法警告:warning: Decision can match input such as "WS" using multiple alternatives: 1, 2
但是实际上,经过后来的折腾,早就解决了的。
但是,有时候,也会遇到比较难处理而始终搞不定的,比如:
写antlr语法期间,调试期间,遇到最多的,可能就属不匹配的问题了。
对于不匹配的问题,其原因有各种各样,而导致不匹配的。
目前已经遇到的,大致有这几类:
比如:
【已解决】antlr中支持EDDL的多国语言字符串其中用的是rule而非token
【已解决】antlr中匹配OPERATOR出错:mismatched input ‘&’ expecting set null
【已解决】antlr解析出错:MismatchedSetException(0!=null)
【已解决】antlr解析双引号出错:MismatchedTokenException(0!=0)
【未解决】antlr中不识别双引号(double quote)
【基本解决】antlr v3,用包含{$channel=HIDDEN;}语法,结果解析出错:MissingTokenException
如果是自己语法不小心写错了,自己仔细调试后,还是可以发现。
然后改为正确的所要匹配的内容,即可。
ANTLR v4中,由于一些语法的变化,导致语法检查更严格,有时候也会导致此类mismatch的问题:
【已解决】antlr v4的语法出错:line 1:0 mismatched input ‘a’ expecting A
详见:
详见:
【已解决】antlr出错no viable alternative at input ‘__LBL__show’
【已解决】antlr解析字符串STRING出错:no viable alternative at input,对应的错误是NoViableAltException(0@[null])
【已解决】antlr调试语法代码时出错:mismatched character ’5′ expecting ‘I’,no viable alternative at input ’7′
【已解决】antlr调试解析出错:NoViableAltException(0@[null])
【已解决】Antlr v3代码编译出错:syntax error: antlr: NoViableAltException(37@[])
如果ANTLR语法写的有问题的话,则是无法生成对应的代码的。
错误有多种可能:
比如是由于符号类型冲突而无法生成代码,详见:
有时候,是在ANTLR的option中,添加了一些不支持的参数或选项,则导致此错误。
比如:
【已解决】antlr语法出错:rewrite syntax or operator with no output option; setting output=AST
ANTLRWorks使用期间,也常会遇到很多问题,比如:
由于antlrworks本身版本的问题,而导致编译出错的:
【已解决】ANTLRWorks 1.5编译代码出错:Compiler failed with result code 1
目录
对于ANLTR开发方面的经验总结如下:
而对于,真正的用ANTLR去实现预处理这个功能,可以参考之前我的一些折腾:
【记录】将antlr v2的C/C++的preprocess,即cpp.g,转换为antlr v3
【记录】用antlr的preprocess去预处理一个新的eddl文件去除eddl中不支持的元素对应的文件内容
ANTLR中,对于异常处理,支持的很好,功能很丰富了。
对此,我们可以利用ANTLR的异常方面的信息,去实现一些自己所需要的功能,比如:
【记录】antlr异常处理:在ParseTree去getTree之后,判断某个树节点是否出现异常
其中,关于异常处理的方面的经验和心得,可以先去参考:
【整理】antlr的Exception Handling异常处理中的异常Exception的类型
其他的一些,关于异常处理方面的折腾,供参考:
【记录】尝试折腾antlr v3的异常处理和错误恢复:VARIABLE的CLASS的值INPUT故意写错为INPUT1
对于ANTLR的异常处理方面,有更多可以扩展和利用的空间:
ANTLR遇到错误,出现异常时,其默认的机制中,就已经支持:自动尝试恢复错误,然后回退到前一步,继续选择别的分支路径,继续执行下去
而希望实现:当ANTLR解析出错时,就退出,则也是支持的。
详见:
ANTLR解析期间,遇到错误,会自动抛出异常,会打印出一些错误信息。
其默认的异常出错信息,已经相对比较全面了。
但是如果想要输出更多的,其他方面的,详细出错信息,则可以参考:
【记录】用antlr预处理异常MismatchedTokenException时能输出更详细的信息
ANTLR中,ANTLR v4之前,是不支持左递归的。
当然,在有些时候,也是可以使用递归的。
比如:
而对于ANTLR中的递归的话,尤其是在Lexer中,有时候会很难实现自己所要的效果。
详见:
【未解决】antlr中setText()在递归嵌套的token中无效
关于ANTLR的解析性能,相对很不错了。
只是,有时候,自己的实现不够好的话,还是需要想办法,再去优化性能的:
ANTLR中,对于用.g所生成的代码,有两种模式:debug版本和非debug版本
是否是debug,会有很大区别:
比如就会导致后续测试代码出错还是正常运行:
【问题】android中调试antlr时执行xxx_return去获得parserResult时出错
比如会影响到是否可以获得生成的AST中节点之间的父子关系:
之前遇到的问题:对于ANTLR来说,默认所生成的AST中,没有节点的父子关系。
经过一番折腾,最终是找到了,如何获得节点的父子关系:
【已解决】antlr中获得的AST的CommonTree这个树的变量中,不存在所想要的父子(parent,child)关系
[1] What is ANTLR?
[4] 【整理】antlr的历史版本
[5] 【整理】ANTLR应用案例
[6] 【整理】antlr在技术上的优势
[15] 【整理】ANTLR v3的语法
[19] 【已解决】用antlrworks-1.2.2.jar编译代码出错:error: cannot find symbol,g.NEWLINE();,symbol: method NEWLINE()
[21] 【记录】写antrl的语法时的一个心得
[31] 【未解决】Eclipse中用Debug(Java)调试Antlr出错:unable to connect to ANTLR Debugger,Connection refused: connect
[36] 【已解决】antrl代码编译出错:Decision can match input such as "’#include’" using multiple alternatives: 1, 2
[37] 【未解决】antlr语法警告:warning: Decision can match input such as "WS" using multiple alternatives: 1, 2
[60] 【已解决】ANTLRWorks调试出错:Cannot launch the debuggerTab. Time-out waiting to connect to the remote parser
[73] 【记录】Antlr中的异常处理学习笔记
[88] 【整理】关于antlr的一些资料