课程
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












