1

I'm trying to write a piece of grammar to express field access for a hierarchical structure, something like a.b.c where c is a field of a.b and b is a field of a.

To evaluate the value of a.b.c.d.e we need to evaluate the value of a.b.c.d and then get the value of e. To evalutate the value of a.b.c.d we need to evalute the value of a.b.c and then get the value of d and so on...

If you have a tree like this (the arrow means "lhs is parent of rhs"):

Node(e) -> Node(d) -> Node(c) -> Node(b) -> Node(a)

the evaluation is quite simple. Using recursion, we just need to resolve the value of the child and then access to the correct field.

The problem is: I have this 3 rules in my ANTLR grammar file:

tokens {
    LBRACE  = '{' ;
    RBRACE  = '}' ;
    LBRACK  = '[' ;
    RBRACK  = ']' ;
    DOT     = '.' ;
    ....
}

reference
    : DOLLAR LBRACE selector RBRACE -> ^(NODE_VAR_REFERENCE selector)
;

selector
    : IDENT access -> ^(IDENT access)
;

access
    : DOT IDENT access? -> ^(IDENT<node=com.at.cson.ast.FieldAccessTree> access?)
    | LBRACK IDENT RBRACK access? -> ^(IDENT<node=com.at.cson.ast.FieldAccessTree> access?)
    | LBRACK INTEGER RBRACK access? -> ^(INTEGER<node=com.at.cson.ast.ArrayAccessTree> access?)
;

As expected, my tree has this form:

ReferenceTree
  IdentTree[a]
    FieldAccessTree[b]
      FieldAccessTree[c]
        FieldAccessTree[d]
          FieldAccessTree[e]

The evaluation is not that easy as in the other case because I need to get the value of the current node and then give it to the child and so on...

Is there any way to reverse the order of the tree using ANTLR or I need to do it manually?

Antonio
  • 1,065
  • 3
  • 14
  • 27

1 Answers1

1

You can only do this by using the inline tree operator1, ^, instead of a rewrite rule.

A demo:

grammar T;

options {
  output=AST;
}

tokens {
  ROOT;
  LBRACK = '[' ;
  RBRACK = ']' ;
  DOT    = '.' ;
}

parse
 : selector+ EOF -> ^(ROOT selector+)
 ;

selector
 : IDENT (access^)*
 ;

access
 : DOT IDENT             -> IDENT
 | LBRACK IDENT RBRACK   -> IDENT
 | LBRACK INTEGER RBRACK -> INTEGER
 ;

IDENT   : 'a'..'z'+;
INTEGER : '0'..'9'+;
SPACE   : ' ' {skip();};

Parsing the input:

a.b.c    a[1][2][3]

will produce the following AST:

enter image description here


1 for more info about inline tree operators and rewrite rules, see: How to output the AST built using ANTLR?

Community
  • 1
  • 1
Bart Kiers
  • 166,582
  • 36
  • 299
  • 288