ANTLR教程

版本:v1.0

Crifan Li

摘要

本文主要介绍了ANTLR方面的内容,包括ANTLR是什么,如何进行ANTLR的开发,总结了ANTLR的语法知识,整理了ANTLR的相关的开发工具,总结了ANTLR常见问题及解决办法,然后总结了ANTLR的一些内容等等

[提示] 本文提供多种格式供:
在线阅读 HTML HTMLs PDF CHM TXT RTF WEBHELP
下载(7zip压缩包) HTML HTMLs PDF CHM TXT RTF WEBHELP

HTML版本的在线地址为:

http://www.crifan.com/files/doc/docbook/antlr_tutorial/release/html/antlr_tutorial.html

有任何意见,建议,提交bug等,都欢迎去讨论组发帖讨论:

http://www.crifan.com/bbs/categories/antlr_tutorial/

2013-12-15

修订历史
修订 1.0 2013-12-15 crl
  1. 把之前教程的地址整理过来

目录

前言
1. 本文目的
2. 学习ANTLR之前
1. ANTLR简介
1.1. ANTLR是什么
1.2. ANTLR版本历史
1.3. ANTLR的应用领域
1.4. ANTLR技术的优势
1.5. 和ANTLR相关的一些概念
2. ANTLR的开发流程
2.1. ANTLR的开发流程
2.2. ANTLR v4的开发流程
2.3. 把ANTLR整合到自己的程序中
3. ANTLR的语法Grammar详解
3.1. 完整的ANTLR语法的解释
3.2. 详解部分ANTLR语法
3.2.1. ANTLR中的lexer和parser的header的含义
3.2.2. antlr v2和antlr v3的语法对比
3.2.3. ANTLR中的fragment
4. ANTLR的开发工具
4.1. ANTLR开发环境之命令行
4.2. ANTLR开发环境之ANTLRWorks
4.2.1. ANTLRWorks v1:可运行的单独的jar包
4.2.2. ANTLRWorks v2:基于Netbeans的IDE
4.3. ANTLR开发环境之Eclipse+ANTLR的插件
5. ANLTR常见问题及解答
5.1. ANTLR的语法方面常见问题及解决办法
5.1.1. The following token definitions can never be matched because prior tokens match the same input
5.1.2. Decision can match input such as xxx using multiple alternatives
5.1.3. MismatchedSetException和mismatched input xxx expecting set yyy
5.1.4. syntax error: unterminated rule detected at xxx while looking for lexer rule element
5.1.5. NoViableAltException和no viable alternative at input xxx
5.1.6. Cannot generate the grammar because, duplicate token type xxx when collapsing subrule into set
5.1.7. rewrite syntax or operator with no output option xxx
5.1.8. UnwantedTokenException(found=xxx)
5.1.9. org.antlr.runtime.EarlyExitException
5.1.10. reference to rewrite element include without reference on left of ->
5.2. ANTLRWorks方面常见问题及解决办法
5.2.1. Compiler exception: java.io.IOException Cannot run program javac
5.2.2. Cannot launch the debuggerTab. Time-out waiting to connect to the remote parser
5.2.3. xxxParser.java error: <xxx> expected
5.2.4. Compiler failed with result code 1
6. ANTLR开发经验总结
6.1. ANTLRWorks使用心得
6.1.1. ANTLRWorks有时候会挂掉
6.2. ANTLR的预处理Preprocess
6.2.1. ANTLR自身是不支持预处理功能的
6.2.2. 可以使用ANTLR去实现预处理的功能
6.3. ANTLR的异常处理
6.3.1. ANTLR出错异常时就退出(不继续恢复错误和继续运行)
6.3.2. ANTLR出错异常时显示更多详细信息
6.4. ANTLR的递归
6.5. ANTLR解析性能
6.6. ANTLR中的条件性匹配
6.7. ANTLR相关资源下载
6.7.1. ANTLR语法示例参考代码
6.7.2. ANTLR相关开发工具下载
6.7.3. ANTLR相关资料和文档下载
6.8. ANTLR中debug和非debug版本
6.8.1. ANTLR生成的AST中没有节点的父子关系
参考书目

