如何解决简单的歧义

时间:2015-02-13 06:26:58

标签: c# antlr ambiguity

我刚开始使用Antlr并且卡住了。我有下面的语法,我试图解决歧义来解析像Field:ValueString这样的输入。

expression : Field ':' ValueString;
Field : Letter LetterOrDigit*;
ValueString : ~[:];
Letter : [a-zA-Z];
LetterOrDigit : [a-zA-Z0-9];
WS: [ \t\r\n\u000C]+ -> skip;

假设a:b被传入语法,a和b都被标识为Field。如何在Antlr4(C#)中解决此问题?

2 个答案:

答案 0 :(得分:1)

您可以在词法规则中使用语义谓词来执行前瞻(或后面)而不消耗字符(ANTLR4 negative lookahead in lexer

在你的情况下,为了消除歧义,你可以检查Field规则之后的字符是:还是你可以检查ValueString之前的字符是: }。

the第一个案例:

expression : Field ':' ValueString;
Field : Letter LetterOrDigit* {_input.LA(1) == ':'}?;
ValueString : ~[:];
Letter : [a-zA-Z];
LetterOrDigit : [a-zA-Z0-9];
WS: [ \t\r\n\u000C]+ -> skip;

在第二个中(请注意,FieldValueString订单已被反转):

expression : Field ':' ValueString;
ValueString : {_input.LA(-1) == ':'}? ~[:];
Field : Letter LetterOrDigit*;
Letter : [a-zA-Z];
LetterOrDigit : [a-zA-Z0-9];
WS: [ \t\r\n\u000C]+ -> skip;

另请考虑对fragmentLetter

使用LetterOrDigit关键字
fragment Letter : [a-zA-Z];
fragment LetterOrDigit : [a-zA-Z0-9];

“[使用fragment关键字]您还可以定义不是令牌的规则,而是帮助识别令牌。这些片段规则不会导致解析器看到令牌。” (来源https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Lexer+Rules

答案 1 :(得分:1)

解决这个问题的方法是简单地定义一个解析器规则,该规则可以是这两个词法分析器中的任何一个:

expression : Field ':' value;
value : Field | ValueString;
Field : Letter LetterOrDigit*;
ValueString : ~[:];
Letter : [a-zA-Z];
LetterOrDigit : [a-zA-Z0-9];
WS: [ \t\r\n\u000C]+ -> skip;

解析器将按预期工作并且语法保持简单,但您可能需要向访问者或侦听器实现添加方法。