我需要识别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规则,但对于数字规则却不一样,因为它不识别第一个示例中的整数数组:

在这种情况下,可以使用更好的纯上下文无关语法,但在格式I30 (表示宽度为30的整数)的情况下呢?
主要问题是:这种语法是否可以使用语义谓词?
发布于 2014-12-22 22:46:32
解析树似乎以数字规则结尾,因为数字规则会抛出一个异常(但它不会出现在图表中.)。如果您运行生成的代码,您可以看到它,如果您仔细观察异常,它会说(行信息可能对您不同):
线程"main“java.util.EmptyStackException at java.util.Stack.peek(Stack.java:102) at FortranParser.numbers(FortranParser.java:305) at Main.main(Main.java:9)中的异常
抛出异常的代码是:
public final void numbers() throws RecognitionException {
....
else if ( (LA5_0==DIGIT) && ((int4_stack.peek().n < 4))) {
alt5=1;
}因此,您的问题是语义谓词被传播到数字规则,而在那个级别上范围堆栈是空的,因此int4_stack.peek()抛出一个异常。
避免这种情况的一个方法是在全局范围内使用一个变量,例如:
@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}?
;这只是一个解决办法,以避免您得到的错误,也许(知道错误)有一个更好的解决方案,您不需要搞乱您的语义谓词。
但是,我认为,答案是肯定的,用那个语法来使用语义谓词是可能的。
https://stackoverflow.com/questions/27605243
复制相似问题