質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

Q&A

1回答

810閲覧

局所変数の記号表への登録方法

shido

総合スコア21

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

0グッド

1クリップ

投稿2018/01/14 12:26

JavaでC言語の簡単なコンパイラを作成中なのですが、局所変数の記号表への登録について困っています
字句解析→構文解析→意味解析→コード生成の順です
{}からでたら消去するというのはわかるのですが、そうすると意味解析で記号表に局所変数の情報が存在していないのでNullPointerを吐かれてしまいます。
詳しい方御指南をお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

{}からでたら消去するというのはわかるのですが

変数表をどういう形式で、いつ生成して、どこにどのように記録しているか自分にはわかりません。間違い方は色々考えられますがどう間違っているかわからないので、どうすべきかについても具体的なコメントはしにくくように思います。

##どんな内部設計をしていますか?
変数表に限らず、「情報をいつ生成し、どのような形式・場所に記録し、どのように参照し、どう後始末するか」は明確に設計しておくべきものです。それが曖昧だと正しく論理を作ることはおぼつきません。ご質問の内容から言って質問者さんは少なくとも充分設計をしておられない(または曖昧にしている)ままコードを書いておられるように感じます。簡単な練習プログラムのようなものなら気ままに書いて動かしてみるというのでもよいでしょう。しかしコンパイラーのような複雑なものならもっとしっかり設計しておくべきと思います。

またもし他者に意見を求めるなら、まず最初にご自分の設計を明示すべきと思います。少なくとも「字句解析→構文解析→意味解析→コード生成の順です」という説明ではあまりに大雑把すぎて説明になっているとは言い難いです。どんなコンパイラーでもその流れで設計されていることが普通なので言う必要がないくらいです。より的確なアドバイスを求めたいならそれなりに詳しく質問者さんの設計内容を説明すべきだと思います。例えば構文解析ではどんな構造を生成しているか、意味解析ではどんなものを生成しているのかといったことです。少なくとも「こういうふうに作っているのだろう・・・」と想像できるぐらいには説明しないと具体的なコメントがしにくいと思います。コンパイラーといっても「どれもこれも同じデータ構造・論理でできている」わけではなく色々な作り方があると思うのです。

###どんな仕様のCなのでしょう?
今日のCは「ブロックの先頭だけでなく任意の場所に変数を宣言する」ことが許されてますがそういうものと、初期のCの仕様のように「関数ブロックの先頭でしか変数の宣言を許さない」ものでは変数表の構成そのものも違うように思います。質問者さんがどの仕様を想定しておられるかにより妥当な方式もまたそれに従い違ったものになると思います。(ただ、本件についてはこの点を気にする以前のもっと根本的な話であるような気もします)

###変数表はいつまで必要になり得るでしょうか?
内部の作りの違いの例を挙げてみます。

情報はそれが必要とされる期間だけ存在してないと困ります。アクセスするにもかかわらずその前に消去してしまってはNPEなどの不具合が起きるのは当然ですよね・・・。まずいつまで必要なのか考えてみましょう。意味解析を終えたらコード生成の前に消してよいでしょうか?多分それはコンパイラーの作り方に依存していかようにも変わると思います。例えば意味解析の結果として生成する中間木が

[代入, 左辺値=変数a, 右辺値=[加算, 変数a, 定数1]]

みたいなものとして、コード生成時に変数表を用いて変数aのスタック上の位置を決定するといった方法も考えられます。そういう場合は変数表はコード生成まで必要になるでしょう。一方

[代入, 左辺値=スタック(offset=0,type=int), 右辺値=[加算, スタック(offset=0,type=int),定数1]]

のようにすると変数表はコード生成では必要とならないでしょう。上記の中間木をあるブロックの中の全ての文について生成したら変数表はもはや必要ないのでその時点で消去してもかまわないと思います。

最初に戻ります。変数表はいつまで必要でいつ消すべきでしょうか?。それは上に書いたような設計に左右されますがどちらの設計方法でもコンパイラーは作れますので、いつ消すべきかもそれに応じて変わります。


はっきりとは言えませんが。ソースファイル全体を構文解析する際に変数表を作っておられるとしたら、そうせずに意味解析時に変数表を作るという手もあると思います。しかし・・・Cの構文上「識別子が関数名なのか変数名なのか」がわからないと構文解析ができない部分があるかも知れませんね。その場合は構文解析時に変数表を作らざるを得ないでしょう。ただどちらにしても意味解析前に構文解析の時点で}をパースした際には、ローカル変数表を単に消すのではなく、ローカル変数が定義された関数の情報として保持しておくべきではないかと思います。

投稿2018/01/14 15:00

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2018/01/15 00:32

> Cの構文上「識別子が関数名なのか変数名なのか」がわからないと構文解析ができない ではなく「typedef名かどうか」がわからないと構文解析ができないところがあったような気がします。変数表というより他の識別子の表の話になるかもです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問