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

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

新規登録して質問してみよう
ただいま回答率
86.02%
コンパイラ

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

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Q&A

解決済

コンパイラ(Pl’0)

gorizo2
gorizo2

総合スコア1

コンパイラ

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

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

1回答

0グッド

1クリップ

312閲覧

投稿2022/11/24 03:20

編集2022/11/24 07:28

visualstudioでPL0コンパイラを編集しています。pl'0で新しくswich文を使用できるようにしようと思いコンパイラ編集しています。現在は下記のようにプログラムを変更したのですが、値が一致しているcaseのみ実行する方法が思いつきません。コンパイルはできる状態なので、未定義のエラーなどではなさそうです。わかる方いらっしゃいましたら教えていただきたいです。
出典 : 中田育男氏のホームページ > コンパイラ > PL0'コンパイラのソースリスト
http://www.k.hosei.ac.jp/~nakata/oCompiler/PL0compiler/prog_proc1.html
http://www.k.hosei.ac.jp/~nakata/oCompiler/PL0compiler/compile.c

現段階のプログラム
case Switch:
token = nextToken();
expression(); /式のコンパイル/
a = genCodeR();
backP2 = nextCode();
token = checkGet(token, Case );
token = nextToken();
expression();
b = genCodeR();
if (a == b) {
token = nextToken();
statement();
}
else {
token = nextToken();
genCodeV(jmp, backP2);
}
if (token.kind == Ret) {
statement();
return;
}
else {
token = nextToken();
}

実行するpl'0ファイル
function multiply(x,y)
var a,b,c;
begin
a:=x; b:=y; c:=0;
switch a+1
case 1; c:=a+b;
case 2; c:=a-b;
return c;
end;

const m=1,n=2;
var x,y;

begin
x:=m; y:=n;
writeln; write multiply(x,y); writeln
end.

現在のエラー状況
イメージ説明

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

otn

2022/11/24 05:48

中田さんのお名前が誤記です。
gorizo2

2022/11/24 07:28

すみません。ご指摘ありがとうございます。
actorbug

2022/11/24 14:19 編集

質問の「現段階のプログラム」を追加するだけだと、a,b,Switch,Caseの定義が無いのでコンパイルできません。こちらで適当に補って実行してみましたが、「現在のエラー状況」にあるようなエラーは起こらずに「2」を表示して正常終了しました。エラーを再現するために、元のソースからの改変部分をすべて質問に載せてもらえないでしょうか。 あと、実装しようとしているswitchの構文規則を明示してもらえませんか。明らかにC言語のswitchと構文が違うため、どう書くのが正しいのかわかりません。
actorbug

2022/11/24 20:40

質問にコードを記述する場合は、「コードの挿入」ボタンを使用してください。そのまま張り付けると、インデントや一部記号が消えるので見づらいです。 具体的な方法については、以下の質問を参照してください。(「コードの挿入」ボタンの見た目が「<code>」から「</>」に変わっているので注意) https://teratail.com/questions/238564
gorizo2

2022/11/25 02:04

どのように補って『2』を表示して正常終了したのでしょうか?
actorbug

2022/11/25 14:17 編集

getsource.hのkeys内のend_of_KeyWd,の前にSwitch,Case,追加 getsource.cのKeyWdT[]内の{"$dummy1",end_of_KeyWd},前に{"switch",Switch},{"case",Case},追加 compile.cのstatement()の先頭にint a, b;を追加 compile.cのstatement()内のswitch内に「現段階のプログラム」コピペ 動作が違うということは、質問に書いていないコードに問題があるということです。 エラーを再現するために、元のソースからの改変部分をすべて質問に載せてもらえないでしょうか。(2回目)

回答1

0

ベストアンサー

「現段階のプログラム」を見る限り、まだ新たな構文を実装するには理解が足りないように見えます。

if (a == b) {というコードを書いていることから、「目的コードを生成するコード」と「生成される目的コード」の区別がついていないのではないでしょうか。「生成される目的コード」で比較を行いたいはずなのに、これだと「目的コードを生成するコード」で比較を行ってしまっています。まずは、この区別がつくとこまろで学習を進めることをお勧めします。

それができたら、次は単純なコードの書き換えを実装できるようになりましょう。例えば、switch文もcaseが1つだと確定していれば、単純なif文に書き換えられます。あとは、switchを読み込んだ際に、このifと同じ目的コードを生成できれば、実装できたことになります。

switch a+1 case 1; c:=a+b; end

if a+1=1 then c:=a+b

ここまできてようやく、caseが複数の場合にどのように実装するかを検討できる段階になります。


まずは、switchの構文規則を決めておきましょう。WikipediaのPL/0を参考に、以下のようにEBNFで定義してみます。switchがどこで終わるか分からないと不便なので、最後にendを記述するルールとしておきます。

switch_statement = "switch" expression {"case" expression ";" statement ";"} "end"

次に、どのように実装するか考えましょう。以下の文を考えます。

switch a+1 case 1; c:=a+b; case 2; c:=a-b; end

とりあえず、elseを実装したif文の繰り返しに変換できればよさそうです。

if a+1=1 then c:=a+b else if a+1=2 then c:=a-b

ただ、これだとa+1が複数回現れるので、現状の構文解析器で実装するのは困難です。そこで、こっそり関数内関数$switchを定義して、それを呼び出す形にしてみましょう。(ユーザが定義不可な名前にして、ユーザ定義関数とのバッティングを防止する)

function $switch($n) if $n=1 then begin c:=a+b; return 0 end else if $n=2 then begin c:=a-b; return 0 end else return 0; $switch(a+1)

最後の$switch(a+1)にて、関数を呼び出して戻り値を無視するようなことをやらなければなりませんが、関数を呼び出した後で、目的コードとしてict -1を生成すれば可能です。(本来の使い方とは異なりますが)

あとは、こちらと同じ結果となる目的コードを生成できれば、現状の枠組みの中でもswitchを実装できます。

・・・というわけで、switchの実装はけっこう難易度が高いです。ほかにも、こっそりa+1保存用の変数を追加する、目的コードの種類を増やすなどの方法もありますが、どちらにしろ難しいのは変わりません。

投稿2022/11/25 22:38

編集2022/11/26 03:46
actorbug

総合スコア1767

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

同じタグがついた質問を見る

コンパイラ

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

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。