如何"覆盖"流行模式?


Lexer.g4
...
TEST: 'EXEC' -> pushMode (LG2)
...
mode LG2;
...
END_LG2: S_SEMICOLON -> type(S_SEMICOLON), popMode;
...

大多数时候,LG2被用作"岛"语言。但在某些情况下,我也希望能够直接启动 LG2 模式。我可以按如下方式实现:

ANTLRInputStream input = new ANTLRInputStream(...);
PL1Lexer lexer = new PL1Lexer(input);
lexer.pushMode(PL1Lexer.DB2);

问题是在这种情况下,我不希望";"跳回到另一种语言。简而言之:如果我直接从那里开始,我怎么能"停留"在 LG2 语言中?有没有办法"覆盖"规则

END_LG2: S_SEMICOLON -> type(S_SEMICOLON), popMode;

ND_LG2: S_SEMICOLON -> type(S_SEMICOLON);

在那种情况下?

您可以重写 Lexer.popMode() 方法以使用自定义行为。不需要这样做的选项将涉及ANTLR 4.4.1即将推出的对零长度令牌的支持。

mode LG2;
  // rules here
mode StayInLG2:
  ReturnToLG2
    : -> skip, pushMode(LG2)
    ;

然后,您可以在StayInLG2模式下手动启动。为了响应弹出回StayInLG2模式,ReturnToLG2规则不会创建令牌或匹配任何输入,但会LG2推送回模式堆栈。

PL1Lexer lexer = new PL1Lexer(input);
lexer.mode(StayInLG2);
lexer.pushMode(LG2);
接受的

答案看起来不错,但空规则会导致无法禁止显示的警告:

non-fragment lexer rule ReturnToLG2 can match the empty string

因此,对于类似的问题,我使用了覆盖:

@members {
    @Override
    public int popMode() {
        return _modeStack.isEmpty()
            ? DEFAULT_MODE
            : super.popMode();
    }
}

相关内容

  • 没有找到相关文章

最新更新