Antlr中不明确​​的Lexer规则

时间:2017-11-15 23:10:27

标签: antlr antlr4

我有一个antlr语法,其中有多个lexer规则匹配相同的单词。它在lexing期间无法解决,但是通过语法,它变得毫不含糊。

示例:

conversion: NUMBER UNIT CONVERT UNIT;
NUMBER: [0-9]+;
UNIT: 'in' | 'meters' | ......;
CONVERT: 'in';

输入:1 in in meters

""匹配词法规则UNITCONVERT

如何在保持语法文件可读的同时解决这个问题?

2 个答案:

答案 0 :(得分:1)

根据您问题中的信息,很难说最佳解决方案是什么 - 例如,我不知道您的词法分析器 是什么 - 也不知道我可以告诉你为什么你的词法规则根本不明确。

根据我对antlr的经验,lexer规则通常不带任何语义含义;它们只是匹配某种正则表达式的文本。所以,我没有VARIABLEMETHOD_NAME等,而只是拥有IDENTIFIER,然后将其计算在更高的水平。

换句话说,似乎(从我可以从你的问题中收集的很少)你可能会因为用语法规则替换UNITCONVERT,或者只有一条规则而受益: / p>

conversion: NUMBER TEXT TEXT TEXT

并验证ANTLR侦听器/ tree-walker / etc中的文本值。

修改

感谢您使用词法规则更新您的问题。现在很清楚为什么它失败了 - 正如BernardK所指出的,antlr将始终选择第一个匹配的词法分析器规则。这意味着两个不明确的词法分析器规则中的第二个不可能匹配,并使您提出的设计不可行。

我的观点是,词法分析规则不是单元验证等事情的正确层;他们擅长结构,而非内容。评估解析树比尝试扭曲antlr语法要实用得多。

最后,您还可以对解析规则执行嵌入式操作,例如针对已知单位集验证ID令牌的值。它可以工作,但会破坏你的语法的可重用性。

答案 1 :(得分:1)

当输入匹配两个词法规则时,ANTLR选择最长或第一个,请参阅disambiguate。根据您的语法,in将被解释为UNIT,永远不会被CONVERT和规则

conversion: NUMBER UNIT CONVERT UNIT;

无法正常工作,因为有三个UNIT令牌:

$ grun Question question -tokens -diagnostics input.txt 
[@0,0:0='1',<NUMBER>,1:0]
[@1,1:1=' ',<WS>,channel=1,1:1]
[@2,2:3='in',<UNIT>,1:2]
[@3,4:4=' ',<WS>,channel=1,1:4]
[@4,5:6='in',<UNIT>,1:5]
[@5,7:7=' ',<WS>,channel=1,1:7]
[@6,8:13='meters',<UNIT>,1:8]
[@7,14:14='\n',<NL>,1:14]
[@8,15:14='<EOF>',<EOF>,2:0]
Question last update 0159
line 1:5 missing 'in' at 'in'
line 1:8 mismatched input 'meters' expecting <EOF>

您可以做的只是IDTEXT令牌,并用标签区分它们,如下所示:

grammar Question;

question
@init {System.out.println("Question last update 0132");}
    :   conversion NL EOF
    ;

conversion
    :   NUMBER unit1=ID convert=ID unit2=ID
        {System.out.println("Quantity " + $NUMBER.text + " " + $unit1.text +
         " to convert " + $convert.text + " " + $unit2.text);}
    ;

ID      : LETTER ( LETTER | DIGIT | '_' )* ; // or TEXT : LETTER+ ;     
NUMBER  : DIGIT+ ;

NL      : [\r\n] ;
WS      : [ \t] -> channel(HIDDEN) ; // -> skip ;

fragment LETTER : [a-zA-Z] ;
fragment DIGIT  : [0-9] ;

执行:

$ grun Question question -tokens -diagnostics input.txt 
[@0,0:0='1',<NUMBER>,1:0]
[@1,1:1=' ',<WS>,channel=1,1:1]
[@2,2:3='in',<ID>,1:2]
[@3,4:4=' ',<WS>,channel=1,1:4]
[@4,5:6='in',<ID>,1:5]
[@5,7:7=' ',<WS>,channel=1,1:7]
[@6,8:13='meters',<ID>,1:8]
[@7,14:14='\n',<NL>,1:14]
[@8,15:14='<EOF>',<EOF>,2:0]
Question last update 0132
Quantity 1 in to convert in meters

标签可以从访问者的规则上下文中获得,因此很容易区分相同类型的标记。