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”,在其中使用注释,然后在遍历解析树时处理检测问题。这些都感觉不是最佳的。当然一定有办法解决这个问题吗?
我实际上最终是这样解决的:
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)
我的解析树最终仍然看起来像我想要的那样。
我正在开发的实际语法更加复杂,基于这种方法的解决方法也是如此。但总的来说,这种方法似乎运作良好。
针对您的问题的快速而肮脏的解决方法可以是:更改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)
此解决方案的缺点是,您不能将标识符作为标记来获取,而是对每个字符进行标记。