首页 > 技术文章 > Test语言编译器V0.8

hate13 2015-07-02 22:28 原文

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

一、词法分析

特点:

(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("请输入源程序文件名(包括路径):\n");
    // scanf("%s", Scanin);
    // printf("请输入词法分析输出文件名(包括路径):\n");
    // 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("打开词法分析输入文件出错!\n");
        return 1;
    }
    if ((fout = fopen(Scanout, "w")) == NULL) {
        printf("创建词法分析输出文件出错!\n");
        return 2;
    }
    return 0;
}

char getNextChar() {
    char ch = getc(fin);
    if (ch == '\n') frow++;
    return ch;
}

int TESTscan() {
    int es = Init();
    if (es > 0) return es;

    frow = brow = 1;
    ch = getNextChar();
    while (ch != EOF) {
        while (ch == ' ' || ch == '\n' || ch == '\t') {
            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] = '\0';
            if (isLong == true) { // 标识符太长
                es = 3;
                printf("ERROR(%d): 标识符\"%s\"超长\n", brow, token);
                fprintf(fout, "%d\t%s\t%s\n", brow, "ERROR", token);
                continue;
            }

            k = 0;
            char str[MAXLENGTH + 2];
            for (i = 0; i < strlen(token); i++) { // 小写化
                str[i] = tolower(token[i]);
            }
            str[i] = '\0';
            while (k < KEYWORDNUM && strcmp(str, keyword[k]))
                k++;
            if (k >= KEYWORDNUM)
                fprintf(fout, "%d\t%s\t%s\n", brow, "ID", token);
            else
                fprintf(fout, "%d\t%s\t%s\n", brow, str, token);
        } else if (isdigit(ch)) { // 数字
            j = 0;
            token[j++] = ch;
            ch = getNextChar();
            while (isdigit(ch)) {
                token[j++] = ch;
                ch = getNextChar();
            }
            token[j] = '\0';
            fprintf(fout, "%d\t%s\t%s\n", brow, "NUM", token);
        } else if (strchr(singleword, ch) > 0) { // 单分界符
            token[0] = ch;
            token[1] = '\0';
            fprintf(fout, "%d\t%s\t%s\n", brow, token, token);
            ch = getNextChar();
        } else if (strchr(doubleword, ch) > 0) { // 双分界符
            token[0] = ch;
            ch = getNextChar();
            if (ch == '=') {
                token[1] = ch;
                token[2] = '\0';
                ch = getNextChar();
            } else token[1] = '\0';
            fprintf(fout, "%d\t%s\t%s\n", 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] = '\0';
                fprintf(fout, "%d\t%s\t%s\n", brow, token, token);
            }
        } else if (ch == '\"') { // 字符串
            j = 0;
            ch = getNextChar();
            while (ch != '\"') {
                token[j++] = ch;
                ch = getNextChar();
            }
            token[j] = '\0';
            fprintf(fout, "%d\t%s\t%s\n", brow, "STR", token);
            ch = getNextChar();
        } else { // 命名不规范
            token[0] = ch;
            token[1] = '\0';
            if (ch < 0) { //中文处理
                ch = getNextChar();
                token[1] = ch;
                token[2] = '\0';
            }
            es = 4;
            fprintf(fout, "%d\t%s\t%s\n", brow, "ERROR", token);
            printf("ERROR(%d): 符号\"%s\"不规范\n", brow, token);
            ch = getNextChar();
        }
    }
    fprintf(fout, "%d\tEOF\tEOF\n", 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("\n打开%s错误!\n", Scanout);
        es = 10;
    }

    if ((fout = fopen(Scanout, "w")) == NULL) {
        printf("\n打开%s错误!\n", Scanout);
        es = 10;
    }

    if (es == 0) es = program();
    printf("=====语法分析结果!======\n");
    switch (es) {
        case 0:
            printf("语法分析成功!\n");
            break;
        case 10:
            printf("打开文件失败!\n");
            break;
        case 1:
            printf("ERROR(%d): \"%s\"前面缺少{\n", wrow, token1);
            break;
        case 2:
            printf("ERROR(%d): \"%s\"前面缺少}\n", wrow, token1);
            break;
        case 3:
            printf("ERROR(%d): \"%s\"前面缺少标识符\n", wrow, token1);
            break;
        case 4:
            printf("ERROR(%d): \"%s\"前面缺少分号\n", wrow, token1);
            break;
        case 5:
            printf("ERROR(%d): \"%s\"前面缺少(\n", wrow, token1);
            break;
        case 6:
            printf("ERROR(%d): \"%s\"前面缺少)\n", wrow, token1);
            break;
        case 7:
            printf("ERROR(%d): \"%s\"前面缺少操作数\n", wrow, token1);
            break;
        case 9:
            printf("ERROR(%d): \"%s\"前面缺少主程序\n", wrow, token1);
            break;
        case 11:
            printf("ERROR(%d): 主程序名错误!\n", wrow);
            break;
        case 12:
            printf("ERROR(%d): \"%s\"前面缺少while\n", wrow, token1);
            break;
        case 25:
            printf("ERROR(%d): \"%s\"已超出程序末尾\n", wrow, token1);
            break;
        case 26:
            printf("ERROR(%d): else没有匹配的if\n", wrow);
    }
    fclose(fin);
    fclose(fout);
    return es;
}

