词法分析器c语言编写
时间: 2023-07-02 10:09:40 浏览: 42
词法分析器是编译器的重要组成部分,它用于将输入的源代码分解成单个的标记(Token),每个标记代表一个语言结构,如关键字、标识符、常量、操作符等,以便后续的语法分析器进行处理。下面是一个简单的词法分析器的C语言实现。
```c
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_TOKEN_LEN 100
// 定义标记类型
typedef enum {
TOKEN_KEYWORD,
TOKEN_IDENTIFIER,
TOKEN_CONSTANT,
TOKEN_OPERATOR,
TOKEN_UNKNOWN
} token_type;
// 定义标记结构体
typedef struct {
char str[MAX_TOKEN_LEN];
token_type type;
} token;
// 判断字符串是否为关键字
int is_keyword(char* str) {
char* keywords[] = {"if", "else", "while", "for", "int", "float", "char", "void"};
int num_keywords = sizeof(keywords) / sizeof(keywords[0]);
for (int i = 0; i < num_keywords; i++) {
if (strcmp(str, keywords[i]) == 0) {
return 1;
}
}
return 0;
}
// 判断字符是否为操作符
int is_operator(char c) {
char* operators[] = {"+", "-", "*", "/", "%", "=", "==", "!=", ">", "<", ">=", "<="};
int num_operators = sizeof(operators) / sizeof(operators[0]);
for (int i = 0; i < num_operators; i++) {
if (operators[i][0] == c) {
return 1;
}
}
return 0;
}
// 获取下一个标记
token get_next_token(FILE* fp) {
char c = fgetc(fp);
token t;
t.str[0] = c;
t.str[1] = '\0';
if (isalpha(c)) { // 标识符或关键字
int i = 1;
while (isalnum(c = fgetc(fp))) {
t.str[i++] = c;
}
t.str[i] = '\0';
if (is_keyword(t.str)) {
t.type = TOKEN_KEYWORD;
} else {
t.type = TOKEN_IDENTIFIER;
}
ungetc(c, fp);
} else if (isdigit(c)) { // 常量
int i = 1;
while (isdigit(c = fgetc(fp))) {
t.str[i++] = c;
}
if (c == '.') {
t.str[i++] = c;
while (isdigit(c = fgetc(fp))) {
t.str[i++] = c;
}
}
t.str[i] = '\0';
t.type = TOKEN_CONSTANT;
ungetc(c, fp);
} else if (is_operator(c)) { // 操作符
int i = 1;
while (is_operator(t.str[i] = fgetc(fp))) {
i++;
}
t.str[i] = '\0';
t.type = TOKEN_OPERATOR;
ungetc(t.str[i], fp);
} else if (c == EOF) { // 文件结束标记
t.type = TOKEN_UNKNOWN;
} else { // 未知字符
t.type = TOKEN_UNKNOWN;
}
return t;
}
int main() {
FILE* fp = fopen("source.c", "r");
if (fp == NULL) {
printf("File not found");
return 1;
}
token t;
while (t.type != TOKEN_UNKNOWN) {
t = get_next_token(fp);
printf("%s\t%d\n", t.str, t.type);
}
fclose(fp);
return 0;
}
```
在上面的代码中,我们定义了五种标记类型,分别是关键字、标识符、常量、操作符和未知字符。然后我们定义了一个标记结构体,用于存储标记的字符串和类型。接着我们实现了三个函数:
- `is_keyword`:判断一个字符串是否为关键字。
- `is_operator`:判断一个字符是否为操作符。
- `get_next_token`:从文件中读取下一个标记。
最后在`main`函数中,我们循环调用`get_next_token`函数,直到读取到未知字符为止。对于每个标记,我们输出其字符串和类型。注意,在读取标识符和常量时,我们需要读取多个字符,因此需要使用循环来读取。而在读取操作符时,因为一个操作符有可能由多个字符组成,因此我们同样需要使用循环来读取。
相关推荐
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)