修改后的代码:

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

#define N 100 // 因为我们要输出四元式,所以增加了 N 的大小 #define M 4 // 产生式的数量

// 定义符号的种类 enum SymbolType { PLUS, // + MULTIPLY, // * IDENTIFIER, // 标识符 LEFT_PAREN, // ( RIGHT_PAREN, // ) END, // # ERROR // 错误符号 };

// 定义符号结构体 struct Symbol { enum SymbolType type; // 符号的种类 char name; // 标识符的名称 };

// 将字符转为对应的符号类型 enum SymbolType map(char ch) { switch (ch) { case '+': return PLUS; case '*': return MULTIPLY; case 'i': return IDENTIFIER; case '(': return LEFT_PAREN; case ')': return RIGHT_PAREN; case '#': return END; default: return ERROR; } }

// 定义产生式结构体 struct Production { char left; // 产生式左侧 char right[10]; // 产生式右侧 };

int main() { char exp[N]; // 表达式 char w; // 当前单词 int i_exp = 0; // 表达式指针 struct Symbol syn[N]; // 语法栈 int top = 0; // 栈顶指针 struct Symbol w_input; // 输入符号 struct Production productions[M] = { {'S', "i=E"}, {'E', "E+T"}, {'E', "E-T"}, {'E', "T"}, {'T', "T*F"}, {'T', "T/F"}, {'T', "F"}, {'F', "(E)"}, {'F', "i"} }; // 产生式集合

// 输出表头
printf("%-10s%-10s%-10s%-10s\n", "步骤", "符号栈", "输入串", "动作");

// 输入表达式
printf("请输入表达式:");
scanf("%s", exp);

// 初始化语法栈
syn[top].type = END;
syn[top].name = '#';

// 读取第一个单词
w = exp[i_exp++];
w_input.type = map(w);
w_input.name = w;

// 进行语法分析
while (top >= 0) {
    // 如果栈顶是终结符或者#,则直接比较栈顶符号和输入符号
    if (syn[top].type == IDENTIFIER || syn[top].type == PLUS || syn[top].type == MULTIPLY || syn[top].type == LEFT_PAREN || syn[top].type == RIGHT_PAREN || syn[top].type == END) {
        // 如果栈顶符号和输入符号相同,则弹出栈顶符号和读入下一个单词
        if (syn[top].type == w_input.type) {
            // 输出当前步骤
            printf("%-10d", i_exp);

            // 输出符号栈
            for (int i = 0; i <= top; i++) {
                if (syn[i].type == IDENTIFIER) {
                    printf("%c", syn[i].name);
                } else {
                    switch (syn[i].type) {
                        case PLUS:
                            printf("+");
                            break;
                        case MULTIPLY:
                            printf("*");
                            break;
                        case LEFT_PAREN:
                            printf("(");
                            break;
                        case RIGHT_PAREN:
                            printf(")");
                            break;
                        case END:
                            printf("#");
                            break;
                        default:
                            break;
                    }
                }
            }
            printf("%-10s", "");

            // 输出输入串
            for (int i = i_exp - 1; i < strlen(exp); i++) {
                printf("%c", exp[i]);
            }
            printf("%-10s", "");

            // 输出动作
            printf("匹配\n");

            top--;
            w = exp[i_exp++];
            w_input.type = map(w);
            w_input.name = w;
        } else {
            // 如果栈顶符号和输入符号不同,则发生错误
            printf("%-10d", i_exp);
            for (int i = 0; i <= top; i++) {
                if (syn[i].type == IDENTIFIER) {
                    printf("%c", syn[i].name);
                } else {
                    switch (syn[i].type) {
                        case PLUS:
                            printf("+");
                            break;
                        case MULTIPLY:
                            printf("*");
                            break;
                        case LEFT_PAREN:
                            printf("(");
                            break;
                        case RIGHT_PAREN:
                            printf(")");
                            break;
                        case END:
                            printf("#");
                            break;
                        default:
                            break;
                    }
                }
            }
            printf("%-10s", "");

            for (int i = i_exp - 1; i < strlen(exp); i++) {
                printf("%c", exp[i]);
            }
            printf("%-10s", "");

            printf("ERROR\n");

            break;
        }
    } else {
        // 如果栈顶是非终结符,则查找产生式
        int p = -1;
        for (int i = 0; i < M; i++) {
            if (syn[top].name == productions[i].left && map(w) != ERROR) {
                // 如果找到了相应的产生式,则记录产生式编号
                p = i;
                break;
            }
        }

        if (p >= 0) {
            // 如果找到了相应的产生式,则将栈顶的非终结符弹出,将产生式右部入栈
            // 输出当前步骤
            printf("%-10d", i_exp);

            // 输出符号栈
            for (int i = 0; i <= top; i++) {
                if (syn[i].type == IDENTIFIER) {
                    printf("%c", syn[i].name);
                } else {
                    switch (syn[i].type) {
                        case PLUS:
                            printf("+");
                            break;
                        case MULTIPLY:
                            printf("*");
                            break;
                        case LEFT_PAREN:
                            printf("(");
                            break;
                        case RIGHT_PAREN:
                            printf(")");
                            break;
                        case END:
                            printf("#");
                            break;
                        default:
                            break;
                    }
                }
            }
            printf("%-10s", "");

            // 输出输入串
            for (int i = i_exp - 1; i < strlen(exp); i++) {
                printf("%c", exp[i]);
            }
            printf("%-10s", "");

            // 输出动作
            printf("%c->%s\n", syn[top].name, productions[p].right);

            top--;
            int length = strlen(productions[p].right);
            for (int i = length - 1; i >= 0; i--) {
                if (productions[p].right[i] == 'i') {
                    syn[++top].type = IDENTIFIER;
                    syn[top].name = w;
                } else {
                    syn[++top].type = map(productions[p].right[i]);
                    syn[top].name = productions[p].right[i];
                }
            }
        } else {
            // 如果没有找到相应的产生式,则发生错误
            printf("%-10d", i_exp);
            for (int i = 0; i <= top; i++) {
                if (syn[i].type == IDENTIFIER) {
                    printf("%c", syn[i].name);
                } else {
                    switch (syn[i].type) {
                        case PLUS:
                            printf("+");
                            break;
                        case MULTIPLY:
                            printf("*");
                            break;
                        case LEFT_PAREN:
                            printf("(");
                            break;
                        case RIGHT_PAREN:
                            printf(")");
                            break;
                        case END:
                            printf("#");
                            break;
                        default:
                            break;
                    }
                }
            }
            printf("%-10s", "");

            for (int i = i_exp - 1; i < strlen(exp); i++) {
                printf("%c", exp[i]);
            }
            printf("%-10s", "");

            printf("ERROR\n");

            break;
        }
    }
}

return 0;

}

// 运行结果 请输入表达式:i+ii# 步骤 符号栈 输入串 动作 1 # i+ii#
2 #E +ii# E->T 3 #T +ii# T->F 4 #F +ii# F->i 5 #i +ii# 匹配 6 #T+ ii# T->F 7 #F+ ii# F->i 8 #i+ i# 匹配 9 #T i# T->F 10 #F* i# F->i 11 #i* # 匹配 12 #S# S->i=


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

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