ANTLR4 DefaultErrorStrategy无法注入缺少的令牌

ANTLR4 DefaultErrorStrategy无法注入缺少的令牌,antlr4,Antlr4,我尝试在TestRig中运行以下语法: grammar COBOLfragment; // hidden tokens WS : [ ]+ -> channel(HIDDEN); NL : '\n' -> channel(HIDDEN); // keywords PERIOD : '.'; DIVISION : 'DIVISION'; SECTION : 'SECTION'; DATA : 'DATA'; WORKING_STORAGE : 'WORKING-STORAGE'

我尝试在TestRig中运行以下语法:

grammar COBOLfragment;

// hidden tokens
WS : [ ]+ -> channel(HIDDEN);
NL : '\n' -> channel(HIDDEN);

// keywords
PERIOD : '.';

DIVISION : 'DIVISION';
SECTION : 'SECTION';

DATA : 'DATA';
WORKING_STORAGE : 'WORKING-STORAGE';

FILE : 'FILE';

FD : 'FD';

EXTERNAL : 'EXTERNAL';
GLOBAL : 'GLOBAL';

BLOCK : 'BLOCK';
CONTAINS : 'CONTAINS';
CHARACTERS : 'CHARACTERS';

// data
INTEGER : [0-9]+;
ID : [A-Z][A-Z0-9]*;

dataDivision :
    DATA DIVISION PERIOD
    fileSection?
    workingStorageSection?
;

fileSection :
    FILE SECTION PERIOD
    fileDescription*
;

fileDescription :
    FD fileName=ID
//    (IS? GLOBAL)?          // 1. IS GLOBAL clause
//    (IS? EXTERNAL)?        // 2. IS EXTERNAL clause
    blockClause?
    PERIOD
;

blockClause :
    BLOCK CONTAINS? blockSize=INTEGER CHARACTERS
;

workingStorageSection :
    WORKING_STORAGE SECTION PERIOD
;
通过以下输入:

DATA DIVISION.
FILE SECTION.
FD FD01
WORKING-STORAGE SECTION.
很明显,输入的第三行(“FD FD01”)缺少了
fileDescription
规则中要求的终止符
PERIOD

DefaultErrorStrategy
正确地确认了这一点,并召唤出丢失的令牌:

在stderr上显示正确的报告:
行4:0缺失。'WORKING-STORAGE'

但如果已启用注释掉的片段(即,再次将子句“is EXTERNAL”和“is GLOBAL”引入语法),则单标记插入失败:

在stderr上显示误导性报告:
第4行:0输入“工作存储”时没有可行的替代方案

如何使完整语法(带IS-EXTERNAL和IS-GLOBAL子句)保留更正缺少句点的能力?

旁注1:如果我启用IS EXTERNAL或IS GLOBAL,但不是两个子句,那么
DefaultErrorStrategy
可以很好地工作并注入缺少的标记

旁注2:为启用两个子句的语法生成的代码具有以下额外代码(与仅启用其中一个子句的语法相比):


adaptivePredict()
调用是罪魁祸首,因为它在解析器有机会
匹配(句点)
(在生成的代码中,而不是粘贴在这里)之前,在输入'WORKING-STORAGE'时抛出了
没有可行的替代方法。

我已经设法解决了它,为这两个is子句添加了一个新子句:

(此处仅更改了片段)

现在,
DefaultErrorStrategy
开始工作,并注入缺少的
时段

为什么不
isClauses:(是全局的?)是外部的
当然,我先试过了。但是得到了一个警告(警告(154):规则“fileDescription”包含一个可选块,其中至少有一个可选块可以匹配空字符串),并且没有插入缺少的
句点

public final FileDescriptionContext fileDescription() ... {
    ...
    try {
        ...
        switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) {
        case 1:
            {
            setState(31);
            _la = _input.LA(1);
            if (_la==IS) {
                {
                setState(30); match(IS);
                }
            }

            setState(33); match(GLOBAL);
            }
            break;
        }
        ...
    }
    catch (RecognitionException re) {
        ...
...
fileDescription :
    FD fileName=ID
    isClauses?
    blockClause?
    PERIOD
;

isClauses :
    IS? GLOBAL (IS? EXTERNAL)?
|   IS? EXTERNAL
;
...