当我使用'pushMode'和'popMode'时,我的语法失败,但是当我使用'mode'时,它会起作用。
这种语法结构有效:
TAG: '{' -> pushMode( TAG_MODE ), skip;
TEXT: ~[{]+;
mode TAG_MODE;
TAG_COMMENT: '*' -> skip, mode( COMMENT_MODE );
mode COMMENT_MODE;
END_COMMENT: .*? '*}' -> skip, popMode;
COMMENT_TEXT: . -> type( SYNTAX_ERROR ), popMode;
现在,如果我将TAG_COMMENT更改为使用'pushMode'而不是'popMode'而失败了,我将从评论标记开始放松所有内容。
这个语法结构失败了:
TAG: '{' -> pushMode( TAG_MODE ), skip;
TEXT: ~[{]+;
mode TAG_MODE;
TAG_COMMENT: '*' -> skip, pushMode( COMMENT_MODE ), popMode;
mode COMMENT_MODE;
END_COMMENT: .*? '*}' -> skip, popMode;
COMMENT_TEXT: . -> type( SYNTAX_ERROR ), popMode;
任何人都可以解释我的不同之处;在我看来,它们应该在功能上是等价的,除了第二种方法使用另一个级别的词法分析器堆栈。
我实际上更喜欢使用失败的构造,因为太容易使用'mode'(goto)搞定lexer堆栈,而如果所有东西都使用'pushMode'和'popMode',那么将lexer堆栈保持在顺序。
也可以使用空集退出模式吗? 类似的东西:
mode MODE1;
TAG_IDENT: IDENT;
TAG_EMPTY: -> popMode; // Hopefully exits and doesn't consume a token
有什么想法吗?
答案 0 :(得分:2)
在TAG_COMMENT
规则中,您使用pushMode
后紧跟popMode
。结果与删除两条指令的结果相同。相反的顺序会产生非常不同的影响,如下面的第1项所示。
您可以颠倒pushMode
中popMode
和TAG_COMMENT
指令的顺序,但这在语义上等同于更简单的单mode
指令:< / p>
TAG_COMMENT
: '*'
-> skip, mode(COMMENT_MODE)
;
从popMode
规则中删除COMMENT_TEXT
操作(如果评论未终结,则输入的其余部分都在评论中。)
答案 1 :(得分:0)
@ Terry151151我是Antlr的新手,但我通过添加第二个“popMode”来实现类似的结果。在二级模式。这可能仅适用于具有一个规则的模式,在第二模式完成时它会推动并需要弹出。
尝试更改以下行:
TAG_COMMENT: '*' -> skip, pushMode( COMMENT_MODE );
和
END_COMMENT: .*? '*}' -> skip, popMode, popMode;