首页 > 其他分享 >简单编译器

简单编译器

时间:2023-06-12 22:14:21浏览次数:47  
标签:code counter instruct 编译器 sml 简单 table array

目录

0x01 背景

《C语言大学教程-第八版》(《C How to Program》)391页,第十二章作业,专题:创建自己的编译器

在练习题7.27至练习题7.29中,我们介绍了Simpletron机器语言(Simpletron Machine Language,SML),还实现了一个Simpletron计算机模拟器来运行采用SML编写的程序。在练习题12.25至练习题12.29中,将创建一个将采用高级语言编写的程序转换成Simpletron机器语言程序的编译器。这个专题将程序设计的全过程“捆绑在一起”。我们将用新的高级语言来编写一些程序,用我们创建的这个编译器来编译这些程序,然后用在练习题7.28中创建的Simpletron计算机模拟器来运行这些程序

0x02 SML语法

  1. 代码格式

    行号	代码
    35 	 rem add y to total
    
  2. (空格),\t,\n,\0进行分隔,每个符号间都需要分隔符

    65 let t = ( ( 3 - 1 ) * ( 2 - t ) ) / ( 2 ^ 3 )
    
  3. 不区分大小写

  4. 定义关键字

    1. rem注释,例:10 rem add y to total

    2. input定义变量,例:10 INPUT x,y

    3. ifgoto判断跳转,例:20 if y == x goto 60

    4. goto无条件跳转,例:50 goto 20

    5. let变量赋值,例:50 let t = y,50 let t = t + y

    6. print输出变量,例:50 print x

    7. end程序结束,例50 end

    8. for,to,step,nextfor循环,step可以省略,默认步长1,例:

      50 for x to 10 step 2
      ...
      80 next
      
    9. gets,puts输入\输出字符串,例:

      45 gets s 10 
      50 puts s 10
      
    10. gosub,return跳转指定地址\返回指定地址,例:

      65 gosub 75
      95 print t
      99 end
      75 let t = t + 2
      80 return 95
      

0x03 应用

源码:

05 rem test
10 for x = 0 to 10 step 2
11 rem 这里x会输出3次
15 print x
20 if x == 6 goto 30
25 next 
26 rem 输入y
30 input y
31 rem 输出刚刚输入的y
35 print y
65 gosub 75
66 rem 输出重新计算的y
95 print y
96 end
97 rem 重新计算y
75 let y = ( ( y + 10 ) / ( 10 - x ) ) * ( 2 ^ 3 )
80 return 95

编译过程:

image

image

sml.txt文件:

+2098
+3098
+2197
+2199
+2099
+3196
+4216
+2099
+3095
+2194
+2199
+1199
+2099
+3193
+4216
+4004
+1092
+1192
+4021
+1192
+4300
+2092
+3096
+2190
+2096
+3199
+2189
+2090
+3289
+2188
+2095
+3591
+2187
+2088
+3387
+2186
+2192
+4019
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0003
+0000
+0006
+0000
+0002
+0010
+0000
+0000
+0000
-9999

执行

image

0x04 SML_C实现

sml_compiler.h

#pragma once
/*
 * SML编译器
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define SIZE 1000
#define FLAG -9999

// 输入/输出操作
// 从终端将一个字读到内存指定单元中
#define READ 10
// 将内存指定单元中的一个字写到终端
#define WRITE 11
// 回车换行
#define CRLF 12
// 输入字符串
#define INSTRING 13 
// 输出字符串
#define OUTSTRING 14     

// 载入/存储操作
// 将指定单元中的一个字载入累加器
#define LOAD 20
// 从累加器将一个字存放回内存指定单元中
#define STORE 21

// 算术运算操作
// 将内存中指定单元中的一个字域累加器中的字相加,结果留在累加器中
#define ADD 30
// 将累加器中的字减去内存指定单元中的一个字,结果留在累加器中
#define SUBTRACT 31
// 将累加器中的字除以内存指定单元中的一个字,结果留在累加器中
#define DIVIDE 32
// 将累加器中的字乘以内存指定单元中的一个字,结果留在累加器中
#define MUTIPLY 33
// 求模,结果放在累加器中
#define MODE 34
// 求幂,结果放在累加器中
#define POWER 35 

// 控制操作的转移
// 转移到内存指定单元
#define BRANCH 40
// 如果累加器为负数,则转移到内存指定单元
#define BRANCHNGE 41
// 如果累加器为零,则转移到内存指定单元
#define BRANCHZERO 42
// 停机,即程序完成了它的任务
#define HALT 43

// map文件句柄
FILE* map_file_ptr;
// map文件名
#define MAP_FILE_NAME "map_file.txt"

//用有100元素的一维数组 memory 来模拟 Simpletron 的内存
int memory[SIZE] = { 0 };
// 使用变量 accumulator来表示累加器寄存器
int accumulator = 0;
// 使用变量 instructionCounter来跟踪包含正在执行的指令的内存位置
int instructionCounter = 0;
// 使用变量 operationCode来说明当前正在执行的操作, 也就是命令字的左边2位
int operation_code = 0;
// 使用变量 operand来指出当前指令所操作的内存位置,命令的右两位
int operand = 0;
// 不要直接从内存执行指令。而是将要执行的下一条指令从内存转移到变量 instructionRegister中
// 然后“取掉”左边的2位,并将它们放置在变量 operationCode中,“取掉”右边的2位,并将它们放置在 Operand中。
int instruction_register = 0;
// 指令计数器
int num = 0;
// debug flag debug模式默认关闭
int debug = 0;

// 下一条指令
void next_instruction();
// 执行指令
int do_instruction();
// 打印内存
void dump();
// 读取 sml指令
int read_file(int n, char* file_name);
// 打印程序头
void print_head();
// 打印到 map文件中
void print_to_map(char* message, int code);
// 除零错误
int err_zero(int operand);
// 累加器溢出
int err_accumulator(int accumulator);
// 操作码错误
int err_operand_code(int operation_code);
// 换行
void new_line();
// 输入字符串
void in_str();
// 输出字符串
void out_str();

sml_compiler.c

#include "sml_compiler.h"

/*程序开始*/
int main(void)
{
    // 存放指令字符串数组
    char code_array[CODESIZE] = { 0 };

    // 没有解析数组初始化全部为-1
    for (int i = 0; i < TABLESIZE; i++)
    {
        un_analyze_array[i] = -1;
    }

    // 第一次编译,填充符号表,指令表
    first_compile(code_array);
    // 打印指令数组
    // print_sml(sml, SMLSIZE);
    // 打印符号表
    print_symbol_table(symbol_table, TABLESIZE);

    // 填充第一次编译未能处理的符号给填充上
    for (int i = 0; i < SMLSIZE && compile_flag == 1; i++)
    {
        if (un_analyze_array[i] != -1)
        {
            sml[i] += search_symbol_table(un_analyze_array[i], TABLESIZE, LINE_SYMBOL);
        }
    }
    // 指令结束语句
    sml[SMLSIZE - 1] = -9999;
    print_sml(sml, SMLSIZE);

    // 将SML指令写入文件
    write_file(sml);

    return 0;//程序结束
}//main函数结束

