JavaでC言語の簡単なコンパイラを作成中なのですが、局所変数の記号表への登録について困っています
字句解析→構文解析→意味解析→コード生成の順です
{}からでたら消去するというのはわかるのですが、そうすると意味解析で記号表に局所変数の情報が存在していないのでNullPointerを吐かれてしまいます。
詳しい方御指南をお願い致します。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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
総合スコア18394
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/01/15 00:32