Semantic Predicates antlr don't recognize chain of integers of width 4

我的未来我决定 提交于 2019-12-24 02:30:29

问题


I need to recognize arrays of integers in Fortran's I4 format (stands for an integer of width four) as the following example:

Using a pure context-free grammar:

WS  :   ' '        ;    

MINUS   : '-'   ;  


DIGIT  :   '0'..'9'        ;

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

numbers
    :    int4*;

The above example is correctly matched:

However if I use semantic predicates to encode semantic constraints of rule 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}?
   ;

it works for the int4 rule, but it's not the same for the numbers rule, because it doesn't recognize the array of integers of the first example:

In this case may be better pure context-free grammar, but in case of the format I30 (stands for an integer of width 30)?

The main question is: Is it possible to use Semantic Predicates with this grammar?


回答1:


Your parse tree seems to end at the numbers rule because your numbers rule throws an exception (but it does not show up in the diagram...). You can see it if you run the code generated, and if you take a closer look at the exception, it says (line info may differ for you):

Exception in thread "main" java.util.EmptyStackException
  at java.util.Stack.peek(Stack.java:102)
  at FortranParser.numbers(FortranParser.java:305)
  at Main.main(Main.java:9)

and the code throwing the exception is:

public final void numbers() throws RecognitionException {
                ....
                else if ( (LA5_0==DIGIT) && ((int4_stack.peek().n < 4))) {
                        alt5=1;
                }

So your problem is that the semantic predicate gets propagated to the numbers rule, and at that level the scope stack is empty, hence int4_stack.peek() throws an exception

A trick to avoid it is that you use a variable in the global scope, e.g.:

@members {
    int level=0;
}

and modify the semantic predicates to check level before the predicates, just like:

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}?
   ;

This is just a workaround to avoid the error that you get, maybe (knowing the error) there is a better solution and you don't need to mess up your semantic predicates.

But, I think, the answer is yes, it is possible to use semantic predicates with that grammar.



来源:https://stackoverflow.com/questions/27605243/semantic-predicates-antlr-dont-recognize-chain-of-integers-of-width-4

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!