//===============================================================================================
// 将SML指令写入文件
void write_file(int sml[SMLSIZE])
{
    FILE* fptr;
    char fname[30];

    printf("写入指令的文件名:");
    gets_s(fname, 30);

    if ((fptr = fopen(fname, "w")) == NULL)
        printf("打开文件失败!\n");
    else
    {
        for (int i = 0; i < SMLSIZE; i++)
        {
            fprintf(fptr, "%+05d\n", sml[i]);
        }
    }
}
// 指令计数器检查
bool instruct_check(void)
{
    if (instruct_counter > SMLSIZE)
    {
        // 停止编译
        printf("\n指令溢出错误:指令数大于内存,溢出!停止编译。\n");
        compile_flag = 0;
        return false;
    }
    else
        return true;
}
//第一次编译
void first_compile(char* code_array)
{
    // 源文件句柄
    FILE* fptr;
    // 文件名
    char file_name[20];
    // 读取行数计数器
    int line = 0;

    printf("输入 simple程序文件名:");
    // gets_s()只从标准输入(通常是键盘)中读取数据,长度20个字符
    gets_s(file_name, 20);
    // 打开文件
    if ((fptr = fopen(file_name, "r")) == NULL)
    {
        printf("文件打开失败。\n");
    }
    // 获取一行代码
    fgets(code_array, CODESIZE - 1, fptr);

    // 转小写
    up_to_low(code_array, CODESIZE);

    // 生成符号表
    create_symbol_table(code_array);
    while (!feof(fptr) && compile_flag == 1)
    {
        // 数组清零
        memset(code_array, 0, sizeof(code_array));
        // 获取一行代码
        fgets(code_array, CODESIZE - 1, fptr);
        line++;
        //将代码中的大写字母改成小写字母
        up_to_low(code_array, CODESIZE);
        // 如果是 for语句
        if (strstr(code_array, FOR_CODE) != NULL)
        {
            // 查找 for语句循环结束后的跳转地址
            for_goto_line = search_for_goto_line(fptr, line);
            if (for_goto_line == -1) {
                printf("语法错误:for语句缺少 next语句。\n");
                compile_flag = 0;
            }
        }
        // 生成符号表及SML指令
        create_symbol_table(code_array);
    }
    // 关闭文件
    fclose(fptr);
}
//查找 for语句循环结束后的跳转地址
int search_for_goto_line(FILE* fptr, int line)
{
    int count = 0;
    int line_code = 0;
    char s[CODESIZE] = { 0 };
    // 将文件内位置指针移至开头
    rewind(fptr);
    // 获取一行代码 
    fgets(s, CODESIZE - 1, fptr);
    while (!feof(fptr))
    {
        count++;
        if (count == line)
        {
            while (!feof(fptr))
            {
                // 获取一行代码
                fgets(s, CODESIZE - 1, fptr);
                if (strstr(s, NEXT_CODE) != NULL)
                {
                    // 获取一行代码
                    fgets(s, CODESIZE - 1, fptr);
                    // 获取到 next语句下一行行号
                    line_code = atoi(s);
                    // 文件内部位置指针返回到调用时的位置
                    count = 0;
                    // 将文件内位置指针移至开头
                    rewind(fptr);
                    while (!feof(fptr))
                    {
                        // 获取一行代码
                        fgets(s, CODESIZE - 1, fptr);
                        if (count == line)
                        {
                            return line_code;
                        }
                        count++;
                    }
                }
            }
        }
        fgets(s, CODESIZE - 1, fptr);//获取一行代码
    }
    return -1;//未找到
}
// 大写转小写字母
void up_to_low(char* code, int size)
{
    for (int i = 0; i < size; i++)
    {
        // 判断是字母
        if (isalpha(code[i]))
            // 全部转小写
            code[i] = tolower(code[i]);
    }
}
// 生成符号表和SML指令
// codeArray: 一行代码字符串
void create_symbol_table(char* one_line_code)
{
    // 一行代码分解出的指令数组
    char code_spilt_array[CODESIZE][CODESIZE] = { 0 }; //分解数组
    // 分解字符串的个数
    int code_split_array_len = 0;
    // 一行代码符号表填充完成标识
    int fill_over_flag = 1;
    char infix[INFIXSIZE] = { 0 };//中缀表达式记录数组
    // 一行代码的备份
    char one_line_code_copy[CODESIZE] = { 0 }; 

    // 指令语句复制
    strcpy(one_line_code_copy, one_line_code);

    // 一行代码分解后字符的个数
    code_split_array_len = strtok_string(code_spilt_array, one_line_code, SPLIT_OPERATOR);

    // 解析语句
    for (int code_index = 0; code_index < code_split_array_len && fill_over_flag == 1; code_index++)
    {
        //第1个字符串
        if (code_index == 0)
        {
            //行号入符号表处理
            line_symbol_process(code_spilt_array, code_index);
        }
        else
        {
            // 判断指令是不是关键字
            if (keywords(code_spilt_array[code_index])) 
            {
                // 是关键字
                // 判断指令是不是注释
                if (rem_code(code_spilt_array, code_index)) {
                    // 是注释,退出一行的循环
                    fill_over_flag = 0;
                }
                else
                {
                    if (strcmp(code_spilt_array[code_index], INPUT_CODE) == 0) {
                        // 如果是 input指令
                        fill_over_flag = input_code(code_spilt_array, code_index);
                    }
                    if (strcmp(code_spilt_array[code_index], IF_CODE) == 0) 
                    {
                        // 如果是if指令
                        // 在符号表中找 if关键字后面的变量
                        if (search_symbol_table(code_spilt_array[code_index + 1][0], TABLESIZE, VARIABLE_SYMBOL) == -1) {
                            // 符号表中未找到“if”指令后的变量
                            // 单字符变量名入符号表
                            symbol_table[table_counter].symbol = code_spilt_array[code_index + 1][0];
                            // 类型
                            symbol_table[table_counter].type = VARIABLE_SYMBOL;
                            // 地址
                            symbol_table[table_counter].location = sml_up_count;
                            // 符号表计数器加1
                            table_counter++;
                            // 高位数据计数器减一
                            sml_up_count--; 
                            // 生成SML指令
                            fill_over_flag = if_goto_code(code_spilt_array, code_index);
                        }
                        else
                        {
                            //如果符号表中找到“if”指令后的变量,无需插入符号表
                            fill_over_flag = if_goto_code(code_spilt_array, code_index);
                        }
                    }// if指令结束
                    if (strcmp(code_spilt_array[code_index], LET_CODE) == 0)
                    {
                        // 如果是 let指令
                        if (search_symbol_table(code_spilt_array[code_index + 1][0], TABLESIZE, VARIABLE_SYMBOL) == -1) {
                            // 符号表中未找到"let"指令后的变量名x
                            // 单字符变量名入符号表
                            symbol_table[table_counter].symbol = code_spilt_array[code_index + 1][0];
                            // 类型
                            symbol_table[table_counter].type = VARIABLE_SYMBOL;
                            symbol_table[table_counter].location = sml_up_count;
                            // 记录 let左操作数变量的内存位置
                            let_variable_location = sml_up_count;
                            sml_up_count--;
                            // 符号表计数器加1
                            table_counter++;
                            // 判断 let x =
                            if (code_spilt_array[code_index + 2][0] == ASSIGNMENT_OPERATOR)
                            {
                                //第二次编译 let指令
                                let_code(code_spilt_array, code_index, code_split_array_len);
                                //获取中缀表达式
                                process_infix(infix, one_line_code_copy);
                            }
                            // 退出循环
                            fill_over_flag = 0; 
                        }
                        else
                        {
                            // 符号表中找到"let"指令后的变量名x
                            // 记录 let左操作数变量的内存位置
                            let_variable_location = search_symbol_table(code_spilt_array[code_index + 1][0], TABLESIZE, VARIABLE_SYMBOL);
                            if (code_spilt_array[code_index + 2][0] == ASSIGNMENT_OPERATOR)
                            {
                                // 解析 let表达式
                                let_code(code_spilt_array, code_index, code_split_array_len);
                                // 处理中缀表达式
                                process_infix(infix, one_line_code_copy);
                            }
                            else {
                                printf("let指令后缺少\'=\'运算符。\n");
                                // 停止编译
                                compile_flag = 0;
                            }
                            fill_over_flag = 0;

                        }//let指令后第1个变量解析结束

                    }// let指令解析结束
                    if (strcmp(code_spilt_array[code_index], GOTO_CODE) == 0)
                    {
                        // goto指令处理
                        fill_over_flag = goto_code(code_spilt_array, code_index);
                    }
                    if (strcmp(code_spilt_array[code_index], PRINT_CODE) == 0)
                    {
                        //print指令处理
                        fill_over_flag = print_code(code_spilt_array, code_index);
                    }
                    if (strcmp(code_spilt_array[code_index], END_CODE) == 0)
                    {
                        // end指令处理
                        fill_over_flag = end_code(code_spilt_array, code_index);
                    }
                    if (strcmp(code_spilt_array[code_index], GOSUB_CODE) == 0)
                    {
                        //gosub 下一条指令地址,待填充,但是内存位置当前是可以确定的
                        return_address = instruct_counter + 1;
                        //gosub 指令处理
                        fill_over_flag = gosub_code(code_spilt_array, code_index);
                    }
                    if (strcmp(code_spilt_array[code_index], RETURN_CODE) == 0)
                    {
                        // SML return指令
                        sml[instruct_counter] = BRANCH * 100 + return_address; 
                        instruct_counter++;
                        instruct_check();
                        sml_low_count++;
                        fill_over_flag = 0;
                    }
                    if (strcmp(code_spilt_array[code_index], FOR_CODE) == 0)
                    {
                        // for指令处理
                        fill_over_flag = for_code(code_spilt_array, code_index);
                    }
                    if (strcmp(code_spilt_array[code_index], NEXT_CODE) == 0)
                    {
                        // 直接跳转到 for_return_address的地址
                        sml[instruct_counter] = BRANCH * 100 + for_return_address;
                        instruct_counter++;
                        instruct_check();
                        sml_low_count++;
                        fill_over_flag = 0;
                    }
                    if (strcmp(code_spilt_array[code_index], GETS_CODE) == 0)
                    {
                        // gets语句处理
                        fill_over_flag = gets_code(code_spilt_array, code_index);
                    }
                    if (strcmp(code_spilt_array[code_index], PUTS_CODE) == 0)
                    {
                        // puts语句处理
                        fill_over_flag = puts_code(code_spilt_array, code_index);
                    }

                }//非rem指令解析结束
            }
            else {
                // 单行指令只有行号,错误
                printf("语法错误:指令关键字错误。\n");
                // 停止编译
                compile_flag = 0;
            }//指令关键字解析结束
        }//其他字符串解析结束
    }
}
//行号入符号表处理
void line_symbol_process(char code_spilt_array[][CODESIZE], int n)
{
    // 是第一个行号,并且是数字类型
    if (isdigit(code_spilt_array[n][0]))
    {
        // tablecount:符号表计数器
        // symbol是符号
        symbol_table[table_counter].symbol = atoi(code_spilt_array[n]);
        // L是定义的行号类型
        symbol_table[table_counter].type = LINE_SYMBOL;
        // 在内存中的地址
        symbol_table[table_counter].location = sml_low_count;
        // 符号表计数器+1
        table_counter++;
    }
    // 如果第一个指令是@,for循环标识
    else if (code_spilt_array[n][0] = AT_SYMBOL)
    {
        // 行号
        symbol_table[table_counter].symbol = code_spilt_array[n][0];
        // F符号
        symbol_table[table_counter].type = FOR_STMBOL;
        // 在内存中的地址
        symbol_table[table_counter].location = sml_low_count;
        table_counter++;
    }
    else {
        printf("语法错误:缺少行号。\n");
        compile_flag = 0;//停止编译
    }
}
// rem指令处理
bool rem_code(char code_spilt_array[][CODESIZE], int n)
{
    // 判断是不是注释
    if (strcmp(code_spilt_array[n], REM_CODE) == 0) 
        // 是注释
        return true;
    // 不是注释
    return false;
}
//input指令处理
int input_code(char code_spilt_array[][CODESIZE], int n)
{
    int guard = 1;
    // input指令后面跟的就是参数
    input_parameters_parse(code_spilt_array[n + 1]);

    guard = 0;//退出循环 
    return guard;
}

