编译原理实验词法分析c++代码
时间: 2023-09-09 08:12:02 浏览: 144
以下是一个基本的词法分析器的C代码,用于分析输入的源代码并将其拆分为单个令牌:
```c
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAXTOKENLEN 100
typedef enum {
nulsym = 1, identsym, numbersym, plussym, minussym,
multsym, slashsym, oddsym, eqsym, neqsym,
lessym, leqsym, gtrsym, geqsym, lparentsym,
rparentsym, commasym, semicolonsym, periodsym,
becomessym, beginsym, endsym, ifsym, thensym,
whilesym, dosym, callsym, constsym, varsym,
procsym, writesym, readsym, elsesym
} token_type;
char* reserved_words[] = {
"null", "begin", "call", "const", "do", "else",
"end", "if", "odd", "procedure", "read", "then",
"var", "while", "write"
};
typedef struct {
int type;
char value[MAXTOKENLEN];
} token;
token token_list[MAXTOKENLEN];
int token_index = 0;
// 从输入的字符串中提取下一个令牌并添加到令牌列表中
void add_token(int type, char* value) {
token t;
t.type = type;
strncpy(t.value, value, MAXTOKENLEN);
token_list[token_index++] = t;
}
// 判断一个字符是否为运算符
int is_operator(char c) {
return (c == '+' || c == '-' || c == '*' || c == '/'
|| c == '(' || c == ')' || c == '=' || c == ','
|| c == '.' || c == '<' || c == '>' || c == ';'
|| c == ':' || c == '!') ? 1 : 0;
}
// 判断一个字符串是否为保留字
int is_reserved(char* s) {
int i;
for (i = 0; i < 15; i++) {
if (strcmp(s, reserved_words[i]) == 0) {
return i + 1;
}
}
return 0;
}
// 扫描输入字符串并生成令牌列表
void lex(char* input) {
int i, j;
for (i = 0; i < strlen(input); i++) {
// 忽略空格和换行符
if (isspace(input[i])) {
continue;
}
// 如果是运算符,添加到令牌列表中
if (is_operator(input[i])) {
if (input[i] == ':' && input[i+1] == '=') {
add_token(becomessym, ":=");
i++;
} else if (input[i] == '<' && input[i+1] == '=') {
add_token(leqsym, "<=");
i++;
} else if (input[i] == '>' && input[i+1] == '=') {
add_token(geqsym, ">=");
i++;
} else if (input[i] == '<' && input[i+1] == '>') {
add_token(neqsym, "<>");
i++;
} else {
char op[2] = {input[i], '\0'};
add_token(strchr("+-*/=(),.<>;:", input[i]) - "+", op);
}
// 如果是数字,扫描整个数字并添加到令牌列表中
} else if (isdigit(input[i])) {
char number[MAXTOKENLEN] = {0};
int k = 0;
while (isdigit(input[i])) {
number[k++] = input[i++];
}
add_token(numbersym, number);
i--;
// 如果是字母,扫描整个标识符并添加到令牌列表中
} else if (isalpha(input[i])) {
char ident[MAXTOKENLEN] = {0};
int k = 0;
while (isalpha(input[i]) || isdigit(input[i])) {
ident[k++] = input[i++];
}
int reserved_type = is_reserved(ident);
if (reserved_type) {
add_token(reserved_type, ident);
} else {
add_token(identsym, ident);
}
i--;
} else {
printf("Error: Invalid character '%c'\n", input[i]);
return;
}
}
}
int main() {
char input[MAXTOKENLEN];
printf("Enter your input: ");
fgets(input, MAXTOKENLEN, stdin);
lex(input);
printf("Token list:\n");
for (int i = 0; i < token_index; i++) {
printf("(%d, %s)\n", token_list[i].type, token_list[i].value);
}
return 0;
}
```
该代码使用了一个`token`结构体来保存每个令牌的类型和值,并使用一个`token_list`数组来保存所有的令牌。`lex`函数扫描输入字符串并使用`add_token`函数将所有令牌添加到`token_list`数组中。`is_operator`函数用于判断一个字符是否为运算符,`is_reserved`函数用于判断一个字符串是否为保留字。在`main`函数中,先输入源代码并调用`lex`函数对其进行词法分析,然后输出所有生成的令牌列表。
阅读全文