Search code examples
javaantlrdslparser-generator

ANTLR tree parser grammar rewrite rule for *


I have a tree grammar, part of the grammar is shown below

transitions
    :'transitions' '=' INT ('(' INT ',' INT ')') + ';' -> ^(TRANSITIONS INT INT INT*)
    ;

and here is the respective part of the tree parser grammar,

transitions
    :^(TRANSITIONS INT INT INT*)
    {System.out.println("");}
    ;

I have used + rewrite rule and that is basically repitition. In the grammar above, the user is entering minimum 3 integer values, say one possible input,

  transitions 1 (5,0)

2nd possible input

transitions 2 (5,0) (5,1)

3rd possible input

transitions 3 (5,0) (5,1) (5,2)

and so on.
The first integer determines how many pairs of integers there will be. The problem is how will I access these integer inputs in my parser grammar and how can I possibly print these in the println statement above?

Please refer to my question ANTLR java test file can't create object of tree grammar for the complete grammar I have written.


Solution

  • I suggest you keep the "pairs" of numbers in a separate rule:

    parser grammar

    transitions
     : 'transitions' '=' INT pair+ ';' -> ^(TRANSITIONS INT pair+)
     ;
    
    pair
     : '(' INT ',' INT ')' -> ^(PAIR INT INT)
     ;
    

    tree grammar

    transitions
     : ^(TRANSITIONS INT pair+) {System.out.println("transitions.INT=" + $INT.text);}
     ;
    
    pair
     : ^(PAIR a=INT b=INT) {System.out.println("pair=" + $a.text + ", " + $b.text);}
     ;
    

    EDIT

    A quick demo:

    grammar T;
    
    options {
      output=AST;
      ASTLabelType=CommonTree;
    }
    
    tokens {
      TRANSITIONS;
      PAIR;
    }
    
    parse
     : transitions EOF!
       {
         CommonTree root = $transitions.tree;
    
         int count = root.getChildCount();
    
         Tree child1 = root.getChild(0);
         Tree child2 = root.getChild(1);
         Tree child3 = root.getChild(2);
         Tree child4 = root.getChild(3);
    
         System.out.println("root=" + root.getToken().getText() + " has " + count + " child nodes:");
         System.out.println(" - child1=" + child1.toStringTree());
         System.out.println(" - child2=" + child2.toStringTree());
         System.out.println(" - child3=" + child3.toStringTree());
         System.out.println(" - child4=" + child3.toStringTree());
    
         String secondValueFromLastPair = child4.getChild(1).getText();
         System.out.println("\nsecondValueFromLastPair=" + secondValueFromLastPair);
       }
     ;
    
    transitions
     : 'transitions' '=' INT pair+ ';' -> ^(TRANSITIONS INT pair+)
     ;
    
    pair
     : '(' INT ',' INT ')' -> ^(PAIR INT INT)
     ;
    
    INT   : '0'..'9'+;
    SPACE : ' ' {skip();};
    

    If you now parse the input "transitions = 3(5,0) (5,1) (5,2);", you'd see the following being printed to the console:

    root=TRANSITIONS has 4 child nodes:
     - child1=3
     - child2=(PAIR 5 0)
     - child3=(PAIR 5 1)
     - child4=(PAIR 5 1)
    
    secondValueFromLastPair=2