// 参数解析
void  input_parameters_parse(char* parameters)
{
    int parameter_size;
    char parameter_split_array[CODESIZE][CODESIZE] = { 0 };//分解参数数组

    /*参数检查*/
    if (strlen(parameters) == 0)
    {
        printf("语法错误:缺少参数!\n");
        compile_flag = 0;//停止编译
    }
    else
    {
        // 判断参数逗号分隔符
        for (unsigned int i = 0; i < strlen(parameters); i++)
        {
            if ((i % 2) != 0)
            {
                if (parameters[i] != ',') {
                    printf("语法错误:参数间的分隔符请使用\',\'分隔符!\n");
                    compile_flag = 0;//停止编译
                }
            }
        }
    }

    // 分解参数列表
    parameter_size = strtok_string(parameter_split_array, parameters, " ,\t\n\0");
    for (int i = 0; i < parameter_size; i++)
    {
        /*处理符号表-符号表中未找到*/
        if (search_symbol_table(parameter_split_array[i][0], TABLESIZE, VARIABLE_SYMBOL) == -1) {
            // 符号表中未找到
            // 单字符变量名入符号表
            symbol_table[table_counter].symbol = parameter_split_array[i][0];
            // 类型
            symbol_table[table_counter].type = VARIABLE_SYMBOL;
            symbol_table[table_counter].location = sml_up_count;
            // 生成SML指令
            // 将参数加载到内存中
            sml[instruct_counter] = READ * 100 + symbol_table[table_counter].location;
            sml_up_count--;
            table_counter++;
            sml_low_count++;
            instruct_counter++;
            instruct_check();
        }
        else
        {
            // 如果符号表中已经存在
            // SML指令
            sml[instruct_counter] = READ * 100 + search_symbol_table(parameter_split_array[i][0], TABLESIZE, VARIABLE_SYMBOL);
            sml_up_count--;
            table_counter++;
            sml_low_count++;
            instruct_counter++;
            instruct_check();
        }
    }
}
int if_goto_code(char code_spilt_array[][CODESIZE], int n)
{
    int guard = 1;
    // 第一步加y加载到累加器中
    // SML指令
    sml[instruct_counter] = LOAD * 100 + search_symbol_table(code_spilt_array[n + 1][0], TABLESIZE, VARIABLE_SYMBOL);
    instruct_counter++;
    sml_low_count++;
    instruct_check();

    // 第二部 if语句处理
    // todo ylc 只处理“==”,其他大于小于情况暂未处理
    // todo ylc 复杂二维表达式没有处理
    // todo ylc bool类型的符号没有处理
    if (is_relational_operators(code_spilt_array[n + 2]) == 1)
    {
        if (isdigit(code_spilt_array[n + 3][0]))
        {
            //如果是数字符
            if (search_symbol_table(atoi(code_spilt_array[n + 3]), TABLESIZE, CONSTANT_SYMBOL) != -1) {
                // 没有找到常量值
                sml[instruct_counter] = SUBTRACT * 100 + search_symbol_table(atoi(code_spilt_array[n + 3]), TABLESIZE, CONSTANT_SYMBOL);//SML指令   
                instruct_counter++;
                instruct_check();  
                sml_low_count++;   
            }
            else
            {
                // 未找到“==”运算符后的变量
                // 常量值入符号表
                symbol_table[table_counter].symbol = atoi(code_spilt_array[n + 3]);
                // 类型
                symbol_table[table_counter].type = CONSTANT_SYMBOL;
                symbol_table[table_counter].location = sml_up_count;
                // 常量值存入内存
                // 整数常量存入内存
                sml[sml_up_count] = atoi(code_spilt_array[n + 3]);
                sml_up_count--;

                // SML指令
                sml[instruct_counter] = SUBTRACT * 100 + symbol_table[table_counter].location;   
                instruct_counter++;
                instruct_check();
                sml_low_count++;
                table_counter++;
            }
        }
        else
        {
            // 单字变量符
            if (search_symbol_table(code_spilt_array[n + 3][0], TABLESIZE, VARIABLE_SYMBOL) != -1) {
                // 找到变量'x'
                sml[instruct_counter] = SUBTRACT * 100 + search_symbol_table(code_spilt_array[n + 3][0], TABLESIZE, VARIABLE_SYMBOL);//SML指令   
                instruct_counter++;
                instruct_check();
                sml_low_count++;
            }
            else
            {
                // 未找到“==”运算符后的变量
                symbol_table[table_counter].symbol = code_spilt_array[n + 3][0];
                symbol_table[table_counter].type = VARIABLE_SYMBOL;
                symbol_table[table_counter].location = sml_up_count;
                sml[instruct_counter] = SUBTRACT * 100 + symbol_table[table_counter].location;
                instruct_counter++;
                instruct_check();
                sml_low_count++;
                table_counter++;
            }
        }
    }
    // 第三步 goto语句处理
    if (strcmp(code_spilt_array[n + 4], GOTO_CODE) == 0)
    {
        if (search_symbol_table(atoi(code_spilt_array[n + 5]), TABLESIZE, LINE_SYMBOL) != -1)
        {
            // 符号表中找到
            sml[instruct_counter] = HALT * 100 + atoi(code_spilt_array[n + 5]);
            instruct_counter++;
            instruct_check();
            sml_low_count++;
        }
        else
        {
            sml[instruct_counter] = BRANCHZERO * 100 + 00;
            // goto的地址不确定,第二次编译的时候处理
            un_analyze_array[instruct_counter] = atoi(code_spilt_array[n + 5]);
            instruct_counter++;
            instruct_check();
            sml_low_count++;
        }
    }
    else {
        printf("语法错误:缺少 goto指令。\n");
        compile_flag = 0;//停止编译
    }
    guard = 0;//退出循环    
    return guard;
}
// let指令处理
void let_code(char code_spilt_array[][CODESIZE], int code_index, int code_spilt_array_size)
{
    // 处理表达式-表达式所有符号入符号表
    // n 是 let的位置,n+1是赋值左值的位置,n+2是'='的位置
    for (int j = code_index + 3; j < code_spilt_array_size; j++)
    {
        
        if (isalpha(code_spilt_array[j][0]))
        {   //如果首字符是字符: let x = y
            if (search_symbol_table(code_spilt_array[j][0], TABLESIZE, VARIABLE_SYMBOL) == -1)
            {
                //符号表中未找到
                symbol_table[table_counter].symbol = code_spilt_array[code_index + 1][0]; 
                symbol_table[table_counter].type = VARIABLE_SYMBOL;
                symbol_table[table_counter].location = sml_up_count;
                sml_up_count--;
                table_counter++;
            }
        }
        else if (isdigit(code_spilt_array[j][0])) 
        {
            //如果首字符是数字 let x = 1 + 2
            if (search_symbol_table(atoi(code_spilt_array[j]), TABLESIZE, CONSTANT_SYMBOL) == -1)
            {
                symbol_table[table_counter].symbol = atoi(code_spilt_array[j]);
                symbol_table[table_counter].type = CONSTANT_SYMBOL;
                symbol_table[table_counter].location = sml_up_count;
                sml[sml_up_count] = atoi(code_spilt_array[j]);
                sml_up_count--;
                table_counter++;
            }
        }
    }
}
//获取 infix中缀表达式
void process_infix(char* infix, char* s)
{
    //将表达式中缀转换为后缀表示法
    int j = 0;
    //查找'='
    while (s[j] != ASSIGNMENT_OPERATOR)
    {
        j++;
    }
    strcpy(infix, &s[j + 1]);
    // 将结尾的换行符替换为空字符
    j = 0;
    while (infix[j] != '\n') {
        j++;
    }
    infix[j] = NULL_CHAR;
    //表达式转换及计数
    infix_to_postfix(infix);
}
//goto指令处理
int goto_code(char code_spilt_array[][CODESIZE], int code_index)
{
    int guard = 1;
    int addr = atoi(code_spilt_array[code_index + 1]);
    if (search_symbol_table(addr, TABLESIZE, LINE_SYMBOL) != -1)
    {
        // SML指令 
        sml[instruct_counter] = BRANCH * 100 + search_symbol_table(addr, TABLESIZE, LINE_SYMBOL);  
        //指令计数器加1
        instruct_counter++;
        //指令计数器检查
        instruct_check(); 
        //低位数据计数器加1
        sml_low_count++;
    }
    else//符号表中未找到
    {
        // 可能是往下跳,还没有编译到,放到未处理中,后续处理
        // SML指令  
        sml[instruct_counter] = BRANCH * 100 + 00;
        un_analyze_array[instruct_counter] = addr;
        instruct_counter++;
        instruct_check();
        sml_low_count++;
    }
    guard = 0;
    return guard;
}
// print指令处理
int print_code(char code_spilt_array[][CODESIZE], int code_index)
{
    int guard = 1;
    int parameter_array_len;
    char parameter_array[CODESIZE][CODESIZE] = { 0 };

    // 参数检查
    if (strlen(code_spilt_array[code_index + 1]) == 0)
    {
        printf("语法错误:缺少参数!\n");
        compile_flag = 0;//停止编译
    }
    else
    {
        // 判断参数逗号分隔符
        for (unsigned int i = 0; i < strlen(code_spilt_array[code_index + 1]); i++)
        {
            if ((i % 2) != 0)
            {
                if (code_spilt_array[code_index + 1][i] != ',') {
                    printf("语法错误:参数间的分隔符请使用\',\'分隔符!\n");
                    compile_flag = 0;//停止编译
                }
            }
        }
    }

    // 分解参数列表
    parameter_array_len = strtok_string(parameter_array, code_spilt_array[code_index + 1], " ,\t\n\0");

    for (int i = 0; i < parameter_array_len; i++)
    {
        if (search_symbol_table(parameter_array[i][0], TABLESIZE, VARIABLE_SYMBOL) != -1)
        {
            // 符号表中找到
            // SML指令
            sml[instruct_counter] = WRITE * 100 + search_symbol_table(parameter_array[i][0], TABLESIZE, VARIABLE_SYMBOL); 
            //指令计数器加1 
            instruct_counter++;
            //指令计数器检查
            instruct_check();
            //低位数据计数器加1
            sml_low_count++;
        }
        else
        {
            //符号表中未找到
            printf("语法错误!该变量不存在。\n");
            compile_flag = 0;//停止编译
        }
    }

    guard = 0;//退出循环 
    return guard;
}
// end指令处理
int end_code(char code_spilt_array[][CODESIZE], int n)
{
    int guard = 1;
    sml[instruct_counter] = HALT * 100 + 00;
    instruct_counter++; 
    instruct_check();   
    sml_low_count++;   

    guard = 0;//退出循环 
    return guard;
}
//gosub 指令处理
int gosub_code(char code_spilt_array[][CODESIZE], int code_index)
{
    int guard = 1;
    // 符号表中找到
    int addr = atoi(code_spilt_array[code_index + 1]);
    if (search_symbol_table(addr, TABLESIZE, LINE_SYMBOL) != -1)
    {
        //SML指令
        sml[instruct_counter] = BRANCH * 100 + search_symbol_table(addr, TABLESIZE, LINE_SYMBOL);   
        instruct_counter++;
        instruct_check(); 
        sml_low_count++;
    }
    else
    {
        //符号表中未找到
        sml[instruct_counter] = BRANCH * 100 + 00;
        un_analyze_array[instruct_counter] = addr;
        instruct_counter++;
        instruct_check();
        sml_low_count++;
    }
    guard = 0;//退出循环 
    return guard;
}
// forCode指令处理
// for x = 2 to 10 step 2
int for_code(char code_spilt_array[][CODESIZE], int code_index)
{
    int guard = 1;
    // 接收翻译后的语句
    char translation[CODESIZE] = { 0 };
    char x;
    // 2 || 10 || 2
    int value;
    // 第1步:语法检查
    for_grammar_check(code_spilt_array, code_index);
    // 第2步:翻译语句 x = 2
    // x
    x = code_spilt_array[code_index + 1][0];
    // 2
    value = atoi(code_spilt_array[code_index + 3]);
    // @为 for语句标记符,'\n'符合 let解析条件
    // @ let x = 2\n
    sprintf(translation, "%c%s%c%s%d%s%d%c", AT_SYMBOL, " let ", x, " = ", 0, " + ", value, '\n');
    // printf("%s\n", translation);
    // 生成符号表及SML指令
    create_symbol_table(translation); 

    // 第3步:翻译语句 to 10
    // next循环标号地址,返回时会再次跳转到该行指令
    for_return_address = instruct_counter;
    // 10
    value = atoi(code_spilt_array[code_index + 5]);
    // @ if x == 10 goto for_return_address
    sprintf(translation, "%c%s%c%s%d%s%d", AT_SYMBOL, " if ", x, " == ", value, " goto ", for_goto_line);
    // printf("%s\n", translation);
    // 生成符号表及SML指令
    create_symbol_table(translation); 

    // 第4步:翻译 step 2语句
    if (strcmp(code_spilt_array[7], STEP_CODE) == 0)
    {
        // 含有step关键字
        value = atoi(code_spilt_array[code_index + 7]);//2
        // 写入数组,@为for语句标记符
        // @ let x = x + 2\n
        sprintf(translation, "%c%s%c%s%c%s%d%c", AT_SYMBOL, " let ", x, " = ", x, " + ", value, '\n');
    }
    else//没有 step关键字
    {
        value = 1;//默认 step = 1
        // @ let x = x + 2\n
        sprintf(translation, "%c%s%c%s%c%s%d%c", '@', " let ", x, " = ", x, " + ", value, '\n');//写入数组,@为for语句标记符
    }
    // printf("%s\n", translation);
    //生成符号表及SML指令
    create_symbol_table(translation);

    guard = 0;
    return guard;
}
//gets 输入字符串语句处理
int gets_code(char code_spilt_array[][CODESIZE], int code_index)
{
    int guard = 1;
    // 先计算分配字符串所需的内存空间
    int str_len = atoi(code_spilt_array[code_index + 2]);
    if (search_symbol_table(str_len, TABLESIZE, CONSTANT_SYMBOL) == -1)
    {
        //符号表中未找到
        //整数值入符号表
        symbol_table[table_counter].symbol = code_spilt_array[code_index + 2][0];
        symbol_table[table_counter].type = CONSTANT_SYMBOL;
        symbol_table[table_counter].location = sml_up_count;
        sml_up_count--;
        table_counter++;
    }
    // 字符串预留内存空间
    sml_up_count -= atoi(code_spilt_array[code_index + 2]);
    // 符号表中未找到
    if (search_symbol_table(code_spilt_array[code_index + 1][0], TABLESIZE, STRING_SYMBOL) == -1)
    {
        symbol_table[table_counter].symbol = code_spilt_array[code_index + 1][0];
        symbol_table[table_counter].type = STRING_SYMBOL;
        symbol_table[table_counter].location = sml_up_count;
        sml_up_count--;
        table_counter++;
    }
    // sml指令
    sml[instruct_counter] = INSTRING * 100 + search_symbol_table(code_spilt_array[code_index + 1][0], TABLESIZE, STRING_SYMBOL);
    instruct_counter++;
    instruct_check();
    sml_low_count++;
    guard = 0;
    return guard;
}

