视频加载失败

课程

397 字
约 2 分钟

3.1 赋值语句的三地址代码产生

编译原理labs/lab03-intermediate-code·更新于 2026-09-15

3.1 赋值语句的三地址代码产生

1. 任务描述

本关任务:编写程序,实现在赋值语句的自上而下语法分析基础上,增加动作代码,输出三地址代码。

相关知识

为了完成本关任务,你需要掌握:基于属性文法的递归下降翻译方法。

赋值语句产生三地址代码的属性文法

E -> T {E'.in=T.val} E' {E.val:=E'.val}
E' -> + T {E''.in=E'.in + T.val} E'' {E'.val:=E''.val}
E' -> 空字 {E'.val=E'.in}
T -> F {T'.in=F.val} T' {T.val=T'.val}
T' -> * F {T''.in=T'.in * F.val} T'' {T'.val:=T''.val}
T' -> 空字 {T'.val=T'.in}
F -> (E) {F.val=E.val}
F -> i {F.val=id.entry}
Note

减法运算处理同加法运算,除法运算处理同乘法运算。

编程要求

在右侧编辑器补充产生三地址代码,注意代码中没有提示补全代码的位置。

测试说明

平台会对你编写的代码进行测试:

测试输入: a:=b+c*d;

预期输出:

T1:=c*d
T2:=b+T1
a:=T2

开始你的任务吧,祝你成功!

2. 我的回答

文件 level.cpp:

#include "getsym.h"

// ==========================================
// 补充被覆盖的 treeNode 结构体定义
struct treeNode {
    string element;
    vector<treeNode*> child;
    treeNode(string e) {
        element = e;
    }
};
// ==========================================

void assi_sen(treeNode* tn);                //赋值语句
string expression(treeNode* tn);            //表达式
string item(treeNode* tn);                  //项
string factor(treeNode* tn);                //因子

string sym;

bool error_grammar = false;

int tmp_indx=0;
string newTemp()   //产生临时变量
{
    tmp_indx++;
    return "T"+to_string(tmp_indx);
}

/*
<赋值语句> ::= <标识符>:=<表达式>
*/
void assi_sen(treeNode* tn)
{
    if (sym == "identifier") {
        auto *idt = new treeNode(debugId);
        tn->child.push_back(new treeNode("标识符"));
        tn->child.back()->child.push_back(idt);
        string tmp = debugId;       //保存待赋值的变量
        sym = GETSYM();
        if (sym == ":=") {
            tn->child.push_back(new treeNode(":="));
            sym = GETSYM();
            auto *expressiont = new treeNode("表达式");
            tn->child.push_back(expressiont);
            
            // 获取表达式综合产生的值(变量名或临时变量)
            string exp_val = expression(expressiont);
            
            // 产生最终的赋值三地址代码
            cout << tmp << ":=" << exp_val << endl;

        } else cout<<"error";         //不是变量赋值

    } else return;
}

/*
<表达式> ::= [+|-]<项>{<加法运算符><项>}
*/
string expression(treeNode* tn)
{
    string arg1;
    string unary_opr = ""; // 记录可能存在的单目运算符

    if (sym == "+" || sym == "-" ) {
        tn->child.push_back(new treeNode(sym));
        unary_opr = sym;
        sym = GETSYM();
    }
    auto *itemt = new treeNode("项");
    tn->child.push_back(itemt);
    
    // 获取第一个项的值
    arg1 = item(itemt);
    
    // 如果存在单目减号,则生成产生单目取负的三地址代码
    if (unary_opr == "-") {
        string t = newTemp();
        cout << t << ":=-" << arg1 << endl;
        arg1 = t; // 更新当前值为这个新的临时变量
    }
    
    while (sym == "+" || sym == "-") {
        string opr = sym;
        auto *idt = new treeNode(sym);
        tn->child.push_back(new treeNode("加减运算符"));
        tn->child.back()->child.push_back(idt);
        sym = GETSYM();
        auto *itemts = new treeNode("项");
        tn->child.push_back(itemts);
        
        // 获取后面的项的值
        string arg2 = item(itemts);
        
        // 申请新的临时变量并生成三地址代码
        string t = newTemp();
        cout << t << ":=" << arg1 << opr << arg2 << endl;
        
        // 将当前临时变量更新为下一次计算的左操作数
        arg1 = t;
    }
    return arg1;
}

/*
<项> ::= <因子>{<乘法运算符><因子>}
*/
string item(treeNode* tn)
{
    auto factort = new treeNode("因子");
    tn->child.push_back(factort);
    
    // 获取第一个因子的值
    string arg1 = factor(factort);
    
    while (sym == "*" || sym == "/") {
        string opr = sym;
        auto *idt = new treeNode(sym);
        tn->child.push_back(new treeNode("乘除运算符"));
        tn->child.back()->child.push_back(idt);
        sym = GETSYM();
        auto factorts = new treeNode("因子");
        tn->child.push_back(factorts);
        
        // 获取后面的因子的值
        string arg2 = factor(factorts);
        
        // 申请新的临时变量并生成乘除三地址代码
        string t = newTemp();
        cout << t << ":=" << arg1 << opr << arg2 << endl;
        
        // 将当前临时变量更新为下一次计算的左操作数
        arg1 = t;
    }
    return arg1;
}

/*
<因子> ::= <标识符>|<无符号整数>|'('<表达式>')'
*/
string factor(treeNode* tn)
{
    string val;
    if (sym == "identifier" || sym == "number") {
        string tmp;
        treeNode *idt;
        if (sym == "identifier") {
            tmp = "标识符";
            val = debugId; // 记录标识符的名字
            idt = new treeNode(debugId);
        }
        else {
            tmp = "无符号整数";
            val = debugNum; // 记录整数数值
            idt = new treeNode(debugNum);
        }
        tn->child.push_back(new treeNode(tmp));
        tn->child.back()->child.push_back(idt);
        sym = GETSYM();
    }
    else if (sym == "(") {
        tn->child.push_back(new treeNode("("));
        sym = GETSYM();
        auto *expressiont = new treeNode("表达式");
        tn->child.push_back(expressiont);
        
        // 括号内的表达式,向上传递其值
        val = expression(expressiont);
        
        if (sym == ")") {
            tn->child.push_back(new treeNode(")"));
            sym = GETSYM();
        }
        else cout<<"error";           //因子中包含的表达式的错误结束
    }
    else {
        return "";
    }
    return val;
}

int main() {
    integerArray.clear();
    identifierArray.clear();
    streambuf *stdin_backup = cin.rdbuf();         //备份标准输入流
    string fileinname;
    cin >> fileinname;
    fcin.open(fileinname);
    if (!fcin.is_open()) {
        cout << "failed to open " << fileinname << endl;
        return 0;
    }
    cin.rdbuf(fcin.rdbuf());                //将cin重定向到文件
    auto *assi_sent = new treeNode("赋值语句");
    sym=GETSYM();
    assi_sen(assi_sent);

    cin.rdbuf(stdin_backup);
    fcin.close();
    //Interpret();
    return 0;
}

文件 demo4.txt:

x:=x+y*(a-b)/2

文件 demo5.txt:

x:=(-x)*(5+b)/(c-d)+799

文件 demo6.txt:

x:=-a*((b+c)-d)/2
Profile Image of the Author
Sonder
好想要技术
这是公告标题
这只是一个公告
分类
标签
站点信息
构建平台
GitHub Actions
博客版本
Firefly v6.16.7
文章许可
CC BY-NC-SA 4.0
文章目录