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用のマシン語ファイルを作成可能です。