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

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

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 : ('_' | '#' );

问题是,我想匹配形式ENTITY_ID的变量名称,以便匹配的字符串没有任何空格.将它写为词法规则就足够了,就像我在这里所做的那样,但问题是我想用解析器规则来代替它,因为我想直接访问这两个令牌ENTITY_VAR和ID.我的代码,而不是在整个令牌ENTITY_ID中将它们一起挤回.

请问有什么想法吗?
基本上任何让我直接访问ENTITY_VAR和ID的解决方案都适合我,将ENTITY_ID作为词法分析器规则或将其移动到解析器.

最佳答案 我可以想到几种方法(不是特殊的顺序):

>从规则ENTITY_ID中发出几个令牌.请参阅ANTLR4: How to inject tokens获取灵感
>在解析器中允许空格并在之后进行检查
>使用单个令牌并拆分代码
>使用单个令牌并在将令牌流传递给解析器之前修改令牌流.即lex,修改ENTITY_ID标记并将它们拆分成其他几个标记,然后将此流传递给解析器
>不要跳过空格并在处理这些“额外令牌”时检查它们是否在ENTITY_ID部分内(=>是错误的)(=>忽略错误).
>不要跳过空白并在你的语法中的任何地方添加“WS *”,允许空格(如果语法不是太大,那就好了).
>在解析器规则中插入谓词,检查是否存在空格.
>创建一个像这样的“陷阱”规则:

INVALID_ENTITY_ID : '__' WS+ ENTITY_VAR WS? ('_w_' WS? ID)?
                  | '__' WS? ENTITY_VAR WS+ ('_w_' WS? ID)?
                  | '__' WS? ENTITY_VAR WS? ('_w_' WS+ ID)
                  ;

这将捕获无效的ENTITY_ID,因为它比那些也是个别令牌的部分更长.

如果它不改变“非错误”情况下的解析,我会选择2,即不允许通过允许空格来解释代码.

点赞