• Test语言编译器V0.8


    感觉这个挺好耍的,书上的代码有错误,而且功能有限。

    一、词法分析

    特点:

    (1)可对中文进行识别
    (2)暂不支持负数,可以在读入‘-'时进行简单标记后就能对简单负数进行识别了。

    #include <iostream>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    
    using namespace std;
    
    #define KEYWORDNUM 9    // 关键字个数
    #define MAXLENGTH 39    // 标识符最大长度
    #define MAXFILENAME 100 // 文件名最大长度
    
    namespace Testscan {
        FILE *fin, *fout;
        char Scanin[MAXFILENAME], Scanout[MAXFILENAME];
        char *keyword[KEYWORDNUM] = {"if", "else", "for", "while", "do", "int", "read", "write", "main"};
        char singleword[] = "+-*%(){};,:";
        char doubleword[] = "><=!";
        char token[MAXLENGTH + 2]; // 存放识别单词
        int frow, brow;            // 符号起止行标记
        int i, j, k, es;           // 临时整型变量
        char ch, ch1;              // 临时字符变量
    }
    
    using namespace Testscan;
    
    /*****************************
    错误列表:
    打开输入文件出错
    打开输出文件出错
    标识符过长
    标识符命名不合法
    ******************************/
    
    int Init() {
        // printf("请输入源程序文件名(包括路径):
    ");
        // scanf("%s", Scanin);
        // printf("请输入词法分析输出文件名(包括路径):
    ");
        // scanf("%s", Scanout);
    
        strcpy(Scanin, "C:\Users\Administrator\Desktop\in.txt");
        strcpy(Scanout, "C:\Users\Administrator\Desktop\out1.txt");
    
        if ((fin = fopen(Scanin, "r")) == NULL) {
            printf("打开词法分析输入文件出错!
    ");
            return 1;
        }
        if ((fout = fopen(Scanout, "w")) == NULL) {
            printf("创建词法分析输出文件出错!
    ");
            return 2;
        }
        return 0;
    }
    
    char getNextChar() {
        char ch = getc(fin);
        if (ch == '
    ') frow++;
        return ch;
    }
    
    int TESTscan() {
        int es = Init();
        if (es > 0) return es;
    
        frow = brow = 1;
        ch = getNextChar();
        while (ch != EOF) {
            while (ch == ' ' || ch == '
    ' || ch == '	') {
                ch = getNextChar();
            }
    
            brow = frow;
            if (ch == EOF) break;
    
            if (isalpha(ch)) { // 字母
                j = 0;
                token[j++] = ch;
                bool isLong = false; // 超长标记
                ch = getNextChar();
                while (isalnum(ch)) { // 字母+数字
                    token[j++] = ch;
                    ch = getNextChar();
                    if (j > MAXLENGTH) {
                        isLong = true;
                        while (isalnum(ch)) { // 超长自动截断
                            ch = getNextChar();
                        }
                    }
                }
                token[j] = '';
                if (isLong == true) { // 标识符太长
                    es = 3;
                    printf("ERROR(%d): 标识符"%s"超长
    ", brow, token);
                    fprintf(fout, "%d	%s	%s
    ", brow, "ERROR", token);
                    continue;
                }
    
                k = 0;
                char str[MAXLENGTH + 2];
                for (i = 0; i < strlen(token); i++) { // 小写化
                    str[i] = tolower(token[i]);
                }
                str[i] = '';
                while (k < KEYWORDNUM && strcmp(str, keyword[k]))
                    k++;
                if (k >= KEYWORDNUM)
                    fprintf(fout, "%d	%s	%s
    ", brow, "ID", token);
                else
                    fprintf(fout, "%d	%s	%s
    ", brow, str, token);
            } else if (isdigit(ch)) { // 数字
                j = 0;
                token[j++] = ch;
                ch = getNextChar();
                while (isdigit(ch)) {
                    token[j++] = ch;
                    ch = getNextChar();
                }
                token[j] = '';
                fprintf(fout, "%d	%s	%s
    ", brow, "NUM", token);
            } else if (strchr(singleword, ch) > 0) { // 单分界符
                token[0] = ch;
                token[1] = '';
                fprintf(fout, "%d	%s	%s
    ", brow, token, token);
                ch = getNextChar();
            } else if (strchr(doubleword, ch) > 0) { // 双分界符
                token[0] = ch;
                ch = getNextChar();
                if (ch == '=') {
                    token[1] = ch;
                    token[2] = '';
                    ch = getNextChar();
                } else token[1] = '';
                fprintf(fout, "%d	%s	%s
    ", brow, token, token);
            } else if (ch == '/') { // 注释
                ch = getNextChar();
                if (ch == '*') {
                    ch1 = getNextChar();
                    do { // 删除注释
                        ch = ch1;
                        ch1 = getNextChar();
                    } while ((ch != '*' || ch1 != '/') && ch1 != EOF);
                    ch = getNextChar();
                } else {
                    token[0] = '/';
                    token[1] = '';
                    fprintf(fout, "%d	%s	%s
    ", brow, token, token);
                }
            } else if (ch == '"') { // 字符串
                j = 0;
                ch = getNextChar();
                while (ch != '"') {
                    token[j++] = ch;
                    ch = getNextChar();
                }
                token[j] = '';
                fprintf(fout, "%d	%s	%s
    ", brow, "STR", token);
                ch = getNextChar();
            } else { // 命名不规范
                token[0] = ch;
                token[1] = '';
                if (ch < 0) { //中文处理
                    ch = getNextChar();
                    token[1] = ch;
                    token[2] = '';
                }
                es = 4;
                fprintf(fout, "%d	%s	%s
    ", brow, "ERROR", token);
                printf("ERROR(%d): 符号"%s"不规范
    ", brow, token);
                ch = getNextChar();
            }
        }
        fprintf(fout, "%d	EOF	EOF
    ", brow);
        fclose(fin);
        fclose(fout);
        return es;
    }

    二、语法分析

    特点:

    (1)修正书上代码中存在的大量错误

    (2)增加对复合语句的处理

    (3)支持变量连续定义

    (4)支持字符串(可带空白字符)的输出

    (5)报错具体到行中的具体位置

    (6)无除0报错,首先除0报错不属于语法分析,其次通过改正也只能报5/0这种显式错误,不能报9/(3+2-5)这种错误,因此意义不大

    (7)无死循环错误,首先不属于语法分析,其次现在没有一种程序设计语言能报这种错误,循环中可根据条件改变变量的值,是不可预知的

    #include <stdio.h>
    #include <ctype.h>
    #include <conio.h>
    #include <string.h>
    #include <windows.h>
    
    int TESTparse();
    int program();
    int compound_Stat();
    int statement();
    int expression_Stat();
    int expression();
    int bool_expr();
    int additive_expr();
    int term();
    int factor();
    int if_stat();
    int while_stat();
    int for_stat();
    int write_stat();
    int read_stat();
    int do_while_stat();
    int declaration_stat();
    int declaration_list();
    int statement_list();
    int compound_stat();
    int expression_stat();
    
    #define MAXFILENAME 100 // 文件名最大长度
    #define MAXLENGTH 40    // 字符串最大长度
    
    namespace Testparse1{
        int wrow;                                       // 错误行号
        FILE *fin, *fout;                               // 输入输出文件的指针
        char token[MAXLENGTH], token1[MAXLENGTH];       // token保存单词符号,token1保存单词值
        char Scanin[MAXFILENAME], Scanout[MAXFILENAME]; // 输入输出文件名
    }
    using namespace Testparse1;
    
    int TESTparse() {
        int es = 0;
        if ((fin = fopen(Scanin, "r")) == NULL) {
            printf("
    打开%s错误!
    ", Scanout);
            es = 10;
        }
    
        if ((fout = fopen(Scanout, "w")) == NULL) {
            printf("
    打开%s错误!
    ", Scanout);
            es = 10;
        }
    
        if (es == 0) es = program();
        printf("=====语法分析结果!======
    ");
        switch (es) {
            case 0:
                printf("语法分析成功!
    ");
                break;
            case 10:
                printf("打开文件失败!
    ");
                break;
            case 1:
                printf("ERROR(%d): "%s"前面缺少{
    ", wrow, token1);
                break;
            case 2:
                printf("ERROR(%d): "%s"前面缺少}
    ", wrow, token1);
                break;
            case 3:
                printf("ERROR(%d): "%s"前面缺少标识符
    ", wrow, token1);
                break;
            case 4:
                printf("ERROR(%d): "%s"前面缺少分号
    ", wrow, token1);
                break;
            case 5:
                printf("ERROR(%d): "%s"前面缺少(
    ", wrow, token1);
                break;
            case 6:
                printf("ERROR(%d): "%s"前面缺少)
    ", wrow, token1);
                break;
            case 7:
                printf("ERROR(%d): "%s"前面缺少操作数
    ", wrow, token1);
                break;
            case 9:
                printf("ERROR(%d): "%s"前面缺少主程序
    ", wrow, token1);
                break;
            case 11:
                printf("ERROR(%d): 主程序名错误!
    ", wrow);
                break;
            case 12:
                printf("ERROR(%d): "%s"前面缺少while
    ", wrow, token1);
                break;
            case 25:
                printf("ERROR(%d): "%s"已超出程序末尾
    ", wrow, token1);
                break;
            case 26:
                printf("ERROR(%d): else没有匹配的if
    ", wrow);
        }
        fclose(fin);
        fclose(fout);
        return es;
    }
    
    // <程序>::={<声明序列><语句序列>}
    // program::={<declaration_list><statement_list>}
    int program() {
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = declaration_list(); // 声明语句
        if (es > 0) return es;
    
        if (strcmp(token, "main")) return 9; // main区
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "ID")) return 11; // 程序名
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "{")) return 1; // 判断是否'{'
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = statement_list(); // 语句序列
        if (es > 0) return es;
        if (strcmp(token, "}")) return 2; // 判断是否'}'
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "EOF")) return 25; // 超出程序末尾
        return es;
    }
    
    // <声明序列>::=<声明序列><声明语句>|<声明语句>
    // <declaration_list>::=<declaration_list><declaration_stat>|<declaration_stat>
    int declaration_list() {
        int es = 0;
        while (strcmp(token, "int") == 0) {
            es = declaration_stat();
            if (es > 0) return es;
        }
        return es;
    }
    
    // <声明语句>::=int<变量>;
    // <declaration_stat>::=int ID;
    int declaration_stat() {
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        while (1) { // 支持连续定义
            if (strcmp(token, "ID")) return 3; // 不是标识符
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            if (strcmp(token, ",") == 0) {
                fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
                printf("%s %s
    ", token, token1);
            } else break;
        }
        if (strcmp(token, ";")) return 4; // 缺少分号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        return es;
    }
    
    // <语句序列>::=<语句序列><语句>|<语句>
    // <statement_list>::=<statement_list><statement>|<statement>
    int statement_list() {
        int es = 0;
        while (strcmp(token, "}")) {
            es = statement();
            if (es > 0) return es;
            if (strcmp(token, "EOF") == 0) {
                return 2; // 缺少}
            }
        }
        return es;
    }
    
    // <语句>::=<if语句>|<while语句>|<for语句>|<read语句>|<write语句>|<复合语句>|<表达式语句>
    // <statement>::= <if_stat>|<while_stat>|<for_stat>|<compound_stat>|<expression_stat>
    int statement() {
        int es = 0;
        if ((strcmp(token, "if") == 0 || strcmp(token, "else") == 0)) es = if_stat(); // <IF语句>
        else if (strcmp(token, "while") == 0) es = while_stat();                      // <while语句>
        else if (strcmp(token, "for") == 0) es = for_stat();                          // <for语句>
        else if (strcmp(token, "do") == 0) es = do_while_stat();                      // do_while语句
        else if (strcmp(token, "read") == 0) es = read_stat();                        // <read语句>
        else if (strcmp(token, "write") == 0) es = write_stat();                      // <write语句>
        else if (strcmp(token, "{") == 0) es = compound_stat();                       // <复合语句>
        else if ((strcmp(token, "ID") == 0 || strcmp(token, "NUM") == 0 || strcmp(token, "(") == 0) ||
                 strcmp(token, ";") == 0)
            es = expression_stat();                                                   // <表达式语句>
        return es;
    }
    
    // <IF语句>::=if(<表达式>)<语句>[else<语句>]
    // <IF_stat>::=if(<expr>)<statement>[else<statement>]
    int if_stat() {
        if (strcmp(token, "else") == 0) return 26; // else未匹配if
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "(")) return 5; // 缺少左括号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ")")) return 6; // 缺少右括号
    
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = statement(); // 语句
        if (es > 0) return es;
    
        if (strcmp(token, "else") == 0) { // else部分处理
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            es = statement();
            if (es > 0) return es;
        }
        return es;
    }
    
    // <复合语句>::={<语句序列>}
    // <compound_stat>::={<statement_list>}
    int compound_stat() {
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = statement_list(); // 语句序列
        if (es > 0) return es;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        return es;
    }
    
    // <do_whilie语句>::do{语句序列}while(表达式)
    // <do_whilie_stat>::do{statment_list}while(expression)
    int do_while_stat() {
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "{")) return 1; // 缺少左括号
        es = statement(); //语句
        if (es > 0) return es;
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "while")) return 12; // 缺少while
    
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "(")) return 5; // 缺少左括号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
    
        es = expression(); // 表达式
        if (es > 0) return es;
    
        if (strcmp(token, ")")) return 6; // 缺少右括号
        if (es > 0) return es;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        return es;
    }
    
    // <while语句>::=while(<表达式>)<语句>
    // <while_stat>::=while(<expr>)<statement >
    int while_stat() {
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "(")) return 5; // 缺少左括号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ")")) return 6; // 缺少右括号
    
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = statement();
        if (es > 0) return es;
        return es;
    }
    
    // <for语句>::=for(<表达式>;<表达式>;<表达式>)<语句>
    // <for_stat>::=for(<expr>,<expr>,<expr>)<statement>
    // <for_stat>::=for (<expression>;
    int for_stat() {
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "(")) return 5; // 缺少左括号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ";")) return 4; // 缺少分号
    
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ";")) return 4; // 缺少分号
    
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ")")) return 6; // 缺少右括号
    
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = statement();
        if (es > 0) return es;
        return es;
    }
    
    // <read_语句>::=read<变量>;
    // <read_stat>::=read ID;
    int read_stat() {
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "ID")) return 3; // 缺少标识符
    
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, ";")) return 4; // 缺少分号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        return es;
    }
    
    // <write_语句>::=write <表达式>;
    // <write_stat>::=write <expression>;
    // <write_STR>::write <STR>;
    int write_stat() {
        int es = 0;
        fscanf(fin, "%d %s ", &wrow, token);
        printf("%s ", token);
        if (strcmp(token, "STR") == 0) { // 输出字符串
            fgets(token1, 1024, fin);
            printf("%s", token1);
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            if (strcmp(token, ";")) return 4; // 缺少分号
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            return es;
        }
        fscanf(fin, "%s", &token1);
        printf("%s
    ", token1);
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ";")) return 4; // 缺少分号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        return es;
    }
    
    // <表达式语句>::=<<表达式>;|;
    // <expression_stat>::=<expression>;|;
    int expression_stat() {
        int es = 0;
        if (strcmp(token, ";") == 0) {
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            return es;
        }
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ";") == 0) {
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            return es;
        } else {
            return 4; // 缺少分号
        }
    }
    
    // <表达式>::=<标识符>=<布尔表达式>|<布尔表达式>
    // <expr>::=ID=<bool_expr>|<bool_expr>
    int expression() {
        int es = 0, fileadd;
        char token2[MAXLENGTH + 2], token3[MAXLENGTH + 2];
        if (strcmp(token, "ID") == 0) {
            fileadd = ftell(fin); // 记住当前文件位置
            fscanf(fin, "%d %s %s
    ", &wrow, token2, token3);
            printf("%s %s
    ", token2, token3);
    
            if (strcmp(token2, "=") == 0) { //'='
                fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
                printf("%s %s
    ", token, token1);
                es = bool_expr();
                if (es > 0) return es;
            } else { // "=="
                fseek(fin, fileadd, 0); // 若非'='则文件指针回到'='前的标识符
                es = bool_expr();
                if (es > 0) return es;
            }
        } else {
            es = bool_expr();
        }
        return es;
    }
    
    // <布尔表达式>::=<算术表达式>|<算术表达式>(>|<|>=|<=|==|!=)<算术表达式>
    // <bool_expr>::=<additive_expr>|< additive_expr >(>|<|>=|<=|==|!=)< additive_expr >
    int bool_expr() {
        int es = 0;
        es = additive_expr();
        if (es > 0) return es;
        if (strcmp(token, ">") == 0 || strcmp(token, ">=") == 0 || strcmp(token, "<") == 0 ||
            strcmp(token, "<=") == 0 || strcmp(token, "==") == 0 || strcmp(token, "!=") == 0) {
            char token2[MAXLENGTH + 2];
            strcpy(token2, token); // 保存运算符
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            es = additive_expr();
            if (es > 0) return es;
        }
        return es;
    }
    
    // <算术表达式>::=<项>{(+|-)<项>}
    // <additive_expr>::=<term>{(+|-)< term >}
    // < additive_expr>::=<term>{(+< term >@ADD |-<项>@SUB)}
    int additive_expr() {
        int es = 0;
        es = term();
        if (es > 0) return es;
        while (strcmp(token, "+") == 0 || strcmp(token, "-") == 0) {
            char token2[MAXLENGTH + 2];
            strcpy(token2, token);
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            es = term();
            if (es > 0) return es;
        }
        return es;
    }
    
    // <项>::=<因子>{(*|/)<因子>}
    // < term >::=<factor>{(*| /)< factor >}
    // < term >::=<factor>{(*< factor >@MULT | /< factor >@DIV)}
    int term() {
        int es = 0;
        es = factor();
        if (es > 0) return es;
        while (strcmp(token, "*") == 0 || strcmp(token, "/") == 0 || strcmp(token, "%") == 0) {
            char token2[MAXLENGTH + 2];
            strcpy(token2, token);
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            es = factor();
            if (es > 0) return es;
        }
        return es;
    }
    
    // <因子>::=(<算术表达式>)|<标识符>|<无符号整数>
    // < factor >::=(<additive_expr>)| ID|NUM
    int factor() {
        int es = 0;
        if (strcmp(token, "(") == 0) {
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            es = expression(); // 表达式
            if (es > 0) return es;
            if (strcmp(token, ")")) return 6; // 缺少右括号
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
        } else {
            if (strcmp(token, "ID") == 0) {
                fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
                printf("%s %s
    ", token, token1);
                return es;
            } else if (strcmp(token, "NUM") == 0) {
                fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
                return es;
            } else {
                return 7; // 缺少操作数
            }
        }
        return es;
    }

     

    三、语义分析

    特点同上

    #include <stdio.h>
    #include <ctype.h>
    #include <conio.h>
    #include <string.h>
    #include <windows.h>
    
    int TESTparse();
    int program();
    int compound_Stat();
    int statement();
    int expression_Stat();
    int expression();
    int bool_expr();
    int additive_expr();
    int term();
    int factor();
    int if_stat();
    int while_stat();
    int for_stat();
    int write_stat();
    int read_stat();
    int do_while_stat();
    int declaration_stat();
    int declaration_list();
    int statement_list();
    int compound_stat();
    int expression_stat();
    
    #define MAXVARTABLEP 500 // 定义符号表的容量
    #define MAXFILENAME 100  // 文件名最大长度
    #define MAXLENGTH 40     // 字符串最大长度
    
    namespace Testparse {
        struct Table {       // 定义符号表结构
            char name[MAXLENGTH];
            int address;
        } vartable[MAXVARTABLEP];
        int vartablep = 0, labelp = 0, datap = 0;
    
        int wrow;                                       // 错误行号
        FILE *fin, *fout;                               // 输入输出文件的指针
        char token[MAXLENGTH], token1[MAXLENGTH];       // token保存单词符号,token1保存单词值
        char Scanin[MAXFILENAME], Scanout[MAXFILENAME]; // 输入输出文件名
    }
    using namespace Testparse;
    
    int TESTparse() {
        // system("C:\Users\Administrator\Desktop\test.exe");
        strcpy(Scanin, "C:\Users\Administrator\Desktop\out1.txt");
        strcpy(Scanout, "C:\Users\Administrator\Desktop\out2.txt");
    
    
        int es = 0;
        if ((fin = fopen(Scanin, "r")) == NULL) {
            printf("
    打开%s错误!
    ", Scanout);
            es = 10;
        }
    
        if ((fout = fopen(Scanout, "w")) == NULL) {
            printf("
    打开%s错误!
    ", Scanout);
            es = 10;
        }
    
        if (es == 0) es = program();
        printf("=====语法分析结果!======
    ");
        switch (es) {
            case 0:
                printf("语义分析成功!
    ");
                break;
            case 10:
                printf("打开文件失败!
    ");
                break;
            case 1:
                printf("ERROR(%d): "%s"前面缺少{
    ", wrow, token1);
                break;
            case 2:
                printf("ERROR(%d): "%s"前面缺少}
    ", wrow, token1);
                break;
            case 3:
                printf("ERROR(%d): "%s"前面缺少标识符
    ", wrow, token1);
                break;
            case 4:
                printf("ERROR(%d): "%s"前面缺少分号
    ", wrow, token1);
                break;
            case 5:
                printf("ERROR(%d): "%s"前面缺少(
    ", wrow, token1);
                break;
            case 6:
                printf("ERROR(%d): "%s"前面缺少)
    ", wrow, token1);
                break;
            case 7:
                printf("ERROR(%d): "%s"前面缺少操作数
    ", wrow, token1);
                break;
            case 9:
                printf("ERROR(%d): "%s"前面缺少主程序
    ", wrow, token1);
                break;
            case 11:
                printf("ERROR(%d): 主程序名错误!
    ", wrow);
                break;
            case 12:
                printf("ERROR(%d): "%s"前面缺少while
    ", wrow, token1);
                break;
            case 21:
                printf("ERROR(%d): 符号表溢出
    ", wrow);
                break;
            case 22:
                printf("ERROR(%d): 变量"%s"重复定义
    ", wrow, token1);
                break;
            case 23:
                printf("ERROR(%d): 变量"%s"未声明
    ", wrow, token1);
                break;
            case 25:
                printf("ERROR(%d): "%s"已超出程序末尾
    ", wrow, token1);
                break;
            case 26:
                printf("ERROR(%d): else没有匹配的if
    ", wrow);
        }
        fclose(fin);
        fclose(fout);
        return es;
    }
    
    // 插入符号表
    int name_def(char *name) {
        if (vartablep >= MAXVARTABLEP) return 21; // 符号表溢出
        for (int i = vartablep - 1; i >= 0; i--) {
            if (strcmp(vartable[i].name, name) == 0) {
                return 22; // 变量重复定义
            }
        }
        strcpy(vartable[vartablep].name, name);
        vartable[vartablep++].address = datap++;
        return 0;
    }
    
    // 查询符号表返回地址
    int lookup(char *name, int *paddress) {
        for (int i = 0; i < vartablep; i++) {
            if (strcmp(vartable[i].name, name) == 0) {
                *paddress = vartable[i].address;
                return 0;
            }
        }
        return 23; // 变量未声明
    }
    
    // <程序>::={<声明序列><语句序列>}
    // program::={<declaration_list><statement_list>}
    int program() {
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = declaration_list(); // 声明语句
        if (es > 0) return es;
    
        printf("             符号表
    "); // 符号表输出
        printf("        名字      地址
    ");
        for (int i = 0; i < vartablep; i++)
            printf("%10s%10d
    ", vartable[i].name, vartable[i].address);
    
        if (strcmp(token, "main")) return 9; // main区
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "ID")) return 11; // 程序名
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "{")) return 1; // 判断是否'{'
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = statement_list(); // 语句序列
        if (es > 0) return es;
        if (strcmp(token, "}")) return 2; // 判断是否'}'
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "EOF")) return 25; // 超出程序末尾
        fprintf(fout, "        STOP
    "); // 产生停止指令
        return es;
    }
    
    // <声明序列>::=<声明序列><声明语句>|<声明语句>
    // <declaration_list>::=<declaration_list><declaration_stat>|<declaration_stat>
    int declaration_list() {
        int es = 0;
        while (strcmp(token, "int") == 0) {
            es = declaration_stat();
            if (es > 0) return es;
        }
        return es;
    }
    
    // <声明语句>::=int<变量>;
    // <declaration_stat>::=int ID;
    // <declaration_stat>↓vartablep,datap,codep ->int ID↑n@name-def↓n,t;
    int declaration_stat() {
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        while (1) { // 支持连续定义
            if (strcmp(token, "ID")) return 3; // 不是标识符
            es = name_def(token1); //插入到符号表
            if (es > 0) return es;
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            if (strcmp(token, ",") == 0) {
                fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
                printf("%s %s
    ", token, token1);
            } else break;
        }
        if (strcmp(token, ";")) return 4; // 缺少分号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        return es;
    }
    
    // <语句序列>::=<语句序列><语句>|<语句>
    // <statement_list>::=<statement_list><statement>|<statement>
    int statement_list() {
        int es = 0;
        while (strcmp(token, "}")) {
            es = statement();
            if (es > 0) return es;
            if (strcmp(token, "EOF") == 0) {
                return 2; // 缺少}
            }
        }
        return es;
    }
    
    // <语句>::=<if语句>|<while语句>|<for语句>|<read语句>|<write语句>|<复合语句>|<表达式语句>
    // <statement>::= <if_stat>|<while_stat>|<for_stat>|<compound_stat>|<expression_stat>
    int statement() {
        int es = 0;
        if ((strcmp(token, "if") == 0 || strcmp(token, "else") == 0)) es = if_stat(); // <IF语句>
        else if (strcmp(token, "while") == 0) es = while_stat();                      // <while语句>
        else if (strcmp(token, "for") == 0) es = for_stat();                          // <for语句>
        else if (strcmp(token, "do") == 0) es = do_while_stat();                      // do_while语句
        else if (strcmp(token, "read") == 0) es = read_stat();                        // <read语句>
        else if (strcmp(token, "write") == 0) es = write_stat();                      // <write语句>
        else if (strcmp(token, "{") == 0) es = compound_stat();                       // <复合语句>
        else if ((strcmp(token, "ID") == 0 || strcmp(token, "NUM") == 0 || strcmp(token, "(") == 0) ||
                 strcmp(token, ";") == 0)
            es = expression_stat(); // <表达式语句>
        return es;
    }
    
    // <IF语句>::=if(<表达式>)<语句>[else<语句>]
    // <IF_stat>::=if(<expr>)<statement>[else<statement>]
    // if (<expression>)@BRF↑label1 <statement > @BR↑label2 @SETlabel↓label1 
    // [ else < statement >] @SETlabel↓label2
    //  其中动作符号的含义如下
    //  @BRF↑label1 :输出 BRF label1, 
    //  @BR↑label2:输出 BR label2, 
    //  @SETlabel↓label1:设置标号label1 
    //  @SETlabel↓label2:设置标号label2
    int if_stat() {
        if (strcmp(token, "else") == 0) return 26; // else未匹配if
        int es = 0, label1, label2;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "(")) return 5; // 缺少左括号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ")")) return 6; // 缺少右括号
        label1 = labelp++; // 用label1记住条件为假时要转向的标号
        fprintf(fout, "        BRF LABEL%d
    ", label1);
    
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = statement(); // 语句
        if (es > 0) return es;
    
        label2 = labelp++; // 用label2记住要转向的标号
        fprintf(fout, "        BR LABEL%d
    ", label2);
        fprintf(fout, "LABEL%d:
    ", label1); // 设置label1记住的标号
    
        if (strcmp(token, "else") == 0) { // else部分处理
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            es = statement();
            if (es > 0) return es;
        }
        fprintf(fout, "LABEL%d:
    ", label2); // 设置label2记住的标号
        return es;
    }
    
    // <复合语句>::={<语句序列>} 
    // <compound_stat>::={<statement_list>} 
    int compound_stat() {
        int es = 0;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = statement_list(); // 语句序列
        if (es > 0) return es;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        return es;
    }
    
    // <do_whilie语句>::do{语句序列}while(表达式)
    // <do_whilie_stat>::do{statment_list}while(expression)
    int do_while_stat() {
        int es = 0, label1, label2;
        label1 = labelp++;
        fprintf(fout, "LABEL%d:
    ", label1); // 设置label1标号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "{")) return 1; // 缺少左括号
        es = statement(); // 语句
        if (es > 0) return es;
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "while")) return 12; //缺少while
    
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "(")) return 5; // 缺少左括号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
    
        es = expression(); // 表达式
        if (es > 0) return es;
        label2 = labelp++;
        fprintf(fout, "        BRF LABEL%d
    ", label2);
        fprintf(fout, "        BR LABEL%d
    ", label1);
    
        if (strcmp(token, ")")) return 6; // 缺少右括号
        if (es > 0) return es;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        fprintf(fout, "LABEL%d:
    ", label2); // 设置label2标号
        return es;
    }
    
    // <while语句>::=while(<表达式>)<语句>
    // <while_stat>::=while(<expr>)<statement >
    // <while_stat>::=while @SET↑labellabel1(<expression>) @BRF↑label2 
    //                 <statement >@BR↓label1 @SETlabel↓label2
    // 动作解释如下:
    // @SETlabel↑label1:设置标号label1
    // @BRF↑label2 :输出 BRF label2,
    // @BR↓label1:输出 BR label1,
    // @SETlabel↓label2:设置标号label2
    int while_stat() {
        int es = 0, label1, label2;
        label1 = labelp++;
        fprintf(fout, "LABEL%d:
    ", label1); // 设置label1标号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "(")) return 5; // 缺少左括号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ")")) return 6; // 缺少右括号
    
        label2 = labelp++;
        fprintf(fout, "        BRF LABEL%d
    ", label2);
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = statement();
        if (es > 0) return es;
        fprintf(fout, "        BR LABEL%d
    ", label1);
        fprintf(fout, "LABEL%d:
    ", label2); // 设置label2标号
        return es;
    }
    
    // <for语句>::=for(<表达式>;<表达式>;<表达式>)<语句>
    // <for_stat>::=for(<expr>,<expr>,<expr>)<statement>
    // <for_stat>::=for (<expression>;
    // @SETlabel↑label1< expression >@BRF↑label2@BR↑label3;
    // @SETlabel↑label4 < expression >@BR↓label1) 
    // @SETlabel↓label3 <语句 >@BR↓label4@SETlabel↓label2 
    // 动作解释:
    //    @SETlabel↓label1:设置标号label1
    //    @BRF↑label2 :输出 BRF label2,
    //    @BR↑label3:输出 BR label3,
    //    @SETlabel↓label4:设置标号label4
    //    @BR↑label1:输出 BR label1,
    //    @SETlabel↓label3:设置标号label3
    //    @BR↑label4:输出 BR label4,
    //    @SETlabel↓label2:设置标号label2 
    int for_stat() {
        int es = 0, label1, label2, label3, label4;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "(")) return 5; // 缺少左括号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ";")) return 4; //缺少分号
    
        label1 = labelp++;
        fprintf(fout, "LABEL%d:
    ", label1); // 设置label1标号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = expression();
        if (es > 0) return es;
        label2 = labelp++;
        fprintf(fout, "        BRF LABEL%d
    ", label2);
        label3 = labelp++;
        fprintf(fout, "        BR LABEL%d
    ", label3);
        if (strcmp(token, ";")) return 4; // 缺少分号
    
        label4 = labelp++;
        fprintf(fout, "LABEL%d:
    ", label4); // 设置label4标号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = expression();
        if (es > 0) return es;
        fprintf(fout, "        BR LABEL%d
    ", label1);
        if (strcmp(token, ")")) return 6; // 缺少右括号
    
        fprintf(fout, "LABEL%d:
    ", label3); // 设置label3标号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        es = statement();
        if (es > 0) return es;
        fprintf(fout, "        BR LABEL%d
    ", label4);
        fprintf(fout, "LABEL%d:
    ", label2); // 设置label2标号
        return es;
    }
    
    // <read_语句>::=read<变量>;
    // <read_stat>::=read ID;
    // <read_stat>::=read ID↑n LOOK↓n↑d @IN@STI↓d;
    // 动作解释:
    // @LOOK↓n↑d:查符号表n,给出变量地址d; 没有,变量没定义
    // @IN:输出IN
    // @STI↓d:输出指令代码STI d
    int read_stat() {
        int es = 0, address;
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, "ID")) return 3; // 缺少标识符
    
        es = lookup(token1, &address);
        if (es > 0) return es;
        fprintf(fout, "        IN   
    ");
        fprintf(fout, "        STO   %d
    ", address);
        fprintf(fout, "        POP
    ");
    
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        if (strcmp(token, ";")) return 4; // 缺少分号
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        return es;
    }
    
    // <write_语句>::=write <表达式>;
    // <write_stat>::=write <expression>;
    // <write_STR>::write <STR>;
    // 动作解释:
    // @ OUT:输出 OUT
    int write_stat() {
        int es = 0;
        fscanf(fin, "%d %s ", &wrow, token);
        printf("%s ", token);
        if (strcmp(token, "STR") == 0) { // 输出字符串
            fgets(token1, 1024, fin);
            printf("%s", token1);
            fprintf(fout, "        OUTS %s", token1); // 由于字符串不参与运算,单独考虑,定义OUTS为输出字符串指令
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            if (strcmp(token, ";")) return 4; // 缺少分号
            // fprintf(fout,"        OUT
    ");
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            return es;
        }
        fscanf(fin, "%s", &token1);
        printf("%s
    ", token1);
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ";")) return 4; // 缺少分号
        fprintf(fout, "        OUT
    ");
        fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
        printf("%s %s
    ", token, token1);
        return es;
    }
    
    // <表达式语句>::=<<表达式>;|;
    // <expression_stat>::=<expression>;|;
    int expression_stat() {
        int es = 0;
        if (strcmp(token, ";") == 0) {
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            return es;
        }
        es = expression();
        if (es > 0) return es;
        if (strcmp(token, ";") == 0) {
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            return es;
        } else {
            return 4; //缺少分号
        }
    }
    
    // <表达式>::=<标识符>=<布尔表达式>|<布尔表达式>
    // <expr>::=ID=<bool_expr>|<bool_expr>
    // <expression>::=ID↑n@LOOK↓n↑d@ASSIGN=<bool_expr>@STO↓d |<bool_expr>
    int expression() {
        int es = 0, fileadd;
        char token2[MAXLENGTH + 2], token3[MAXLENGTH + 2];
        if (strcmp(token, "ID") == 0) {
            fileadd = ftell(fin); // 记住当前文件位置
            fscanf(fin, "%d %s %s
    ", &wrow, token2, token3);
            printf("%s %s
    ", token2, token3);
    
            if (strcmp(token2, "=") == 0) { //'='
                int address;
                es = lookup(token1, &address);
                if (es > 0) return es;
                fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
                printf("%s %s
    ", token, token1);
                es = bool_expr();
                if (es > 0) return es;
                fprintf(fout, "        STO %d
    ", address);
                fprintf(fout, "        POP
    ");
            } else { //"=="
                fseek(fin, fileadd, 0); // 若非'='则文件指针回到'='前的标识符
                es = bool_expr();
                if (es > 0) return es;
            }
        } else {
            es = bool_expr();
        }
        return es;
    }
    
    // <布尔表达式>::=<算术表达式>|<算术表达式>(>|<|>=|<=|==|!=)<算术表达式>
    // <bool_expr>::=<additive_expr>|< additive_expr >(>|<|>=|<=|==|!=)< additive_expr >
    // <bool_expr>::=<additive_expr>
    // |< additive_expr >><additive_expr>@GT
    // |< additive_expr ><<additive_expr>@LES
    // |< additive_expr >>=<additive_expr >@GE
    // |< additive_expr ><=< additive_expr >@LE
    // |< additive_expr >==< additive_expr >@EQ
    // |< additive_expr >!=< additive_expr >@NOTEQ
    int bool_expr() {
        int es = 0;
        es = additive_expr();
        if (es > 0) return es;
        if (strcmp(token, ">") == 0 || strcmp(token, ">=") == 0 || strcmp(token, "<") == 0 ||
            strcmp(token, "<=") == 0 || strcmp(token, "==") == 0 || strcmp(token, "!=") == 0) {
            char token2[MAXLENGTH + 2];
            strcpy(token2, token); // 保存运算符
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            es = additive_expr();
            if (es > 0) return es;
    
            if (strcmp(token2, ">") == 0) fprintf(fout, "        GT
    ");
            if (strcmp(token2, ">=") == 0) fprintf(fout, "        GE
    ");
            if (strcmp(token2, "<") == 0) fprintf(fout, "        LES
    ");
            if (strcmp(token2, "<=") == 0) fprintf(fout, "        LE
    ");
            if (strcmp(token2, "==") == 0) fprintf(fout, "        EQ
    ");
            if (strcmp(token2, "!=") == 0) fprintf(fout, "        NOTEQ
    ");
        }
        return es;
    }
    
    // <算术表达式>::=<项>{(+|-)<项>}
    // <additive_expr>::=<term>{(+|-)< term >} 
    // < additive_expr>::=<term>{(+< term >@ADD |-<项>@SUB)}
    int additive_expr() {
        int es = 0;
        es = term();
        if (es > 0) return es;
        while (strcmp(token, "+") == 0 || strcmp(token, "-") == 0) {
            char token2[MAXLENGTH + 2];
            strcpy(token2, token);
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            es = term();
            if (es > 0) return es;
    
            if (strcmp(token2, "+") == 0) fprintf(fout, "        ADD
    ");
            if (strcmp(token2, "-") == 0) fprintf(fout, "        SUB
    ");
        }
        return es;
    }
    
    // <项>::=<因子>{(*|/)<因子>}
    // < term >::=<factor>{(*| /)< factor >} 
    // < term >::=<factor>{(*< factor >@MULT | /< factor >@DIV)} 
    int term() {
        int es = 0;
        es = factor();
        if (es > 0) return es;
        while (strcmp(token, "*") == 0 || strcmp(token, "/") == 0 || strcmp(token, "%") == 0) {
            char token2[MAXLENGTH + 2];
            strcpy(token2, token);
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            es = factor();
            if (es > 0) return es;
    
            if (strcmp(token2, "*") == 0) fprintf(fout, "        MULT
    ");
            if (strcmp(token2, "/") == 0) fprintf(fout, "        DIV
    ");
            if (strcmp(token2, "%") == 0) fprintf(fout, "        MOD
    ");
        }
        return es;
    }
    
    // <因子>::=(<算术表达式>)|<标识符>|<无符号整数>
    // < factor >::=(<additive_expr>)| ID|NUM
    // < factor >::=(< expression >)| ID↑n@LOOK↓n↑d@LOAD↓d |NUM↑i@LOADI↓i
    int factor() {
        int es = 0;
        if (strcmp(token, "(") == 0) {
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
            es = expression(); // 表达式
            if (es > 0) return es;
            if (strcmp(token, ")")) return 6; // 缺少右括号
            fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
            printf("%s %s
    ", token, token1);
        } else {
            if (strcmp(token, "ID") == 0) {
                int address;
                es = lookup(token1, &address); // 查符号表获取地址
                if (es > 0) return es; // 变量没声明
                fprintf(fout, "        LOAD %d
    ", address);
                fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
                printf("%s %s
    ", token, token1);
                return es;
            } else if (strcmp(token, "NUM") == 0) {
                fprintf(fout, "        LOADI %s
    ", token1);
                fscanf(fin, "%d %s %s
    ", &wrow, token, token1);
                return es;
            } else {
                return 7; // 缺少操作数
            }
        }
        return es;
    }

    四、模拟机(解释器)

    特点:

    (1)支持字符串(可带空白字符)输出

    (2)消除LABEL:中:与带:字符串的冲突

    #include <iostream>
    #include <cstdio>
    #include <cctype>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    #define INF 0x3f3f3f3f
    #define MAXFILENAME 100
    #define MAXCODENUM 1000
    #define MAXCODELENGTH 100
    #define MAXDATANUM 1000
    #define MAXLABELNUM 100
    #define MAXSTACK 1000
    
    namespace Testmachine {
        FILE *fin;                              // 用于指向输入文件的指针
        char Scanin[MAXFILENAME];               // 用于接收输入的文件名
        char code[MAXCODENUM][MAXCODELENGTH];   // 代码存放数组
        int data[MAXDATANUM];                   // data[i]表示i地址的数值
        int label[MAXLABELNUM];                 // LABEL数组
        int stack[MAXSTACK], stacktop;          // 操作栈
        char lno[10];
        int codecnt;
        int i, j, es;
    }
    using namespace Testmachine;
    
    int TESTmachine() {
        // printf("请输入目标文件名(包括路径):
    ");
        // system("C:\Users\Administrator\Desktop\test4.exe");
        strcpy(Scanin, "C:\Users\Administrator\Desktop\out2.txt");
    
        es = 0, i = 0, j = 0, stacktop = 0;
        memset(data, -INF, sizeof(data));
        if ((fin = fopen(Scanin, "r")) == NULL) {
            printf("
    打开%s错误!
    ", code);
            return 10;
        }
    
        codecnt = 0;
        i = fscanf(fin, "%s", &code[codecnt]);
        while (!feof(fin)) { // 读入
            i = strlen(code[codecnt]) - 1;
            strncpy(lno, code[codecnt], 5);
            lno[5] = '';
            if (strcmp(lno, "OUTS") == 0) { // 带空格字符串处理
                codecnt++;
                getc(fin); // 跳过空格
                fgets(code[codecnt], 1024, fin);
                i = strlen(code[codecnt]) - 1;
                code[codecnt][i] = '';
            } else if (code[codecnt][i] == ':') { // LABEL,已消除":"冲突
                i = i - 5;
                strncpy(lno, &code[codecnt][5], i);
                lno[i] = '';
                label[atoi(lno)] = codecnt; // 用label数组记住每个标号的地址
                code[codecnt][0] = ':';
                code[codecnt][1] = '';
                strcat(code[codecnt], lno);
                j++;
            }
            codecnt++;
            i = fscanf(fin, "%s", &code[codecnt]);
        }
        fclose(fin);
    
        for (i = 0; i < codecnt; i++) { // 处理
            int l = strlen(code[i]);
            // printf("%d  %s  %d
    ",i,code[i],l);
            if ((l > 1) && (code[i][1] == 'A')) {
                strncpy(lno, &code[i][5], l - 5);
                lno[i] = '';
                itoa(label[atoi(lno)], code[i], 10);
            }
        }
    
        i = 0;
        while (i < codecnt) { // 运行
            if (strcmp(code[i], "LOAD") == 0) {        // LOAD D将D中的内容加载到操作数栈
                i++;
                stack[stacktop] = data[atoi(code[i])];
                stacktop++;
            } else if (strcmp(code[i], "LOADI") == 0) { // LOADI a将常量a压入操作数栈
                i++;
                stack[stacktop] = atoi(code[i]);
                stacktop++;
            } else if (strcmp(code[i], "STO") == 0) {   // STO D将操作数栈栈顶单元内容存入D,且栈顶单元内容保持不变
                i++;
                data[atoi(code[i])] = stack[stacktop - 1];
            } else if (strcmp(code[i], "STI") == 0) {   // STI D 将操作数栈栈顶单元内容存入D,且栈顶单元内容出栈
                i++;
                data[atoi(code[i])] = stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "POP") == 0) {   // POP出栈
                stacktop--;
            } else if (strcmp(code[i], "ADD") == 0) {   // ADD将次栈顶单元与栈顶单元内容出栈并相加,和置于栈顶
                stack[stacktop - 2] = stack[stacktop - 2] + stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "SUB") == 0) {   // SUB将次栈顶单元减去栈顶单元内容并出栈,差置于栈顶
                stack[stacktop - 2] = stack[stacktop - 2] - stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "MULT") == 0) {  // MULT将次栈顶单元与栈顶单元内容出栈并相乘,积置于栈顶
                stack[stacktop - 2] = stack[stacktop - 2] * stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "DIV") == 0) {   // DIV将次栈顶单元与栈顶单元内容出栈并相除,商置于栈顶
                stack[stacktop - 2] = stack[stacktop - 2] / stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "MOD") == 0) {   // MOD将次栈顶单元模栈顶单元内容并出栈,余数置于栈顶
                stack[stacktop - 2] = stack[stacktop - 2] % stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "BR") == 0) {    // BR lab无条件转移到lab
                i++;
                i = atoi(code[i]);
            } else if (strcmp(code[i], "BRF") == 0) {   // BRF lab检查栈顶单元逻辑值,若为假则转移到lab
                i++;
                if (stack[stacktop - 1] == 0) i = atoi(code[i]);
                stacktop--;
            } else if (strcmp(code[i], "EQ") == 0) {    // EQ将栈顶两单元做等于比较,并将结果真或假置于栈顶
                stack[stacktop - 2] = stack[stacktop - 2] == stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "NOTEQ") == 0) { // NOTEQ将栈顶两单元做不等于比较,并将结果真或假置于栈顶
                stack[stacktop - 2] = stack[stacktop - 2] != stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "GT") == 0) {    // GT次栈顶大于栈顶操作数,则栈顶置1,否则置0
                stack[stacktop - 2] = stack[stacktop - 2] > stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "LES") == 0) {   // LES次栈顶小于栈顶操作数,则栈顶置1,否则置0
                stack[stacktop - 2] = stack[stacktop - 2] < stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "GE") == 0) {    // GE次栈顶大于等于栈顶操作数,则栈顶置1,否则置0
                stack[stacktop - 2] = stack[stacktop - 2] >= stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "LE") == 0) {    // LE 次栈顶小于等于栈顶操作数,则栈顶置1,否则置0
                stack[stacktop - 2] = stack[stacktop - 2] <= stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "AND") == 0) {   // AND 将栈顶两单元做逻辑与运算,并将结果真或假置于栈顶
                stack[stacktop - 2] = stack[stacktop - 2] && stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "OR") == 0) {    // OR将栈顶两单元做逻辑或运算,并将结果真或假置于栈顶
                stack[stacktop - 2] = stack[stacktop - 2] || stack[stacktop - 1];
                stacktop--;
            } else if (strcmp(code[i], "NOT") == 0) {   // NOT将栈顶的逻辑值取反
                stack[stacktop - 1] = !stack[stacktop - 1];
            } else if (strcmp(code[i], "IN") == 0) {    // IN从标准输入设备读入一个整型数据,并入栈
                scanf("%d", &stack[stacktop]);
                stacktop++;
            } else if (strcmp(code[i], "OUT") == 0) {   // OUT将栈顶单元内容出栈,并输出到标准输出
                printf("%d
    ", stack[stacktop - 1]);
                stacktop--;
            } else if (strcmp(code[i], "OUTS") == 0) {  // OUTS 字符串输出
                i++;
                printf("%s
    ", code[i]);
            } else if (strcmp(code[i], "STOP") == 0) {  // STOP 停止执行
                break;
            }
            i++;
        }
        return es;
    }

    五、主程序

    #include <stdio.h>
    
    extern int TESTscan();
    extern int TESTparse();
    extern int TESTmachine();
    
    int main() {
        int es = 0;
        es = TESTscan();
        if (es > 0) {
            printf("词法分析有错,编译停止!
    ");
        } else {
            printf("词法分析成功!
    ");
            es = TESTparse();
            if (es > 0) {
                printf("语义分析有错,编译停止!
    ");
            } else {
                printf("语义分析成功!
    ");
                es = TESTmachine();
                if (es > 0) {
                    printf("启动模拟机失败
    ");
                }
            }
        }
    }

    另外用QT写了一个简单界面,如图所示:

    后面又改了下,如图:

    (额、V1.0改成了V0.8,不要在意这些细节)

  • 相关阅读:
    KMP算法中next数组的构建
    vijos 1243 生产产品
    codeforces 557E Ann and Half-Palindrome
    codeforces 557D Vitaly and Cycle
    vijos 1054 牛场围栏 【想法题】
    oracle数据库基本操作
    一位90后程序员的自述:如何从年薪3w到30w
    Oracle 树操作(select…start with…connect by…prior)
    oracle中的条件语句
    重置按钮_reset
  • 原文地址:https://www.cnblogs.com/hate13/p/4617327.html
Copyright © 2020-2023  润新知