antlr4-如何;凌驾;流行音乐模式?

antlr4-如何;凌驾;流行音乐模式?,antlr4,Antlr4,大多数情况下,LG2被用作“孤岛”语言。 但在某些情况下,我希望能够直接启动LG2模式。 我可以做到以下几点: Lexer.g4 ... TEST: 'EXEC' -> pushMode (LG2) ... mode LG2; ... END_LG2: S_SEMICOLON -> type(S_SEMICOLON), popMode; ... 问题是,在这种情况下,我不想要“;”跳回另一种语言。 简言之:如果我直接从LG2语言开始,我如何“保持”LG2语言? 有没有办法“推

大多数情况下,LG2被用作“孤岛”语言。 但在某些情况下,我希望能够直接启动LG2模式。 我可以做到以下几点:

Lexer.g4

...
TEST: 'EXEC' -> pushMode (LG2)
...

mode LG2;

...
END_LG2: S_SEMICOLON -> type(S_SEMICOLON), popMode;
...
问题是,在这种情况下,我不想要“;”跳回另一种语言。 简言之:如果我直接从LG2语言开始,我如何“保持”LG2语言? 有没有办法“推翻”规则

在这种情况下?

您可以重写该方法以使用自定义行为。一个不需要的选项将涉及ANTLR 4.4.1即将推出的对零长度令牌的支持

ND_LG2: S_SEMICOLON -> type(S_SEMICOLON);
然后可以在
StayInLG2
模式下手动启动。作为对弹出回到
StayInLG2
模式的响应,
ReturnToLG2
规则不会创建令牌或匹配任何输入,但会将
LG2
推回到模式堆栈上

mode LG2;

  // rules here

mode StayInLG2:

  ReturnToLG2
    : -> skip, pushMode(LG2)
    ;

接受的答案看起来不错,但空规则会导致无法抑制的警告:

PL1Lexer lexer = new PL1Lexer(input);
lexer.mode(StayInLG2);
lexer.pushMode(LG2);
因此,对于类似的问题,我使用了覆盖:

non-fragment lexer rule ReturnToLG2 can match the empty string
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();
    }
}