如何在语法中不硬编码规则值

时间:2014-08-26 20:30:24

标签: antlr4

我的语法包含以下内容(简明):

block:
: specialfunction

specialfunction
: SPECIALFUNCTION OPAR (parameter (',' parameter)*)? CPAR 
;

SPECIALFUNCTION : 'FUNCTION1'| 'FUNCTION2';

SPECIALFUNCTION的可能值列表可以随时间变化。这些名称也在代码的其他地方使用,所以我不想在语法和代码中对它们进行硬编码,我希望有一个方法可以返回有效的SPECIALFUNCTION,然后可以从代码中的不同位置调用它们以及语法

SPECIALFUNCTION : <make a call to get the current list of SPECIALFUNCTIONS e.g. SomeClass.GetListOfNames>

public SomeClass 
{
     public string GetListOfNames()
     {
          return "'FUNCTION1' | 'ANOTHERSPECIALFUNCTION' | 'NEWONE'";
     }
}

然后,随着新的SpecialFunctions的添加,我只需将其添加到GetListOfNames。

注意我正在使用C#。

2 个答案:

答案 0 :(得分:1)

据我所知,您可以强制词法分析器发出另一种令牌类型,请参阅&#34; Lexer Rule Actions&#34;在this page

如果您修改了这样的常规Identifier规则:

Identifier : [a-z]+ { if (isSpecialFunction(getText()))  setType(SPECIALFUNCTION );}

根据创建词法分析器/解析器后可用的信息,这会使Identifier成为SPECIALFUNCTION

我必须承认,我不知道getText()是否是词法分析器操作中的正确方法。

或者,您也可以在运行时动态创建词法分析器,并通过添加其他替代词来修改词法分析器的来源。

另一种选择是通过更改Identifiers SPECIALFUNCTION的{​​{1}}的令牌类型来修改lexing之后的令牌流。

另一种选择是使SPECIALFUNCTION成为解析器规则,并在解析时检查IdentifierSPECIALFUNCTION

答案 1 :(得分:0)

仅根据您提供的内容,您可以将SPECIALFUNCTION规则更改为

SPECIALFUNCTION : 'func' NAME      ;
NAME            : [A-Z_] [a-zA-Z_]*;

当您遍历解析树时,您可以确定SpecialFunction上下文中的NAME是否可接受。

如果您在解析期间尝试验证运行时选项,则更好的选择可能是将该工作推迟到您遍历解析树时。

要在解析期间执行此操作,请添加语义谓词以验证由NAME匹配的字符串

SPECIALFUNCTION : 'func' NAME { isValidSFName($NAME.text) }?     ;

更新:在您的上一条评论中,您说最好为词法分析器提供一个列表,而不是让词法分析器检查名称的有效性。但是,如果你考虑一下,在词法分析器中检查词法分析器和词法分析器之间没有实际区别,请检查列表。在这两种情况下,就词法分析者而言,规则将成功或失败相同。

相反,如果您的要求是lexer令牌类型列表包含更改的特殊函数名称,那么实现这一点的唯一方法是通过重新编译词法分析器。

注意,如果重新编译词法分析器,则还需要重新编译解析器解析器。令牌类型值不需要在编译周期内保持不变。

更新2:为了澄清您对Bart的建议的评论,NAME规则实际上完成了相同的前瞻而不诉诸用户代码 - 只允许规则匹配任何允许的特殊功能的字符串名称。 NAME规则是否会产生歧义将取决于其他词法分析器规则,但实际上并不难避免。