所以我正在试验Antlr v4,我用一些不同寻常的语法来戳它,以了解它是如何工作的。
我想要一个按字母A,B,C,D顺序组成的语法。这些字母可能会重复。我还将A和B以及C和D组合在一起,以使语法更有趣。所以像这样的字符串是可接受的语法:
AAA
ABCD
ACCCDD
但进展并不顺利。我认为Antlr需要为我的语法制定一个更好的退出规则。它似乎没有意识到,在收集了A和B之后,出现C意味着要转到下一个规则。实际上,它在某种程度上是有效的,但我得到了错误消息,并且生成的解析树中似乎有null元素,比如它在发出错误消息的位置插入了一个额外的元素。
下面是一个错误消息示例:
line 1:2 extraneous input 'C' expecting {'B', 'A'}对于输入'ABCD‘会发生这种情况。所以当Antlr看到C的时候发生了一些奇怪的事情。以下是解析树的输出:
'ABCD': (prog (aOrB (a A) (aOrB (b B) aOrB)) (cOrD (c C) (cOrD (d D) cOrD)) <EOF>)在第一组元素的末尾有一个空的aOrB元素。
知道这是怎么回事吗?当Antlr发出错误并添加空元素时,它“在想”什么呢?我该如何解决这个问题呢?
好了,下面是一些血淋淋的细节。
我的语法是:
grammar Abcd;
prog : aOrB cOrD EOF;
aOrB : ( a | b ) aOrB ;
a : 'A'+ ;
b : 'B'+ ;
cOrD : ( c | d ) cOrD ;
c : 'C'+ ;
d : 'D'+ ;我的Java测试程序:
package antlrtests;
import antlrtests.grammars.*;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
class AbcdTest {
private final String[] testVectors = {
"A", "AABB", "B", "ABCD", "C", "D", };
public void runTests() {
for( String test : testVectors )
simpleTest( test );
}
private void simpleTest( String test ) {
ANTLRInputStream ains = new ANTLRInputStream( test );
AbcdLexer wpl = new AbcdLexer( ains );
CommonTokenStream tokens = new CommonTokenStream( wpl );
AbcdParser wikiParser = new AbcdParser( tokens );
ParseTree parseTree = wikiParser.prog();
System.out.println( "'" + test + "': " + parseTree.toStringTree(
wikiParser ) );
}
}以及我的测试程序的输出。注意,错误消息与常规输出混杂在一起,因为它们是由Antlr在标准错误时打印的。
run:
line 1:1 no viable alternative at input '<EOF>'
'A': (prog (aOrB (a A) aOrB) cOrD <EOF>)
line 1:4 no viable alternative at input '<EOF>'
'AABB': (prog (aOrB (a A A) (aOrB (b B B) aOrB)) cOrD <EOF>)
'B': (prog (aOrB (b B) aOrB) cOrD <EOF>)
line 1:1 no viable alternative at input '<EOF>'
line 1:2 extraneous input 'C' expecting {'B', 'A'}
line 1:4 no viable alternative at input '<EOF>'
'ABCD': (prog (aOrB (a A) (aOrB (b B) aOrB)) (cOrD (c C) (cOrD (d D) cOrD)) <EOF>)
line 1:0 no viable alternative at input 'C'
line 1:1 no viable alternative at input '<EOF>'
line 1:0 no viable alternative at input 'D'
'C': (prog aOrB (cOrD (c C) cOrD) <EOF>)
line 1:1 no viable alternative at input '<EOF>'
'D': (prog aOrB (cOrD (d D) cOrD) <EOF>)
BUILD SUCCESSFUL (total time: 0 seconds)任何帮助都是非常感谢的。
发布于 2013-05-03 10:23:49
这不是你要找的吗?
prog : 'A'* 'B'* 'C'* 'D'* EOF;下面的语法规则匹配无限长的A和B标记序列,因为尾部递归aOrB引用不是可选的。如果输入开始的A和/或B字符足够多,则语法将抛出StackOverflowException,否则将遇到语法错误。
aOrB : ( a | b ) aOrB ;如果你想维护分组,你可以使用这个语法。我只对aOrB和cOrD规则进行了更改。由于a规则匹配一系列A标记,因此aOrB规则使用a?而不是a* (只能出现一个a实例,并且整个A标记系列都是它的子代)。
grammar Abcd;
prog : aOrB cOrD EOF;
aOrB : a? b?;
a : 'A'+ ;
b : 'B'+ ;
cOrD : c? d?;
c : 'C'+ ;
d : 'D'+ ;下面是另一个匹配相同语言的语法(但生成不同的解析树),其中显示了*、+和?量词的其他选项。我不推荐使用这种语法,但您应该仔细查看它,以了解每个选择都在做什么,并理解为什么它与我上面给出的语法完全匹配。
grammar Abcd;
prog : aOrB cOrD? EOF;
aOrB : a* b;
a : 'A' ;
b : 'B'* ;
cOrD : (c d* | d+);
c : 'C'+ ;
d : 'D' ;发布于 2013-05-03 13:07:05
您是否意识到您的aOrB规则并不强制对a和b进行任何排序?与您的cOrD规则类似。
https://stackoverflow.com/questions/16350239
复制相似问题