alpha version から beta version へ
古い「ウルトラマンPC」のコンパクトフラッシュから発掘したファイルです。
ちょうど良いので、こいつも完成させます。
まず、ドキュメントからです。「完全な仕様書」にすることと、書式をHTML書式としなきゃですね。
以下どうぞ。
1360用クロスコンパイラ
TNKB Ver 1.01
Beta version.
【著作権について】
・このプログラムの著作権は作者である綿貫克が保持します。
・このプログラムを使用して起こるいかなる損害も作者は責任を負いません。
・個人使用の範囲内であれば改変は自由です。
0.初めに
SHARP PC-1360 のゲーム作成ツールといえばすぐに「TYコンパイラ」が思い浮かびます。しかし、その「TYコンパイラ」も、使っているうちに以下の改善要望を持ちました。
a) 文法エラー時には、メッセージを出力してコンパイルを中止して欲しい。
b) 変数の扱いや文法をBASICに近いものにして欲しい。
では、「TYコンパイラ」を改造すべきでしょうか?
しかし、それに手を加えるのは容易な事ではありませんでした。
そこで、私はクロスコンパイラを独自に開発しました。
本プログラムは再帰降下型の構文解析という技術を基に作成されました。
私はこの技術の習得におおよそ4年係りました。
それだけに喜びもひとしおです。
1.使用方法
1.1 準備
TnkBを使用するためには以下の準備が必要です。
1) パソコンと1360およびこれを接続する通信アダプタとクロスケーブル
2) TYコンパイラのランタイムルーチン RUNTIME.OBJ
3) 1360用マシン語ファイル転送ソフト BINRS.EXE および BINRX.OBJ
4) 1360用クロスアセンブラ TNKASM.EXE
5) 1360用クロスコンパイラ TNKB.EXE および RUNTIME.H
1360とパソコンを通信アダプタを介してクロスケーブルで接続します。
通信アダプタは純正品のCE−130Tがありますが ORANGE氏の考案された
「レベルダウンコンバータ」を用いることができます。
BINRSをダウンロードし、DOCファイルの説明に従って1360に
BINRXをロードして下さい。もちろんパソコン側にもBINRSを準備
しておきます。
TYコンパイラの”RUNTIME.OBJ”を1360にロードして下
さい。”RUNTIME.OBJ”がない場合コンパイラで作成したマシン
語プログラムは動作できません。(暴走します。)
TYコンパイラは工学社「PIOスペシャル3」にて発表されました。
1360友達から手にいれましょう。どうしても入手できない時は相談にの
ります。
1.2 TnkBの開発フロー
TnkBを用いたプログラム開発は以下の様に行われます。
(Start)
!
(Editor) <----+ エディット : Word Masterなどを用いてTnkCのソースを作成
! !
! Error !
( TnkB )------ + コンパイル : TnkBを用いてアセンブラファイルに変換
!
!
(TnkAsm) アセンブル : TnkAsmを用いてバイナリファイルに変換
! (*1)
!
( BINRS ) ロード : BINRSにより1360に転送
! (*2)
!
( End )
*1
TnkAsmは1360用クロスアセンブラです。詳細についてはTnkAsmを参照し
てください。(;BBSPREにアップロードしてあります。)
*2
BINRSはRev氏作成の1360用通信ソフトです。詳細についてはBINRSドキュメントを参照してください。(;BBSSHARPにアップロードされております。)
1.3 コンパイルの方法
コマンドラインに以下のように入力します。
拡張子を省略すると ファイル名 .TNK が仮定されます。
TNKB ファイル名 [ .拡張子 ]
TNKBは、ファイル名で示されるソースをコンパイルし、ファイル名.ASCとい
うファイルを作成します。生成されたファイルはそのままではPC-1360Kで
は使用出来ません。
1.4 バイナリファイルの作成。
1360で使用するためには別にTNKASMを用いてバイナリファイルを
作成する作業が必要です。コマンドラインに以下のように入力してください。
TNKASM ファイル名
これにより、ファイル名.OSC というバイナリファイルが作成されました。
PC-1360 に転送するには BINRS を使用します。転送の方法は BINRS の ドキュ メントファイルをご参照下さい。
2.文法
TnkBのソースは以下のような形をしています。
【 TnKBのソース(例) 】
10 FOR A=0 TO 10
20 PRINT A
30 NEXT A
40 END
文には一行毎に行番号があり、一行は複数のステートメントから構成さ
れています。
【 制限 】
TnkBソース中に全角文字やタブ記号を入れてはいけません。
字句解析手続きが無限ループします。
2.1 扱えるデータ
データは1バイトの大きさを持ち、以下の種類があります。
正の整数
・10進数 1バイトの符号なし整数です。
例 10
・16進数 &で始まる1バイトの符号なし整数です。
例 &1A
文字 ”で囲まれた1バイトの文字コードです。
例 "X"
2.2 変数
変数はデータを格納しておく入れ物で、以下の種類があります。
・単純変数
単純変数は英文字から始まる英数字8文字までの名前を持ちます。
変数には正の整数と文字変数があり、$記号により区別をします。
正の整数:0〜255までの範囲の数を記憶している変数です。
文字変数:1バイトの文字を記憶している変数です。
例 TANUKI 正の整数用の単純変数
MAN 同じく
COMPILER 同じく
C3PO$ 文字用の単純変数
R2D2$ 同じく
単純変数はプログラムに登場する順に内部RAMに一つずつ割り
当てられます。
・配列変数
配列宣言により、配列変数を使用することが出来ます。
単純変数と同じく1バイトの数値を記憶するためのものですが、配列
変数の場合には変数を表のように扱うことができます。
配列変数も英文字から始まる英数字8文字までの名前を持ちます。
配列変数は宣言順に連続して内部RAMに割り当てられますが、
単純変数と配列変数を合計27個以上内部RAMに割り当てようとす
るとコンパイルエラーとなります。
2.3 式
演算は正の整数どうしに限られ、変数および定数の加減乗除、AND
OR、それに関係演算ができます。
【とても残念ですが文字列の加算は出来ません。】
例 A$ = "ABCD" + "EFGH" …これはNGです。
・正の整数どうしの加減乗除:桁溢れは無くなります。
例えば5+251の値は0になります。
演算記号はBASICと同じです。
例 TERM = FACTOR + FACTOR
・ANDとOR :BASICと同じです。
例 LOWCASE = UPCASE AND 16
・関係演算 :条件成立時255、不成立時に0になります。
演算記号は=,>=,<=,<>です。
例 CARRY = (A >= B)
・演算の優先順位
順位1.AND及び×
順位2.OR及び+
順位3.関係演算
2.4 関数
TYコンパイラと同じ関数をサポートしています。
ASC関数 文字のアスキーコードを得る。
例 A = ASC(B$)
CHR$関数 式の値をアスキーコードとする文字を得る。
例 B$ = CHR$(A+3)
INKEY$関数 キー入力された文字を得る。
例 K$ = INKEY$
POINT関数 グラフィックパターンを得る。
例 PATTERN = POINT(BEAMX , BEAMY)
RND関数 0から式の値までの範囲で乱数を得る。
例 XPOS = RND(4) 0から4までの乱数を得る。
ルート関数 平方根を得る。(但し、結果は正の整数)
例 ROOT = SQRT(4)
2.5 ステートメント
TYコンパイラに加えて、新しくFOR文とNEXT文、およびDIM
文とREM文をサポートしました。
さらに、IF文はLETやTHENの後にマルチステートメントを書く
ことができ、BASICに近い感覚でプログラムすることができます。
以下ABC順に説明します。
BEEP文 音楽を鳴らします。
BEEP ON 演奏の許可
BEEP OFF 演奏の禁止
BEEP "CDEFGAB" ドレミファソラシド
CLEAR文 内部RAMを全てクリアします。
CLEAR
CLS文 画面表示を消します。
CLS 全画面を消します
CLS n (n=0..3) n で示す行を消します。
CURSOR文 文字を表示する位置を決定します
CURSOR 3,3
DATA文 データテーブルを作成します。
DATA 10,11,13,14
END文 プログラムを終了します
END
GCURSOR文 グラフィックのカーソル位置を決定します
GCURSOR(10,10)
GOSUB文 サブルーチンを呼び出します。
GOSUB 210
GOTO文 プログラムの流れを無条件に変更します。
GOTO 10
GPRINT文 グラフィックパターンを表示します。
GPRINT "0123456789ABCDEF"
IF文 プログラムの流れを式の値に応じて変更します。
IF A>10 LET A = 10
IF (A=10) AND (B = 20) THEN PRINT A+B:GOTO 320
INPUT文 キー入力を行い、結果を文字変数に格納します。
INPUT A$
PRESET文 グラフィックカーソル位置の1ドットを消去します。
PRESET(STARX,STARY)
PRINT文 文字カーソル位置に文字を表示します。
PRINT "Hello, SC!"
PSET文 グラフィックカーソル位置の1ドットを表示します。
PSET(STARX,STARY)
READ文 データをDATA文で確保したテーブルから読みだします。
RESTORE文をあらかじめ実行する必要があります。
READ X,Y
RESTORE文 データテーブルの読みだし準備を行います。
RESTORE 340
RETURN文 サブルーチンからメインルーチンに復帰します。
RETURN
USING文 数値の表示方法を決定します。
USING 2 数値を2桁で表示
USING 3 数値を3桁で表示
USING USING指定の解除
WAIT文 プログラムのスピードをコントロールします。
WAIT n (n=0-255) nが多い程スピードが低下します。
WAIT プログラムを停止します。
インライン文 TnkBの出力ファイル中にマシン語プログラムを
展開します。
3.プログラム内容
TnkBは主に3つの手続きに分かれています。
字句解析手続き
式のコンパイル手続き
文のコンパイル手続き
3.1 字句解析手続き
Getchar手続き
ソースリストから文字を1つピックアップし、変数chに格納する。
但しソースリストはフリーフォーマット形式。
Getsymbol手続き
Getcharにより得た変数chが何かを調べる。
そのchによって以下の処理を行う。
< 空白:Space >
Ch が空白の時は読みとばす。
< 10進定数:Decimal >
Ch が数字の時<10進定数>とみなし、数字の続く限りGetchar
手続きを呼出し、chを読み続ける。
<10進定数>を変数 inum に格納する。
変数 Symbol には intliteral を返す。
< 文字定数:Letters >
Ch が記号”の時<文字定数>とみなし、次に記号”の来る限り読
み続け、文字列を変数Stringsに格納する。変数 Symbol はLetters
を格納する。
< 識別子:Identefier >
Ch が英数字の時に続く文字は<識別子>である
<ステートメント>の識別子であれば、その種類を字句の型へ返す。
その他のときは<関数>かもしれないので、文字列を変数 ID に格納
する。変数 Symbol にはIdentifierを格納する。
英字Aまたは英字Bの時<変数名>とみなす。続く文字が記号$の時は特に、<文字定数>であるとみなす。変数 SymbolはIdentifier。
さらに続く文字が記号(であれば、それは<配列変数>であるが字句解析では配列の添字まで言及しない。<因子>の解析において<配列の添字>::= (<式>)という構文を解析する。
< インライン展開 Inline statement >
Ch が !記号の時に続く文字はインライン展開用の文字である。その文字が0−9,A−Fである限りGetChar手続きにより読み取り、変数 Strings に格納。変数 Symbol は SyInline 手続きに渡す。
< 特殊記号 Others >
Ch が比較演算子などの特殊記号の時にはその種類を返す。
3.2 式のコンパイル手続き
3.2.1 概要
式のコンパイルは式の構文をプログラム化することにより実現出来
ます。
式の優先順位は以下のとおりです。
(式)または関数 > 関係演算 > 乗法演算 > 加法演算
2*3+4 は、まず乗法演算である 2*3を行い、続いて+4という加法演
算を行います。
3.2.2 手続きの仕様
<式>を以下のように定義します。
<式> ::= <単純式> <関係演算子> <単純式>
<単純式> ::= <項> { <加法演算子> <項> }
<項> ::= <因子> { <乗法演算子> <因子> }
<因子> ::= <定数> | <変数> | <関数> |(式)
Expression手続き
式の入口です。関係演算の続く限りここで処理を続けます。
Simpleexpression手続き
単純式の入口です。乗法演算の続く限り以下の処理を続けます。
因子の型チェック
因子同士を乗するオブジェクトを生成する。
Term手続き
項の入口です。加法演算の続く限り以下の処理を続けます。
因子の型チェック
因子同士を加算するオブジェクトを生成する。
Factor手続き
因子の種類に応じて以下の処理を行います。
定数 : Literal 定数の値を求める。
識別子 : Identifier 変数のアドレスを求める
左括弧 : LeftParen Expression手続きを呼び出す。
3.3 文のコンパイル手続き
3.3.1 概要
文をコンパイルするということもまた、BNF(バッカスナウア記法)によって定義された構文図をプログラム化することにより実現出来るのです。
3.3.2 手続きの仕様
<文>、<行>、<プログラム>を以下のとおり定義します。
<文> ::= <代入文>|<実効文>
<行> ::= <行番号><文>{:<文>}<改行>
<TNKCのプログラム> ::= <行>{<行>}<EOF>
Assignstatement手続き
代入文をコンパイルします。
<代入文> ::= <変数名>=<式>
先ず字句解析ルーチンからIdentifierが戻ってきたらそれは
<変数名>です。変数リストをチェックします。
次にSyeqが戻って来るはずです。Syeqが戻ってきたら、<式>
のコンパイル手続きを呼び出します。
式のコンパイル手続きは、結果をAレジスタに格納するオブ
ジェクトを生成するので<代入文>としてはAレジスタの内容
を変数にストアするオブジェクトを付加してあげればOKです。
ExecuteStatement手続き
<代入文>以外の文である<実効文>をコンパイルします。
<実効文>には非常にたくさんのバリエーションがあります。
そのため、文一つ毎に手続きが用意されています。
Statement手続き
文をコンパイルします。
文の種類を判別し、Assignstatement手続きまたはExecute-
Statement手続きを呼び出します。
Oneline手続き
行をコンパイルします。
行番号を行番号リストに登録し、<改行>がくるまでStatement
手続きを呼出しつづけます。
4.変更来歴
93.06.22 IF文の判断を誤るバグを修正した。
93.06.25 同一アドレスのラベルを出力する方法を EQU * に変更した。
93.06.28 コマンド名を TNKC より TNKB に変更。
93.10.26 IF文の構文を IF <式> THEN <文> に変更した。
93.10.28 USING文,RESTORE文の追加。
93.11.01 INLINE文の追加。
93.11.03 手続き Expression における PUSH の生成忘れを訂正した。
93.11.08 同 Expression における余計な PUSH の生成を抑止した。
01.
5.終わりに
今の所、TnkBは実用性が充分とはいえません。いくつかのバグも発見されています。今後バージョンアップを重ね、より確かな翻訳処理系して提供してゆく所存です。
開発中、ポケット通信では以下のかたにご指導頂き真に有難う御座いました。
M.Nakabayashi様
E.Kako様
さらには、バイナリ転送プログラムBINRSの使用を快諾戴いたRev氏に
感謝いたします。
本ソフトは BORLAND INTERNATIONAL 社の Turbo Pascal V7.0 で開発しました。
付録1 参考文献
近成人 「試作コンパイラの設計と実装」 PJ 工学社
疋田輝男 「コンパイラ」 昭晃堂
山口敏郎 「TYコンパイラ」 PIOスペシャル3 工学社
付録2 エラーメッセージ一覧
Syntax error. コマンド名の綴りが間違っている。
"(" expected. 括弧がない。
")" expected. とじ括弧がない。
"," expected. カンマがない。
NEXT is missing. FOR文に対応するNEXT文がない。
FOR is missing. NEXT文に対応するFOR文がない。
GOSUB is missing. RETURN文に対応するGOSUB文がない。
RETURN is missing. GOSUB文に対応するRETURN文がない。
DIM is missing. 配列宣言がない。
Bad expression. 式が間違っている。
Undefined lineno. 飛び先の行番号がない。
RESTORE is missing. RESTORE文がない。
Literal data over. 数値データが規定値を越えて使用されている。
付録3 TnkBのBNF図
−データ−
<文字> ::= <英大文字>|<英小文字>|<その他の記号>
<数> ::= 0|1|2|3|4|5|6|7|8|9
<英大文字> ::= A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
<英小文字> ::= a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z
<その他の記号> ::= π|<ルート> |*|/|+|-|!|"|#|$|%|&|'|(|)|^|¥|@|,|.|[|]
<ルート> ::= SQRT
<十進数> ::= <数>{<数>}
<マシンゴデータ>::= <M1><M1>{<M1><M1>}
<M1> ::= <数>|A|B|C|D|E|F
<十進定数> ::= <十進数>
<文字定数> ::= ”<文字>”
<変数> ::= <単純変数>|<配列変数>
<単純変数> ::= <英大文字>{$}
<配列変数> ::= <配列B>(式)
<配列B> ::= A|A$|B|B$
−式−
<加法演算子> ::= +|−|OR
<乗法演算子> ::= *|/|AND
<関係演算子> ::= =|<>|<=|>=|=>|=<
<式> ::= <単純式><関係演算子><単純式>
<単純式> ::= <項>{<加法演算子><項>}
<項> ::= <因子>{<乗法演算子><因子>}
<因子> ::= <定数>|<変数>|<関数>|(式)
<定数> ::= <十進定数>|<文字定数>
−関数−
<関数> ::= <ASC関数>|<CHR$関数>|<INKEY$関数>|<POINT関数>|<RND関数>|<ルート関数>
<ASC関数> ::=ASC<変数>
<CHR$関数> ::=CHR$<式>
<INKEY$関数> ::=INKEY$
<POINT関数> ::=POINT(<式>,<式>)
<RND関数> ::=RND<式>
<ルート関数> ::=<ルート><式>
−文−
<文> ::= <代入文>|<実行文>
<代入文> ::= <変数>=<式>
<実行文> ::= <BEEP文>|<CLEAR文>|<CLS文>|<CURSOR文>|<DATA文>|<END文>
|<GCURSOR文>|<GOSUB文>|<GOTO文>|<GPRINT文>|<IF文>|<INPUT文>
|<PRESET文>|<PRINT文>|<PSET文>|<READ文>|<RESTORE文>|<RETURN文>
|<USING文>|<WAIT文>|<インライン文>
<BEEP文> ::= BEEP|<BEEP2>
<BEEP2> ::= ε|<文字定数>|OFF
<CLEAR文> ::= CLEAR
<CLS文> ::= CLS
<CURSOR文> ::= CURSOR<式>,<式>
<DATA文> ::= DATA <定数>{,<定数>}
<END文> ::= END
<GCURSOR文> ::= GCURCOR(<式>,<式>)
<GOSUB文> ::= GOSUB<行番号>
<GOTO文> ::= GOTO<行番号>
<GPRINT文> ::= GPRINT<GPRINT2>
<GPRINT2> ::= ε|#<式>|<式>
<IF文> ::= IF<式><IF2>{:<文>}
<IF2> ::= LET<代入文>|THEN<実行文>
<INPUT文> ::= INPUT<INPUT2>
<INPUT2> ::= <変数>|<文字定数>;<変数>
<PRESET文> ::= PRESET(<式>,<式>)
<PRINT文> ::= PRINT(式)
<PSET文> ::= PSET(<式>,<式>)
<READ文> ::= READ<変数>{,<変数>}
<RESTORE文> ::= RESTORE<行番号>
<RETURN文> ::= RETURN
<USING文> ::= USING
<WAIT文> ::= WAIT<WAIT2>
<WAIT2> ::= ε|<式>
<インライン文> ::= !<マシンゴデータ>
−プログラム−
<行番号> ::= <行番号1><行番号2>
<行番号1> ::= 1|2|3|4|5|6|7|8|9
<行番号2> ::= <十進数>
<行> ::= <行番号><文>{:<文>}<改行>
<TNKBプログラム> ::= <行>{<行>}<EOF>
付録3 PC−1350への対応について。
RUNTIME.Hファイルに定義してあるエントリ番地を1350用に
改造することにより1350用のマシン語ファイルを作成可能です。