如何在 ANTLR 语法中指定行首关键字这也适用于第一个输入行

问题描述

这是一个关于为 another Stackoverflow question 提出的关于行首关键字的解决方案的剩余问题的问题。

我正在为一种编程语言编写一个 ANTLR4 词法分析器和解析器,其中某些东西是关键字,以防它是一行的第一个非空白标记。让我用一个例子来解释这一点。假设“bla”是一个关键字,那么在以下示例中:

foo bla
    bla foo foo
foo bla bla

第二个“bla”应该被识别为关键字,但其他的不应该。

为了实现这一点,我定义了以下简单的 ANTLR4 语法:

grammar foobla;

// PARSER

main
    : line* EOF
    ;

line
    : indicator text*
    ;

indicator
    : foo
    | bla
    ;

foo: FOO ;
bla: BLA ;
text: TEXT ;

// LEXER

WHITESPACE: [ \t] -> skip ;

fragment NL: [\n\r\f]+[ \t]* ;
fragment NONNL: ~[\n\r\f] ;

// Indicators
FOO: NL 'foo' ;
BLA: NL 'bla' ;

TEXT: NONNL+ ;

这类似于How to detect beginning of line,or: "The name 'getCharPositionInLine' does not exist in the current context"中给出的答案。

现在我的问题。这工作正常,除非在输入程序的第一行中使用了“bla”或“foo”关键字。我可以想到两种方法解决这个问题,但我不知道如何实现:

  • 使用类似 BOF(文件开头)令牌之类的东西。但是,我在手册中找不到这样的概念
  • 在解析开始之前,使用钩子在输入文件的开头动态添加新行,最好通过在 g4 文件本身中指定某些内容。这是我在手册中找不到的

我不想因为这个而编写额外的应用程序/包装器来向输入文件添加新行。

解决方法

这是另一个想法:

在您的 BLA 词法分析器规则中添加一个谓词,该谓词检查令牌流的末尾(尚未添加 BLA 令牌)以查看最后一个非空白令牌位于哪一行。如果该行与当前标记行不同,则您知道 BLA 标记实际上是一个 BLA 标记,否则将其类型设置为 IDENTIIFIER