我在一个子规则中有语义谓词的语法,要求在调用规则中进行初始化,以便正确执行,例如..
decl_specifier_seq
@init {
//some initialization required by a semantic predicate
}
: decl_specifier+ ;
decl_specifier
:
storage_class_specifier //auto, register, static, extern, mutable
| {/*semantic predicate requiring the initialization*/}? type_specifier
| function_specifier //inline, virtual, explicit
;
但有些测试显示语义谓词抛出NullPointerException,因为它在调用规则的@init {}块中的初始化之前被调用。
检查生成的Parser代码后,我发现还有另一个函数包含我的语义谓词:
private boolean decl_specifier_sempred(Decl_specifierContext _localctx, int predIndex)
在调用@init {}块进行初始化之前,似乎调用了此函数。这是一个错误或设计的东西?该例外包含上述函数的名称:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.antlr.v4.runtime.misc.TestRig.process(TestRig.java:249)
at org.antlr.v4.runtime.misc.TestRig.process(TestRig.java:211)
at org.antlr.v4.runtime.misc.TestRig.main(TestRig.java:143)
Caused by: java.lang.NullPointerException
at cppParser.CPPProcessorParser.decl_specifier_sempred(CPPProcessorParse
r.java:10989)
at cppParser.CPPProcessorParser.sempred(CPPProcessorParser.java:10853)
at org.antlr.v4.runtime.atn.SemanticContext$Predicate.eval(SemanticConte
xt.java:119)
at org.antlr.v4.runtime.atn.ParserATNSimulator.evalSemanticContext(Parse
rATNSimulator.java:1295)
at org.antlr.v4.runtime.atn.ParserATNSimulator.execATN(ParserATNSimulato
r.java:539)
at org.antlr.v4.runtime.atn.ParserATNSimulator.adaptivePredict(ParserATN
Simulator.java:415)
at cppParser.CPPProcessorParser.cppCompilationUnit(CPPProcessorParser.ja
va:330)
... 7 more
在调用@init {}块之前遇到异常。
答案 0 :(得分:1)
ANTLR 4根据它们是否是“上下文敏感”来确定谓词的行为。上下文敏感谓词使用$语法来引用当前规则中定义的参数,标签,本地或规则/标记。在您的情况下,您正在定义和初始化标准ANTLR语法之外的状态信息,因此无法知道谓词是上下文敏感的。有两种方法可以解决这个问题:
locals
块中的谓词中使用,而不是在@members块中。 $ctx
的引用。例如,您可以在谓词的末尾添加/*$ctx*/
。如果遇到上下文敏感谓词但没有可用的上下文信息(如代码的情况),则假定谓词为true。