我正在尝试在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”)缺少PERIOD
规则中要求的终结符fileDescription
。
DefaultErrorStrategy
正确地确认了这一点并让人联想到遗失的标记:
在stderr上显示正确的报告:line 4:0 missing '.' at 'WORKING-STORAGE'
。
但如果已注释掉的片段被启用(即,条件'IS EXTERNAL'和'IS GLOBAL'再次被带入语法中),则单个令牌插入失败:
在stderr上显示误导性报告:line 4:0 no viable alternative at input 'WORKING-STORAGE'
如何启用完整语法(使用IS EXTERNAL和IS GLOBAL子句)保留纠正丢失的PERIOD的能力?
附注1:如果我启用IS EXTERNAL或IS GLOBAL,但不启用两个子句,那么DefaultErrorStrategy
可以正常工作并注入丢失的令牌。
附注2:为两个子句启用的语法生成的代码具有以下额外代码(与仅启用其中一个语法的语法相比):
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) {
...
adaptivePredict()
调用是罪魁祸首,因为它在解析器有机会no viable alternative at input 'WORKING-STORAGE'
之前抛出match(PERIOD)
(在生成的代码中,未粘贴在此处)。
答案 0 :(得分:0)
我设法解决了为两个IS子句添加新子句:
(这里只是片段改变了)
...
fileDescription :
FD fileName=ID
isClauses?
blockClause?
PERIOD
;
isClauses :
IS? GLOBAL (IS? EXTERNAL)?
| IS? EXTERNAL
;
...
现在DefaultErrorStrategy
完成了工作并注入了缺失的PERIOD
。
为什么不isClauses : (IS? GLOBAL?) (IS? EXTERNAL)?;
好吧,我当然先尝试过。但是得到了一个警告(警告(154):规则'fileDescription'包含一个可选块,其中至少有一个可以匹配空字符串的替代方案)并且没有丢失PERIOD
注入。