簡(jiǎn)單的詞法分析器

任務(wù)

你將使用圖轉(zhuǎn)移算法手工實(shí)現(xiàn)一個(gè)小型的詞法分析器。

  • 分析器的輸入:存儲(chǔ)在文本文件中的字符序列山橄,字符取自ASCII字符集垮媒。文件中可能包括下面幾種記號(hào):關(guān)鍵字if、符合C語(yǔ)言標(biāo)準(zhǔn)的標(biāo)識(shí)符航棱、無(wú)符號(hào)整型數(shù)字睡雇、空格符、回車符\n饮醇。
  • 分析器的輸出:打印出所識(shí)別的記號(hào)的種類它抱、及記號(hào)開始行號(hào)、開始列號(hào)信息朴艰。
    注意:1. 忽略空格及回車符观蓄;2. 對(duì)于標(biāo)識(shí)符和數(shù)字,要輸出符號(hào)的具體詞法單元(見(jiàn)下面的示例)祠墅。
    【示例】對(duì)于下面的文本文件:
    ifx if iif if 234
    iff if
    你的輸出應(yīng)該是(注意侮穿,因?yàn)槲谋撅@示的原因,列號(hào)信息可能不一定準(zhǔn)確):
    ID(ifx) (1, 1)
    IF (1, 4)
    ID(iif) (1, 8)
    IF (1, 13)
    NUM(234) (1, 16)
    ID(iff) (2, 1)
    IF (2, 8)

程序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE 1024  //每行做大的字節(jié)數(shù)

//詞法的類型
enum Kind {
    IF,
    ID,
    NUM
};

//存儲(chǔ)每個(gè)詞的信息的結(jié)構(gòu)體
struct Token {
    enum Kind kind;
    char* value;
    int row;
    int col;
};

struct Token *Token_new(enum Kind kind, char *value, int row, int col) {
    struct Token *token = (struct Token*)malloc(sizeof(*token));
    token->value = (char*)malloc(sizeof(*value));
    strncpy(token->value, value, strlen(value));
    token->kind = kind;
    token->row = row;
    token->col = col;
    return token;
}
//用于存放所有詞的鏈表結(jié)構(gòu)
struct List {
    struct Token *token;
    struct List *next;
};

struct List *all_word;
struct List* List_new(struct Token* t, struct List* list) {
    struct List* p = (struct List*)malloc(sizeof(*p));
    p->token = t;
    p->next = list;
    return p;
}

void List_print(struct List* list) {
    if (!list) {
        return;
    }
    List_print(list->next);

    switch (list->token->kind) {
        case IF: {
            printf("IF (%d, %d)\n", list->token->row, list->token->col);
            break;
        }
        case ID: {
            printf("ID(%s) (%d, %d)\n", list->token->value, list->token->row, list->token->col);
            break;
        }
        case NUM: {
            printf("NUM(%s) (%d, %d)\n", list->token->value, list->token->row, list->token->col);
            break;
        }
        default:
            break;
    }
}

//處理單詞
void Process_word(char *word, int len, int row, int col) {
    if (strcmp("if", word) == 0) {
        struct Token *token = Token_new(IF, word, row, col);
        all_word = List_new(token, all_word);
    }else if (Is_num(word, len) == 1) {
        struct Token *token = Token_new(NUM, word, row, col);
        all_word = List_new(token, all_word);
    } else {
        struct Token *token = Token_new(ID, word, row, col);
        all_word = List_new(token, all_word);
    }
}

//判斷是否為數(shù)字
int Is_num(char* word, int len) {
    for (int i = 0; i < len; i++) {
        if (word[i] < '0' || word[i] > '9'){
            return 0;
        }
    }
    return 1;
}



