简单的词法分析器

任务

你将使用图转移算法手工实现一个小型的词法分析器。

  • 分析器的输入:存储在文本文件中的字符序列,字符取自ASCII字符集。文件中可能包括下面几种记号:关键字if、符合C语言标准的标识符、无符号整型数字、空格符、回车符\n。
  • 分析器的输出:打印出所识别的记号的种类、及记号开始行号、开始列号信息。
    注意:1. 忽略空格及回车符;2. 对于标识符和数字,要输出符号的具体词法单元(见下面的示例)。
    【示例】对于下面的文本文件:
    ifx if iif if 234
    iff if
    你的输出应该是(注意,因为文本显示的原因,列号信息可能不一定准确):
    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 
#include 
#include 

#define MAX_LINE 1024  //每行做大的字节数

//词法的类型
enum Kind {
    IF,
    ID,
    NUM
};

//存储每个词的信息的结构体
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;
}
//用于存放所有词的链表结构
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);
    }
}

//判断是否为数字
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; //当前的行数
    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;
}

你可能感兴趣的:(简单的词法分析器)