1

私はコンパイラーを学び、文字と整数の2つのタイプを扱う単純な言語のコードジェネレーターを作成しています。

ユーザー入力がスキャナーによってスキャンされ、パーサーによって解析された後、入力のAST表現を取得します。整数、演算子、変数を含む式のみを処理する、さらに単純な言語のコード生成を作成しました。

ただし、この新しい言語では、次のような型宣言のサブツリーを取得することがあります。

(IS TYPE (x) (INT))

これは、xがINT型であることを示しています。

これらの型宣言を処理するコードジェネレーターのケースがあるべきですか?または、これは単にセマンティックアナライザーが型チェックを行うためのものなので、型がチェックされたと想定し、ツリーのこの部分を無視して、xに値を割り当てるだけでよいのでしょうか。

4

2 に答える 2

1

両方の状況が考えられます。コード ジェネレーターにその機能を本当に追加する必要があるかどうかを確認するために、言語について詳しく説明する必要があります。それとも不要な場合はスキップし、プログラミング言語の設計に関するこの困難で興味深いトピックで余分な作業を避ける必要があります。 .

「コードジェネレーター」は、プログラミング言語(おそらく小さなもの)で入力コードとして受け取り、別のプログラミング言語(おそらく小さなもの)でコードを出力するプログラムですか?

このツールは通常「トランスレータ」と呼ばれます。

「コードジェネレーター」とは、プログラミング言語を入力として受け取り、プログラミング言語のようなアセンブラ/バイトコードを出力するプログラムですか?

このツールは通常「コンパイラ」と呼ばれます。

注: 「パイル」は「スタック」の同義語です。

通常、AST には操作のタイプまたは関数呼び出しが格納されます。例、c:

...
int a = 3;
int b = 5;
float c = (float)(a * b);
...

最後の行は、次のような AST を生成します (他の行では AST をスキップします)。

..................................................................
..................................................................
......................+--------------+............................
......................|    [root]    |............................
......................| (no type) =  |............................
......................+------+-------+............................
.............................|....................................
.................+-----------+------------+.......................
.................|........................|.......................
...........+-----+-----+....+-------------+-------------+.........
...........| (int) c   |....| (float) (cast operation)  |.........
...........+-----------+....+-------------+-------------+.........
..........................................|.......................
....................................+-----+-----+.................
....................................| (int) ()  |.................
....................................+-----+-----+.................  
..........................................|.......................
....................................+-----+-----+.................
....................................| (int) *   |.................
....................................+-----+-----+.................
..........................................|.......................
..............................+-----------+-----------+...........
..............................|.......................|...........
........................+-----+-----+...........+-----+-----+.....
........................| (int)  a  |...........| (float) b |.....
........................+-----------+...........+-----------+.....
..................................................................
..................................................................

「(float)」は、質問と同様に、演算子または関数のようにキャストされることに注意してください。

幸運を。

于 2011-11-18T18:27:40.237 に答える
1

これが宣言なら

(IS TYPE (x) (INT))

次に、x をメモリに配置する必要があります。C と自動変数の場合、ローカルの自動変数はスタックに割り当てられます。必要なサイズのスタックを割り当てるには、すべてのローカル変数のサイズとサイズが型からのものであることを知っておく必要があります。

この変数がレジスターに格納されている場合、必要なサイズのレジスターを選択する必要があります (x86 については、AL、AX、EAX、RAX - 異なるサイズの同じレジスター) を選択する必要があります。

また、異なるデータ サイズ (例: char、short、int または 8 ビット、16 ビット、32 ビットなど) を操作できる AST にあいまいな操作がある場合にも、型が必要です。一部のアセンブラでは、データのサイズが命令自体にエンコードされます。そのため、codegen は変数のサイズを記憶する必要があります。

または、操作のタイプが AST に記録されていない場合、ADD:

(ADD (x) (y))

float と int の両方の追加 (ADDまたはFADD命令) を意味する場合があるため、正しいバリアントを選択するには codegen で x と y の型が必要です。

于 2011-11-18T16:29:10.957 に答える