前言

1. 本文目的

本文目的在于,介绍ANTLR是什么,以及如何用ANTLR开发自己的解析器,以及总结常见的ANTLR错误的原因和解决办法。

2. 学习ANTLR之前

需要了解一些相关背景概念和知识:

【整理】与antlr相关的背景知识:LL(k) vs LR(k), lexer vs parser, NFA vs DFA, computing lookahead

然后后续再去学习ANTLR,才会更加清楚相关的原理和概念。

第 1 章 ANTLR简介

1.1. ANTLR是什么

ANTLR==ANother Tool for Language Recognition

  • ANTLR是和语言有关的工具
  • ATNLR是一个框架
  • 你可以用ANLTR去构建一个识别器,解析器,编译器,转换器

1.2. ANTLR版本历史

总结一下ANTLR的发展历史,历史版本:

【整理】和ANTLR有关的历史和背景知识

【整理】antlr的历史版本

1.3. ANTLR的应用领域

ANTLR可以用在很多领域中,主要是涉及到解析器,解析特定的语法的,都可以去实现。

详见:

【整理】ANTLR应用案例

1.4. ANTLR技术的优势

【整理】antlr在技术上的优势

1.5. 和ANTLR相关的一些概念

折腾ANTLR之前,需要对于和ANTLR相关的一些概念,有所了解:

【整理】与antlr开发相关的一些东西:StringTemplate,antlr的IDE(antlrworks,Eclipse的antlr插件)

第 2 章 ANTLR的开发流程

2.1. ANTLR的开发流程

关于ANTLR的基本的开发流程和示例,详见:

ANTLR Basic Tutorial

2.2. ANTLR v4的开发流程

关于ANTLR v4的环境搭建,可参考:

【记录】搭建ANTLR v4开发环境

期间,可能会出现一些问题,详见:

【已解决】antlr v4中运行grun Hello r -tree,结果无输出

【已解决】运行grun Hello r -tree出错:Can’t load Hello as lexer or parser

2.3. 把ANTLR整合到自己的程序中

对于搞清楚了基本的ANTLR开发流程后,

写好了ANTLR的.g的语法文件,生成了对应的lexer和parser的代码

比如xxxLexer.java和xxxParser.java

接下来,就是要搞清楚,如何去将对应的代码,集成到自己的程序中,为程序所用了:

这方面,可以参考:

【记录】把ANTLR v3整合到Android的App中

【记录】把通过TreeParser去解析树Tree的功能集成到(Android的)Java环境中

第 3 章 ANTLR的语法Grammar详解

ANTLR的语法,虽然有ANTLR作者写的书,其中有解释,但是感觉还是解释的不够详细。

其中,很多内容,还是需要经过自己的实践,才能更好的理解的。

下面,总结一下,目前对ANTLR中部分的语法的理解:

3.1. 完整的ANTLR语法的解释

这个是看了作者的书籍后,总结出来的,相对比较全面的语法的解释:

【整理】antlr中的各种语法:集合元素(Element Sets),标签元素(Element Labels),构造树操作符(Tree construction operators)

【整理】ANTLR v3的语法

3.2. 详解部分ANTLR语法

3.2.1. ANTLR中的lexer和parser的header的含义

另外关于header方面的含义,总结如下:

【整理】antlr中的.g语法文件中的lexer和parser的header的语法和含义

3.2.2. antlr v2和antlr v3的语法对比

详见:

【整理】antlr v2和antlr v3的语法的差异

其他的,还有一些心得:

【记录】写antrl的语法时的一个心得

第 4 章 ANTLR的开发工具

总结ANTLR的相关开发工具或环境:

目前已知有几种常见方式:

  • 命令行式开发ANTLR
  • 用ANTLRWorks去开发ANTLR
  • 基于Eclipse去开发ANTLR

下面分别介绍:

4.1. ANTLR开发环境之命令行

基于命令行下去开发ANTLR

自己使用对应的命令,去从antlr的.g的文件,生成对应的lexer和parser等相关的代码

然后再继续去用对应的代码,写测试代码去测试。