// <程序>::={<声明序列><语句序列>}
// program::={<declaration_list><statement_list>}
int program() {
    int es = 0;
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = declaration_list(); // 声明语句
    if (es > 0) return es;

    if (strcmp(token, "main")) return 9; // main区
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "ID")) return 11; // 程序名
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "{")) return 1; // 判断是否'{'
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = statement_list(); // 语句序列
    if (es > 0) return es;
    if (strcmp(token, "}")) return 2; // 判断是否'}'
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", 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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    while (1) { // 支持连续定义
        if (strcmp(token, "ID")) return 3; // 不是标识符
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        if (strcmp(token, ",") == 0) {
            fscanf(fin, "%d %s %s\n", &wrow, token, token1);
            printf("%s %s\n", token, token1);
        } else break;
    }
    if (strcmp(token, ";")) return 4; // 缺少分号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", 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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "(")) return 5; // 缺少左括号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ")")) return 6; // 缺少右括号

    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = statement(); // 语句
    if (es > 0) return es;

    if (strcmp(token, "else") == 0) { // else部分处理
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", 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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = statement_list(); // 语句序列
    if (es > 0) return es;
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", 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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "{")) return 1; // 缺少左括号
    es = statement(); //语句
    if (es > 0) return es;
    printf("%s %s\n", token, token1);
    if (strcmp(token, "while")) return 12; // 缺少while

    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "(")) return 5; // 缺少左括号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);

    es = expression(); // 表达式
    if (es > 0) return es;

    if (strcmp(token, ")")) return 6; // 缺少右括号
    if (es > 0) return es;
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    return es;
}

// <while语句>::=while(<表达式>)<语句>
// <while_stat>::=while(<expr>)<statement >
int while_stat() {
    int es = 0;
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "(")) return 5; // 缺少左括号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ")")) return 6; // 缺少右括号

    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", 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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "(")) return 5; // 缺少左括号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ";")) return 4; // 缺少分号

    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ";")) return 4; // 缺少分号

    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ")")) return 6; // 缺少右括号

    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", 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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "ID")) return 3; // 缺少标识符

    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, ";")) return 4; // 缺少分号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", 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\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        if (strcmp(token, ";")) return 4; // 缺少分号
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        return es;
    }
    fscanf(fin, "%s", &token1);
    printf("%s\n", token1);
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ";")) return 4; // 缺少分号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    return es;
}

