我有以下ANTLR 4组合语法:
grammar Example;
fieldList: field* ;
field: 'field' identifier '{' note '}' ;
note: NOTE ;
identifier: IDENTIFIER ;
NOTE: [A-Ga-g] ;
IDENTIFIER: [A-Za-z0-9]+ ;
WS: [ trn]+ -> skip ;
这解析:
field x { A }
field x { B }
这不会:
field a { A }
field b { B }
在解析失败的情况下,我认为词法分析器变得混乱并发出一个 NOTE 令牌,我希望它发出一个标识符令牌。
编辑:
在从词法分析器出来的令牌中,"NOTE"令牌显示在解析器期望"标识符"的位置。"NOTE"具有更高的优先级,因为它首先显示在语法中。所以,我可以想到两种方法来解决这个问题...首先,我可以更改语法以消除"NOTE"和"IDENTIFIER"的歧义(例如在"NOTE"前面添加"$")。或者,我可以只使用"标识符",在那里我会使用 note,然后在我遍历解析树时处理检测问题。这两种感觉都不是最佳的。肯定有办法解决这个问题吗?
我实际上最终是这样解决的:
grammar Example;
fieldList: field* ;
field: 'field' identifier '{' note '}' ;
note: NOTE ;
identifier: IDENTIFIER | NOTE ;
NOTE: [A-Ga-g] ;
IDENTIFIER: [A-Za-z0-9]+ ;
WS: [ trn]+ -> skip ;
我的解析树最终仍然看起来像我想要的样子。
我正在开发的实际语法更复杂,基于这种方法的解决方法也是如此。但总的来说,这种方法似乎效果很好。
快速而肮脏的问题修复可以是:更改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: [ trn]+ -> skip ;
此解决方案的缺点是,您不会将标识符作为令牌获取,而是标记每个字符。