我在处理空白方面遇到了一些麻烦。在下面的语法摘录中,我设置了词法分析器,以便解析器跳过空格:
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
形式的变量名称,以便匹配的字符串没有任何空格。将它写为lexer规则就足够了,就像我在这里做的那样,但问题是我想用解析器规则来代替它,因为我想直接访问这两个令牌ENTITY_VAR
和ID
分别来自我的代码,而不是将它们整合在一个完整的令牌中ENTITY_ID
。
请问任何想法?
基本上任何允许我直接访问ENTITY_VAR
和ID
的解决方案都适合我,将ENTITY_ID
作为词法规则或将其移至解析器。
答案 0 :(得分:2)
我可以想到几种方法(不是特殊的顺序):
ENTITY_ID
中发出几个令牌。请参阅ANTLR4: How to inject tokens获取灵感ENTITY_ID
标记并将它们拆分成其他几个标记,然后将此流传递给解析器ENTITY_ID
部分内(=>是错误)或不是(=>忽略错误)。创建一个“陷阱”规则,如下所示:
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,即不允许通过允许空格来解释代码。
答案 1 :(得分:0)
据我通过浏览文档设法理解,它看起来不像是可行的。
解析器规则似乎仅适用于默认通道,因此我无法将WS
发送到channel(HIDDEN)
,然后仅针对单个解析器规则进行恢复。
另一方面,antlr explains here的作者认为自版本4以来无法分解任何令牌。
即使我根本不喜欢它,似乎最快的方法是从词法分析器解析它(如在问题的代码中),只是为了从Java再次重新解析它字符串。
不过,我的结论还是有任何其他更好的选择或更正。
答案 2 :(得分:0)
在一个管道中挂钩两个解析器,就像你自己的回答一样,是一个健全而简单的设计/解决方案,而且我非常确定ANTLR能够帮助解决这个问题。
我不太了解ANTLR人员在流/源解析方面的工作。但是,采用两遍策略应该足够有效,因为第一遍只是使用常规语言,O(c * N)
超过输入的大小c
。
如果您想要一张费用为O(k * N)
(大k)的单一通行证,您可以考虑PEG,其中有implementations in Java(我还没试过) )。