我的语法包含以下内容(简明):
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#。
答案 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
成为解析器规则,并在解析时检查Identifier
是SPECIALFUNCTION
。
答案 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规则是否会产生歧义将取决于其他词法分析器规则,但实际上并不难避免。