// <表达式语句>::=<<表达式>;|;
// <expression_stat>::=<expression>;|;
int expression_stat() {
    int es = 0;
    if (strcmp(token, ";") == 0) {
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        return es;
    }
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ";") == 0) {
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", 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\n", &wrow, token2, token3);
        printf("%s %s\n", token2, token3);

        if (strcmp(token2, "=") == 0) { //'='
            fscanf(fin, "%d %s %s\n", &wrow, token, token1);
            printf("%s %s\n", 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\n", &wrow, token, token1);
        printf("%s %s\n", 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\n", &wrow, token, token1);
        printf("%s %s\n", 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\n", &wrow, token, token1);
        printf("%s %s\n", 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\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        es = expression(); // 表达式
        if (es > 0) return es;
        if (strcmp(token, ")")) return 6; // 缺少右括号
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
    } else {
        if (strcmp(token, "ID") == 0) {
            fscanf(fin, "%d %s %s\n", &wrow, token, token1);
            printf("%s %s\n", token, token1);
            return es;
        } else if (strcmp(token, "NUM") == 0) {
            fscanf(fin, "%d %s %s\n", &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("\n打开%s错误!\n", Scanout);
        es = 10;
    }

    if ((fout = fopen(Scanout, "w")) == NULL) {
        printf("\n打开%s错误!\n", Scanout);
        es = 10;
    }

    if (es == 0) es = program();
    printf("=====语法分析结果!======\n");
    switch (es) {
        case 0:
            printf("语义分析成功!\n");
            break;
        case 10:
            printf("打开文件失败!\n");
            break;
        case 1:
            printf("ERROR(%d): \"%s\"前面缺少{\n", wrow, token1);
            break;
        case 2:
            printf("ERROR(%d): \"%s\"前面缺少}\n", wrow, token1);
            break;
        case 3:
            printf("ERROR(%d): \"%s\"前面缺少标识符\n", wrow, token1);
            break;
        case 4:
            printf("ERROR(%d): \"%s\"前面缺少分号\n", wrow, token1);
            break;
        case 5:
            printf("ERROR(%d): \"%s\"前面缺少(\n", wrow, token1);
            break;
        case 6:
            printf("ERROR(%d): \"%s\"前面缺少)\n", wrow, token1);
            break;
        case 7:
            printf("ERROR(%d): \"%s\"前面缺少操作数\n", wrow, token1);
            break;
        case 9:
            printf("ERROR(%d): \"%s\"前面缺少主程序\n", wrow, token1);
            break;
        case 11:
            printf("ERROR(%d): 主程序名错误!\n", wrow);
            break;
        case 12:
            printf("ERROR(%d): \"%s\"前面缺少while\n", wrow, token1);
            break;
        case 21:
            printf("ERROR(%d): 符号表溢出\n", wrow);
            break;
        case 22:
            printf("ERROR(%d): 变量\"%s\"重复定义\n", wrow, token1);
            break;
        case 23:
            printf("ERROR(%d): 变量\"%s\"未声明\n", wrow, token1);
            break;
        case 25:
            printf("ERROR(%d): \"%s\"已超出程序末尾\n", wrow, token1);
            break;
        case 26:
            printf("ERROR(%d): else没有匹配的if\n", 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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = declaration_list(); // 声明语句
    if (es > 0) return es;

    printf("             符号表\n"); // 符号表输出
    printf("        名字      地址\n");
    for (int i = 0; i < vartablep; i++)
        printf("%10s%10d\n", vartable[i].name, vartable[i].address);

    if (strcmp(token, "main")) return 9; // main区
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "ID")) return 11; // 程序名
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "{")) return 1; // 判断是否'{'
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = statement_list(); // 语句序列
    if (es > 0) return es;
    if (strcmp(token, "}")) return 2; // 判断是否'}'
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "EOF")) return 25; // 超出程序末尾
    fprintf(fout, "        STOP\n"); // 产生停止指令
    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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    while (1) { // 支持连续定义
        if (strcmp(token, "ID")) return 3; // 不是标识符
        es = name_def(token1); //插入到符号表
        if (es > 0) return es;
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        if (strcmp(token, ",") == 0) {
            fscanf(fin, "%d %s %s\n", &wrow, token, token1);
            printf("%s %s\n", token, token1);
        } else break;
    }
    if (strcmp(token, ";")) return 4; // 缺少分号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", 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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "(")) return 5; // 缺少左括号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ")")) return 6; // 缺少右括号
    label1 = labelp++; // 用label1记住条件为假时要转向的标号
    fprintf(fout, "        BRF LABEL%d\n", label1);

    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = statement(); // 语句
    if (es > 0) return es;

    label2 = labelp++; // 用label2记住要转向的标号
    fprintf(fout, "        BR LABEL%d\n", label2);
    fprintf(fout, "LABEL%d:\n", label1); // 设置label1记住的标号

    if (strcmp(token, "else") == 0) { // else部分处理
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        es = statement();
        if (es > 0) return es;
    }
    fprintf(fout, "LABEL%d:\n", label2); // 设置label2记住的标号
    return es;
}

// <复合语句>::={<语句序列>} 
// <compound_stat>::={<statement_list>} 
int compound_stat() {
    int es = 0;
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = statement_list(); // 语句序列
    if (es > 0) return es;
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", 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:\n", label1); // 设置label1标号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "{")) return 1; // 缺少左括号
    es = statement(); // 语句
    if (es > 0) return es;
    printf("%s %s\n", token, token1);
    if (strcmp(token, "while")) return 12; //缺少while

    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "(")) return 5; // 缺少左括号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);

    es = expression(); // 表达式
    if (es > 0) return es;
    label2 = labelp++;
    fprintf(fout, "        BRF LABEL%d\n", label2);
    fprintf(fout, "        BR LABEL%d\n", label1);

    if (strcmp(token, ")")) return 6; // 缺少右括号
    if (es > 0) return es;
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    fprintf(fout, "LABEL%d:\n", 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:\n", label1); // 设置label1标号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "(")) return 5; // 缺少左括号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ")")) return 6; // 缺少右括号

    label2 = labelp++;
    fprintf(fout, "        BRF LABEL%d\n", label2);
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = statement();
    if (es > 0) return es;
    fprintf(fout, "        BR LABEL%d\n", label1);
    fprintf(fout, "LABEL%d:\n", 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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "(")) return 5; // 缺少左括号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ";")) return 4; //缺少分号

    label1 = labelp++;
    fprintf(fout, "LABEL%d:\n", label1); // 设置label1标号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = expression();
    if (es > 0) return es;
    label2 = labelp++;
    fprintf(fout, "        BRF LABEL%d\n", label2);
    label3 = labelp++;
    fprintf(fout, "        BR LABEL%d\n", label3);
    if (strcmp(token, ";")) return 4; // 缺少分号

    label4 = labelp++;
    fprintf(fout, "LABEL%d:\n", label4); // 设置label4标号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = expression();
    if (es > 0) return es;
    fprintf(fout, "        BR LABEL%d\n", label1);
    if (strcmp(token, ")")) return 6; // 缺少右括号

    fprintf(fout, "LABEL%d:\n", label3); // 设置label3标号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    es = statement();
    if (es > 0) return es;
    fprintf(fout, "        BR LABEL%d\n", label4);
    fprintf(fout, "LABEL%d:\n", 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\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, "ID")) return 3; // 缺少标识符

    es = lookup(token1, &address);
    if (es > 0) return es;
    fprintf(fout, "        IN   \n");
    fprintf(fout, "        STO   %d\n", address);
    fprintf(fout, "        POP\n");

    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    if (strcmp(token, ";")) return 4; // 缺少分号
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", 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\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        if (strcmp(token, ";")) return 4; // 缺少分号
        // fprintf(fout,"        OUT\n");
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        return es;
    }
    fscanf(fin, "%s", &token1);
    printf("%s\n", token1);
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ";")) return 4; // 缺少分号
    fprintf(fout, "        OUT\n");
    fscanf(fin, "%d %s %s\n", &wrow, token, token1);
    printf("%s %s\n", token, token1);
    return es;
}

