【NUAA编译原理实验】pl/0编译器

目录

词法分析cifa.h

语法分析yufa.cpp

样例代码

输出


无first集和follow集纠错,使用的是线性符号表,读者均可自行修改

词法分析cifa.h

#pragma once
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <fstream>
using namespace std;

string err_msg[]=
{
    "标识符非法",
    "标识符不能以数字开头",
    "后面缺少=",
    "错误字符输入"
};
int row = 1, col = 0;
int err = 0;

struct token
{
    string strToken;
    int row, col;
    int kind;//1-id, 2-const, 3-other, 4-key
};

void error(int n, char ch)
{
    err++;
    cout << "Error" << err << ", " << err_msg[n] << " " << ch << endl;
}

string Concat(char ch, string& strToken)
{
    strToken += ch;
    return strToken;
}

bool IsLetter(char ch)
{
    if((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool IsDigit(char ch)
{
    if(ch >= '0' && ch <= '9')
    {
        return true;
    }
    else
    {
        return false;
    }
}

int Reserve(string &strToken, vector<string> table)
{
    int i = 1;
    for(i;i < table.size();i++)
    {
        if(strToken == table[i])
        {
            return i;
        }
    }
    return 0;
}

int insertID(string &strToken, vector<string> &table)
{
    table.push_back(strToken);
    return table.size();
}

int insertConst(string &strToken, vector<int> &table)
{
    table.push_back(atoi(&strToken[0]));
    return table.size();
}

void cifa(vector<token> &T)
{
    string Table[] =
    {"", "program", "const", "var", "procedure",
     "begin", "end", "if", "then", "else", "while", "do",
     "call", "read", "write", "odd"};
    vector<string> reserve_table(Table, Table + 15);
    vector<string> sign_table;
    vector<int> const_table;
    token t;

    ifstream infile("code5.txt");
    if(!infile)
    {
        cout << "can not open codeFile!" << endl;
    }
    ofstream outfile("temp.txt");
    if(!outfile)
    {
        cout << "can not open tempFile!" << endl;
    }

    char ch;
    int code, value;
    string strToken;

    infile.get(ch);
    col++;

    if(ch == ' ')
    {
        while(!infile.eof())
        {
            if(IsLetter(ch) || IsDigit(ch))
            {
                infile.seekg(-1, ios::cur);
                col--;
                break;
            }
            else
            {
                infile.get(ch);
                col++;
            }
        }
    }

    while(!infile.eof())
    {
        strToken = "";
        if(IsLetter(ch))
        {
            while(IsLetter(ch) || IsDigit(ch))
            {
                Concat(ch, strToken);
                infile.get(ch);
                if(!infile) break;
                col++;
            }
            
            code = Reserve(strToken, reserve_table);
            if(code == 0)
            {
                value = Reserve(strToken, sign_table);
                if(value == 0)
                {
                    value = insertID(strToken, sign_table);
                    outfile << "(" << strToken << ", $ID, " << value << ")" << endl;

                    t.strToken = strToken;
                    t.row = row;
                    t.col = col - strToken.length();
                    t.kind = 1;
                    T.push_back(t);
                }
                else
                {
                    outfile << "(" << strToken << ", $ID, " << value << ")" << endl;

                    t.strToken = strToken;
                    t.row = row;
                    t.col = col - strToken.length();
                    t.kind = 1;
                    T.push_back(t);
                }
            }
            else
            {
                outfile << "(" << strToken << ", -, " << code << ")" << endl;

                t.strToken = strToken;
                t.row = row;
                t.col = col - strToken.length();
                t.kind = 4;
                T.push_back(t);

                if(code == 7)
                {
                    if(ch != ' ')
                    {
                        cout << row << "行" << col << "列:";
                        error(0, ch);//
                    }
                }
            }
        }
        else if(IsDigit(ch))
        {
            while(IsDigit(ch))
            {
                Concat(ch, strToken);
                infile.get(ch);
                if(!infile) break;
                col++;
            }
            if(IsLetter(ch))
            {
                cout << row << "行" << col << "列:";
                error(1, ch);//
            }
            else
            {
                value = insertConst(strToken, const_table);
                outfile << "(" << strToken << ", $INT, " << value << ")" << endl;

                t.strToken = strToken;
                t.row = row;
                t.col = col - strToken.length();
                t.kind = 2;
                T.push_back(t);
            }
        }
        else if(ch == '=')
        {
            outfile << "($=, -)" << endl;
            
            t.strToken = "=";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

            infile.get(ch);
            col++;
        }
        else if(ch == '+')
        {
            outfile << "($+, -)" << endl;
            
            t.strToken = "+";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

            infile.get(ch);
            col++;
        }
        else if(ch == '-')
        {
            outfile << "($-, -)" << endl;
            
            t.strToken = "-";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

            infile.get(ch);
            col++;
        }
        else if(ch == '*')
        {
            infile.get(ch);
            col++;
            if(ch == '*')
            {
                outfile << "($POWER, -)" << endl;
            
                t.strToken = "**";
                t.row = row;
                t.col = col;
                t.kind = 3;
                T.push_back(t);

                infile.get(ch);
                col++;
            }
            else
            {
                outfile << "($STAR, -)" << endl;
            
                t.strToken = "*";
                t.row = row;
                t.col = col;
                t.kind = 3;
                T.push_back(t);

            }
        }
        else if(ch == '/')
        {
            outfile << "($/, -)" << endl;
            
            t.strToken = "/";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

            infile.get(ch);
            col++;
        }
        else if(ch == '<')
        {
            infile.get(ch);
            col++;
            if(ch == '>')
            {
                outfile << "($<>, -)" << endl;
            
                t.strToken = "<>";
                t.row = row;
                t.col = col;
                t.kind = 3;
                T.push_back(t);

                infile.get(ch);
                col++;
            }
            else if(ch == '=')
            {
                outfile << "($<=, -)" << endl;
            
                t.strToken = "<=";
                t.row = row;
                t.col = col;
                t.kind = 3;
                T.push_back(t);

                infile.get(ch);
                col++;
            }
            else
            {
                outfile << "($<, -)" << endl;
            
                t.strToken = "<";
                t.row = row;
                t.col = col;
                t.kind = 3;
                T.push_back(t);

            }
        }
        else if(ch == '>')
        {
            infile.get(ch);
            col++;
            if(ch == '=')
            {
                outfile << "($>=, -)" << endl;
            
                t.strToken = ">=";
                t.row = row;
                t.col = col;
                t.kind = 3;
                T.push_back(t);

                infile.get(ch);
                col++;
            }
            else
            {
                outfile << "($>, -)" << endl;
            
                t.strToken = ">";
                t.row = row;
                t.col = col;
                t.kind = 3;
                T.push_back(t);

            }
        }
        else if(ch == ';')
        {
            outfile << "($;, -)" << endl;
            
            t.strToken = ";";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

            infile.get(ch);
            col++;
        }
        else if(ch == '(')
        {
            outfile << "($(, -)" << endl;
            
            t.strToken = "(";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

            infile.get(ch);
            col++;
        }
        else if(ch == ')')
        {
            outfile << "($), -)" << endl;
            
            t.strToken = ")";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

            infile.get(ch);
            col++;
        }
        else if(ch == '{')
        {
            outfile << "(${, -)" << endl;
            
            t.strToken = "{";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

            infile.get(ch);
            col++;
        }
        else if(ch == '}')
        {
            outfile << "($}, -)" << endl;
            
            t.strToken = "}";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

            infile.get(ch);
            col++;
        }
        else if(ch == '\n' || ch == ' ' || ch == 9)
        {
            if(ch == '\n')
            {
                row++;
                col = 0;
            }
            infile.get(ch);
            col++;
        }
        else if(ch == ':')
        {
            infile.get(ch);
            col++;
            if(ch == '=')
            {
                outfile << "($:=, -)" << endl;
            
                t.strToken = ":=";
                t.row = row;
                t.col = col;
                t.kind = 3;
                T.push_back(t);

                infile.get(ch);
                col++;
            }
            else
            {
                cout << row << "行" << col << "列:";
                error(2, ch);//
                infile.get(ch);
                col++;
            }
        }
        else if(ch == ',')
        {
            outfile << "($,, -)" << endl;
            
            t.strToken = ",";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

			infile.get(ch);
			col++;
        }
        else
        {
            cout << row << "行" << col << "列:";
            error(3, ch);//
            
            t.strToken = "NULL";
            t.row = row;
            t.col = col;
            t.kind = 3;
            T.push_back(t);

            infile.get(ch);
            col++;
        }
    }
    infile.close();
    outfile.close();
}

语法分析yufa.cpp

#include "cifa.h"
#include <cstdio>
using namespace std;

#define NULL_DEF -100//空NULL

int goal = 0;

vector<token> t;
int t_index = 0;
string op[] = {
    "LIT",
    "LOD",
    "STO",
    "CAL",
    "INT",
    "JMP",
    "JPC",
    "WRT",
    "OPR",
    "RED"
};
enum opcode
{
    LIT,
    LOD,
    STO,
    CAL,
    INT,
    JMP,
    JPC,
    WRT,
    OPR,
    RED
};

typedef struct
{
    int f;
    int l;
    int a;
}code;
vector<code> mid_code;//中间代码
typedef struct
{
    string name;
    int kind;//1-variable 2-constant 3-procedure
    int value;
    int level;
    int address;
    int size;
}namelist;
vector<namelist> table;//符号表
int level = 0;
int address = 0;
int dx = 3;//记录开辟空间个数,默认是3,SL DL RA

class yufa
{
    public:
    //报错
    void error(token _t, string msg)
    {
        goal = 1;
        cout << _t.row << "行" << _t.col << "列:Error" << err << ", " << _t.strToken << msg << endl;
        err++;
    }
    //调用词汇
    token getsym()
    {
        if(t_index > t.size())
        {
            exit(0);//!
        }
        token _token = t[t_index];
        t_index++;
        return _token;
    }
    //记录符号表
    void enter(string name, int kind, int value, int lev, int address, int size)
    {
        namelist _table;
        _table.name = name;
        _table.kind = kind;
        _table.value = value;
        _table.level = lev;
        _table.address = address;
        _table.size = size;

        table.push_back(_table);
    }
    //生成中间代码
    void gen(int f, int l, int a)
    {
        code _pcode;
        _pcode.f = f;
        _pcode.l = l;
        _pcode.a = a;
        mid_code.push_back(_pcode);
    }
    //查询符号表
    int find_table(string val, int lev)
    {
        int index=table.size() - 1;
        for(index;index>=0;index--)
        {
            if(table[index].name == val)
            {
                if(table[index].level <= lev)
                    return index;
            }
        }
        return -1;
    }
    //<prog> → program <id>;<block>
    void prog()
    {
        token _t = getsym();
        if(_t.strToken == "program")
        {
            _t = getsym();
            if(_t.kind == 1)
            {
                _t = getsym();
                if(_t.strToken == ";")
                {
                    block(0);
                }
                else
                {
                    error(_t, "后面缺少';'");
                }
            }
            else
            {
                error(_t, "语法错误, 缺少程序名称");
            }
        }
        else
        {
            error(_t, "缺少关键字'program'");
        }
    }
    //<block> → [<condecl>][<vardecl>][<proc>]<body>
    void block(int dx0)
    {
        dx = 3 + dx0;
        int cx1 = mid_code.size();
        int idSize;
        gen(JMP, 0, 0);
        token _t = getsym();
        if(_t.strToken == "const")
        {
            _const();
            _t = getsym();
            while(_t.strToken == ",")
            {
                _const();
                _t = getsym();
            }
            if(_t.strToken == ";")
            {
                _t = getsym();
            }
            else
            {
                error(_t, "缺少';'");
            }
        }
        if(_t.strToken == "var")
        {
            _t = getsym();
            if(_t.kind == 1)
            {
                enter(_t.strToken, 1, NULL_DEF, level, dx, NULL_DEF);
                dx++;
                _t = getsym();
            }
            else
            {
                error(_t, "'var'后面需要跟标识符");
            }
            while(_t.strToken == ",")
            {
                _t = getsym();
                if(_t.kind == 1)
                {
                    enter(_t.strToken, 1, NULL_DEF, level, dx, NULL_DEF);
                    dx++;
                    _t = getsym();
                    continue;
                }
            }
            if(_t.strToken == ";")
            {
                _t = getsym();
            }
            else
            {
                error(_t, "缺少';'");
            }
        }
        while(_t.strToken == "procedure")
        {
            _t = getsym();

            token temp;
            temp = _t;

            if(_t.kind != 1)
            {
                error(_t, "函数名不是标识符");
            }
            _t = getsym();

            int goal = 0; //判断是否进入(id, id)
            //(id, id)
            if(_t.strToken == "(")
            {
                idSize = 0;
                goal = 1;

                do
                {
                    _t = getsym();
                    if(_t.kind != 1)
                    {
                        error(_t, "不是标识符");
                    }
                    idSize++;
                    enter(_t.strToken, 1, NULL_DEF, level+1, idSize + 2, NULL_DEF);
                    _t = getsym();
                } while(_t.strToken == ",");
                if(_t.strToken != ")")
                {
                    error(_t, "缺少关键字')'");
                    t_index--;
                    _t = getsym();
                }
                else
                {
                    enter(temp.strToken, 3, NULL_DEF, level, mid_code.size(), idSize);
                    _t = getsym();
                }
            }

            if(_t.strToken != ";")
            {
                error(_t, "缺少';'");
                t_index--;
            }
            if(goal == 0) enter(temp.strToken, 3, NULL_DEF, level, mid_code.size(), 0); //无参数型函数

            level++;
            int cur_Dx = dx;//当前变量的个数
            block(idSize);
            level--;
            dx = cur_Dx;
            _t = getsym();
            if(_t.strToken == ";")
            {
                _t = getsym();
            }
            else break;
        }
        t_index--;

        code instruction;
        instruction.f = JMP;
        instruction.l = 0;
        instruction.a = mid_code.size();
        mid_code[cx1] = instruction;
        gen(INT, 0, dx);//开辟空间
        body();
        gen(OPR, 0, 0);//返回调用点,退栈
    }
    //<const> → <id>:=<integer>
    void _const()
    {
        token _t = getsym();
        string variable = _t.strToken;
        if(_t.kind == 1)
        {
            token _tt = _t;
            _t = getsym();
            if(_t.strToken == ":=")
            {
                _t = getsym();
                if(_t.kind == 2)
                {
                    enter(variable, 2, atoi(_t.strToken.c_str()), level, NULL_DEF, NULL_DEF);
                }
                else
                {
                    error(_t, "':='后面需要跟整数");
                }
            }
            else
            {
                error(_t, "缺少':='");
            }
        }
        else
        {
            error(_t, "缺少标识符");
        }
    }
    //<body> → begin <statement>{;<statement>}end
    void body()
    {
        token _t = getsym();
        if(_t.strToken != "begin")
        {
            error(_t, "缺少'begin'");
            t_index--;
        }
        statement();
        _t = getsym();
        while(_t.strToken == ";")
        {
            statement();
            _t = getsym();
        }
        if(_t.strToken != "end")
        {
            error(_t, "缺少'end'");
            t_index--;
        }
    }
    // <statement> → <id> := <exp>               
	// 	      |if <lexp> then <statement>[else <statement>]
    //         	      |while <lexp> do <statement>
    //                       |call <id>([<exp>{,<exp>}])
    //                      |<body>
    //                      |read (<id>{,<id>})
    //                      |write (<exp>{,<exp>})
    void statement()
    {
        token _t = getsym();
        if(_t.strToken == "end")
        {
            error(_t, ";多余的");
            t_index--;
            return;
        }
        // <id> := <exp> 
        if(_t.kind == 1)
        {
            int i = find_table(_t.strToken, level);
            if(i == -1)
            {
                error(_t, "未定义");
            }
            else if(table[i].kind != 1)
            {
                error(_t, "不是一个变量");
            }
            _t = getsym();
            if(_t.strToken != ":=")
            {
                error(_t, "缺少':='");
                t_index--;
            }
            expression();

            if(i != -1)
            {
                gen(STO, level - table[i].level, table[i].address);
            }
        }
        // if <lexp> then <statement>[else <statement>]
        else if(_t.strToken == "if")
        {
            lexp();
            _t = getsym();
            if(_t.strToken != "then")
            {
                error(_t, "缺少关键字'then");
                t_index--;
            }
            int cx2 = mid_code.size();
            gen(JPC, 0, 0);
            statement();

            code instruction;
            instruction.f = JPC;
            instruction.l = 0;
            instruction.a = mid_code.size() + 1;
            mid_code[cx2] = instruction;
            _t = getsym();
            if(_t.strToken == "else")
            {
                int cx1 = mid_code.size();
                gen(JMP, 0, 0);
                statement();
                //回填if结束语句地址
                code instruction;
                instruction.f = JMP;
                instruction.l = 0;
                instruction.a = mid_code.size();
                mid_code[cx1] = instruction;
            }
            else t_index--;
        }
        // while <lexp> do <statement>
        else if(_t.strToken == "while")
        {
            int jmp_addr = mid_code.size();
            lexp();
            _t = getsym();
            if(_t.strToken != "do")
            {
                error(_t, "缺少关键字'do'");
                t_index--;
            }
            int cx2 = mid_code.size();
            gen(JPC, 0, 0);
            statement();
            gen(JMP, 0, jmp_addr);

            code instruction;
            instruction.f = JPC;
            instruction.l = 0;
            instruction.a = mid_code.size();
            mid_code[cx2] = instruction;
        }
        // call <id>([<exp>{,<exp>}])
        else if(_t.strToken == "call")
        {
            _t = getsym();
            if(_t.kind != 1)
            {
                error(_t, "函数名必须是标识符");
            }

            int i = find_table(_t.strToken, level);
            if(i == -1)
            {
                error(_t, "函数未定义");
            }
            else if(table[i].kind == 3)
            {
                _t = getsym();
                if(_t.strToken == "(")
                {
                    int idSize=0, index=i - table[i].size;
                    do
                    {
                        expression();
                        idSize++;
                        if(level == table[i].level)
                            gen(STO, -1, table[index].address);
                        else
                            gen(STO, -(level - table[i].level), table[index].address);
                        index++;
                        _t = getsym();
                    } while (_t.strToken == ",");
                    if(idSize < table[i].size)
                    {
                        error(_t, "参数太少");
                    }
                    else if(idSize > table[i].size)
                    {
                        error(_t, "参数太多");
                    }
                    else
                    {
                        if(_t.strToken != ")")
                        {
                            error(_t, "缺少关键字')'");
                            t_index--;
                        }
                    }
                }
                else
                    t_index--;
                gen(CAL, level - table[i].level, table[i].address);
            }
            else
            {
                error(_t, "不是函数名");
            }
            
        }
        //read
        else if(_t.strToken == "read")
        {
            _t = getsym();
            if(_t.strToken == "(")
            {
                do
                {
                    _t = getsym();
                    if(_t.kind == 1)
                    {
                        int i = find_table(_t.strToken, level);
                        if(i == -1)
                        {
                            error(_t, "未定义");
                        }
                        else if(table[i].kind == 1)
                        {
                            gen(RED, 0, 0);//
                            gen(STO, level - table[i].level, table[i].address);
                        }
                        else
                        {
                            error(_t, "不是变量");
                        }
                    }
                    else
                    {
                        error(_t, "不是标识符");
                    }
                    _t = getsym();
                } while(_t.strToken == ",");
                if(_t.strToken != ")")
                {
                    error(_t, "缺少关键字')'");
                    t_index--;
                }
            }
            else
            {
                error(_t, "缺少关键字'('");
                t_index--;
            }
        }
        //write
        else if(_t.strToken == "write")
        {
            _t = getsym();
            if(_t.strToken == "(")
            {
                do
                {
                    expression();
                    gen(WRT, 0, 0);
                    gen(OPR, 0, 15);
                    _t = getsym();
                } while(_t.strToken == ",");
                if(_t.strToken != ")")
                {
                    error(_t, "缺少关键字')'");
                    t_index--;
                }
            }
            else
            {
                error(_t, "缺少关键字'('");
                t_index--;
            }
        }
        //body()
        else
        {
            t_index--;
            body();
        }
    }
    // <exp> → [+|-]<term>{<aop><term>}
    void expression()
    {
        token _t = getsym();
        if(_t.strToken == "+" || _t.strToken == "-")
        {
            term();
            if(_t.strToken == "-")
            {
                gen(OPR, 0, 1);
            }
        }
        else
        {
            t_index--;
            term();
        }
        _t = getsym();
        while(_t.strToken == "+" || _t.strToken == "-")
        {
            term();
            if(_t.strToken == "+")
            {
                gen(OPR, 0, 2);
            }
            else if(_t.strToken == "-")
            {
                gen(OPR, 0, 3);
            }
            _t = getsym();
        }
        t_index--;
    }
    // <term> → <factor>{<mop><factor>}
    void term()
    {
        factor();
        token _t = getsym();
        while(_t.strToken == "*" || _t.strToken == "/")
        {
            factor();
            if(_t.strToken == "*")
            {
                gen(OPR, 0, 4);
            }
            else if(_t.strToken == "/")
            {
                gen(OPR, 0, 5);
            }
            _t = getsym();
        }
        t_index--;
    }
    // <factor>→<id>|<integer>|(<exp>)
    void factor()
    {
        token _t = getsym();
        if(_t.kind == 1)
        {
            int i = find_table(_t.strToken, level);
            if(i == -1)
            {
                error(_t, "未定义");
            }
            else
            {
                if(table[i].kind == 2)
                {
                    gen(LIT, 0, table[i].value);
                }
                else if(table[i].kind == 1)
                {
                    gen(LOD, level - table[i].level, table[i].address);
                }
                else if(table[i].kind == 3)
                {
                    error(_t, "为过程名出错");
                }
            }
        }
        else if(_t.kind == 2)
        {
            gen(LIT, 0, atoi(_t.strToken.c_str()));
        }
        else if(_t.strToken == "(")
        {
            expression();
            _t = getsym();
            if(_t.strToken != ")")
            {
                error(_t, "缺少右括号");
                t_index--;
            }
        }
    }
    // <lexp> → <exp> <lop> <exp>|odd <exp>
    void lexp()
    {
        token _t = getsym();
        if(_t.strToken == "odd")
        {
            expression();
            gen(OPR, 0, 6);
        }
        else
        {
            t_index--;
            expression();
            _t = getsym();
            if(_t.strToken != "=" && _t.strToken != "<>" &&
               _t.strToken != "<" && _t.strToken != "<=" &&
               _t.strToken != ">" && _t.strToken != ">=")
            {
                error(_t, "缺少比较运算符");
                t_index--;
            }
            expression();
            if(_t.strToken == "=")
            {
                gen(OPR, 0, 7);
            }
            else if(_t.strToken == "<>")
            {
                gen(OPR, 0, 8);
            }
            else if(_t.strToken == "<")
            {
                gen(OPR, 0, 9);
            }
            else if(_t.strToken == ">=")
            {
                gen(OPR, 0, 10);
            }
            else if(_t.strToken == ">")
            {
                gen(OPR, 0, 11);
            }
            else if(_t.strToken == "<=")
            {
                gen(OPR, 0, 12);
            }
        }
    }
    
    int stack[8000];//运行栈 SL DL RA
    int get_sl(int B, int lev)
    {
        int res_B = B;
        while(lev > 0)
        {
            res_B = stack[res_B];
            lev--;
        }
        return res_B;
    }
    void interpreter()
    {
        for(int i=0;i<8000;i++) stack[i] = 0;
        int B = 0;//基地址寄存器
        int T = 0;//栈顶指示器寄存器
        code I;//指令寄存器
        int P = 0;//程序地址寄存器

        cout << "开始解释执行P代码..." << endl;
        I = mid_code[P];
        P++;
        while(P!=0)
        {
            if(I.f == JMP)//直接跳转
            {
                P = I.a;
            }
            else if(I.f == JPC)//栈顶为0跳转
            {
                T--;
                if(stack[T] == 0)
                {
                    P = I.a;
                }
            }
            else if(I.f == INT)//开辟空间
            {
                T += I.a;
            }
            else if(I.f == LOD)
            {
                stack[T] = stack[get_sl(B, I.l) + I.a];
                T++;
            }
            else if(I.f == STO)
            {
                T--;
                if(I.l == -1) stack[T + I.a] = stack[T];
                else
                    stack[get_sl(B, I.l) + I.a] = stack[T];
            }
            else if(I.f == LIT)
            {
                stack[T] = I.a;
                T++;
            }
            else if(I.f == CAL)//call
            {
                stack[T] = get_sl(B, I.l);
                stack[T + 1] = B;
                stack[T + 2] = P;
                B = T;
                P = I.a;
            }
            else if(I.f == WRT)//write
            {
                cout << "输出:" << endl;
                cout << stack[T - 1] << endl;
                T--;
            }
            else if(I.f == OPR)
            {
                if(I.a == 0)//过程调用结束,返回调用点并退栈
                {
                    T = B;
                    P = stack[T + 2];
                    B = stack[T + 1];
                }
                else if(I.a == 1)//取反
                {
                    stack[T - 1] = -stack[T - 1];
                }
                else if(I.a == 2)//加法
                {
                    T--;
                    stack[T - 1] = stack[T - 1] + stack[T];
                }
                else if(I.a == 3)//减法
                {
                    T--;
                    stack[T - 1] = stack[T - 1] - stack[T];
                }
                else if(I.a == 4)//乘法
                {
                    T--;
                    stack[T - 1] = stack[T - 1] * stack[T];
                }
                else if(I.a == 5)//除法
                {
                    
                    T--;
                    if(stack[T] == 0)
                    {
                        cout << "error, NaN错误!" << endl;
                        P = mid_code.size();
                    }
                    else
                        stack[T - 1] = (int)(stack[T - 1] / stack[T]);
                }
                else if(I.a == 6)//奇偶
                {
                    stack[T - 1] = stack[T - 1] % 2;
                }
                else if(I.a == 7)//==
                {
                    T--;
                    stack[T - 1] = (stack[T - 1] == stack[T]);
                }
                else if(I.a == 8)//!=
                {
                    T--;
                    stack[T - 1] = (stack[T - 1] != stack[T]);
                }
                else if(I.a == 9)//<
                {
                    T--;
                    stack[T - 1] = (stack[T - 1] < stack[T]);
                }
                else if(I.a == 10)//>=
                {
                    T--;
                    stack[T - 1] = (stack[T - 1] >= stack[T]);
                }
                else if(I.a == 11)//>
                {
                    T--;
                    stack[T - 1] = (stack[T - 1] > stack[T]);
                }
                else if(I.a == 12)//<=
                {
                    T--;
                    stack[T - 1] = (stack[T - 1] <= stack[T]);
                }
            }
            else if(I.f == RED)//read
            {
                cout << "请输入: " << endl;
                cin >> stack[T];
                T++;
            }
            
            I = mid_code[P];
            if(P == 0)
            {
                break;
            }
            P++;
        }
    }
    void listcode()
    {
        cout << "listcode:" << endl;
        for(int i=0;i<mid_code.size();i++)
        {
            printf("%5d ", i);
            cout << op[mid_code[i].f] << "\t";
            printf("%d\t%d\n", mid_code[i].l, mid_code[i].a);
        }
        cout << endl;
    }
    void listtable()
    {
        cout << "listtable:" << endl;
        cout << "name" << "\t" << "kind" << "\t" << "level" << "\t" << "value" << "\t" << "address" << "\t" << "size" << endl;
        for(int k=0;k<table.size();k++)
        {
            cout << table[k].name << "\t";
            cout << table[k].kind << "\t";
            cout << table[k].level << "\t";
            cout << table[k].value << "\t";
            cout << table[k].address << "\t";
            cout << table[k].size << endl;
        }
        cout << endl;
    }
};

int main()
{
    cifa(t);
    yufa y;
    y.prog();
    if(goal == 0)
    {
        y.listcode();
        y.listtable();
        y.interpreter();
    }
    else
    {
        cout << "total error: " << err << " 个" << endl;
    }
}

样例代码

通过修改cifa.h部分可以更换编译的代码

# code3.txt
program p;
var res, i, n;
    procedure fib(x,y,n);
    var sum;
    begin
        sum := 0;
        if n<2 then
            res := 1
        else
        begin
            call fib(x,y,n-1);
            sum := sum + res;
            call fib(x,y,n-2);
            sum := sum + res;
            res := sum
        end
    end
begin
    i := 0;
    read(n);
    while i <= n do
    begin 
        call fib(2+3,3+4,i);
        write(res);
        i := i + 1
    end
end
# code4.txt
program a;
var x;
procedure B(n);
    procedure C(n);
        procedure E(n);
        begin
            x := n-1;
            if x > -10 then 
            begin 
                call C(x)
            end
        end
    begin
        x:= n-1;
        call E(x)
    end;
    procedure D(n);
    begin
        x:= n-1;
        call C(x)
    end
begin
    x:= n-1;
    call D(x)
end

begin
    x := 0;
    call B(x);
    write(x)
end
# code1.txt
program xi;
const a:=5;
var j,sum,x;
procedure sum1(x);
var j;
begin
    j:=1;
    sum:=0;
    while j<=x do
        begin
            sum:=sum+j;
            j:=j+1;
            write(j)
        end;
    write(sum)
end
begin
    read(x,j);
    call sum1(j+5);
    write(j)
end

输出

运行code3.txt结果

listcode:
    0 JMP       0       41
    1 JMP       0       2
    2 INT       0       7
    3 LIT       0       0
    4 STO       0       6
    5 LOD       0       5
    6 LIT       0       2
    7 OPR       0       9
    8 JPC       0       12
    9 LIT       0       1
   10 STO       1       3
   11 JMP       0       40
   12 LOD       0       3
   13 STO       -1      3
   14 LOD       0       4
   15 STO       -1      4
   16 LOD       0       5
   17 LIT       0       1
   18 OPR       0       3
   19 STO       -1      5
   20 CAL       1       1
   21 LOD       0       6
   22 LOD       1       3
   23 OPR       0       2
   24 STO       0       6
   25 LOD       0       3
   26 STO       -1      3
   27 LOD       0       4
   28 STO       -1      4
   29 LOD       0       5
   30 LIT       0       2
   31 OPR       0       3
   32 STO       -1      5
   33 CAL       1       1
   34 LOD       0       6
   35 LOD       1       3
   36 OPR       0       2
   37 STO       0       6
   38 LOD       0       6
   39 STO       1       3
   40 OPR       0       0
   41 INT       0       6
   42 LIT       0       0
   43 STO       0       4
   44 RED       0       0
   45 STO       0       5
   46 LOD       0       4
   47 LOD       0       5
   48 OPR       0       12
   49 JPC       0       69
   50 LIT       0       2
   51 LIT       0       3
   52 OPR       0       2
   53 STO       -1      3
   54 LIT       0       3
   55 LIT       0       4
   56 OPR       0       2
   57 STO       -1      4
   58 LOD       0       4
   59 STO       -1      5
   60 CAL       0       1
   61 LOD       0       3
   62 WRT       0       0
   63 OPR       0       15
   64 LOD       0       4
   65 LIT       0       1
   66 OPR       0       2
   67 STO       0       4
   68 JMP       0       46
   69 OPR       0       0

listtable:
name    kind    level   value   address size
res     1       0       -100    3       -100
i       1       0       -100    4       -100
n       1       0       -100    5       -100
x       1       1       -100    3       -100
y       1       1       -100    4       -100
n       1       1       -100    5       -100
fib     3       0       -100    1       3
sum     1       1       -100    6       -100

开始解释执行P代码...
请输入:
2
输出:
1
输出:
1
输出:
2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学不会c++吃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值