川合のプログラミング言語自作のためのテキスト第三版#9a

(1) HL-9a

#include <acl.c>

typedef unsigned char *String;	// こう書くと String は unsigned char * の代用になる.

int loadText(String path, String t, int siz) → HL-4と同じなので省略

///////////////////////////////////////////////////////////////////////////////

#define MAX_TC  1000 // トークンコードの最大値.
String ts[MAX_TC + 1]; // トークンの内容(文字列)を記憶.
int tl[MAX_TC + 1]; // トークンの長さ.
unsigned char tcBuf[(MAX_TC + 1) * 10]; // トークン1つ当たり平均10バイトを想定.
int tcs = 0, tcb = 0;

AInt var[MAX_TC + 1];	// 変数.

int getTc(String s, int len) → HL-8aと同じなので省略

///////////////////////////////////////////////////////////////////////////////

int isAlphabetOrNumber(unsigned char c) → HL-2と同じなので省略

int lexer(String s, int tc[])
{
    int i = 0, j = 0, len; // i:今s[]のどこを読んでいるか、j:これまでに変換したトークン列の長さ.
    for (;;) {
        (中略)
        } else {
            printf("syntax error : %.10s\n", &s[i]);
            exit(1);
        }
+       if (strncmp(&s[i], "//", 2) == 0) {	// コメント.
+comment:
+           while (s[i] != 0 && s[i] != '\n')
+               i++;
+           continue;
+       }
+       if (len == 7 && strncmp(&s[i], "include", 7) == 0) goto comment; // include をコメント扱いする(=無視する).
        tc[j] = getTc(&s[i], len);
        i += len;
        j++;
    }
}

int tc[10000];	// トークンコード.

enum { TcSemi = 0, TcDot, TcWiCard, Tc0, Tc1, Tc2, Tc3, Tc4, Tc5, Tc6, Tc7, Tc8, TcBrOpn, TcBrCls, TcSqBrOpn, TcSqBrCls, TcCrBrOpn, TcCrBrCls,
    TcEEq, TcNEq, TcLt, TcGe, TcLe, TcGt, TcPlus, TcMinus, TcAster, TcSlash, TcPerce, TcAnd, TcShr, TcPlPlus, TcEqu,
    TcComma, TcExpr, TcExpr0, TcTmp0, TcTmp1, TcTmp2, TcTmp3, TcTmp4, TcTmp5, TcTmp6, TcTmp7, TcTmp8, TcTmp9 };

char tcInit[] = "; . !!* 0 1 2 3 4 5 6 7 8 ( ) [ ] { } == != < >= <= > + - * / % & >> ++ = , !!** !!*** _t0 _t1 _t2 _t3 _t4 _t5 _t6 _t7 _t8 _t9";

///////////////////////////////////////////////////////////////////////////////

int phrCmp_tc[32 * 100], ppc1, wpc[9], wpc1[9]; // ppc1:一致したフレーズの次のトークンをさす, wpc[]:ワイルドカードのトークンの場所をさす.

int phrCmp(int pid, String phr, int pc) → HL-7と同じなので省略

///////////////////////////////////////////////////////////////////////////////

typedef AInt *IntP; // こう書くと IntP は AInt * の代わりに使えるようになる.

enum { OpCpy = 0, OpCeq, OpCne, OpClt, OpCge, OpCle, OpCgt, OpAdd, OpSub, OpMul, OpDiv, OpMod, OpAnd, OpShr, 
    OpAdd1, OpNeg, OpGoto, OpJeq, OpJne, OpJlt, OpJge, OpJle, OpJgt, OpLop, OpPrint, OpTime, OpEnd,
!   OpPrints, OpAryNew, OpAryInit, OpArySet, OpAryGet, OpOpnWin, OpSetPix0, OpM64s, OpRgb8, OpWait,
+   OpXorShift, OpGetPix, OpFilRct0, OpPrm, OpF16Sin, OpF16Cos, OpInkey, OpDrwStr0, OpGprDec, OpBitBlt };

IntP ic[10000], *icq; // ic[]:内部コード、icq:ic[]への書き込み用ポインタ.

void putIc(int op, IntP p0, IntP p1, IntP p2, IntP p3) → HL-6と同じなので省略

///////////////////////////////////////////////////////////////////////////////

char tmp_flag[10]; // 一時変数の利用状況を管理.

int tmpAlloc() → HL-7と同じなので省略

void tmpFree(int i) → HL-7と同じなので省略

///////////////////////////////////////////////////////////////////////////////

int epc, epc1;	// exprのためのpcとpc1.

int exprSub(int priority);	// exprSub1()が参照するので、プロトタイプ宣言.
int expr(int j);
int phrCmpPutIc(int pid, String phr, int pc, int *pi, int lenExpr, int op, int *err);

int exprSub1(int i, int priority, int op) → HL-7と同じなので省略

int exprSub(int priority) → HL-9と同じなので省略

int expr(int j) → HL-7と同じなので省略

///////////////////////////////////////////////////////////////////////////////

enum { IfTrue = 0, IfFalse = 1 };

void ifgoto(int i, int not, int label) → HL-8と同じなので省略

int tmpLabelNo;

int tmpLabelAlloc() → HL-8と同じなので省略

#define BInfSiz		10

int binf[BInfSiz * 100], bd, lbd; // binf:block-info, bd:block-depth, lbd:loop-block-depth

enum { BlkIf = 1, BlkFor, BlkMain }; // BlkMainをHL-9aで追加.
enum { IfLabel0 = 1, IfLabel1 };
enum { ForLopBgn = 1, ForCont, ForBrk, ForLbd0, ForWpc01, ForWpc11, ForWpc02, ForWpc12 };

int phrCmpPutIc(int pid, String phr, int pc, int *pi, int lenExpr, int op, int *err) → HL-9と同じなので省略

///////////////////////////////////////////////////////////////////////////////

int compile(String s)
{
    (中略)
        } else if (phrCmpPutIc(28, "bitblt(!!***8, !!**0, !!**1, !!**2, !!**3, !!**4);",           pc, 0, 5, OpBitBlt,  &e0)) {
+       } else if (phrCmpPutIc(29, "printTime();", pc, 0, 0, OpTime, &e0)) { // time;と同じ(C言語っぽく書けるようにした)
+       } else if (phrCmp(30, "void aMain() {", pc)) {
+           bd += BInfSiz;
+           binf[bd] = BlkMain; // ただ認識しているだけで、なにもしてない.
+       } else if (phrCmp(31, "}", pc) && binf[bd] == BlkMain) {
+           bd -= BInfSiz; // ただコードブロックを閉じているだけ.
+       } else if (phrCmp(32, "#", pc)) { // 何もせずに無視.
+       } else if (phrCmp(33, "int", pc) || phrCmp(34, "AWindow", pc)) {
+           while (tc[pc] != TcSemi) // セミコロンまでを読み飛ばす.
+               pc++;
+           ppc1 = pc;
        } else if (phrCmp( 8, "!!***0;", pc)) {	// これはかなりマッチしやすいので最後にする.
            e0 = expr(0);
    (中略)
}

AWindow *win;
 
void exec() → HL-9と同じなので省略

int run(String s) → HL-6と同じなので省略

///////////////////////////////////////////////////////////////////////////////

void aMain() → HL-9と同じなので省略

(2) プログラム例 (HL-9aで実行できるプログラム)





(3) "tl9builtin.c"の中身

次回に続く

こめんと欄


コメントお名前NameLink

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS