掃描器 -- scan.c

計算語言學

簡介

詞彙

語法

語意

理解

問題領域

語言生成

語法剖析

語意分析

處理方法

正規表達式

BNF 語法

掃描

剖析器

符號表

解譯

編譯

翻譯

各種語言

組合語言

程式語言

標記語言

維基語言

自然語言

中文

英文

程式實作

JavaScript

C

Python

相關書籍

自然語言處理

編譯器設計

系統程式

訊息

相關網站

參考文獻

最新修改

簡體版

English

程式:scan.c

#include <stdio.h>
#include <assert.h>

#define LEN_MAX 256

#define SPACE " \t\n\r"     // 空白字元
#define ALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" // 英文字母
#define DIGIT "0123456789"    // 數字字元
#define SYMBOL "~!@#$%^&*()_+{}:<>?-=[]|\"\\;',./" // 符號字元
#define OP "+-*/%<=>!&|"        // 運算符號字元集 (用來取得 +,-,*,/, ++, ...)

FILE *file;
char ch;
int line=1, pos=0;
char token[LEN_MAX];
int  tokenIdx = 0;

#define cmember(ch, set) (strchr(set, ch) != NULL)// 測試字元 ch 是否在 set 當中

char cnext() {
    token[tokenIdx++]=ch;
    ch=fgetc(file);
    return ch;
}

char* tnext() {
    while (cmember(ch, SPACE)) { // 忽略空白
        tokenIdx = 0;
        if (ch=='\n') {
            line++;
            pos = 1;
        }
        cnext();
    }
    if (feof(file)) return NULL;
    tokenIdx = 0;
    if (ch == '\"') { // 如果是 " 代表字串開頭
        // 字串常數 : string = ".."
        cnext(); // 跳過 "
        while (ch != '\"') cnext(); // 一直讀到下一個 " 符號為止。
        cnext(); // 跳過 "
    } else if (cmember(ch, OP)) { // 如果是OP(+-*/<=>!等符號)
          // 運算符號 : OP = ++, --, <=, >=, ...
        while (cmember(ch, OP)) cnext(); // 一直讀到不是OP為止
    } else if (cmember(ch, DIGIT)) { // 如果是數字
           // 數字常數 : number = 312, 77568, ...
        while (cmember(ch, DIGIT)) cnext(); // 一直讀到不是數字為止
        // 浮點常數 : float = 3.14, ...
        if (ch == '.') cnext(); // 取得小數點
        while (cmember(ch, DIGIT)) cnext(); // 取得小數部分
    } else if (cmember(ch, ALPHA)) { // 如果是英文字母
        // 基本詞彙 : token = int, sum, i, for, if, x1y2z, ....
        while (cmember(ch, ALPHA) || cmember(ch, DIGIT))
            cnext(); // 一直讀到不是英文字母 (或數字)為止
    } else // 其他符號,都解讀為單一字元
        cnext(); // 傳回單一字元
    token[tokenIdx] = '\0';
    return token;
}

int scan() {
    tokenIdx = 0;
    cnext();
    while (tnext() != NULL) {
        printf("%s\n", token);
    }
}

int main(int argc, char * argv[]) {
    assert(argc > 1);
    char *fname = argv[1];
    file = fopen(fname, "r");
    scan();
    fclose(file);
}

輸入檔: test.c0

int x=1, y=2;

struct Date {
    int year, month, day;
}

struct Person {
    char *name;
    Date birthday;
}

int total(int* a) {
    int s = 0;
    for (int i=0; i<10; i++)
        s = s+a[i];
    return s;
}

char* getName(Person *p) {
    return p->name;
}

int main() {
    int b[10], a=3;
    int t = total(b);
    Person p;
    p.birthday.year = 1990;
    t = 3 + (5 * a);
    return t;
}

編譯執行結果

D:\oc\compiler>gcc scan.c -o scan

D:\oc\compiler>scan test.c0
int
x
=
1
,
y
=
2
;
struct
Date
{
int
year
,
month
,
day
;
}
struct
Person
{
char
*
name
;
Date
birthday
;
}
int
total
(
int
*
a
)
{
int
s
=
0
;
for
(
int
i
=
0
;
i
<
10
;
i
++
)
s
=
s
+
a
[
i
]
;
return
s
;
}
char
*
getName
(
Person
*
p
)
{
return
p
->
name
;
}
int
main
(
)
{
int
b
[
10
]
,
a
=
3
;
int
t
=
total
(
b
)
;
Person
p
;
p
.
birthday
.
year
=
1990
;
t
=
3
+
(
5
*
a
)
;
return
t
;
}

Facebook

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