_localctx 在 antlr4 语义谓词中为 null 的原因可能是什么?

What could be a reason for `_localctx` being null in an antlr4 semantic predicate?

我正在使用列表标签来收集标记和语义谓词来验证我的解析器语法中的序列。例如

line
:
    (text+=WORD | text+=NUMBER)+ ((BLANK | SKIP)+ (text+=WORD | text+=NUMBER)+)+ 
    {Parser.validateContext(_localctx)}? 
    (BLANK | SKIP)*
;

哪里

WORD: [\u0021-\u002F\u003A-\u007E]+; // printable ASCII characters (excluding SP and numbers)
NUMBER: [\u0030-\u0039]+; // printable ASCII number characters
BLANK: '\u0020';
SKIP: '\u0020\u0020' | '\t'; // two SPs or a HT symbol

Parser.validateContext 中用于验证 line 规则的部分将像这样实现

private static final boolean validateContext(ParserRuleContext context) {
   //.. other contexts
   if(context instanceof LineContext) 
       return "<reference-sequence>".equals(Parser.joinTokens(((LineContext) context).text, " "));
   return false;}

其中 Parser.joinTokens 定义为

private static String  joinTokens(java.util.List<org.antlr.v4.runtime.Token> tokens, String delimiter) {
    StringBuilder builder = new StringBuilder();
    int i = 0, n;
    if((n = tokens.size()) == 0) return "";
    builder.append(tokens.get(0).getText());
    while(++i < n) builder.append(delimiter + tokens.get(i).getText());
    return builder.toString();}

两者都放在语法文件开头的 @parser::members 子句中。


我的问题是:有时 _localctx 引用是 null 而我收到 "no viable alternative" 错误。这些可能是因为失败的谓词保护了各自的规则而没有给出替代方案。

为什么 _localctx 会是 null 是有原因的吗?


更新: this question 的答案似乎表明在预测期间也会调用语义谓词。也许在预测期间没有创建上下文并且 _localctx 设置为 null.

谓词中 _localctx 的语义未定义。允许的行为包括但不限于以下(并且可能在任何发布期间更改):

  1. 编译失败(没有具有该名称的标识符)
  2. 使用了错误的上下文对象
  3. 没有上下文对象(空)

要从谓词中引用当前规则的上下文,您需要改用 $ctx

请注意,这同样适用于谓词中使用的规则参数、局部变量、and/or return 值。例如,参数 a 不能引用为 a,而必须是 $a.