編譯器 cc0 -- 1.1 版

編譯器設計

編譯器簡介

高階語言

語法理論

剖析器

語意理論

符號表

直譯器

型態系統

中間碼

目標語言

最佳化

錯誤處理

進階議題

原始碼下載

程式實作

C 語言

案例研究

JavaScript

V8

Lua

Oberon

NeoPascal

pcc

tcc

gcc

C--

Lex

YACC

AntLR

LLVM

CLang

訊息

相關網站

參考文獻

最新修改

簡體版

English

檔案:cc0v1.1.zip

輸入檔:test.c0

int debug = 1;

int sum(int n) {
    int s=0;
    for (i=0; i<n; i++)
        s = s + i;
    return s;
}

int swap(int a, int b) {
    t = a;
    a = b;
    b = t;
}

int main() {
    int x=3, y=5, z;
    if ((x+y)>6)
        z = 0;
    else
        z = 1;

    int i=0, s=0;
    while (i<10) {
        s = s + i;
        i++;
    }

    int total=sum(10);
    =swap(x, y);
}

編譯執行

D:\oc\cc0\v1.1>gcc scanner.c cc0lib.c -o scanner

D:\oc\cc0\v1.1>scanner test.c0
token=int      tag=ID       kind=1,TYPE     line=1
token=debug    tag=ID       kind=3,VAR      line=1
token==        tag=OP       kind=4,NONE     line=1
token=1        tag=INTEGER  kind=4,NONE     line=1
token=;        tag=OP       kind=4,NONE     line=1
token=int      tag=ID       kind=1,TYPE     line=3
token=sum      tag=ID       kind=3,VAR      line=3
token=(        tag=OP       kind=4,NONE     line=3
token=int      tag=ID       kind=1,TYPE     line=3
token=n        tag=ID       kind=3,VAR      line=3
token=)        tag=OP       kind=4,NONE     line=3
token={        tag=OP       kind=4,NONE     line=3
token=int      tag=ID       kind=1,TYPE     line=4
token=s        tag=ID       kind=3,VAR      line=4
token==        tag=OP       kind=4,NONE     line=4
token=0        tag=INTEGER  kind=4,NONE     line=4
token=;        tag=OP       kind=4,NONE     line=4
token=for      tag=ID       kind=0,KEY      line=5
token=(        tag=OP       kind=4,NONE     line=5
token=i        tag=ID       kind=3,VAR      line=5
token==        tag=OP       kind=4,NONE     line=5
token=0        tag=INTEGER  kind=4,NONE     line=5
token=;        tag=OP       kind=4,NONE     line=5
token=i        tag=ID       kind=3,VAR      line=5
token=<        tag=OP       kind=4,NONE     line=5
token=n        tag=ID       kind=3,VAR      line=5
token=;        tag=OP       kind=4,NONE     line=5
token=i        tag=ID       kind=3,VAR      line=5
token=++       tag=OP       kind=4,NONE     line=5
token=)        tag=OP       kind=4,NONE     line=5
token=s        tag=ID       kind=3,VAR      line=6
token==        tag=OP       kind=4,NONE     line=6
token=s        tag=ID       kind=3,VAR      line=6
token=+        tag=OP       kind=4,NONE     line=6
token=i        tag=ID       kind=3,VAR      line=6
token=;        tag=OP       kind=4,NONE     line=6
token=return   tag=ID       kind=0,KEY      line=7
token=s        tag=ID       kind=3,VAR      line=7
token=;        tag=OP       kind=4,NONE     line=7
token=}        tag=OP       kind=4,NONE     line=8
token=int      tag=ID       kind=1,TYPE     line=10
token=swap     tag=ID       kind=3,VAR      line=10
token=(        tag=OP       kind=4,NONE     line=10
token=int      tag=ID       kind=1,TYPE     line=10
token=a        tag=ID       kind=3,VAR      line=10
token=,        tag=OP       kind=4,NONE     line=10
token=int      tag=ID       kind=1,TYPE     line=10
token=b        tag=ID       kind=3,VAR      line=10
token=)        tag=OP       kind=4,NONE     line=10
token={        tag=OP       kind=4,NONE     line=10
token=t        tag=ID       kind=3,VAR      line=11
token==        tag=OP       kind=4,NONE     line=11
token=a        tag=ID       kind=3,VAR      line=11
token=;        tag=OP       kind=4,NONE     line=11
token=a        tag=ID       kind=3,VAR      line=12
token==        tag=OP       kind=4,NONE     line=12
token=b        tag=ID       kind=3,VAR      line=12
token=;        tag=OP       kind=4,NONE     line=12
token=b        tag=ID       kind=3,VAR      line=13
token==        tag=OP       kind=4,NONE     line=13
token=t        tag=ID       kind=3,VAR      line=13
token=;        tag=OP       kind=4,NONE     line=13
token=}        tag=OP       kind=4,NONE     line=14
token=int      tag=ID       kind=1,TYPE     line=16
token=main     tag=ID       kind=3,VAR      line=16
token=(        tag=OP       kind=4,NONE     line=16
token=)        tag=OP       kind=4,NONE     line=16
token={        tag=OP       kind=4,NONE     line=16
token=int      tag=ID       kind=1,TYPE     line=17
token=x        tag=ID       kind=3,VAR      line=17
token==        tag=OP       kind=4,NONE     line=17
token=3        tag=INTEGER  kind=4,NONE     line=17
token=,        tag=OP       kind=4,NONE     line=17
token=y        tag=ID       kind=3,VAR      line=17
token==        tag=OP       kind=4,NONE     line=17
token=5        tag=INTEGER  kind=4,NONE     line=17
token=,        tag=OP       kind=4,NONE     line=17
token=z        tag=ID       kind=3,VAR      line=17
token=;        tag=OP       kind=4,NONE     line=17
token=if       tag=ID       kind=0,KEY      line=18
token=(        tag=OP       kind=4,NONE     line=18
token=(        tag=OP       kind=4,NONE     line=18
token=x        tag=ID       kind=3,VAR      line=18
token=+        tag=OP       kind=4,NONE     line=18
token=y        tag=ID       kind=3,VAR      line=18
token=)        tag=OP       kind=4,NONE     line=18
token=>        tag=OP       kind=4,NONE     line=18
token=6        tag=INTEGER  kind=4,NONE     line=18
token=)        tag=OP       kind=4,NONE     line=18
token=z        tag=ID       kind=3,VAR      line=19
token==        tag=OP       kind=4,NONE     line=19
token=0        tag=INTEGER  kind=4,NONE     line=19
token=;        tag=OP       kind=4,NONE     line=19
token=else     tag=ID       kind=0,KEY      line=20
token=z        tag=ID       kind=3,VAR      line=21
token==        tag=OP       kind=4,NONE     line=21
token=1        tag=INTEGER  kind=4,NONE     line=21
token=;        tag=OP       kind=4,NONE     line=21
token=int      tag=ID       kind=1,TYPE     line=23
token=i        tag=ID       kind=3,VAR      line=23
token==        tag=OP       kind=4,NONE     line=23
token=0        tag=INTEGER  kind=4,NONE     line=23
token=,        tag=OP       kind=4,NONE     line=23
token=s        tag=ID       kind=3,VAR      line=23
token==        tag=OP       kind=4,NONE     line=23
token=0        tag=INTEGER  kind=4,NONE     line=23
token=;        tag=OP       kind=4,NONE     line=23
token=while    tag=ID       kind=0,KEY      line=24
token=(        tag=OP       kind=4,NONE     line=24
token=i        tag=ID       kind=3,VAR      line=24
token=<        tag=OP       kind=4,NONE     line=24
token=10       tag=INTEGER  kind=4,NONE     line=24
token=)        tag=OP       kind=4,NONE     line=24
token={        tag=OP       kind=4,NONE     line=24
token=s        tag=ID       kind=3,VAR      line=25
token==        tag=OP       kind=4,NONE     line=25
token=s        tag=ID       kind=3,VAR      line=25
token=+        tag=OP       kind=4,NONE     line=25
token=i        tag=ID       kind=3,VAR      line=25
token=;        tag=OP       kind=4,NONE     line=25
token=i        tag=ID       kind=3,VAR      line=26
token=++       tag=OP       kind=4,NONE     line=26
token=;        tag=OP       kind=4,NONE     line=26
token=}        tag=OP       kind=4,NONE     line=27
token=int      tag=ID       kind=1,TYPE     line=29
token=total    tag=ID       kind=3,VAR      line=29
token==        tag=OP       kind=4,NONE     line=29
token=sum      tag=ID       kind=3,VAR      line=29
token=(        tag=OP       kind=4,NONE     line=29
token=10       tag=INTEGER  kind=4,NONE     line=29
token=)        tag=OP       kind=4,NONE     line=29
token=;        tag=OP       kind=4,NONE     line=29
token==        tag=OP       kind=4,NONE     line=30
token=swap     tag=ID       kind=3,VAR      line=30
token=(        tag=OP       kind=4,NONE     line=30
token=x        tag=ID       kind=3,VAR      line=30
token=,        tag=OP       kind=4,NONE     line=30
token=y        tag=ID       kind=3,VAR      line=30
token=)        tag=OP       kind=4,NONE     line=30
token=;        tag=OP       kind=4,NONE     line=30
token=}        tag=OP       kind=4,NONE     line=31