int main() {
    FILE *file;
    char strLine[MAX_LINE];
    char str[MAX_LINE];
    if ((file = fopen("/home/hz/a.txt", "r")) == NULL) {
        printf("Open Failed!");
        return -1;
    }

    int curr_row = 0; //當(dāng)前的行數(shù)
    while (!feof(file)) {
        curr_row++;

        if(fgets(strLine, MAX_LINE, file)){
            printf("%s", strLine);
            int len = strlen(strLine);
            int str_save_len = 0;
            for (int i = 0; i < len; i++) {
                char c = strLine[i];
                switch (c) {
                    case ' ': {
                        if (str_save_len > 0) {
                            str[str_save_len] = '\0';
                            Process_word(str, str_save_len, curr_row, i + 1);
                            str_save_len = 0;
                        }
                        break;
                    }
                    case '\n': {
                        if (str_save_len > 0) {
                            str[str_save_len] = '\0';
                            Process_word(str, str_save_len, curr_row, i + 1);
                            str_save_len = 0;
                        }
                        break;
                    }
                    default: {
                        str[str_save_len++] = c;
                    }
                }
            }

        }
    }

    List_print(all_word);
    fclose(file);
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末毁嗦,一起剝皮案震驚了整個(gè)濱河市亲茅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖克锣,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茵肃,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡娶耍,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門饼酿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)榕酒,“玉大人,你說(shuō)我怎么就攤上這事故俐∠胗ィ” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵药版,是天一觀的道長(zhǎng)辑舷。 經(jīng)常有香客問(wèn)我,道長(zhǎng)槽片,這世上最難降的妖魔是什么何缓? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮还栓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谷婆。我一直安慰自己纪挎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布跟匆。 她就那樣靜靜地躺著异袄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪玛臂。 梳的紋絲不亂的頭發(fā)上隙轻,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音垢揩,去河邊找鬼玖绿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛叁巨,可吹牛的內(nèi)容都是我干的斑匪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼狡蝶,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了贮勃?” 一聲冷哼從身側(cè)響起贪惹,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寂嘉,沒(méi)想到半個(gè)月后奏瞬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寓搬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年珍昨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片句喷。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡镣典,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出唾琼,到底是詐尸還是另有隱情骆撇,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布父叙,位于F島的核電站神郊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏趾唱。R本人自食惡果不足惜涌乳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望甜癞。 院中可真熱鬧夕晓,春花似錦、人聲如沸悠咱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)析既。三九已至躬贡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間眼坏,已是汗流浹背拂玻。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人檐蚜。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓魄懂,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親闯第。 傳聞我的和親對(duì)象是個(gè)殘疾皇子市栗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Java實(shí)現(xiàn)簡(jiǎn)單的詞法分析器: 需求分析5類符號(hào)保留字(keywords):if、int咳短、for填帽、while、do...
    芒果菠蘿蛋炒飯閱讀 12,452評(píng)論 2 16
  • 個(gè)人學(xué)習(xí)批處理的初衷來(lái)源于實(shí)際工作诲泌;在某個(gè)迭代版本有個(gè)BS(安卓手游模擬器)大需求盲赊,從而在測(cè)試過(guò)程中就重復(fù)涉及到...
    Luckykailiu閱讀 4,725評(píng)論 0 11
  • 詞法分析器 詞法分析器又稱掃描器铣鹏。詞法分析是指將我們編寫的文本代碼流解析為一個(gè)一個(gè)的記號(hào)敷扫,分析得到的記號(hào)(Toke...
    435fa00b72e7閱讀 1,613評(píng)論 0 3
  • 允許的修飾符 有些修飾符能在所有允許的地方出現(xiàn), 但并非所有的都這樣. 通常, 影響 regex 編譯的修飾符(...
    焉知非魚閱讀 1,343評(píng)論 0 1
  • 那天早早的就沒(méi)有了睡意,起床沖個(gè)熱水澡澡诚卸,精神飽滿的準(zhǔn)備考試葵第。 匆匆吃過(guò)早飯,百度瀏覽著當(dāng)今社會(huì)上跟科技有關(guān)的信息...
    一曦清露閱讀 328評(píng)論 0 1