オケゲム氏版 PL/0 改造バージョン(実験版) 本ファイルはオケゲム氏作の yacc + C による PL/0 インプリメンテーショ ンを修正して、若干の文法仕様を拡張し、処理系自身の機能仕様も若干変更 したものである。 【文法上の変更】 以下に文法上の拡張点を示す。 0)手続き及び関数(後述)に対して引数を使用可能。 仮引数は当該ブロックでローカルに宣言されたと同じ効果を有する。ロー カル変数との違いは、呼び出された時点での実引数の値を初期値として持っ ている点だけである。すべての実引数は値渡しである。したがって仮引数に 代入して値を書き換えることは許される。 ある手続き・関数の引数の個数は固定であり、可変個の引数を受け取るよう なことはできない。呼び出し時には正確に仮引数と同じ個数の実引数が指定 されていなければならない。 以下は引数を2つ受け取り、その和を表示する手続きの例である。PL/0 は モノタイプ言語なので仮引数の型を指定する必要はない。 procedure foo(a, b); begin print a + b end もちろん引数を持たない手続き/関数を宣言できる。その場合呼び出し時に は引数を囲む括弧は一切書かない(書いてはいけない)。 1)関数を追加した。 手続きのキーワード PROCEDURE の代わりに、FUNCTION を用いて定義する。 以下は与えられた引数の2倍の値を返す関数宣言の例である。PL/0 はモノ タイプ言語なので仮引数と同様に、関数の戻り値型を指定する必要はない。 なお、引数無しの関数も宣言可能である。 function bar(n); begin bar := n * 2 end 関数のソース内での戻り値の指定は、Pascal と同様、自らの関数名に代入 する事で行うものとした。関数の本体では、自分自身の関数名に代入可能で ある事を除けば、その他の機能は実質的に手続きと同じである。 関数の中で戻り値を設定しているかどうかはチェックしていない。もし戻り 値を特に指定しない場合には 0 が戻される。 2)IF 文に(省略可能な)ELSE 節を追加した。 構文は Pascal に準じる。 3)REPEAT - UNTIL 文を追加した。 構文は Pascal に準じる。 4)FOR 文を追加した。 構文は Pascal に準じる。制御変数は単純な変数かもしくは仮引数として 予め宣言されていなければならない。初期値式と終値式はループを開始する 前に1度だけ評価される。従って終値式の値を変えるような作業をループ本 体で行ってもループ回数には影響は生じない。ループを終了した時点での制 御変数の値は公式には不定であるとする(現バージョンでは「使わなかった 最初の値」を保持しているが、将来の拡張の伏線として)。 5)PRINT 文の機能を拡張した。 PRINT 文を実行すると通常は出力の後で改行が行われるが、キーワード PRINT の直後に「!」を置くことでこれを抑制することができる。 PRINT の オペランドには任意の数の式を「,」で区切って書く事ができる。式を全く 書かずに PRINT だけでも構わない。その場合には単に改行が行われるされ る。 各々の式の値は、特に指定しないと空白を一つ出力した後に左詰めで出力さ れるが、式の後に「:」ともう一つの式を指定する事で出力幅を指定するこ とが可能。その場合には幅指定が正の値であれば右詰め出力、負の値であれ ばその幅を確保したうえで左詰め出力となる。ただし、実際に必要な出力幅 が指定された幅よりも大きい場合には、幅指定は無視される。 1) PRINT 2) PRINT x, y, z 3) PRINT x:5, y, z:n 4) PRINT! w * 3:k + 2 上記の例ではそれぞれ次のように出力が行われる。 1)改行のみ行う。 2)x, y, z の値を左詰めで順次出力の後改行する。 3)x の値を 5 桁右詰めで、y の値を左詰めで、z の値を n の値 の桁で右詰めして出力し改行する。 4)w * 3 の値を k + 2 の幅で出力するが改行は行わない。 6)配列変数を追加した。 通常の変数に加えて、配列変数を許すことにした。通常の変数と同じくキー ワード VAR を用いて宣言する。次のように通常変数と混在させて宣言して もよい。 var a, b[10], c, d[20]; 宣言時には整定数もしくは CONST 宣言された識別子を用いて配列のサイズ (要素数)を指定する。添字は常に 0 から割り当てられるので、最大の添 字は size - 1 までである。 例: var b[10]; の場合、用意される配列要素は b[0] 〜 b[9] までである。 処理系上の制約から配列には「宣言可能な最大サイズ」が存在するが、これ は文法上は規定しないし、現在の PL/0 処理系ではこの制限に関してはチェッ クしていない。このため制限を越えるサイズの配列を取った場合の結果は保 証しない。 一方、配列の添字の値が宣言したサイズを越えていないかどうかのチェック は実行時に行っている。もし添字の値が許される範囲の外にあれば、エラー メッセージとプログラムカウンタの値を表示して、即座に PL/0 プログラム の実行を中止する。 配列全体を実引数として手続きや関数に渡すことはできない。また、仮引数 部分で配列変数を宣言することはできない(今後の検討課題か?)。しかし、 配列は各ブロックにおいて宣言することができる。このため、手続きや関数 の内側でローカルな配列を宣言することは許される。スコープルールなどは 通常の変数に準じる。 7)コメントを許容する コメントは (* で始まり *) で終わるものとする。文法上はコメントは空 白と同じ扱いである。 * * * 【処理系の変更】 次に処理系(コンパイラ・インタープリタ系)自身も少し変更を加えた。 コマンド pl0 は以下の構文で起動する。 pl0 [-c -s -x] [file] 1)入力ファイル ソースファイルをリダイレクトではなく、コマンドの引数としても指 定可能。ただし高々1つしか指定できない。2つ以上指定した場合、 2つめ以降は無視される。また無指定の場合 stdin を読み込むので、 従来同様リダイレクトを用いる事も可能。 2)コマンドライン・フラグ 以下のフラグを設けた。 -c コンパイル後のコードを表示する。 -s 入力ソースを表示する。 -x コンパイルが成功したら実行する。 ただし、オリジナルとのコンパチビリティを維持するため、何もフラ グを指定していない場合には -csx が指定されたものと見なす。 3)ソースの表示形式の変更 ソースファイルは行番号付きで表示される。 * * * 【仮想マシンの変更】 注:本節は純粋にテクニカルな内容であり、ユーザとして PL/0 を使う場 合には気にする必要はない。 文法上の拡張機能のいくつかをサポートするため、若干仮想マシンに改造 を施している。ここではそれについて述べる。これはコンパイラが作りにく いと仮想マシンのアーキテクチャを拡張するという、非常に安易な改造者 (きだ)の姿勢を良くしめしている。 1)サブルーチンリターン命令(f_ret) オリジナルではリターン命令は汎用機能命令 f_opr の一種として実装さ れていたが、本バージョンでは f_ret として独立させた。手続き/関数へ の引数の導入に伴い、引数として渡された領域を捨て去って呼び出し側に戻 る命令が存在すると便利なためである。f_ret の addr の値がこの捨て去る べき領域のワード数を指定するために用いられる。addr は非負の数でなけ ればいけない。なお level フィールドは現在未使用。 2)PRINT 命令(f_prt) リターン命令と同様に、v_prt を f_prt へと変更した。こちらは level フィールドによって次の3つの機能を行う。なお、addr フィールドは未使 用。 level 0 改行を出力する。スタックデータは消費しない。 1 スタックトップを十進左詰め出力する。 2 スタックセカンドの値をそのスタックトップの幅で十進右 詰め出力する。実際に必要な幅がスタックセカンドの値よ りも大きい場合には実際の幅だけ出力する。 3)配列要素参照命令(f_ldx) スタックトップの値を添字であるとして、level と addr で指定された配 列を参照する命令である。スタックトップの添字値は消費され、代わりにそ こにロードした値が格納される。この命令では添字の範囲チェックは行わな い。 4)配列要素格納命令(f_stx) スタックセカンドの値を添字であるとして、level と addr で指定された 配列へとスタックトップの値を格納する命令である。スタックトップの値と スタックセカンドの添字値は消費される。この命令では添字の範囲チェック は行わない。 5)配列範囲チェック命令(f_chk) 現在スタックトップに積まれている値(stack[sp])に対して、 level <= stack[sp] < addr を満たしているかどうかをチェックする。条件が満たされていれば次の命令 の実行へと移る。条件が満たされていない場合には例外を発生し、プログラ ムの実行を中断する。仮想マシンの機能としてこの例外を無視する手段はな い。 6)スタックトップの複製命令(f_dup) for 文のサポートのために設けた。ループの終値を示す式を評価後、スタッ クトップに「溜めて」置く。ループ本体の実行直前に f_dup で複製して制 御変数の値と比較する。 7)スタックトップの破棄命令(f_drp) for 文のサポートのために設けた。for が終了したときに終値の値を捨て るために用いる。 【改造者】 きだ あきら SDI00379 @ NIFTY-Serve akida @ 日経 MIX pcs32370 @ ASCII-Net AMF44721 @ PC-VAN 【著作権】 本ソフトウェアはオケゲム氏によって作られ、Public Domain 宣言された ものである。また、きだは、自分の改造部分の著作権を放棄する。したがっ て本ソフトウェアは全体としてやはり Public Domain である。 【免責】 勝手ながら、このプログラムを使用したことによる結果等について作者 (原作者であるオケゲム氏および改造者である、きだ)は責任を負いかねま す。特段の悪意を持っていないことだけは確かですが、あくまで使用者の責 任において利用して下さい。 とくに現在のバージョンにはバグが多く含まれているかもしれないことを お断りしておきます 【原リリースの read me】 以下の文章はオリジナルリリースに付属していたものです。 ------------------------------------------------------ 1.このアーカイブの内容 このアーカイブには、yaccで記述したPL/0処理系のソースがおさめて あります。処理系はコンパイラとインタプリタからなります。 アーカイブの圧縮率を高めるために、二重にアーカイブされています。お手数 ですが、_PL0.LZH を解凍してお使い下さい。 2.言語仕様 N.Wirth の名著+=[*1]に掲載されているPL/0言語の仕様にほぼ準拠して います。異なる点のみを下記に列挙します。 (1)オリジナルのPL/0は手続き本体は任意の文を記述できるが、オケ ゲム版では複文(begin 〜 end)のみが記述できる。これは、誤りか らの復帰を簡単に行えるようにする都合。 (2)オリジナルのPL/0には出力文はなく、その代わりに第入文の結果 を印字するようになっているが、オケゲム版では、print 文を設け、 第入文で表示を行わないようにした。 【例】 print a; aの値を表示する (3)言語仕様の変更というほどのものではないが、% をソース内に記述す ると、その時点のシンボルダンブを表示するようにした。% 自体は空 白として扱われる。 3.使用法 適当なファイル名でPL/0のソースを作成して下さい。例えばソースファイ ルが foo.pl0 という名前だとすると、 A>pl0 pl0 とリダイレクトしないで起動することもできます。この場合は、PL/0のプロ グラムをキー入力することになります。 4.コンパイルの方法 添付のメイクファイルは下記の開発ツールを前提としています。 MS−DOSでのコンパイル LSI C Ver3.3 または Turbo C Ver2.0 または Turbo C++ Ver1.01 kmyacc make (LSI C 付属のものまたは Borland のもの ) UNIXでのコンパイル cc(pcc)またはgcc yacc(OS添付のもの) make(OS添付のもの) LSI C を使用される場合は makefile.lcc を、Turbo C を使用される場合は makefile.tcc を、UNIXの場合は makefile.uni を、それぞれ makefile と いう名前にリネームして使用して下さい。また、makeとしてkmyaccを お使いの場合は、コンパイル時に yaccpar.c がカレントディレクトリになけれ ばなりません。このファイルは、kmyacc に同梱されています。 ほぼANSI規格あるいはオールドファッションのC言語の範囲で記述してい ますので、他のコンパイラ等に移植するのは容易だと思います。ANSI規格に ない機能として、strdup() 関数を使っています。strdup() が処理系に用意され てない場合には、下記のようにして容易に作成することができます。 char *strdup(s) char *s; { char *p; p = malloc(strlen(s) + 1); if (p != NULL) strcpy(p, s); return p; } プロトタイプ宣言のありなしを定義済みマクロ __STDC__ によって切り換えて います。プロトタイプ宣言はサポートしているが、__STDC__ が定義されないコ ンパイラ(LSI C-86 など)では、明示的に __STDC__ を指定して下さい。 makefile.lcc にはこの指定が含まれています。 unixとMS−DOSでは、yaccの生成するヘッダファイル名が異なり ます。このために、定義済みマクロ MSDOS によってこれらを区別しています。 MS−DOS上で、マクロ MSDOS が定義されないコンパイラを使用される場合 は、MSDOS を明示的に定義して下さい。添付の makefile には、この指定が含ま れています。 5.著作権・免責等 このプログラムは、N.Wirth の決めたPL/0の仕様を元にオケゲムが作成し ました。 このプログラムに関する著作権はすべて放棄します。 また、勝手ながら、このプログラムを使用したことによる結果等については、 作者は責任を負いかねますので、使用者の責任において利用して下さい。 とくに現在のバージョンにはバグが多く含まれているかもしれないことをお断 りしておきます [*1] N.Wirth 著、片山訳、アルゴリズム+データ構造=プログラム、日 本コンピュータ協会、1979、6000円 ocheghem /松田晋(日経MIX ockeghem NIFTY−Serve QGB01521 PC−VAN LFA60821)