//puts输出字符串语句处理
int puts_code(char code_spilt_array[][CODESIZE], int code_index)
{
    int guard = 1;
    // 要显示的字符串结尾添加空字符
    sml[search_symbol_table(code_spilt_array[code_index + 1][0], TABLESIZE, STRING_SYMBOL) + atoi(code_spilt_array[code_index + 2])] = '\0';
    // SML指令 第1个字节为长度,第2个字节开始
    sml[instruct_counter] = OUTSTRING * 100 + search_symbol_table(code_spilt_array[code_index + 1][0], TABLESIZE, STRING_SYMBOL);
    instruct_counter++;
    instruct_check();
    sml_low_count++;
    guard = 0;
    return guard;
}
// for语句语法错误检查,step关键字不检查
void for_grammar_check(char code_spilt_array[][CODESIZE], int code_index)
{
    if (isalpha(code_spilt_array[2][0]) == 0) {
        printf("语法错误:变量定义错误!\n");
        compile_flag = 0;
    }
    if (code_spilt_array[3][0] != '=') {
        printf("语法错误:\'=\'缺失!\n");
        compile_flag = 0;
    }
    if (strcmp(code_spilt_array[5], "to") != 0) {
        printf("语法错误:缺少关键字to!\n");
        compile_flag = 0;
    }
    if (isdigit(code_spilt_array[6][0]) == 0) {
        printf("语法错误:变量定义错误!\n");
        compile_flag = 0;
    }
}
//判断是否是运算符
int is_relational_operators(char* s)
{
    if (strcmp(s, EQ_RELATION) == 0)
        return 1;
    if (strcmp(s, GE_RELATION) == 0)
        return 2;
    if (strcmp(s, LE_RELATION) == 0)
        return 3;
    if (strcmp(s, GT_RELATION) == 0)
        return 4;
    if (strcmp(s, LT_RELATION) == 0)
        return 5;
    return -1;
}
// 查找符号变量或常量的内存位置
int search_symbol_table(int value, int size, char c)
{
    for (int i = 0; i < size; i++)
    {
        // 符号的值相同,符号的类型相同
        if (symbol_table[i].symbol == value && symbol_table[i].type == c)
            // 返回符号的内存位置
            return symbol_table[i].location;
    }
    return -1;//未找到
}

