LR0分析程序的设计与实现代码,使用C语言
时间: 2023-12-12 15:03:05 浏览: 102
以下是一个简单的LR(0)分析程序的设计和实现代码,使用了C语言:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STATES 100
#define MAX_SYMBOLS 100
#define MAX_PRODUCTIONS 100
// 定义文法
char *grammar[] = {
"S->E",
"E->E+T",
"E->T",
"T->T*F",
"T->F",
"F->(E)",
"F->id"
};
int num_symbols = 5;
// 定义项目
char *closure(char **I, int n) {
char **J = I;
int m = n;
while (1) {
int item_added = 0;
for (int i = 0; i < m; i++) {
char *item = J[i];
int dot_pos = strchr(item, '.') - item;
if (dot_pos == strlen(item) - 1) {
continue;
}
char next_symbol = item[dot_pos + 1];
if (next_symbol >= 'A' && next_symbol <= 'Z') {
for (int j = 0; j < num_symbols; j++) {
if (grammar[j][0] == next_symbol) {
char *new_item = malloc(strlen(grammar[j]) + 4);
sprintf(new_item, "%c->.%s", next_symbol, grammar[j] + 3);
if (!strstr(J[0], new_item) && !strstr(J[m-1], new_item)) {
J[m++] = new_item;
item_added = 1;
} else {
free(new_item);
}
}
}
}
}
if (!item_added) {
break;
}
}
char *closure = malloc(m * (strlen(grammar[0]) + 1));
strcpy(closure, J[0]);
for (int i = 1; i < m; i++) {
strcat(closure, "/");
strcat(closure, J[i]);
}
return closure;
}
// 定义goto函数
int goto(char **I, int n, char X, char **J) {
int m = 0;
for (int i = 0; i < n; i++) {
char *item = I[i];
int dot_pos = strchr(item, '.') - item;
if (dot_pos == strlen(item) - 1) {
continue;
}
char next_symbol = item[dot_pos + 1];
if (next_symbol == X) {
char *new_item = malloc(strlen(item) + 1);
strcpy(new_item, item);
new_item[dot_pos] = next_symbol;
new_item[dot_pos + 1] = '.';
J[m++] = new_item;
}
}
char *closure_J = closure(J, m);
int ret = 1;
for (int i = 0; i < n; i++) {
if (strcmp(I[i], closure_J) == 0) {
ret = 0;
break;
}
}
if (ret) {
strcpy(I[n], closure_J);
}
free(closure_J);
return ret ? n + 1 : -1;
}
// 构造LR(0)自动机
char *states[MAX_STATES];
int num_states = 1;
char *queue[MAX_STATES];
void construct_LR0_automaton() {
char *C = closure((char *[]){"S->.E"}, 1);
states[0] = C;
queue[0] = C;
int head = 0, tail = 1;
while (head < tail) {
C = queue[head++];
for (char symbol = 'A'; symbol <= 'Z'; symbol++) {
char *J[MAX_PRODUCTIONS];
int m = goto(C, strlen(C), symbol, J);
if (m > 0) {
states[num_states] = J[0];
for (int i = 1; i < m; i++) {
strcat(states[num_states], "/");
strcat(states[num_states], J[i]);
}
queue[tail++] = states[num_states];
num_states++;
}
}
}
}
// 定义LR(0)分析表
enum Action {
SHIFT,
REDUCE,
ACCEPT
};
struct TableEntry {
enum Action action;
int num;
};
struct TableEntry action[MAX_STATES][MAX_SYMBOLS];
int goto_table[MAX_STATES][MAX_SYMBOLS];
void construct_LR0_table() {
for (int i = 0; i < num_states; i++) {
for (int j = 0; j < MAX_SYMBOLS; j++) {
action[i][j].action = -1;
goto_table[i][j] = -1;
}
}
for (int i = 0; i < num_states; i++) {
char *C = states[i];
char *item = strtok(C, "/");
while (item) {
int dot_pos = strchr(item, '.') - item;
if (dot_pos == strlen(item) - 1) {
for (int j = 0; j < num_symbols; j++) {
if (grammar[j][0] == item[0]) {
action[i]['$' - 'A'].action = ACCEPT;
action[i]['$' - 'A'].num = j;
break;
}
}
} else {
char X = item[dot_pos + 1];
if (X >= 'a' && X <= 'z') {
action[i][X - 'A'].action = SHIFT;
action[i][X - 'A'].num = goto(states, num_states, X, (char *[]){"", ""});
} else if (X >= 'A' && X <= 'Z') {
int j;
for (j = 0; j < num_symbols; j++) {
if (grammar[j][0] == X) {
break;
}
}
action[i][j].action = REDUCE;
action[i][j].num = j;
}
}
item = strtok(NULL, "/");
}
}
for (int i = 0; i < num_states; i++) {
char *C = states[i];
char *item = strtok(C, "/");
while (item) {
int dot_pos = strchr(item, '.') - item;
if (dot_pos < strlen(item) - 1) {
char X = item[dot_pos + 1];
if (X >= 'A' && X <= 'Z') {
goto_table[i][X - 'A'] = goto(states, num_states, X, (char *[]){"", ""});
}
}
item = strtok(NULL, "/");
}
}
}
// 测试
int parse_LR0(char *string) {
int stack[MAX_STATES];
int top = 0;
stack[top++] = 0;
char *input_str = malloc(strlen(string) + 2);
strcpy(input_str, string);
strcat(input_str, "$");
int output[MAX_PRODUCTIONS];
int num_output = 0;
while (1) {
int state = stack[top - 1];
char a = input_str[0];
if (action[state][a - 'A'].action == -1) {
printf("error\n");
return -1;
}
switch (action[state][a - 'A'].action) {
case SHIFT:
stack[top++] = action[state][a - 'A'].num;
input_str++;
break;
case REDUCE: {
int num = action[state][a - 'A'].num;
output[num_output++] = num;
char *production = grammar[num];
int len = strlen(production) - 3;
for (int i = 0; i < len * 2; i++) {
top--;
}
state = stack[top - 1];
stack[top++] = goto_table[state][production[0] - 'A'];
break;
}
case ACCEPT:
output[num_output++] = num_symbols;
for (int i = 0; i < num_output; i++) {
printf("%s\n", grammar[output[i]]);
}
return 0;
}
}
}
int main() {
construct_LR0_automaton();
construct_LR0_table();
parse_LR0("id+id*id");
return 0;
}
```
这段代码实现了一个简单的LR(0)分析程序,包括构造LR(0)自动机和分析表,以及使用分析表进行语法分析的过程。
阅读全文