使用Antlr4识别语法版本

时间:2019-03-06 15:37:17

标签: antlr antlr4

是否有让Antlr4识别用于解析输入的语法版本的好方法?

如果我有两个语法,即GA和GB,其中GA是GB的子集,而GB则是从GA导入的,如果解析的输入是使用GA或GB解析的,是否可以让Antlr4报告?

我可以先尝试先使用GB解析,如果失败则尝试使用GA解析,但我想知道是否有一种更有效的方法让Antlr跟踪使用的规则并说:“我成功解析了此规则但只使用了GA语法中的规则”。

2 个答案:

答案 0 :(得分:0)

正确的方法是将每个规则(或仅关键规则)与解析器版本相关联。

首先,您需要一个字段来跟踪当前版本:

@members {
    int currentVersion = 1;
}

现在,让我们假设您有一个规则RULE_ONE与版本 one 相关,而RULE_TWO与版本 two 相关。
每次接受与较高版本相关的规则时,currentVersion字段都应更改:

RULE_ONE
      {currentVersion = Math.max(1, currentVersion);} //1 is the parser version
    : some_token
    ;

RULE_TWO
      {currentVersion = Math.max(2, currentVersion);} //2 is the parser version
    : some_token
    ;

因此,解析完成后,您可以获得已使用的最大版本。

答案 1 :(得分:0)

并非完全是您的要求,但是in my MySQL grammar我必须支持多个服务器版本,这是通过使用语义谓词来实现的。这意味着,我可以使用一个语法并根据解析器中的serverVersion字段启用/禁用某些路径。看起来像这样:

alterDatabase:
    DATABASE_SYMBOL schemaRef (
        createDatabaseOption+
        | {serverVersion < 80000}? UPGRADE_SYMBOL DATA_SYMBOL DIRECTORY_SYMBOL NAME_SYMBOL
    )
;

,效果很好。即使在the lexer中,我也可以使用这种方法(但出于性能原因,其中包含验证语义谓词),这使我可以打开和关闭关键字,如下所示:

CONTRIBUTORS_SYMBOL: C O N T R I B U T O R S {serverVersion < 50700}?;