当语法谓词数量较大时,将Antlr3语法谓词转换为Antlr4中的等效语法

当语法谓词数量较大时,将Antlr3语法谓词转换为Antlr4中的等效语法,antlr4,antlr3,Antlr4,Antlr3,我的Antlr3解析器规则如下所示: ruleA: (TOKEN_1) => TOKEN_1 ruleToken1 | (TOKEN_2) => TOKEN_2 ruleToken2 .... .... <many more such rules> | genericRuleA ; 这很好,除非如果ruleToken1的其余部分失败,解析器会自动选择genericRuleA作为首选路径。所以现在,我有一个副作用,就是能够“重载”命名函

我的Antlr3解析器规则如下所示:

ruleA:
   (TOKEN_1) => TOKEN_1 ruleToken1
   | (TOKEN_2) => TOKEN_2 ruleToken2
   ....
   ....
   <many more such rules>
   | genericRuleA
;
这很好,除非如果
ruleToken1
的其余部分失败,解析器会自动选择
genericRuleA
作为首选路径。所以现在,我有一个副作用,就是能够“重载”命名函数。这在某些情况下可能有用,但在我的情况下,要求明确不允许这种重载,即命名函数必须符合
ruleToken1
中列出的特定结构,如果违反该结构,则报告错误。为其编写此语法的系统不支持重载函数

genericRuleA
必须满足命名函数以外的任何功能

我的第一个问题:有没有标准的方法来实现这种转换?

我见过的一种方法是创建与命名函数(TOKEN_1、TOKEN_2等)相对应的令牌列表;构造一个
@parser::member
函数,如果输入标记在此列表中具有成员身份,则该函数将返回
true
。因此,假设适当定义了一个
isNamedFunction()
,则该规则如下所示:

ruleA:
    TOKEN_1 ruleToken1
    | TOKEN_2 ruleToken2
    | {!isNamedFunction()}? genericRuleA
;
当您只有几个命名函数时,这可能会起作用,但如果您可能有数百个(例如,考虑TSQL中的内置函数),那么构建该列表将非常麻烦。更不用说,随着新命名函数的出现,我将不得不不断更新该列表

因此,我的后续问题是:假设上面概述的语义谓词方法是正确的方法,那么有没有一种方法可以以编程方式组装列表?

一种似乎有希望的方法是从
getExpectedTokens()
构建它。在这里,我将稍微重新构造规则,使所有命名函数都属于一个规则(我们称之为
namedRuleA
),如下所示:

规则a:
蒙德鲁利亚
|总规则
;
namedRuleA:
令牌1规则令牌1
|令牌2规则令牌2
....
....
;
然后从ruleA的
ATNState
[
recognizer.getATN().states.get(recognizer.getState())
]开始,我会沿着过渡走到
namedRuleA
ATNState
,然后使用
getATN().getExpectedTokens(
ruleA:
    TOKEN_1 ruleToken1
    | TOKEN_2 ruleToken2
    | {!isNamedFunction()}? genericRuleA
;
ruleA:
    namedRuleA
    | genericRuleA
;

namedRuleA:
   TOKEN_1 ruleToken1
   | TOKEN_2 ruleToken2
   ....
   ....
   <many more such rules>
;