// 判断是否指令关键字
bool keywords(char* s)
{
    if (strcmp(s, REM_CODE) == 0)
        return true;
    if (strcmp(s, INPUT_CODE) == 0)
        return true;
    if (strcmp(s, LET_CODE) == 0)
        return true;
    if (strcmp(s, PRINT_CODE) == 0)
        return true;
    if (strcmp(s, GOTO_CODE) == 0)
        return true;
    if (strcmp(s, IF_CODE) == 0)
        return true;
    if (strcmp(s, END_CODE) == 0)
        return true;
    if (strcmp(s, GOSUB_CODE) == 0)
        return true;
    if (strcmp(s, RETURN_CODE) == 0)
        return true;
    if (strcmp(s, FOR_CODE) == 0)
        return true;
    if (strcmp(s, NEXT_CODE) == 0)
        return true;
    if (strcmp(s, GETS_CODE) == 0)
        return true;
    if (strcmp(s, PUTS_CODE) == 0)
        return true;
    if (strcmp(s, TO_CODE) == 0)
        return true;
    if (strcmp(s, STEP_CODE) == 0)
        return true;
    return false;
}
// 分解字符串并保存字符串数组
int strtok_string(char result_array[][INFIXSIZE], char* s, char* separator)
{
    // 循环标识
    char* token;
    int split_size = 0;   //计数器
    // 第一次分解
    token = strtok(s, separator);
    while (token != NULL)
    {
        // 分解的子串放入结果数组
        strcpy(result_array[split_size++], token);
        // 继续分解其他子串
        token = strtok(NULL, separator);
    }
    return split_size;
}
// 打印SML数组
void print_sml(int* s, int size)
{
    printf("\nSML内存:\n");
    for (int i = 0; i < size; i++)
    {
        printf("%+05d%c", s[i], ((i + 1) % 10) == 0 ? '\n' : ' ');
    }
    putchar('\n');
}
// 打印符号表
void print_symbol_table(TableEntry* s, int size)
{
    printf("\n符号表:\n");
    printf("\n%s\t\t%s\t\t%s\n", "符号", "类型", "位置");
    for (int i = 0; i < size; i++)
    {
        if ((isalpha(s[i].symbol) && ((s[i].type == 'V') || (s[i].type == 'S'))) || s[i].symbol == '@')
            printf("\'%c\'\t\t", s[i].symbol);
        else
            printf("%2d\t\t", s[i].symbol);
        printf("%c\t\t%02d\n", s[i].type, s[i].location);
    }
    putchar('\n');
}
// 表达式转换及计数
void infix_to_postfix(char* infix)
{
    // 链表节点指针初始化
    StackNodePtr startPtr = NULL;
    // 后缀表达式记录数组
    char postfix_array[INFIXSIZE][INFIXSIZE] = { 0 };
    // 分解数组
    char split_infix[INFIXSIZE][INFIXSIZE] = { 0 }; 
    // 临时字符
    char tmp_ch;
    // 字符个数
    int split_infix_size = 0;
    // 计数器
    int i = 0;
    // 后缀表达式字符串个数
    int postfix_array_size = 0;
    // 计算结果
    int result = 0;

    /*将左括号压入堆栈*/
    tmp_ch = LEFT_BRACKETS;
    // 将左括号压入栈
    push(&startPtr, tmp_ch);
    // 输出栈,测试
    // print_stack(startPtr);

    // 在 infix末尾追加')'
    tmp_ch = RIGHT_BRACKETS;
    while (infix[i] != NULL_CHAR) 
        // 移到 infix结尾
        i++;
 
    // 插入' '
    infix[i] = SPACE_CHAR;
    // 插入')'
    infix[i + 1] = tmp_ch;
    // 补上空字符
    infix[i + 2] = NULL_CHAR;
    // printf("%s\n", infix);

    // 到这里,infix就只剩右值
    // 分解文本并保存字符串数组
    split_infix_size = strtok_string(split_infix, infix, SPLIT_OPERATOR);

    // 将中缀表达式转换为后缀符号
    do_infix_to_postfix(&startPtr, split_infix, split_infix_size, postfix_array);

    // 输出,测试 
    // print_stack(startPtr);    
    // for (int i = 0; i < split_infix_size; i++)
    // {
    //     printf("%s ", postfix_array[i]);
    // }
    // printf("\n");

    // 计算转换后的后缀表达式字符串个数
    while (postfix_array[postfix_array_size][0] != '\0')
    {
        postfix_array_size++;
    }

    result = postfix_to_sml(&startPtr, postfix_array, postfix_array_size);
    // printf("表达式的结果 = %d\n", result);
}

