1

我正在尝试编写一段语法来表达层次结构的字段访问,例​​如abc其中cab的字段,b是 a 的字段

要评估abcde的值,我们需要评估abcd的值,然后得到e的值。要评估abcd的值,我们需要评估abc的值,然后得到d的值,依此类推......

如果您有这样的树(箭头表示“lhs 是 rhs 的父级”):

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

评价很简单。使用递归,我们只需要解析孩子的值,然后访问正确的字段。

问题是:我的 ANTLR 语法文件中有这 3 条规则:

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

正如所料,我的树有这种形式:

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

评估并不像其他情况那么容易,因为我需要获取当前节点的值,然后将其提供给子节点等等......

有没有办法使用 ANTLR 来反转树的顺序,或者我需要手动完成?

4

1 回答 1

1

您只能通过使用内联树运算符1^而不是重写规则来执行此操作。

一个演示:

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();};

解析输入:

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

将产生以下 AST:

在此处输入图像描述


1有关内联树运算符和重写规则的更多信息,请参阅:如何输出使用 ANTLR 构建的 AST?

于 2012-11-21T18:55:05.870 回答