Antlr中模棱两可的Lexer规则



我有一个antlr语法,它有多个与同一单词匹配的lexer规则。它在词汇过程中无法解决,但有了语法,它就变得毫不含糊了。

示例:

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

输入:1 in in meters

单词"in"与lexer规则UNITCONVERT相匹配。

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

当一个输入匹配两个lexer规则时,ANTLR会选择最长的或第一个,请参阅消除歧义。根据您的语法,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      : [rn] ;
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

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

根据您问题中的信息,很难说最好的解决方案是什么-例如,我不知道您的lexer规则是什么-我也不知道为什么您的lexr规则根本不明确。

根据我使用antlr的经验,lexer规则通常不具有任何语义;它们只是匹配某种正则表达式的文本。所以,与其有VARIABLEMETHOD_NAME等,我只需要IDENTIFIER,然后在更高的级别上计算它。

换言之,(从我从你的问题中了解到的一点)你可能会从用语法规则取代UNITCONVERT中受益,或者只使用一条规则:

conversion: NUMBER TEXT TEXT TEXT

以及验证ANTLR监听器/树遍历器等中的文本值。

编辑

感谢您使用lexer规则更新您的问题。现在很清楚为什么它失败了——正如BernardK所指出的,antlr总是会选择第一个匹配的lexer规则。这意味着两个不明确的lexer规则中的第二个不可能匹配,这会使您提出的设计变得不可行。

我的观点是lexer规则不是做单元验证之类事情的正确层;他们擅长结构,而不是内容。评估解析树将比试图扭曲antlr语法更实用。

最后,您还可以对解析规则执行嵌入操作,比如根据一组已知的单元验证ID令牌的值。它可以工作,但会破坏语法的可重用性。

相关内容

  • 没有找到相关文章

最新更新