Antlr3 语义谓词antlr don';t识别宽度为4的整数链

Antlr3 语义谓词antlr don';t识别宽度为4的整数链,antlr3,predicate,Antlr3,Predicate,我需要识别Fortran I4格式的整数数组(表示宽度为4的整数),如下例所示: 使用纯上下文无关语法: WS : ' ' ; MINUS : '-' ; DIGIT : '0'..'9' ; int4: WS WS (WS| MINUS ) DIGIT | WS (WS| MINUS ) DIGIT DIGIT | (WS|

我需要识别Fortran I4格式的整数数组(表示宽度为4的整数),如下例所示:

使用纯上下文无关语法:

WS  :   ' '        ;    

MINUS   : '-'   ;  


DIGIT  :   '0'..'9'        ;

int4:
               WS  WS  (WS| MINUS )  DIGIT  
             | WS  (WS| MINUS )  DIGIT  DIGIT  
             | (WS| MINUS | DIGIT  )  DIGIT  DIGIT  DIGIT    
   ;

numbers
    :    int4*;
上述示例正确匹配:

但是,如果我使用语义谓词对规则int4的语义约束进行编码:

int4
scope { int n; }
@init { $int4::n = 0; }
 : ( {$int4::n < 3}?=> WS {$int4::n++;} )*
   ( MINUS {$int4::n++;} )?
   ( {$int4::n < 4}?=> DIGIT{$int4::n++;} )+
    {$int4::n == 4}?
   ;
int4
作用域{int n;}
@init{$int4::n=0;}
:({$int4::n<3}?=>WS{$int4::n++;})*
(减去{$int4::n++;})?
({$int4::n<4}?=>数字{$int4::n++;})+
{$int4::n==4}?
;
它适用于int4规则,但与数字规则不同,因为它无法识别第一个示例中的整数数组:

在这种情况下,纯上下文无关语法可能更好,但在I30格式(表示宽度为30的整数)的情况下,是否更好


主要问题是:是否可以将语义谓词用于此语法?

您的解析树似乎以数字规则结尾,因为数字规则引发异常(但它没有显示在图表中…)。如果运行生成的代码,您可以看到它,如果仔细查看异常,它会说(行信息可能会因您而异):

引发异常的代码是:

public final void numbers() throws RecognitionException {
                ....
                else if ( (LA5_0==DIGIT) && ((int4_stack.peek().n < 4))) {
                        alt5=1;
                }
并修改语义谓词以检查谓词之前的级别,如下所示:

int4
scope { int n; }
@init { $int4::n = 0; level++; }
@after { level--; }
 : ( {level==0 || $int4::n < 3}?=> WS {$int4::n++;} )*
   ( MINUS {$int4::n++;} )?
   ( {level==0 || $int4::n < 4}?=> DIGIT{$int4::n++;} )+
    {$int4::n == 4}?
   ;
int4
作用域{int n;}
@init{$int4::n=0;level++;}
@在{level--;}之后
:({level==0 | |$int4::n<3}?=>WS{$int4::n++})*
(减去{$int4::n++;})?
({level==0 | |$int4::n<4}?=>digital{$int4::n++})+
{$int4::n==4}?
;
这只是一个解决方法,可以避免出现错误,也许(知道错误)有更好的解决方案,而且不需要弄乱语义谓词


但是,我认为答案是肯定的,可以在语法中使用语义谓词。

@BartKiers为了更好地理解这个问题,我编辑了几分钟ago@BartKiers是的,但当我在int4规则中添加语义谓词时,解析树似乎以数字结尾,正如你在解析树的最后一张图片中看到的!你的回答真的很有用,而且很有效!我认为这是一个很好的解决方案,本例中抛出的异常应该由ANTLR的开发人员解决。由于我使用的是ANTLRWorks 1.4.2,可能这个问题在上一个版本中已经解决了。
@members {
    int level=0;
}
int4
scope { int n; }
@init { $int4::n = 0; level++; }
@after { level--; }
 : ( {level==0 || $int4::n < 3}?=> WS {$int4::n++;} )*
   ( MINUS {$int4::n++;} )?
   ( {level==0 || $int4::n < 4}?=> DIGIT{$int4::n++;} )+
    {$int4::n == 4}?
   ;