合肥工业大学HFUT编译原理课程设计---算数表达式转四元式 语法制导翻译(C++实现 QT实现GUI)

部分代码如下(仅供参考)

//部分函数和数据结构设计省略,可通过最下方链接下载
void firstvt_lastvt()     //遍历一遍所有产生式,更新firstvt、lastvt集合
{
    for(int s = 0; s < grammar.size(); s++)
    {
        string grammar_this = grammar[s];       //存储每一次遍历的产生式
        int t = grammar_this.find("->");        //t为‘-’的位置
        string grammar_left = grammar_this.substr(0, t);  //左串 即非终结符
        t+=2;
        string grammar_right = grammar_this.substr(t);     //右串

        vector<string> Y;
        Y = splitStringtoVector(grammar_right);         //右串分割为终结符与非终结符组成的vector一元组
        int k = Y.size();

        //Y[0]为终结符  P -> a...
        if(vt.count(Y[0]) != 0)
            firstvt[vn[grammar_left]].insert(Y[0]);
        //Y[1]为终结符  P -> Qa...
        else if(k > 1 && vt.count(Y[1]) != 0)
            firstvt[vn[grammar_left]].insert(Y[1]);
        //Y[0]为非终结符 P -> Q...
        if(vn.count(Y[0]) != 0)
        {
            firstvt[vn[grammar_left]] = merge_set(firstvt[vn[grammar_left]],firstvt[vn[Y[0]]]);
        }

        // P -> ...a
        if(vt.count(Y[k-1]) != 0)
            lastvt[vn[grammar_left]].insert(Y[k-1]);
        // P -> ...aQ
        else if(k > 2 && vt.count(Y[k-2]) != 0)
            lastvt[vn[grammar_left]].insert(Y[k-2]);
        // P -> ...Q
        if(vn.count(Y[k-1]) != 0)
            lastvt[vn[grammar_left]] = merge_set(lastvt[vn[grammar_left]],lastvt[vn[Y[k-1]]]);
    }
}

void iteration()    //迭代计算firstvt与lastvt集合
{
    bool flag = false; //收敛标志
    set <string> old_firstvt[50];
    set <string> old_lastvt[50];


    int times = 0;                   //直到收敛经历的迭代轮数

    while(!flag)
    {
        flag = true;
        times++;
        firstvt_lastvt();
        for(auto t = vn.begin(); t != vn.end(); t++)
        {
            if(firstvt[t->second].size() != old_firstvt[t->second].size() || lastvt[t->second].size() != old_lastvt[t->second].size())  //不收敛
                flag = false;
            old_firstvt[t->second] = firstvt[t->second];
            old_lastvt[t->second] = lastvt[t->second];
        }
    }
    cout << "times: " << times << endl;
}



float string_to_float(string s)
{
    if(s[0] == '-')
        return -string_to_float(s.substr(1));
    float ans = 0;
    if(s.find('.') != string::npos)
    {
        string l = s.substr(0,s.find('.'));
        string r = s.substr(s.find('.')+1);
        float base_l = 1;
        float base_r = 0.1;
        for(int i = l.size()-1; i >= 0; i--)
        {
            ans+=(l[i] - '0')*base_l;
            // cout << ans << endl;
            base_l*=10;
        }
        for(int i = 0; i < r.size(); i++)
        {
            ans+=(r[i] - '0')*base_r;
            base_r/=10;
            // cout << ans << endl;
        }
    }
    else
    {
        float base = 1;
        for(int i = s.size()-1; i >= 0; i--)
        {
            ans+=(s[i] - '0')*base;
            base*=10;
            // cout << ans << endl;
        }
    }
    return ans;
}

int get_ind(string s)   //获取中间结果下标
{
    int ans = 0;
    int base = 1;
    for(int i = s.size()-1; i > 0; i--)
    {
        ans+=(s[i]-'0')*base;
        base*=10;
    }
    return ans;
}

bool contain_alp(string s)  //输入表达式是否包含字母
{
    for(int i = 0; i < s.size(); i++)
    {
        if(s[i] >= 'a' && s[i] <= 'z')
            return true;
    }
    return false;
}

