编写对空白敏感的解析器规则,同时从词法分析器中跳过WS

Ric*_* T. 5 grammar antlr antlr4

我在处理空白时遇到了一些麻烦。在下面的语法摘录中,我设置了词法分析器,以便解析器跳过空格:

ENTITY_VAR
    : 'user'
    | 'resource'
    ;

INT : DIGIT+ | '-' DIGIT+ ;
ID : LETTER (LETTER | DIGIT | SPECIAL)* ;
ENTITY_ID : '__' ENTITY_VAR ('_w_' ID)?;

NEWLINE : '\r'? '\n';

WS : [ \t\r\n]+ -> skip; // skip spaces, tabs, newlines

fragment LETTER : [a-zA-Z];
fragment DIGIT : [0-9];
fragment SPECIAL : ('_' | '#' );
Run Code Online (Sandbox Code Playgroud)

问题是,我想与形式的变量名进行匹配,以ENTITY_ID使匹配的字符串没有任何空格。像我在这里一样将其编写为词法分析器规则就足够了,但事实是,我想使用解析器规则来代替它,因为我想直接访问这两个标记,ENTITY_VARID分别从我的代码中直接访问并且不要将它们完全挤压在一起ENTITY_ID

有什么想法吗?基本上,任何可以让我直接访问ENTITY_VAR并且ID适合我的解决方案都可以ENTITY_ID作为词法分析器规则保留下来,或者将其移至解析器中。

Onu*_*nur 2

我能想到的有几种方法(排名不分先后):

  1. 从规则中发出几个令牌ENTITY_ID。请参阅ANTLR4:如何注入代币以获得灵感
  2. 允许解析器中存在空格并随后进行检查
  3. 使用单个令牌并拆分代码
  4. 使用单个令牌并修改令牌流,然后将其传递给解析器。即 lex,修改ENTITY_ID标记并将其拆分为其他几个标记,然后将此流传递给解析器
  5. 不要跳过空格,并且在处理这些“额外标记”时检查它们是否在部分内ENTITY_ID(=> 是错误)或不在(=> 忽略错误)。
  6. 不要跳过空格并在语法中允许空格的任何地方添加“WS*”(如果语法不是太大,则可以)。
  7. 在解析器规则中插入谓词,检查之间是否有空格。
  8. 创建一个像这样的“陷阱”规则:

    INVALID_ENTITY_ID : '__' WS+ ENTITY_VAR WS? ('_w_' WS? ID)?
                      | '__' WS? ENTITY_VAR WS+ ('_w_' WS? ID)?
                      | '__' WS? ENTITY_VAR WS? ('_w_' WS+ ID)
                      ;
    
    Run Code Online (Sandbox Code Playgroud)

    这将捕获无效的ENTITY_IDs,因为它比也将成为单独标记的部分更长。

我会选择 2,如果它不会改变“非错误”情况下的解析,即没有代码因允许空格而被不同地解释。