C语言词法分析器代码实现

代码实现

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

// 定义单词符号的种别编码
#define ID 10
#define NUM 20
#define ASSIGN 21
#define PLUS 22
#define MINUS 23
#define TIMES 24
#define DIVIDE 25
#define LPAREN 26
#define RPAREN 27
#define LBRACE 30
#define RBRACE 31
#define COMMA 32
#define COLON 33
#define SEMICOLON 34
#define LESS 35
#define GREATER 36
#define EQUAL 37
#define NOT_EQUAL 38
#define AND 41
#define OR 43

// 定义状态转换图
int transitionTable[24][14] = {
    //      letter   digit   =    +    -    *    /    &    <    >    !    ;    :    ,    {    }    [    ]   (   )  空格   \n  \t
    /* 0 */ {   1,      2,    3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18, 19,  20,  0,   0,   0},
    /* 1 */ {   1,      1,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 2 */ {   0,      2,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 3 */ {   0,      0,    22,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 4 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 5 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 6 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 7 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 8 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 9 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 10 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 11 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 12 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 13 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 14 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 15 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 16 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 17 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 18 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 19 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 20 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 21 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 22 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 23 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0}
};

// 定义关键字表
char *KEY_WORDS[7] = {
    'main', 'int', 'char', 'if', 'else', 'for', 'while'
};

// 定义存放单词符号二元式的数据结构
#define MAXLENGTH 255

union WORDCONTENT {
    char T1[MAXLENGTH];
    int T2;
    char T3;
};

typedef struct WORD {
    int code;
    union WORDCONTENT value;
} WORD;

// 词法分析器的扫描函数
void Scanner(char *sourceCode, FILE *outputFile) {
    int currentState = 0;
    int length = strlen(sourceCode);
    char token[MAXLENGTH];
    int tokenLength = 0;
    
    for (int i = 0; i < length; i++) {
        char currentChar = sourceCode[i];
        int column;
        
        // 根据当前字符确定列索引
        if ((currentChar >= 'a' && currentChar <= 'z') || (currentChar >= 'A' && currentChar <= 'Z')) {
            column = 0; // letter
        } else if (currentChar >= '0' && currentChar <= '9') {
            column = 1; // digit
        } else if (currentChar == '=') {
            column = 2;
        } else if (currentChar == '+') {
            column = 3;
        } else if (currentChar == '-') {
            column = 4;
        } else if (currentChar == '*') {
            column = 5;
        } else if (currentChar == '/') {
            column = 6;
        } else if (currentChar == '&') {
            column = 7;
        } else if (currentChar == '<') {
            column = 8;
        } else if (currentChar == '>') {
            column = 9;
        } else if (currentChar == '!') {
            column = 10;
        } else if (currentChar == ';') {
            column = 11;
        } else if (currentChar == ':') {
            column = 12;
        } else if (currentChar == ',') {
            column = 13;
        } else if (currentChar == '{') {
            column = 14;
        } else if (currentChar == '}') {
            column = 15;
        } else if (currentChar == '[') {
            column = 16;
        } else if (currentChar == ']') {
            column = 17;
        } else if (currentChar == '(') {
            column = 18;
        } else if (currentChar == ')') {
            column = 19;
        } else if (currentChar == ' ' || currentChar == '\n' || currentChar == '\t') {
            column = 20;
        } else {
            printf('Invalid character at position %d\n', i+1);
            return;
        }
        
        int nextState = transitionTable[currentState][column];
        
        // 根据下一个状态进行相应操作
        if (nextState == 0) {
            // 识别完成一个单词符号
            token[tokenLength] = '\0';
            tokenLength = 0;
            
            // 判断识别出的单词符号的种别编码
            int code;
            if (currentState == 1) {
                // 判断是否为关键字
                int isKeyword = 0;
                for (int j = 0; j < 7; j++) {
                    if (strcmp(token, KEY_WORDS[j]) == 0) {
                        isKeyword = 1;
                        break;
                    }
                }
                
                if (isKeyword) {
                    code = currentState;
                } else {
                    code = ID;
                }
            } else if (currentState == 2) {
                code = NUM;
            } else {
                code = currentState;
            }
            
            // 将识别出的单词符号的二元式写入输出文件
            WORD word;
            word.code = code;
            if (code == ID || code == NUM) {
                strcpy(word.value.T1, token);
            }
            
            fwrite(&word, sizeof(WORD), 1, outputFile);
            
            // 恢复初始状态
            currentState = 0;
        } else {
            // 继续识别
            token[tokenLength++] = currentChar;
            currentState = nextState;
        }
    }
}

int main() {
    char *sourceCode = 'main()\n'
                       '{'\n'
                       '    int i = 10;'
                       '    while(i) i = i - 1;'
                       '}';
    
    FILE *outputFile = fopen('output.txt', 'wb');
    
    if (outputFile == NULL) {
        printf('Failed to open output file.\n');
        return 1;
    }
    
    Scanner(sourceCode, outputFile);
    
    fclose(outputFile);
    
    printf('Lexical analysis completed.\n');
    
    return 0;
}

代码解析

1. 头文件

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

2. 常量定义

// 定义单词符号的种别编码
#define ID 10
#define NUM 20
#define ASSIGN 21
#define PLUS 22
#define MINUS 23
#define TIMES 24
#define DIVIDE 25
#define LPAREN 26
#define RPAREN 27
#define LBRACE 30
#define RBRACE 31
#define COMMA 32
#define COLON 33
#define SEMICOLON 34
#define LESS 35
#define GREATER 36
#define EQUAL 37
#define NOT_EQUAL 38
#define AND 41
#define OR 43

3. 状态转换图

// 定义状态转换图
int transitionTable[24][14] = {
    //      letter   digit   =    +    -    *    /    &    <    >    !    ;    :    ,    {    }    [    ]   (   )  空格   \n  \t
    /* 0 */ {   1,      2,    3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18, 19,  20,  0,   0,   0},
    /* 1 */ {   1,      1,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 2 */ {   0,      2,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 3 */ {   0,      0,    22,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 4 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 5 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 6 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 7 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 8 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 9 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 10 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 11 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 12 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 13 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 14 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 15 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 16 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 17 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 18 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 19 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 20 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 21 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 22 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0},
    /* 23 */ {   0,      0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  0,   0,   0,   0,   0}
};

4. 关键字表

// 定义关键字表
char *KEY_WORDS[7] = {
    'main', 'int', 'char', 'if', 'else', 'for', 'while'
};

5. 数据结构

// 定义存放单词符号二元式的数据结构
#define MAXLENGTH 255

union WORDCONTENT {
    char T1[MAXLENGTH];
    int T2;
    char T3;
};

typedef struct WORD {
    int code;
    union WORDCONTENT value;
} WORD;

6. 扫描函数

// 词法分析器的扫描函数
void Scanner(char *sourceCode, FILE *outputFile) {
    int currentState = 0;
    int length = strlen(sourceCode);
    char token[MAXLENGTH];
    int tokenLength = 0;
    
    for (int i = 0; i < length; i++) {
        char currentChar = sourceCode[i];
        int column;
        
        // 根据当前字符确定列索引
        if ((currentChar >= 'a' && currentChar <= 'z') || (currentChar >= 'A' && currentChar <= 'Z')) {
            column = 0; // letter
        } else if (currentChar >= '0' && currentChar <= '9') {
            column = 1; // digit
        } else if (currentChar == '=') {
            column = 2;
        } else if (currentChar == '+') {
            column = 3;
        } else if (currentChar == '-') {
            column = 4;
        } else if (currentChar == '*') {
            column = 5;
        } else if (currentChar == '/') {
            column = 6;
        } else if (currentChar == '&') {
            column = 7;
        } else if (currentChar == '<') {
            column = 8;
        } else if (currentChar == '>') {
            column = 9;
        } else if (currentChar == '!') {
            column = 10;
        } else if (currentChar == ';') {
            column = 11;
        } else if (currentChar == ':') {
            column = 12;
        } else if (currentChar == ',') {
            column = 13;
        } else if (currentChar == '{') {
            column = 14;
        } else if (currentChar == '}') {
            column = 15;
        } else if (currentChar == '[') {
            column = 16;
        } else if (currentChar == ']') {
            column = 17;
        } else if (currentChar == '(') {
            column = 18;
        } else if (currentChar == ')') {
            column = 19;
        } else if (currentChar == ' ' || currentChar == '\n' || currentChar == '\t') {
            column = 20;
        } else {
            printf('Invalid character at position %d\n', i+1);
            return;
        }
        
        int nextState = transitionTable[currentState][column];
        
        // 根据下一个状态进行相应操作
        if (nextState == 0) {
            // 识别完成一个单词符号
            token[tokenLength] = '\0';
            tokenLength = 0;
            
            // 判断识别出的单词符号的种别编码
            int code;
            if (currentState == 1) {
                // 判断是否为关键字
                int isKeyword = 0;
                for (int j = 0; j < 7; j++) {
                    if (strcmp(token, KEY_WORDS[j]) == 0) {
                        isKeyword = 1;
                        break;
                    }
                }
                
                if (isKeyword) {
                    code = currentState;
                } else {
                    code = ID;
                }
            } else if (currentState == 2) {
                code = NUM;
            } else {
                code = currentState;
            }
            
            // 将识别出的单词符号的二元式写入输出文件
            WORD word;
            word.code = code;
            if (code == ID || code == NUM) {
                strcpy(word.value.T1, token);
            }
            
            fwrite(&word, sizeof(WORD), 1, outputFile);
            
            // 恢复初始状态
            currentState = 0;
        } else {
            // 继续识别
            token[tokenLength++] = currentChar;
            currentState = nextState;
        }
    }
}

7. 主函数

int main() {
    char *sourceCode = 'main()\n'
                       '{'\n'
                       '    int i = 10;'
                       '    while(i) i = i - 1;'
                       '}';
    
    FILE *outputFile = fopen('output.txt', 'wb');
    
    if (outputFile == NULL) {
        printf('Failed to open output file.\n');
        return 1;
    }
    
    Scanner(sourceCode, outputFile);
    
    fclose(outputFile);
    
    printf('Lexical analysis completed.\n');
    
    return 0;
}

运行结果

运行以上代码后,会在当前目录下生成一个名为output.txt的文件,其中保存了源程序的单词符号二元式的代码。

总结

本文提供了一个简单的C语言词法分析器代码,用于实现对源程序字符串的词法分析,并将词法分析结果保存到文件中。代码结构清晰,注释详细,适合初学者学习和参考。

参考资料

代码下载

词法分析器代码

联系方式

如果您有任何问题或建议,请随时联系我。

邮箱: yourEmail@example.com

微信: yourWeChatID

QQ: yourQQNumber

希望本文对您有所帮助!

C语言词法分析器代码实现详解

原文地址: https://www.cveoy.top/t/topic/SfZ 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录