• 締切済み

コンパイラの作成

 皆さんのお力を貸してください.  現在, Java 言語を用いてコンパイラを作成しているのですが, 関数の引数として 1 次元配列を渡す方法 ( 配列の要素全体のコピーを渡すのではなく配列の先頭の番地を渡す方法 ) と参照渡しのプログラム記述方法が解らず悩んでおります.  何卒ご教授お願いいたします.

みんなの回答

回答No.5

これは、情報学科で出された課題ですか? なかなか難しいですね。 簡単に説明しますと、以下の変更を加えます。 caller(関数が呼び出す)側:  配列変数の先頭アドレスをスタックに積む。 callee(関数が呼び出される)側:  引数の配列を使用する場合、callerがスタックに積んだ値を配列の先頭アドレスとして処理する。 targetのアーキテクチャ(CellV内のexecute()を読めば理解出来ます。本にも書いてあるかもしれません。)、CellK内の文法解析の順番を理解出来れば、比較的少ないコーディングですむと思います。 他に方法はあるかもしれませんが、 私の試した方法を書いておきます。 ただし、大雑把な説明なので、以下の変更だけではコンパイルしません。他にも修正、追加する必要があります。 大変でしょうが、頑張って下さい。 -------------------------------------------- caller(呼び出し)側の変更:  配列でない変数を引数にして関数を呼び出す場合は、その変数の値をスタックに積みます。  これは、CellK.javaの中では、  cellV.genCodeT(CellV.lod, tIndex);  という文で実行されています。    これを配列を引数に出来るように拡張するには、配列の先頭アドレスをスタックに積みます。  これは、  cellV.genCodeT(CellV.lda, tIndex);  という文で実行出来ます。 callee(呼び出される)側:  CellK.javaの中で、function()という関数がありますが、ここではfunctionのparseを行なっています。  この中で、while文の中に、if(token.kind == CellG.I)という文がありますが、これは引数が変数(配列でない)の場合の、変数のparameter登録等の処理を行なっています。  配列の引数に対応するには、else if文を追加し、その中で登録等の処理をします。  例:else if (token.kind == CellG.aI) { ... }  また、CellG.javaの中で、識別子の種類を列挙したfinal変数の一覧がありますが、これに配列パラメータの識別子を追加する必要があると思います。  例:static final int parAI = 45;  次に、statement()の中で、配列に代入する場合の処理を行なっている箇所があるのですが(case CellG.arrI)、配列が引数である場合の処理を追加する必要があります。配列が引数である場合は、callee側は配列のアドレスをスタックから読む必要があります(caller側で積んだアドレスがありますよね?)。 case CellG.parAI:   cellV.genCodeT(CellV.lod, tIndex); /* lod 先頭番地 */ case CellG.arrI の中の、  cellV.genCodeT(CellV.lda, tIndex); との違いを理解して下さい。  最後に、引数配列の値を読む場合も同様に、factor()内のcase文に処理を追加します。  case CellG.parAI:   cellV.genCodeT(CellV.lod, tIndex); /* lod 先頭番地 */

No-001
質問者

補足

 twoandhalf さん丁寧な解答ありがとうございます.twoandhalf さんは当参考書を 利用したことがあるのでしょうか?今新たに, "%"( 余りの計算 ) が出来るように拡 張しようと考えているのですが, こちらについてもアドバイスを頂けないでしょう か.よろしくお願いします.

回答No.4

配列の場合、コピーを渡す方が面倒くさかったりする。 こちらを読めばわかるかな。 http://www.atmarkit.co.jp/fjava/rensai3/eclipsejava06/eclipse06_1.html

  • kacchann
  • ベストアンサー率58% (347/594)
回答No.3