//==========================================================================================
// 表达式中缀转后缀表示方法

// 将一个节点插入到栈顶
void push(StackNodePtr* topPtr, int value)
{
    // 指向新节点的指针
    StackNodePtr newPtr;

    // 创建新节点
    newPtr = malloc(sizeof(StackNode));

    /*在栈顶插入节点*/
    if (newPtr != NULL)
    {
        newPtr->data = value;
        newPtr->nextPtr = *topPtr;
        // 栈顶替换
        *topPtr = newPtr;
    }
    else
        printf("%c插入失败,没有足够的内存。\n", value);
}
// 从栈顶删除一个节点
int pop(StackNodePtr* topPtr)
{
    // 临时节点的指针
    StackNodePtr tempPtr;
    // 节点值
    int popValue;

    tempPtr = *topPtr;
    popValue = (*topPtr)->data;
    *topPtr = (*topPtr)->nextPtr;
    free(tempPtr);
    return popValue;
}
// 判断堆栈是否为空
int is_empty(StackNodePtr sPtr)
{
    return sPtr == NULL;
}
//输出堆栈
void print_stack(StackNodePtr topPtr)
{
    /*如果堆栈为空*/
    if (topPtr == NULL)
        printf("堆栈为空。\n\n");
    else
    {
        printf("堆栈:\n");
        while (topPtr != NULL)
        {
            printf("%c--> ", topPtr->data);
            // 下一个节点
            topPtr = topPtr->nextPtr;
        }
        // 打印结尾NULL
        printf("NULL\n\n");
    }
}
// 将中缀表达式转换为后缀表达式
void do_infix_to_postfix(StackNodePtr* topPtr, const char split_infix[][INFIXSIZE], 
    const int split_infix_size, char postfix[][INFIXSIZE])
{
    //postfix数组下标
    int postfix_index = 0;
    // 栈第判空
    if (!is_empty(*topPtr))
    {
        for (int i = 0; i < split_infix_size; i++)
        {
            if (isdigit(split_infix[i][0]))
            {
                // 如果是数字
                strcpy(postfix[postfix_index], split_infix[i]);
                postfix_index++;
            }
            if (isalpha(split_infix[i][0]))
            {
                // 如果是单字符变量名
                strcpy(postfix[postfix_index], split_infix[i]);
                postfix_index++;
            }
            if (split_infix[i][0] == LEFT_BRACKETS) 
                // 如果是左括号
                push(topPtr, split_infix[i][0]);

            if (is_operator(split_infix[i][0]))
            {
                // 如果是运算符
                if (is_operator((*topPtr)->data))
                {
                    // 如果堆栈栈顶是运算符
                    if (precedence(split_infix[i][0]) <= precedence((*topPtr)->data))
                    {
                        postfix[postfix_index][0] = pop(topPtr);
                        postfix_index++;
                        push(topPtr, split_infix[i][0]);
                    }
                    else
                        push(topPtr, split_infix[i][0]);
                }
                else     //栈顶不是运算符
                    push(topPtr, split_infix[i][0]);
            }
            
            if (split_infix[i][0] == RIGHT_BRACKETS)
            {
                //如果是右括号
                while ((*topPtr)->data != LEFT_BRACKETS)
                {
                    postfix[postfix_index][0] = pop(topPtr);
                    postfix_index++;
                }
                pop(topPtr);
            }
        }
    }
    else
        printf("堆栈为空。\n");
}
//确定是否为运算符
int is_operator(char c)
{
    // todo ylc 暂时只判断这6中运算符的优先级
    switch (c) {
        case ADD_OPERATOR:
        case SUB_OPERATOR:
        case MUL_OPERATOR:
        case DIV_OPERATOR:
        case MODEL_OPERATOR:
        case POWER_OPERATOR:
            return 1;
        default:
            return 0;
    }
}
//确定运算符优先级
int precedence(char opreator)
{
    switch (opreator) {
    case ADD_OPERATOR:
    case SUB_OPERATOR:
        return 13;
    case MUL_OPERATOR:
    case DIV_OPERATOR:
    case MODEL_OPERATOR:
        return 12;
    case POWER_OPERATOR:
        return 6;
    default:
        return 0;
    }
}

