【背景】
之前用过很多次的antlr的IDE:antlrworks
期间,遇到很多需要总结的bug,经验等内容,
现在整理如下。
antlrworksbug总结
有时候存在语法错误的时候,仍然可以编译成功
比如:
我在某次,调试时,前面把BINARY_OPERATOR都改为了binary_operator,所以后面的BINARY_OPERATOR,自然就肯定找不到而出错了。
但是此时,竟然可以正常编译的。。。。
如图:
所以,不能完全相信antlrworks。。。。
antlrworks中,即使语法写对了,但是也还是会报错
用antlrworks当做编辑器,去编辑.g语法文件时,很不好用
其中遇到过:
赋值,粘贴,等等操作了一堆。
然后确定,语法是写对了的
但是估计是antlrworks内部没有及时更新,导致:
虽然语法是对的,但是其还是报错
看起来是:在把语法改正确之前的某次错误的内容,其记住了,但是就一直报错,
即使你后来还是改对了
所以:
作为.g文件的编辑器,语法高亮方面,还是凑合的,可以的
但是作为普通的文本编辑器,以及语法检测等方面,还是不好用,还是有很多bug的。
注:
后来想到了:
貌似是:
当你的(lexer的)token和(parser的)rule,
混写的话,容易出现上述的,有语法错误,但检测不到的问题。
其中:
混写的意思是:
本来是:
.g语法文件中:
要么,前面全是token,后面全是rule
要么,前面全是rule,后面全是token
而混写是:
rule中,混杂着token
(或者是:token中混杂着rule)
之前遇到一次此问题了。
这次又遇到了:
其中,此处的,之前是READ,但是早就编辑过了,移动到别处了,更新语法了,确保正确了。
但是此处还是,无故的,报错,说是找不到什么READ。
antlrworks使用心得,经验总结,注意事项
antlrworks的调试功能支持很丰富
调试时,对应的Break On的部分,选择对应的内容,则可以实现对应的情况下,停止,供你调试
比如,我此处,全选了所有的:
包括:
ALL
Location
Consume
LT
Exception
所以:
每次点击那个单步调试的时候,就可以一点点的看到右边的,events中的输出了:
下图是:后来某次的调试之后的,一堆的events的输出:
然后对于具体含义,后来才大概明白:
首先,从events中,可以看出,
antlr内部执行的每一步,都是如何执行的。
对应的内部涉及到各种算法,目前我也不是很熟悉
其中调用了此处的各种函数,去执行对应的逻辑和判断
这些函数包含:
LT,Location,以及Consume等等
当然,如果出错时,会抛出异常,
比如上面那个MismatchedSetException之类的异常。
其中,唯一稍微清楚点的是:
Consume函数,表示消费了,吃掉了,匹配到了,对应的内容,所以就“消费”,被“吃”掉了。
然后继续后面的匹配。
所以,此处的Break On中的:
Location
Consume
LT
Exception
分别对应上述调用的函数:
Location(xxx)
Consume(xxx)
LT(xxx)
发生的各种异常:根异常都是Recognition Exception,其下包括各种类型的异常。
详见:
【整理】antlr的Exception Handling异常处理中的异常Exception的类型
而对于ALL的意思是:
除了上述那几个类型的输出以为,余下的,各种步骤,是否也中断,是否也停下,供你调试查看。
比如上面那个一堆的events中间就有,除了Location,Consume,LT,Exception之外的Enter xxx等语句,
也都会中断停止,供你调试。
对于,平常我们要的效果:
希望调试时可以实现:
一直运行,知道出现异常再停止
则可以去如下设置和使用:
对于Break On,只选择Exception
表示出现异常时,中断
然后点击那个单步执行(Step Forward)
就可以实现上述的效果了:
一直运行,直到遇到第一个异常,就中断
方便我们发现语法代码匹配所处理的内容,找到第一个出错的位置
效果如图:
如果调试输入文件内容太多,则可能会由于绘制Parse Tree太长而导致antlrworks假死
之前,写了语法,在antlrworks中去调试
但是由于测试所用输入文件内容太长:6000+行
导致:
点击调试运行后:
虽然本身.g语法是对的,解析输入的文件内容也没错
但是由于输入文件内容太多,而导致了那个Parse Tree的界面
会内部调用java代码,去一点点绘制出对应的Parse Tree的
而由于生成的树的节点和内容太多
搞得所耗费时间太长:
一共大概需要十几分钟甚至几十分钟的
而对应的,如果点击掉Parse Tree:
即,只是去调试,但是不生成Parse Tree
其本身调试完毕此大文件的时间,只有10几秒,很快的。
而由于之前耗费N多分钟,才能显示完毕Parse Tree,
搞得:
期间,调试了多次,
结果都是由于antlrworks中,点击后,死掉了
(其实是假死,只是需要足够的时间,去绘制Parse Tree而已)
以为自己的代码或者是输入文件有问题呢。。。。
另外也导致:
正好此时去测试和验证:
antlr的.g语法文件本身,去解析此大的输入文件时,需要耗时多少
结果实际上只是10多秒
结果以为几十分钟呢。。。
所以:
如果你也遇到了,所要测试的文件(或字符串内容)太长(至少单位为千行算)
而可能会导致:
调试时,看起来是antlrworks假死了
实际上是
内部正在耗时,去绘制Parse Tree呢
反过来说:
如果你和我之前一样,本身只是想要测试代码的正确性,输入文件的正确性
暂时不关心那个Parse Tree,则可以在debug时,点击下面的那个Parse Tree,去掉,不显示Parse Tree。
即可避免由于输入文件内容太多,生成Parse Tree耗时太长而导致antlrworks假死的现象了。
如果.g文件无法编译,则很可能是由于原文件是只读文件而导致的
之前就遇到过类似情况:
antlrworks中,无法编辑文件:
即:
鼠标点击文件,结果无法看到希望看到的鼠标变成编辑模式,可以输入文字,可以修改文字的效果:
后来才搞懂根本原因:
原来是当前所用antlrworks载入的文件,本身是只读的:
去掉只读属性后:
antlrworks中,其实还是不能立刻实现编辑文件,需要重新载入后:
才可以编辑文件:
另外:好像如果对于更改文件属性,去掉只读,去点击Apply而不是OK的话,貌似无需直接载入,即可编辑文件的。