在@init之前调用的ANTLR4语义谓词 [英] ANTLR4 Semantic Predicate Called Before @init

查看:131
本文介绍了在@init之前调用的ANTLR4语义谓词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在子规则中有一个带有语义谓词的语法,该规则要求在调用规则中进行初始化才能正确执行,例如.

I have grammar with a semantic predicate in a subrule which requires initialization to be done in the invoking rule in order to execute properly e.g..

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 {}块中的初始化之前被调用.

But some tests show that the semantic predicate throws NullPointerException because it is called before the initialization in the @init{} block of the invoking rule is ever called.

检查生成的解析器代码后,我发现还有另一个函数包含我的语义谓词:

After checking the generated Parser code, I found that there is another function containing my semantic predicate:

private boolean decl_specifier_sempred(Decl_specifierContext _localctx, int predIndex) 

似乎在调用我的@init {}块进行初始化之前已调用此函数.是bug还是设计出来的东西?异常包含以上函数的名称:

It seems that this function is called before my @init{} block is called to do the initialization. Is it a bug or something by design? The exception contains the name of the above function:

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 {}块之前遇到异常.

The exception is encountered before the @init{} block is called.

推荐答案

ANTLR 4根据谓词是否上下文敏感"来确定谓词的行为.上下文敏感谓词使用$语法引用当前规则中定义的参数,标签,本地或规则/令牌.在您的情况下,您似乎正在定义和初始化标准ANTLR语法之外的状态信息,因此它无法知道谓词是上下文敏感的.有两种方法可以解决此问题:

ANTLR 4 determines the behavior of predicates based on whether or not they are "context sensitive". Context sensitive predicates use the $ syntax to reference a parameter, label, local, or rule/token defined in the current rule. It appears in your case you are defining and initializing state information outside of the standard ANTLR syntax, so it has no way to know the predicate is context sensitive. There are two ways to address this issue:

  1. 在规则的locals块而不是@members块中的谓词中定义一个或多个状态变量.
  2. 在谓词中的注释内添加对$ctx的引用.例如,您可以在谓词的末尾添加/*$ctx*/.
  1. Define one or more of your state variables which are used in the predicate in a locals block for the rule instead of in a @members block.
  2. Add a reference to $ctx inside of a comment in the predicates. For example, you could add /*$ctx*/ at the end of the predicate.

如果遇到上下文敏感的谓词,但是没有上下文信息可用(就像您的代码一样),则假定该谓词为true.

If a context sensitive predicate is encountered but no context information is available (as is the case for your code), the predicate is assumed to be true.

这篇关于在@init之前调用的ANTLR4语义谓词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