// <表达式语句>::=<<表达式>;|;
// <expression_stat>::=<expression>;|;
int expression_stat() {
    int es = 0;
    if (strcmp(token, ";") == 0) {
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        return es;
    }
    es = expression();
    if (es > 0) return es;
    if (strcmp(token, ";") == 0) {
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", 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\n", &wrow, token2, token3);
        printf("%s %s\n", token2, token3);

        if (strcmp(token2, "=") == 0) { //'='
            int address;
            es = lookup(token1, &address);
            if (es > 0) return es;
            fscanf(fin, "%d %s %s\n", &wrow, token, token1);
            printf("%s %s\n", token, token1);
            es = bool_expr();
            if (es > 0) return es;
            fprintf(fout, "        STO %d\n", address);
            fprintf(fout, "        POP\n");
        } 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\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        es = additive_expr();
        if (es > 0) return es;

        if (strcmp(token2, ">") == 0) fprintf(fout, "        GT\n");
        if (strcmp(token2, ">=") == 0) fprintf(fout, "        GE\n");
        if (strcmp(token2, "<") == 0) fprintf(fout, "        LES\n");
        if (strcmp(token2, "<=") == 0) fprintf(fout, "        LE\n");
        if (strcmp(token2, "==") == 0) fprintf(fout, "        EQ\n");
        if (strcmp(token2, "!=") == 0) fprintf(fout, "        NOTEQ\n");
    }
    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\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        es = term();
        if (es > 0) return es;

        if (strcmp(token2, "+") == 0) fprintf(fout, "        ADD\n");
        if (strcmp(token2, "-") == 0) fprintf(fout, "        SUB\n");
    }
    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\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        es = factor();
        if (es > 0) return es;

        if (strcmp(token2, "*") == 0) fprintf(fout, "        MULT\n");
        if (strcmp(token2, "/") == 0) fprintf(fout, "        DIV\n");
        if (strcmp(token2, "%") == 0) fprintf(fout, "        MOD\n");
    }
    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\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
        es = expression(); // 表达式
        if (es > 0) return es;
        if (strcmp(token, ")")) return 6; // 缺少右括号
        fscanf(fin, "%d %s %s\n", &wrow, token, token1);
        printf("%s %s\n", token, token1);
    } else {
        if (strcmp(token, "ID") == 0) {
            int address;
            es = lookup(token1, &address); // 查符号表获取地址
            if (es > 0) return es; // 变量没声明
            fprintf(fout, "        LOAD %d\n", address);
            fscanf(fin, "%d %s %s\n", &wrow, token, token1);
            printf("%s %s\n", token, token1);
            return es;
        } else if (strcmp(token, "NUM") == 0) {
            fprintf(fout, "        LOADI %s\n", token1);
            fscanf(fin, "%d %s %s\n", &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("请输入目标文件名(包括路径):\n");
    // 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("\n打开%s错误!\n", 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] = '\0';
        if (strcmp(lno, "OUTS") == 0) { // 带空格字符串处理
            codecnt++;
            getc(fin); // 跳过空格
            fgets(code[codecnt], 1024, fin);
            i = strlen(code[codecnt]) - 1;
            code[codecnt][i] = '\0';
        } else if (code[codecnt][i] == ':') { // LABEL,已消除":"冲突
            i = i - 5;
            strncpy(lno, &code[codecnt][5], i);
            lno[i] = '\0';
            label[atoi(lno)] = codecnt; // 用label数组记住每个标号的地址
            code[codecnt][0] = ':';
            code[codecnt][1] = '\0';
            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\n",i,code[i],l);
        if ((l > 1) && (code[i][1] == 'A')) {
            strncpy(lno, &code[i][5], l - 5);
            lno[i] = '\0';
            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\n", stack[stacktop - 1]);
            stacktop--;
        } else if (strcmp(code[i], "OUTS") == 0) {  // OUTS 字符串输出
            i++;
            printf("%s\n", 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("词法分析有错,编译停止!\n");
    } else {
        printf("词法分析成功!\n");
        es = TESTparse();
        if (es > 0) {
            printf("语义分析有错,编译停止!\n");
        } else {
            printf("语义分析成功!\n");
            es = TESTmachine();
            if (es > 0) {
                printf("启动模拟机失败\n");
            }
        }
    }
}

 

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

 

后面又改了下,如图:

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

 

 

 

推荐阅读