//==========================================================================================
//计算后缀表达式
int postfix_to_sml(StackNodePtr* topPtr, char postfix_array[][INFIXSIZE], int postfix_array_size)
{
    int i = 0;
    int operand1_addr = 0;
    int operand2_addr = 0;
    int result_addr = 0;

    for (i = 0; i < postfix_array_size; i++)
    {
        if (isdigit(postfix_array[i][0]))
        {
            // 如果是数字符,压入内存
            int constant = atoi(postfix_array[i]);
            if (constant > 9999 || constant < -9999)
            {
                printf("语法错误:常量值溢出错误!常量整数值在-9999~+9999之间。\n");
                compile_flag = 0;
            }
            // 在前面已经进行了符号填充,肯定能找到
            // 返回符号表中存储的内存位置
            int temp = search_symbol_table(constant, TABLESIZE, CONSTANT_SYMBOL);
            push(topPtr, temp);//入栈
        }
        else if (islower(postfix_array[i][0]))
        {
            // 如果是小写单字符,压入其对应的内存位置
            // 返回符号表中存储的内存位置
            int temp = search_symbol_table(postfix_array[i][0], TABLESIZE, VARIABLE_SYMBOL);
            // 入栈
            push(topPtr, temp);
        }
        else
        {
            // 运算符
            if (!is_empty(*topPtr))
                // 第2个操作数
                operand2_addr = pop(topPtr);
            else
                printf("堆栈为空.\n");
            if (!is_empty(*topPtr))
                // 第1个操作数,注意顺序
                operand1_addr = pop(topPtr);
            else
                printf("堆栈为空.\n");
            // 生成 sml指令,并压入内存
            result_addr = binary_expression_to_sml(operand1_addr, operand2_addr, postfix_array[i][0]);
            // 将存储结果的地址压入堆栈
            push(topPtr, result_addr);
        }
    }
    // 返回表达式计算结果
    result_addr = pop(topPtr);
    // 将累加器的值保存至=左侧操作数
    // 在进行数学运算时,倒数第二步都是进行计算,在最后一步将计算结果的值存入内存后返回地址
    // 倒数第二步还隐藏了一个动作,运算结果存在累加器中
    // 到这里时,累加器里的值就是最后的结果
    // 编写指令将结果的值放入到左操作数的内存地址中
    sml[instruct_counter] = STORE * 100 + let_variable_location;   
    //指令计数器加1 
    instruct_counter++; 
    //指令计数器检查
    instruct_check();
    //低位数据计数器加1 
    sml_low_count++;    
    return result_addr;
}

