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

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

问题描述

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

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.

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

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{} 块进行初始化之前调用了此函数.这是错误还是设计使然?异常包含上述函数的名称:

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.

如果遇到上下文敏感的谓词但没有可用的上下文信息(如您的代码的情况),则假定该谓词为真.

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.

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

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