第 5 章 ANLTR常见问题及解答

ANTLR开发期间,常常会遇到各种错误,现在总结如下:

5.1. ANTLR的语法方面常见问题及解决办法

5.1.1. The following token definitions can never be matched because prior tokens match the same input

在写ANTLR的grammar时,经常会遇到:

The following token definitions can never be matched because prior tokens match the same input

对于这样的问题,之前遇到过很多。

后来,算是有点明白了,所以专门整理出来其原因和一般的解决思路:

【整理】关于antlr中出错"The following token definitions can never be matched because prior tokens match the same input"的原因和解决思路

另外,之前遇到过很多次,有需要的可以去参考:

5.1.2. Decision can match input such as xxx using multiple alternatives

在写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中STRING出现多重匹配的问题:Decision can match input such as "STRING" using multiple alternatives: 1, 2

5.1.3. MismatchedSetException和mismatched input xxx expecting set yyy

写antlr语法期间,调试期间,遇到最多的,可能就属不匹配的问题了。

对于不匹配的问题,其原因有各种各样,而导致不匹配的。

目前已经遇到的,大致有这几类:

ANTLR v4中,由于一些语法的变化,导致语法检查更严格,有时候也会导致此类mismatch的问题:

【已解决】antlr v4的语法出错:line 1:0 mismatched input ‘a’ expecting A

5.1.4. syntax error: unterminated rule detected at xxx while looking for lexer rule element

详见:

【已解决】antlr v4测试Hello结果出错:syntax error: unterminated rule (missing ‘;’) detected at ‘c ‘ while looking for lexer rule element

5.1.6. Cannot generate the grammar because, duplicate token type xxx when collapsing subrule into set

如果ANTLR语法写的有问题的话,则是无法生成对应的代码的。

错误有多种可能:

比如是由于符号类型冲突而无法生成代码,详见:

【已解决】Antlr语法编译出错:Cannot generate the grammar because, duplicate token type COMPOSITE_OPERATOR when collapsing subrule into set

5.1.7. rewrite syntax or operator with no output option xxx

有时候,是在ANTLR的option中,添加了一些不支持的参数或选项,则导致此错误。

比如:

【已解决】antlr语法出错:rewrite syntax or operator with no output option; setting output=AST

5.1.8. UnwantedTokenException(found=xxx)

比如:

【已解决】antlr调试解析出错:UnwantedTokenException(found=xxx)

5.1.10. reference to rewrite element include without reference on left of ->

比如:

【已解决】antlr代码编译出错:reference to rewrite element include without reference on left of ->

5.2. ANTLRWorks方面常见问题及解决办法

ANTLRWorks使用期间,也常会遇到很多问题,比如:

5.2.2. Cannot launch the debuggerTab. Time-out waiting to connect to the remote parser

【已解决】ANTLRWorks调试出错:Cannot launch the debuggerTab. Time-out waiting to connect to the remote parser

5.2.4. Compiler failed with result code 1

由于antlrworks本身版本的问题,而导致编译出错的:

【已解决】ANTLRWorks 1.5编译代码出错:Compiler failed with result code 1

第 6 章 ANTLR开发经验总结

对于ANLTR开发方面的经验总结如下:

6.1. ANTLRWorks使用心得

在使用ANTLR的最主要的开发工具:ANTLRWorks期间,遇到很多问题,也总结出很多相关技巧。

现整理如下,供参考:

【整理】antlrworks使用心得,经验总结,注意事项,bug总结

【已解决】antlrworks再次出错:Compiler exception: java.io.IOException Cannot run program "C:\Program Files(x86)\Java\jre6\bin\javac": CreateProcess error=2

6.1.1. ANTLRWorks有时候会挂掉

比如之前遇到的:

【记录】antlr的antlrworks某次挂掉的log

6.3. ANTLR的异常处理

ANTLR中,对于异常处理,支持的很好,功能很丰富了。

对此,我们可以利用ANTLR的异常方面的信息,去实现一些自己所需要的功能,比如:

【记录】antlr异常处理:在ParseTree去getTree之后,判断某个树节点是否出现异常

