在同一ANTLR4语法中使用单词作为语言关键字和标识符?



关于以下简化语法

proof_command : 'Proof' 'using' collection '.';
collection : 'Collection' IDENT ':=' section_subset_expr
| 'Collection' KeySOME ':=' IDENT IDENT IDENT
;
KeySOME : 'Some';

(其中 IDENT 只是 Java 中常用的标识符( 我正在尝试解析以下内容:Proof using Collection Some := a b c .这不起作用,并导致以下错误消息:

不匹配的输入"a"期望"section_subset_expr">

这是因为 IDENT 当然也可以是 "一些" .

有没有办法将 Some 用作关键字和标识符,以便正确解析上面的表达式?也许通过语义谓词从收集规则中的 IDENT 中排除"一些"?但那会是什么样子呢?

IDENT : IDENT2;
fragment IDENT2 : FIRST_LETTER (SUBSEQUENT_LETTER)*;
fragment FIRST_LETTER :  [a-z] | [A-Z] | '_' | UNICODE_LETTER;
fragment SUBSEQUENT_LETTER : [a-z] | [A-Z] | DIGIT | '_' | '"' | '''| UNICODE_LETTER | UNICODE_ID_PART;
fragment UNICODE_LETTER : '\' 'u' HEX HEX HEX HEX;
fragment UNICODE_ID_PART : '\' 'u' HEX HEX HEX HEX;
fragment HEX : [0-9a-fA-F];
KeySOME : 'Some'; 

词法分析器的工作方式是,当可以在给定输入上匹配多个规则时,它会根据以下条件决定使用哪一个:

  1. 如果一条规则导致比所有其他规则更长的匹配,则采用该规则(这称为最大多规则(
  2. 如果多个规则导致同样长的匹配,则采用语法中首先出现的规则。直接出现在解析器规则中的文字(例如语法中的"证明"、"使用"和"集合"(将计为出现在任何命名词法分析器规则之前。

因此,由于您的KeySOME规则出现在IDENT后面,因此永远不会被采用,因为任何与KeySOME匹配的输入也与IDENT匹配,并且IDENT排在第一位。

因此,您可以将KeySOME移动到IDENT之前显示,也可以完全删除规则并直接在其位置使用'Some'(即'Collection' 'Some' ':=' IDENT IDENT IDENT(。

最新更新