>関数の引数として 1 次元配列を渡す方法 >参照渡しのプログラム記述方法 なんであれ、 (「自作インタプリタ」内部で確保した)「自作メモリ領域」のアドレス を使うだけ。 たとえばその「自作メモリ領域」というのが 「単純な配列」 ならば、 その配列のインデックスこそが「アドレス」。 つまりその内部自作メモリ全体が、int配列 int[] mem = new int[1000] というものであったら、 mem[11], mem[23], mem[45] この11、23、45などが「アドレス」に相当する…よね? --- ●Point 1 「参照渡し」というのは、 この「アドレスを利用する」ことにほかなりません。 例えば まず mem[11] に値 777 が入っていて、これをある関数foo()の引数として渡す際に、 foo(777) とやるのが値渡しで、 foo(11) とやるのが「参照渡し」。 とりあえずこれで「渡す」側の処理はOK。 --- ●Point 2 次にこれを「受け取る」側の処理も、協調して作る必要がある(よね?)。 つまり、つぎのような関数宣言部 foo(Int a, refInt b) を見て、 「ああ、第一引数は「値渡し」だな。 つまり渡ってきた引数には、「値」そのものが入っているのだから、 これを使いたい時は、引数の中味を直接見ればいいのだな。 第二引数は「参照渡し」だな。 ということは、渡ってきた引数には「アドレス」が入っているのだから、 コレを使いたい時は、引数の中味のアドレスを見て、 次にそのアドレスの参照先(ポイント先)を見ればいいのだな。 まあ1ステップ、処理が増えるだけだな」 と考えればよい。 このへんの話は、理屈的にはむずかしくない。 --- が、 http://book.gihyo.co.jp/s-com/ この「スモールコンパイラの制作で学ぶプログラムのしくみ 」という本の 話だよね? 難易度的には (1)Javaの基礎文法を知っている …1 (2)この本のソースコードを「完全に」理解する…10 (3)前述の「参照」の理屈を押さえる…1 (4)これらを踏まえたうえで、  この本のソースコードを正しく書き換える…3か4 とにもかくにも(2)がすべてで、 まずこれをクリアしないことには、どうしようもない。 --- 大半の学生には、自力で作るのキツイんじゃないかなーとは思うけどね。

No-001
質問者

補足

kacchann さんありがとうございます.使っている参考書は「スモールコンパイラの制作で…」です. kacchann さんはこの本を読んだことがあるのでしょうか?それに「大半の学生には、自力で作るのキツイんじゃないかなー」とまさに感じております.それでかなり切羽詰ってまして.  考えている問題としては, まず配列の方では ( 問 ) 関数の引数として 1 次元配列を渡せるように機能拡張する.  渡し方は配列の要素全体のコピーを渡すのではなく, 配列の先頭の番地を渡す.以下のプログラムで動作確認.  {  I sum(aI a[], I n){ vI s = 0, i; for(i = 0; i < n; i = i+1;){ s = s + a[i]; } return s; } aI a[16]; for(i = 0; i < 16; i = i+1;){ a[i] = i * i; } println sum(a, 16); }$  { I copy(aI a[], aI b[], I n){ vI i; for(i = 0; i < n; i = i+1;){ b[i] = a[i]; } return 0; } vI i; aI a[16], b[16]; for(i = 0; i < 16; i = i+1;){ a[i] = i; } dummy = copy(a, b, 16); for(i = 0; i < 16; i = i+1;){ println b[i]; } }$  なんとかコンパイラを拡張して上記のプログラムを動作させたいのですが, 記述方法が解らないのです.  kacchann さんは記述方法は解りますか?解りましたらアドバイスをお願いいたします.

  • edomin
  • ベストアンサー率32% (327/1003)
回答No.2

私もJavaは詳しくありませんが、 「 Java 言語にはポインタのようなものは存在しません.」 という仕様になっているのですから 「 Java 言語は, 配列及びオブジェクトは参照渡しではないでしょうか.」 という内部動作をプログラム上からアクセスすることは無理なんじゃありませんか?Java自体がどういう風に動いているかは関係なく、ユーザが何を使えるのかが問題なのだと思いますが。

No-001
質問者

補足

 ちょっと良く解らないのですが, 変数自体のアドレスを渡すことが出来るような設計にしたいと考えています.

回答No.1

Javaは詳しくないですが。 Javaでポインタ(番地)を扱うことなんてできましたか?

No-001
質問者

補足

 早速の返信ありがとうございます.確かにおっしゃる通りで Java 言語にはポインタのようなものは存在しません.そのかわり Java 言語は, 配列及びオブジェクトは参照渡しではないでしょうか.Java 自体がそのような仕様になっていると何かで読んだ気がするのですが?  それが本当なら, 配列やオブジェクトの場合は値ではなくメモリアドレスが値で渡されていることになり, それを実現したいと思っているのですが….

関連するQ&A