ANTLR4 pushMode,popMode,mode

时间:2014-11-07 21:28:52

标签: antlr4

当我使用'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

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

TAG_COMMENT规则中,您使用pushMode后紧跟popMode。结果与删除两条指令的结果相同。相反的顺序会产生非常不同的影响,如下面的第1项所示。

  1. 您可以颠倒pushModepopModeTAG_COMMENT指令的顺序,但这在语义上等同于更简单的单mode指令:< / p>

    TAG_COMMENT
      : '*'
        -> skip, mode(COMMENT_MODE)
      ;
    
  2. popMode规则中删除COMMENT_TEXT操作(如果评论未终结,则输入的其余部分都在评论中。)

答案 1 :(得分:0)

@ Terry151151我是Antlr的新手,但我通过添加第二个“popMode”来实现类似的结果。在二级模式。这可能仅适用于具有一个规则的模式,在第二模式完成时它会推动并需要弹出。

尝试更改以下行:

 TAG_COMMENT: '*'                   -> skip, pushMode( COMMENT_MODE );

 END_COMMENT:  .*? '*}'             -> skip, popMode, popMode;