掃描器主程式:scanner.c

#include "cc0.h"    // 引入檔頭,包含資料結構與常數定義
 
void cnext() {                        // 取得下一個字元
    token[tokenIdx++]=ch;            // 將字元放入 token 尾端
    pos++;                            // 位置前進一格
    ch=fgetc(file);                    // 從檔案取出下一個字元 ch
}
 
void tnext() {                        // 取得下一個 token
    while (cmember(ch, SPACE)) {     // 忽略空白
        if (ch=='\n') {                // 如果遇到換行
            line++;                    // 將行數加 1
            pos = 1;                // 位置回到第1個字
        }
        cnext();                    // 取得下一個字元
    }
    if (feof(file)) {                // 如果是檔案結尾
        strcpy(token, "$ENDP");        // 設定 token 為 "$ENDP"
        tag = ENDP;                    // 設定 token 為 "$ENDP"
        return;                        // 傳回 "$ENDP"
    }
    tokenIdx = 0;                    // 從 token[0] 開始取得
    // 字串常數 : string = ".."
    if (ch == '\"') {                 // 如果是 " 代表字串開頭
        cnext();                     // 跳過 "
        while (ch != '\"') cnext(); // 一直讀到下一個 " 符號為止。
        cnext();                     // 跳過 "
        tag=STRING;
    // 運算符號 : OP = ++, --, <=, >=, ...
    } else if (cmember(ch, OPERATOR)) { // 如果是OP(+-*/<=>!等符號)
        while (cmember(ch, OPERATOR)) cnext(); // 一直讀到不是OP為止
        tag=OP;
    // 數字常數 : INTEGER = 312, 77568, ...
    } else if (cmember(ch, DIGIT)) {// 如果是數字
        while (cmember(ch, DIGIT))     // 一直讀到不是數字為止
            cnext();
        tag=INTEGER;                // token 為整數型態
        if (ch == '.') {            // 有小數點 => 實數 : real = 3.14, ...
            cnext();                 // 取得小數點
            tag = FLOAT;            // token 為實數型態
        }
        while (cmember(ch, DIGIT))    // 取得小數部分
            cnext();
    // 基本詞彙 : token = int, sum, i, for, if, x1y2z, ....
    } else if (cmember(ch, ALPHA)) {// 如果是英文字母
        // 一直讀到不是英文字母 (或數字)為止
        while (cmember(ch, ALPHA) || cmember(ch, DIGIT))
            cnext();
        tag=ID;                        // token 為 ID 型態
    // 其他符號,都解讀為單一字元        
    } else {
        tag = OP;                    // token 為運算元 +-*/...
        cnext();                     // token = 單一字元
    }
    token[tokenIdx] = '\0';            // 設定 token 字串結尾的 \0
    if (strFind(keys, token)!=NIL)    // 如果是關鍵字
        kind = KEY;                    //   kind = KEY
    else if (strFind(types, token)!=NIL) // 如果是型態
        kind = TYPE;                //   kind = TYPE
    else if (tag == ID)                // 如果是 ID
        kind = VAR;                    //   kind = VAR
    else                            // 否則
        kind = NONE;                //   kind = VAR
}
 
int init() {                    // 初始化
    fseek(file, 0, SEEK_SET);    // 讓檔案指標回到起始點
    tokenIdx = 0;                // token 從第 0 個字開始取得
    tnext();                    // 取得第一個 token,以便進行判斷
}
 
int scan() {                    // 掃描器的主要功能
    init();                        // 初始化
    while (TRUE) {                // 不斷掃描
        if (tag == ENDP)        // 如果已經到檔尾了
            break;                // 結束跳開
        // 印出 token 的內容與屬性
        printf("token=%-8s tag=%-8s kind=%d,%-8s line=%d\n",
                token, tags[tag], kind, kinds[kind], line);
        tnext();                // 取得下一個 token
    }
}
 
int main(int argc, char * argv[]) {    // 掃描器主程式
    char *fname = argv[1];            // 第一個參數為檔案名稱
    file = fopen(fname, "r");        // 開啟輸入檔 (例如:test.c0)
    scan();                            // 執行掃描動作
    fclose(file);                    // 關閉輸入檔
}

Facebook

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License