Parsing ANTLR 4中的重叠标记

Parsing ANTLR 4中的重叠标记,parsing,antlr,lexer,antlr4,Parsing,Antlr,Lexer,Antlr4,我有以下ANTLR 4组合语法: grammar Example; fieldList: field* ; field: 'field' identifier '{' note '}' ; note: NOTE ; identifier: IDENTIFIER ; NOTE: [A-Ga-g] ; IDENTIFIER: [A-Za-z0-9]+ ; WS: [ \t\r\n]+ -> skip ; 这解析为: field x

我有以下ANTLR 4组合语法:

grammar Example;

fieldList:  field* ;

field:      'field' identifier '{' note '}' ;

note:       NOTE ;
identifier: IDENTIFIER ;

NOTE:       [A-Ga-g] ;
IDENTIFIER: [A-Za-z0-9]+ ;
WS:         [ \t\r\n]+ -> skip ;
这解析为:

field x { A }
field x { B }
这并不是:

field a { A }
field b { B }
在解析失败的情况下,我认为lexer会变得混乱,并在我希望它发出标识符标记的地方发出NOTE标记

编辑:


在从lexer出来的标记中,“NOTE”标记显示在解析器期望的“IDENTIFIER”位置NOTE'具有更高的优先级,因为它在语法中首先显示。所以,我可以想出两种方法来解决这个问题。。。首先,我可以修改语法以消除“NOTE”和“IDENTIFIER”的歧义(比如在“NOTE”前面添加“$”)。或者,我可以在使用note的地方使用“IDENTIFIER”,然后在遍历解析树时处理检测问题。这两个都不是最理想的。肯定有办法解决这个问题

针对您的问题的快速而肮脏的解决方案可以是: 更改
标识符
以仅匹配
注释
的补码。然后将它们放在
标识符中

结果语法:

grammar Example;

fieldList:  field* ;

field:      'field' identifier '{' note '}' ;

note:       NOTE ;
identifier: (NOTE|IDENTIFIER_C)+ ;

NOTE:       [A-Ga-g] ;
IDENTIFIER_C: [H-Zh-z0-9] ;
WS:         [ \t\r\n]+ -> skip ;

此解决方案的缺点是,您不能将标识符作为标记获取,并且您可以标记每个字符。

我实际上是这样解决的:

grammar Example;

fieldList:  field* ;

field:      'field' identifier '{' note '}' ;

note:       NOTE ;
identifier: IDENTIFIER | NOTE ;

NOTE:       [A-Ga-g] ;
IDENTIFIER: [A-Za-z0-9]+ ;
WS:         [ \t\r\n]+ -> skip ;
我的解析树最终还是按照我的意愿运行


我正在开发的实际语法更复杂,基于这种方法的变通方法也更复杂。但总的来说,这种方法似乎很有效。

也许你可以使用词汇模式来解决这个问题,但这在组合语法中不起作用。请参见此处:ANTLR正在按预期工作。当一个令牌可以匹配多个lexer规则时(所有其他条件相同),第一个规则首先匹配。所以“a”应该匹配注释,而不是标识符。