ANTLR 4 中的重叠令牌

Mic*_*ley 5 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 ;
Run Code Online (Sandbox Code Playgroud)

这解析:

field x { A }
field x { B }
Run Code Online (Sandbox Code Playgroud)

这不会:

field a { A }
field b { B }
Run Code Online (Sandbox Code Playgroud)

在解析失败的情况下,我认为词法分析器会感到困惑并在我希望它发出 IDENTIFIER 令牌的地方发出一个 NOTE 令牌。

编辑:

在来自词法分析器的标记中,“NOTE”标记显示在解析器期望“IDENTIFIER”的位置。“NOTE”具有更高的优先级,因为它在语法中首先显示。所以,我可以想出两种方法来解决这个问题......首先,我可以改变语法来消除“NOTE”和“IDENTIFIER”的歧义(例如在“NOTE”前面添加“$”)。或者,我可以只使用“IDENTIFIER”,在其中使用注释,然后在遍历解析树时处理检测问题。这些都感觉不是最佳的。当然一定有办法解决这个问题吗?

Mic*_*ley 5

我实际上最终是这样解决的:

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 ;
Run Code Online (Sandbox Code Playgroud)

我的解析树最终仍然看起来像我想要的那样。

我正在开发的实际语法更加复杂,基于这种方法的解决方法也是如此。但总的来说,这种方法似乎运作良好。


Cv4*_*Cv4 1

针对您的问题的快速而肮脏的解决方法可以是:更改IDENTIFIER为仅匹配 的补集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 ;
Run Code Online (Sandbox Code Playgroud)

此解决方案的缺点是,您不能将标识符作为标记来获取,而是对每个字符进行标记。