您可以有条件地更改 ANTLR 词法分析器模式吗?

Can you conditionally change ANTLR lexer modes?

提问人:WiredWiz 提问时间:11/13/2023 更新时间:11/15/2023 访问量:41

问:

我正在研究一种语言,其中有一种定义对象的外部语法和定义代码的内部语法。内部语法嵌入在各个地方。内部语法以 BEGIN 开头,以 END 结尾。这很简单,除了内部代码语法也可以在代码中包含多个 BEGIN/END 块。所以我的问题是,当我到达最后一个匹配的 END 对时,我可以仅将计数 BEGIN/END 对引用到 popmode 吗?我猜这一定是可能的,但我只是不确定如何在 ANTLR 中最好地做到这一点。下面是一个语法的小例子:

procedure Foobar(somethingHappens: boolean)
  var
      MyRecord: Record "Some Table";
      MyDecimal: Decimal;
      otherBoolean: Boolean;
  begin
      if (somethingHappens) then
      BEGIN
        // do some stuff
      END
      // do other stuff
  end;

我有许多单词在外部语法中是特殊的标记,但在内部语法中的代码中可以用作普通标识符,因此我需要两种模式。

ANTLR ANTLR4 词法分析器

评论


答:

2赞 cschneid 11/13/2023 #1

是的,您可以通过在块中定义适当的变量并在附加到词法分析器规则的操作中操作它来引用计数 BEGIN/END 对,有条件地调用 and and 也许。但你可能不需要。@lexer::members {}pushMode()popMode()_modeStack.peek()

在 BEGIN 规则上。pushMode(BEGINEND_MODE)

在BEGINEND_MODE中编写一个附加规则以匹配 BEGIN,该规则执行相同的操作,递归输入BEGINEND_MODE。

在BEGINEND_MODE执行 .popMode()

BEGIN:
   'BEGIN'
   ->pushMode(BEGINEND_MODE)
   ;

[...]

mode BEGINEND_MODE;

BEGIN1:
   'BEGIN'
   ->pushMode(BEGINEND_MODE),type(BEGIN)
   ;

END:
   'END'
   ->popMode()
   ;

[...]

评论

0赞 WiredWiz 11/13/2023
啊,好吧,我没有意识到 pushMode 和 popMode 命令真正创建了一个模式堆栈,尽管回想起来这很明显,我觉得没有假设这一点有点愚蠢。谢谢!