// 计算表达式op1 operator op2
int binary_expression_to_sml(int op1_addr, int op2_addr, char operator)
{
    // 计算结果的内存位置
    int result_addr = 0;
    // 加法
    if (operator == ADD_OPERATOR) {
        // SML指令,加载到累加器中   
        sml[instruct_counter] = LOAD * 100 + op1_addr;
        // 指令计数器加1
        instruct_counter++; 
        // 指令计数器检查
        instruct_check();
        // 低位数据计数器加1
        sml_low_count++; 

        // SML指令,加指令
        sml[instruct_counter] = ADD * 100 + op2_addr;  
        // 指令计数器加1
        instruct_counter++; 
        // 指令计数器检查
        instruct_check();
        // 低位数据计数器加1
        sml_low_count++; 

        // SML指令,结果存入到内存
        sml[instruct_counter] = STORE * 100 + sml_up_count; 
        // 指令计数器加1 
        instruct_counter++;
        // 指令计数器检查
        instruct_check();
        // 低位数据计数器加1
        sml_low_count++; 
        // 计算结果
        result_addr = sml_up_count; 
    }
    // 减法
    if (operator == SUB_OPERATOR) {
        sml[instruct_counter] = LOAD * 100 + op1_addr;  
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        sml[instruct_counter] = SUBTRACT * 100 + op2_addr;
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        sml[instruct_counter] = STORE * 100 + sml_up_count;
        instruct_counter++; 
        instruct_check();
        sml_low_count++;

        result_addr = sml_up_count;
    }
    // 乘法
    if (operator == MUL_OPERATOR) {
        sml[instruct_counter] = LOAD * 100 + op1_addr; 
        instruct_counter++; 
        instruct_check();
        sml_low_count++;

        sml[instruct_counter] = MULTIPLY * 100 + op2_addr;
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        sml[instruct_counter] = STORE * 100 + sml_up_count;  
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        result_addr = sml_up_count;
    }
    // 除法
    if (operator == DIV_OPERATOR) {
        sml[instruct_counter] = LOAD * 100 + op1_addr; 
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        sml[instruct_counter] = DIVIDE * 100 + op2_addr;
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        sml[instruct_counter] = STORE * 100 + sml_up_count;   
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        result_addr = sml_up_count;
    }
    // 取模
    if (operator == MODEL_OPERATOR) {
        sml[instruct_counter] = LOAD * 100 + op1_addr;
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        sml[instruct_counter] = MODE * 100 + op2_addr;
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        sml[instruct_counter] = STORE * 100 + sml_up_count;
        instruct_counter++; 
        instruct_check();
        sml_low_count++;

        result_addr = sml_up_count;
    }
    // 求幂
    if (operator == POWER_OPERATOR) {
        sml[instruct_counter] = LOAD * 100 + op1_addr;
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        sml[instruct_counter] = POWER * 100 + op2_addr;
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        sml[instruct_counter] = STORE * 100 + sml_up_count;
        instruct_counter++;
        instruct_check();
        sml_low_count++;

        result_addr = sml_up_count;
    }
    sml_up_count--;
    return result_addr;
}

0x05 总结

更深刻的理解计算机软件实现原理与JVM实现原理

标签:code,counter,instruct,编译器,sml,简单,table,array
From: https://www.cnblogs.com/ylc0x01/p/17476211.html

相关文章

  • OSS简单文件上传和本地存储上传
    网站的文件上传方法本地存储上传//本地存储方式MultipartFile接受文件@PostMapping("/save")publicResultsave(Stringusername,Integerage,MultipartFileimage)throwsIOException{log.info("文件:{},{},{}",username,age,image);......
  • jmeter简单调用接口
    需求:Jmeter软件调用天气预报接口 网站:https://www.showapi.com/搜索第三方的天气接口: 0元,立即购买  注册:yidongzjq 密码:Nari.1234 ......
  • sekiro RPC框架的安装与简单使用(转)
    前言上篇介绍了下平头哥的安装使用,这篇再来介绍下渣总的只狼(sekiro)框架然后再简单讲下如何通过平头哥注入sekiro,实现RPC调用一、sekiro是什么1.简介sekiro是由邓维佳(渣总)写的一个基于长链接和代码注入的API服务暴露框架sekiro即可以用于app逆向,又可以用在js逆向找好注入位......
  • 当GaussDB遇上了毕昇编译器
    摘要:当应用软件及硬件确定后,编译器对应用的自动优化将成为应用性能的关键。从应用优化说起一个应用的优化通常有架构级优化、模块级优化和函数级优化,高性能作为云数据库GaussDB主打特性之一,其在这几方面都进行了大量的优化,也有很强的性能表现。如何进一步提升性能,是否还有其他方......
  • vue实现简单的鼠标拖拽横向滚动 和 鼠标滚轮横向滚动
    一.鼠标拖拽滚动以下代码项目中直接使用即可,此种方法是通过鼠标拖拽进行滚动,滑动滚轮无效果。当然快捷键,shift+鼠标滚轮可以控制横向滚动,对用户来说体验不友好。<divclass="tab-listid="nav"><divclass="tab-item"v-for="(item,index)inlist":key=""></div></d......
  • POJ 2019 Cornfields(简单二维RMQ)
    思路:二维RMQ#include<cstdio>#include<cstring>#include<algorithm>usingnamespacestd;constintMAXN=255;intval[MAXN][MAXN];intdmin[MAXN][MAXN][8][8];intdmax[MAXN][MAXN][8][8];voidinitRMQ(intn,intm){for(inti=1;i<=n;i++)......
  • Java 线程池简单使用
    privatefinalThreadPoolExecutorhandleExecutor=newThreadPoolExecutor(3,5,5000L,TimeUnit.MILLISECONDS,newLinkedBlockingQueue<>(),newThreadFactoryBuilder().setNameFormat("MsgCenterHandle-%d").build());......
  • Jumpserver堡垒机简单配置
    Jumpserver是一款由python编写完全开源的跳板机(堡垒机)系统,实现了跳板机应有的功能。基于ssh协议来管理,客户端无需安装agent。此文简要介绍实际操作时,简单配置过程。Jumpserver基于CentOS7安装,可参考⬇️CentOS7一步步安装Jumpserver堡垒机(官方教程版)创建Jumpserver用户1.点击页面......
  • objectARX 插入ole图片简单示意
    代码 //获取BMP文件的数据 HBITMAPhBmp=(HBITMAP)LoadImage(NULL,_T("d:\\123.bmp"),IMAGE_BITMAP,0,0,LR_LOADFROMFILE); if(hBmp==NULL){ acutPrintf(_T("FailedtoloadBMPfile\n")); return; } //打开剪贴板 if(!OpenClipb......
  • nginx-clojure debug构建简单说明
    实际上参考了官方的构建参数,提供一个debug模式的文件原始配置configurearguments:--prefix=--sbin-path=nginx--conf-path=conf/nginx.conf--error-log-path=logs/error.log--http-log-path=logs/access.log--pid-path=logs/nginx.pid--lock-path=logs/nginx.......