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 に答える