C语言词法分析器代码实现详解
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
希望本文对您有所帮助!
原文地址: https://www.cveoy.top/t/topic/SfZ 著作权归作者所有。请勿转载和采集!