其中,关于异常处理的方面的经验和心得,可以先去参考:

【记录】Antlr中的异常处理学习笔记

【整理】antlr的Exception Handling异常处理中的异常Exception的类型

其他的一些,关于异常处理方面的折腾,供参考:

【记录】尝试折腾antlr v3的异常处理和错误恢复:VARIABLE的CLASS的值INPUT故意写错为INPUT1

对于ANTLR的异常处理方面,有更多可以扩展和利用的空间:

6.3.1. ANTLR出错异常时就退出(不继续恢复错误和继续运行)

ANTLR遇到错误,出现异常时,其默认的机制中,就已经支持:自动尝试恢复错误,然后回退到前一步,继续选择别的分支路径,继续执行下去

而希望实现:当ANTLR解析出错时,就退出,则也是支持的。

详见:

【记录】antlr的异常处理:遇到第一个错误就停止和退出

【已解决】在用antlr预处理一个新的hart的eddl文件时希望第一次出错就退出

[注意] ANTLR的API变化导致部分函数失效

之前遇到的,由于ANTLR的API的变化,导致函数接口变化

导致参考别人的ANTLR的示例代码时,会出错。需要去找到最新的API,才能继续使用的。

详见:

【已解决】antlr中尝试出错就退出,结果编译parser出错:error: recoverFromMismatchedSet(IntStream,RecognitionException,BitSet) in xxxParser cannot override recoverFromMismatchedSet(IntStream,RecognitionException,BitSet) in BaseRecognizer,return type void is not compatible with Object

6.3.2. ANTLR出错异常时显示更多详细信息

ANTLR解析期间,遇到错误,会自动抛出异常,会打印出一些错误信息。

其默认的异常出错信息,已经相对比较全面了。

但是如果想要输出更多的,其他方面的,详细出错信息,则可以参考:

【记录】用antlr预处理异常MismatchedTokenException时能输出更详细的信息

【记录】尝试antlr的paraphrase去提供对于用户更好友好的错误信息

【记录】折腾antlr的异常处理:使得当初错时,输出更详细的错误信息,包含堆栈信息

6.4. ANTLR的递归

ANTLR中,ANTLR v4之前,是不支持左递归的。

当然,在有些时候,也是可以使用递归的。

比如:

而对于ANTLR中的递归的话,尤其是在Lexer中,有时候会很难实现自己所要的效果。

详见:

【未解决】antlr中setText()在递归嵌套的token中无效

【未解决】antlr实现#define的宏的多层(递归)替换后,去不掉宏的内容

【基本解决】用antlr匹配嵌套递归的代码

6.5. ANTLR解析性能

关于ANTLR的解析性能,相对很不错了。

只是,有时候,自己的实现不够好的话,还是需要想办法,再去优化性能的:

【记录】尝试优化antlr的lexer和parser以提高继续速度(解析性能)

6.6. ANTLR中的条件性匹配

详见:

【已解决】antlr v3的lexer的条件性匹配

6.7. ANTLR相关资源下载

6.7.1. ANTLR语法示例参考代码

一些可供参考的antlr的语法源码:

【记录】antlr中解析EDDL时解析METHOD中的C代码

【整理】关于antlr的一些资料

6.7.2. ANTLR相关开发工具下载

【资源下载】antlr-4.0-rc-1-complete.jar

6.8. ANTLR中debug和非debug版本

ANTLR中,对于用.g所生成的代码,有两种模式:debug版本和非debug版本

是否是debug,会有很大区别:

比如就会导致后续测试代码出错还是正常运行:

【问题】android中调试antlr时执行xxx_return去获得parserResult时出错

比如会影响到是否可以获得生成的AST中节点之间的父子关系:

6.8.1. ANTLR生成的AST中没有节点的父子关系

之前遇到的问题:对于ANTLR来说,默认所生成的AST中,没有节点的父子关系。

经过一番折腾,最终是找到了,如何获得节点的父子关系:

【已解决】antlr中获得的AST的CommonTree这个树的变量中,不存在所想要的父子(parent,child)关系

参考书目