1

始め方がよくわからないので、これはより一般的な質問です。基本的に、Yacc を使用して、CALC と呼ばれる作成された言語を解釈/変換する必要があります。CALC は、変数に対して算術演算を実行し、それらを出力できます。既に解釈は機能していますが、プロジェクトの 2 番目の部分は、元のファイルのすべての命令を翻訳した C++ ファイルを作成することです。

私の質問は、どうすればいいですか?文法規則のコード内でファイルに書き込みますか、それともメイン内で行いますか? 文法規則コード内で実行しようとしましたが、データが逆方向にファイルに書き込まれていることがわかりました (つまり、4 つの変数を宣言すると、プログラムは元の変数で宣言された最後の変数を出力します)。最初にプログラム、など)。

4

3 に答える 3

2

Yacc はボトムアップ解析を行います。

大まかに次の 2 つの選択肢があります。

  1. 入力によってリダクションが発生し、添付されたコードが実行されると、結果をそのまま出力できますが、常に順序を変更する必要があります。

  2. ルールで抽象構文ツリーを構築し、それを順番にたどることができます。これが通常のアプローチです。

于 2013-03-03T20:38:11.280 に答える
0

データは逆方向にファイルに書き込まれています

この特定のビットは、あなたが望んでいたものとは異なる構成を選択したように聞こえます. Yacc では、左と右の両方の再帰が可能です。これにより、(たとえば) 各項目が表示される順序 (左再帰) でリストを解析したり、その逆の順序でリストを解析したりできます。おそらく今やっている正しい再帰の例を次に示します。

list : ITEM
     | ITEM list

このサブグラマーは、入力に ITEM が含まれている場合、それだけではこれら 2 つのプロダクションのどちらを使用すればよいかわからないことに注意してください。どちらも ITEM で始まります。したがって、パーサーは 1 トークン先を見ます。次のトークンが ITEM でない場合、最初のプロダクションを使用することがわかります。しかし、次のトークンが ITEM である場合、2 番目の生産を処理する必要があります。しかし、そのプロダクションには非終端記号listが含まれています。つまり、パーサーは実際にはまったく削減しませんが、最初の ITEM をスタックにプッシュし、別の を探しに行きますlist

この結果、このサブグラマーに ITEM トークンのリストを与えると、別の ITEM が続いていない ITEM を最終的に確認するまで、それらをスタックにプッシュし続けます。その時点で、最後の ITEM は最初の生成によって削減されます (したがって に変わりlist、他のすべての ITEM は 2 番目の生成によって 1 つずつ削減されます。左再帰に進みます。

list : ITEM         /* matches first ITEM in list */
     | list ITEM    /* matches all other ITEMs in list */

今回、パーサーが ITEM を検出listすると、ITEM で始まるプロダクションは 1 つだけなので、最初のプロダクションによってすぐに削減され、その ITEM が に変わりlistます。ここで、入力ストリームに別の ITEM がある場合、その後に続く ITEM と一致させようとしlist、2 番目のプロダクションと正確に一致させます。

これらは、単純なリストを解析するための一般的なイディオムです。リストが「1 つ以上」ではなく「0 個以上」の場合、単一の ITEM を含むものではなく、単に空のプロダクションを使用することに注意してください。左再帰 (通常は必要) を使用すると、最初のアイテムに一致する別のプロダクションを使用すると、たとえば、後に続く (可能性のある) すべての ITEM を保持する配列を初期化するアクションを配置するのに便利な場所が得られます。

于 2013-03-04T20:43:02.053 に答える
0

これを 2 つのフェーズで行います。yacc を使用して解析ツリーを作成し、ツリーをたどって出力する必要があるものをすべて出力します。

于 2013-03-03T20:43:49.720 に答える