2012-04-23 13 views
0

は、私はこのように私の.Y文法の一部を持っているとしましょうステートメントリスト 後者については、insert_stmt ...関数を通して格納しますが、最初はスタックの先頭に送ります。YACC(バイソン)ASTの簡素化

私の質問は次のとおりです。$$ = $ 1をどうすれば処理できますか? つまり、insert_stmt_listはすべてを構造体に入れて、そこにあることを知っています。その値などを出力できますが、$$ = S1はどこに行きますか?それを読むには? :-)

ありがとうございました!

答えて

1

Re:どのように読むのですか?

あなたは最初にexprを認識しなければならない左回帰文法を持っています。これはstmtに縮小され、make_new_stmt_listによって生成された意味値はstmt1の意味値になります。これは$$ = $1;です。

これは、「最初のシンボルの意味値を(唯一のものになります)右側の意味値とし、それを左側の意味値として伝播する」という意味です。

exprが見られる場合、解析は、他の生産を継続すると:

ここ
stmt : ... 
    | stmt expr { $$ = insert_stmt_list($1, $2); } 

$1が右側にstmtから来ることに$$に割り当てられたセマンティック値であります前もっての削減はstmtを生じた。

exprstmtとして機能するようにシステムを設計しました。さらに、exprは、insert_stmt_listのいずれかの引数として適切な値を生成します。式はリストです。

ので:

  1. あなたの入力だけで一つの発現Eを持っている場合には、出てくるstmtだけでは表現です。

  2. 次の2つの式E1およびE2を持っている場合は、emeges stmtが結果です:あなたは3つの式を持っている場合は、全体的なstmtは、これらの呼び出しの結果である

    insert_stmt_list(E1, E2) 
    
  3. insert_stmt_list(insert_stmt_list(E1, E2), E3) 
    

などとなる。それが意味をなさないかどうかは、この「挿入」操作のセマンティクスによって決まります。

+0

大きな疑問は、実際に私が声明を期待していた場合、代わりに表現をどう扱うかでしたか?私はこれに対処することができました汎用構造体を使用して、どこにフラグ{is_STATEMENT、is_EXPRESSION、...}とそれぞれの構造体へのポインタがあります。これはCがポインタの型を知ることを許さないためです。 – Nitrate

+0

Lisp抽象構文を見ることができます。評価の基本的な統語単位は式です。単一の式が期待されるところで複数の式の副作用が評価されるようにするには、 'progn'のような演算子を使います:'(progn expr1 expr2 ... exprn) '。これは不必要なノードではありません。 – Kaz

0

それはこのような何かを書くことより慣用的です:

stmt : expr { $$ = make_new_stmt_list($1); } 
     | stmt expr { $$ = insert_stmt_list($1, $2); } 

一つの方法または別の、あなたはステートメントリストデータ構造であなたの発現データ構造をラップする必要があります。

+1

解決策の問題は、ast(抽象構文木)の目的で、無意味なノードを破棄することになっているときに、文リストを作成することです。だから私はスタック$$ = $ 1の上に値を置くことが道だったが、すべてがぼやけてしまったという結論に達した:-) – Nitrate

+0

式のリストと単一の式の区別はしかし、必然的に無意味です。これは、抽象構文で見られる種類のものです。あなたがそれを実際に抽象化しないようにする方法。あなたのコードは文字通り文法をとっています。私。 'stmt:expr'は、構文的には文が式であると主張し、それを' $$ = $ 1'に変換しました。より抽象的な見方は、この左再帰的な生成は、シーケンスを構築するための単なる「ジグ」にすぎないということです。 – Kaz