void main_control(string inText)
{

    vector <string>().swap(s);
    vector <string>().swap(sm);

    bool num_alp = contain_alp(inText); //true为含字母表达式
    FILE *history = fopen("C:\\Users\\21911\\Desktop\\history.txt","a+");
    if(history == nullptr)
    {
        cout << "历史文件获取失败!\n";
        return;
    }

    FILE *f = fopen("C:\\Users\\21911\\Desktop\\curAnalysis.txt","w+");   //以重写方式打开文件
    if(f == nullptr)
    {
        cout << "open file error!\n";
        return;
    }
    ind = 1;
    int timess = 0; //规约次数
    string in = inText;
    in_before = splitStringtoVector(in);
    for(int i = 0; i < in_before.size(); i++)
        cout << in_before[i] << " ";
    cout << endl;
    in = trans(in); //转换
    in_after = splitStringtoVector(in);
    in_after.insert(in_after.end(),1,"#");

    in_before.insert(in_before.end(),1,"#");

    int index = 0;  //指示in_after

    s.push_back("#");
    sm.push_back("#");  //结束符入栈
    int k = 0;  //指示符号栈栈顶
    int j;      //指示最靠顶部的终结符
    string a;   //指示下一输入符号
    string Q;   //存储可规约串中间的终结符

    string pp = "T0";
    float result[MAXN]; //存放中间结果 Tk 的值  Tk = result[k]
    string result_alp[MAXN];
    int indind = 0; //指示使用到的编号Tk的下标k

    try{
    do{
        cout << timess++ << ": ";
        for(int u = 0; u < s.size(); u++)
            cout << s[u];
        cout << setw(15) << "\t";
        for(int u = 0; u < sm.size(); u++)
            cout << sm[u];
        cout << endl;

        a = in_after[index++];         //下一输入符号

        if(vt.count(s[k]) != 0)   //即in_[i] 属于 vt
            j = k;
        else
            j = k-1;                //栈内最靠顶部的终结符

        while(table[vt[s[j]]][vt[a]] == 1)    //最靠近栈顶的终结符的优先级大于现行输入终结符  进行规约
        {
            do{
                Q = s[j];
                if(j>=1 && vt.count(s[j-1]) != 0)
                    j=j-1;
                else
                    j=j-2;
            }while(table[vt[s[j]]][vt[Q]] == 0);   //找到可规约串的开头
            //规约s[j+1] ~ s[k]
            int ss = match(s,j+1,k);            //找到此步进行规约用到的产生式编号
            if(ss == -1)
            {
                illegal = false;
                exit(1);
            }
            float op_l,op_r;                    //此步规约式的左右操作数
            string temp1,temp2,temp3;           //暂存左右操作数与操作符
            //s[j+1] s[j+2] s[j+3]

            if(ss == 1 || ss == 2 || ss == 4 || ss == 5)    //若为 + - * / 运算
            {
                temp1 = sm[j+1];    //左操作数 (为Tk编号 或者 字符串)
                temp2 = sm[j+2];    //操作符
                temp3 = sm[j+3];    //右操作数 (为Tk编号 或者 字符串)
                if(!num_alp)    //不含字母/**/
                {
                    // str.append(tos(result[get_ind(temp1)]) + tos(result[get_ind(temp3)]) + temp2);
                    if(temp1[0] == 'T')
                        op_l = result[get_ind(temp1)];
                    else
                        op_l = string_to_float(temp1);
                    if(temp3[0] == 'T')
                        op_r = result[get_ind(temp3)];
                    else
                        op_r = string_to_float(temp3);
                    //获取左右操作数的float形式
                    // cout << op_l << "  " << op_r;
                    switch(temp2[0])    //对 + - * /分类   获取结果存入result[indind]
                    {
                        case '+':
                                result[indind] = op_l + op_r; break;
                        case '-':
                                result[indind] = op_l - op_r; break;
                        case '*':
                                result[indind] = op_l * op_r; break;
                        case '/':
                                result[indind] = op_l / op_r; break;
                    }
                    // cout << "  " << result[indind] << endl;
                    string stream = "(" + sm[j+2] + ", " + sm[j+1] + ", "  + sm[j+3] + ", " +  pp + ")\t\t" + pp + "=";
                    fputs(stream.data(),f);
                    fprintf(f, "%0.6f\n",result[indind]);       //写入文件
                }
                else
                {
                    result_alp[indind] = temp1+temp2+temp3;
                    string stream = "(" + sm[j+2] + ", " + sm[j+1] + ", "  + sm[j+3] + ", " +  pp + ")\t\t" + pp + "=";
                    fputs(stream.data(),f);
                    /*fprintf(f, "%s\n",result_alp[indind]);*/
                    fputs((result_alp[indind]+'\n').data(),f);
                    //写入文件
                }
            }
            // s[j+1]
            else if(ss != 8)    // 非F->(E) 即不带()的产生式
            {
                if(!num_alp)
                {
                    if(sm[j+1][0] == 'T')
                        op_l = result[get_ind(sm[j+1])];
                    else
                        op_l = string_to_float(sm[j+1]);
                    result[indind] = op_l;

                    string stream = "( =: ," + sm[j+1] + ", " + pp + ")\t\t\t" + pp + "=";
                    fputs(stream.data(),f);
                    fprintf(f, "%0.6f\n",result[indind]);
                }
                else {
                    result_alp[indind] = sm[j+1];
                    string stream = "( =: ," + sm[j+1] + ", " + pp + ")\t\t\t" + pp + "=";
                    fputs(stream.data(),f);
//                    fprintf(f, "%s\n",result_alp[indind]);
                    fputs((result_alp[indind]+'\n').data(),f);
                }
            }
            // s[j+1]='(' s[j+2] s[j+3]=')'
            else    // F->(E)单独分析  E位于sm[j+2]的位置
            {
                if(!num_alp)
                {
                    if(sm[j+2][0] == 'T')
                        op_l = result[get_ind(sm[j+2])];
                    else
                        op_l = string_to_float(sm[j+2]);
                    result[indind] = op_l;
                    string stream = "( =: ," + sm[j+2] + ", " + pp + ")\t\t\t" + pp + "=";
                    fputs(stream.data(),f);
                    fprintf(f, "%0.6f\n",result[indind]);
                }
                else
                {
                    result_alp[indind] = sm[j+2];
                    string stream = "( =: ," + sm[j+2] + ", " + pp + ")\t\t\t" + pp + "=";
                    fputs(stream.data(),f);
                    fputs((result_alp[indind]+'\n').data(),f);
                }
            }

            // 删除s[j+1]~s[k]
            for(int q = j+1; q <= k; q++)
            {
                s.erase(s.begin()+j+1);
                // if(ss != 7 && ss != 6 && ss != 3 && ss != 0)
                sm.erase(sm.begin()+j+1);
            }

            k = j+1;    //重置符号栈栈顶位置

            s.push_back(grammar[ss].substr(0,grammar[ss].find("->")));
            // 将找到的规约所用的产生式的左部加入符号栈

            pp = "T";
            pp.append(to_string(indind++));
            sm.push_back(pp);
            //新建一个中间值Tk加入带语义的符号栈
            pp = "T";
            pp.append(to_string(indind));   //下一个存放中间值中间编号
            cout << timess++ << ": ";
            for(int u = 0; u < s.size(); u++)
                cout << s[u];
            cout << setw(15) << "\t";
            for(int u = 0; u < sm.size(); u++)
                cout << sm[u];
            cout << endl;

            //输出规约后的符号栈
        }
        //退出循环 即table[vt[s[j]]][vt[a]] != 1

        if(table[vt[s[j]]][vt[a]] == -1 || table[vt[s[j]]][vt[a]] == 0)
        {
            // cout << "1";
            k++;
            s.push_back(a);
            try{if(index >= 1)
                sm.push_back(in_before[index-1]);}catch(exception &e){
                cout << "002\n";
                cout << index;
                throw(e);
            }
        }
        if(table[vt[s[j]]][vt[a]] == -2)//算符优先分析表中为空
            cout << "error\n";
        }

        while(a != "#");}catch(exception &e){
        cout << "here\n";
        throw(e);
    }
    if(illegal)
    {
        string his = inText+"\n";
        fputs(his.data(),history);
        if(indind >=1 && !num_alp)
            his = to_string(result[indind-1]);
        else if(indind >= 1 && num_alp)
            his = inText;
        his+='\n';
        fputs(his.data(),history);
    }

    fclose(history);
    fclose(f);
    in_before.clear();
    in_after.clear();
    pp.clear();
    f = nullptr;
    history = nullptr;
}

结果展示:

1.Vn、Vt、FirstVT、LastVT以及算符优先分析表:
在这里插入图片描述

2.用户输入及输出显示界面
在这里插入图片描述

3.程序进行算符优先分析与规约过程具体步骤(左分析栈 右属性栈)
在这里插入图片描述

4.历史记录(左侧为输入的算数表达式 右侧为结果)
在这里插入图片描述

5.历史记录文件history(从上到下依次为表达式、结果、表达式、结果…)

在这里插入图片描述

6.当前输入算术表达式分析过程文件curAnalysis
(左侧为四元式 右侧为中间结果)
在这里插入图片描述

源码下载链接:

下载链接

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值