最后还剩下一个, 声明语句的翻译. 因为符号表API已经很完善了, 所以声明语句的翻译不会太困难. 将一些小地方处理好了就行. 难对付的部分是设定初始值, 需要考虑到类型转换. OK, 代码说明一切.
struct List* insDeclarationNode(void* node)
{
struct DeclarationNode* self = (struct DeclarationNode*)node;
// 节点指令
struct List* insList = (struct List*)newArrayList();
AcceptType type = self->dectype;
int i;
// 如果有初值, 这些变量会派上用场
struct IntParamInstruction* loadAddr;
struct AbstractValueNode* initialVal;
// 如果初值需要转型, 就用这个
InstructionCode castCode = (INTEGER == type) ? REAL_2_INT : INT_2_REAL;
InstructionCode assignCode = (INTEGER == type) ? INT_ASSIGN : REAL_ASSIGN;
struct NoParamInstruction* initAssign;
// 赋值结束需要弹出初始值, 这两个留作备用.
int popSize = (INTEGER == type) ? INT_SIZE : REAL_SIZE;
struct IntParamInstruction* popInitVal;
for (i = 0; i < self->vars->length(self->vars); ++i) { // 一次可能声明多个变量
// 调用符号表
int addr = declare((struct VariableNode*)
(self->vars->peekAt(self->vars, i)), type);
if (NULL != (initialVal = (struct AbstractValueNode*) // 如果有初始化
(self->initVals->peekAt(self->initVals, i)))) {
struct List* insInitVal = initialVal->createInstruction(initialVal);
// load 刚刚声明的变量
loadAddr = (struct IntParamInstruction*)
allocate(sizeof(struct IntParamInstruction));
loadAddr->code = CONST_INT;
loadAddr->param = addr;
appendInsList(appendIns(insList, loadAddr), insInitVal);
// 类型不匹配
if (initialVal->typeOf(initialVal) != type) {
struct NoParamInstruction* cast = (struct NoParamInstruction*)
allocate(sizeof(struct NoParamInstruction));
cast->code = castCode;
appendIns(insList, cast);
}
initAssign = (struct NoParamInstruction*)
allocate(sizeof(struct NoParamInstruction));
initAssign->code = assignCode;
popInitVal = (struct IntParamInstruction*)
allocate(sizeof(struct IntParamInstruction));
popInitVal->code = POP;
popInitVal->param = popSize;
appendIns(appendIns(insList, initAssign), popInitVal);
}
}
return insList;
}
接下来, 就要进入... 测试环节了. 这么多指令生成代码, 不测试, 能放心吗?
分享到:
相关推荐
采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。 实验的输入和输出 输入是语法分析提供的正确的单词串,输出为三地址指令形式的四元式序列。 例如:对于语句串 begin a:=2+3*4 x...
语法制导翻译和中间代码生成是编译器设计的关键步骤,它们在编译过程中起着至关重要的作用。首先,我们要回顾编译过程,它通常包括词法分析、语法分析、语义分析和代码生成等阶段。语义分析位于语法分析之后,主要...
例如,当解析到C语言中的if语句时,语法制导翻译会生成对应的条件判断和分支指令。 5. **编译原理实验**: 在学习和实践中,编译原理的实验通常涉及实现上述组件。学生可能需要编写词法分析器、语法分析器,并应用...
《编译原理语法制导翻译》 在计算机科学领域,编译原理是研究如何将高级编程语言转换为机器可理解的指令集的关键分支。语法制导翻译是编译器设计中的一种重要技术,它结合了语法分析和语义处理,以确保程序的正确性...
4. **语法制导翻译**:基于抽象语法树,编译器进行语义分析,检查程序的逻辑正确性。此阶段可能会执行类型检查和常量折叠等操作,并可能引入一些优化。同时,它会根据语法规则生成相应的中间代码。 5. **中间代码...
总结来说,"语义分析器--语法制导翻译绘制图形"项目提供了一个实践编译器设计的平台,涵盖了语义分析、语法制导翻译和图形绘制等多个重要概念。通过深入研究这个项目,开发者可以深化对编译原理的理解,掌握C++编程...
二、语法制导的三地址码 三地址码是一种简单的中间表示(IR)形式,它以指令的形式表示计算过程,每个指令通常包含三个地址:操作符、操作数1和操作数2。例如,"x = y + z" 可以转化为 "x = add(y, z)"。这种表示...
5. **代码生成**:尽管这不是直接的后缀表达式到机器代码的转换,但在此阶段,我们可以开始思考如何将后缀表达式转换为实际的指令序列,以便于执行。 在"编译原理"的文件中,可能会包含关于这些步骤的详细描述,...
在树的每个节点上,编译器执行与该节点对应的语法制导规则,这可能包括计算值、生成目标代码指令、存储或传递数据等。这种做法使得编译器可以精确地按照源代码的语法结构生成目标代码,从而确保程序的正确性。 语法...
5. **语法制导技术**:语法制导技术是在进行语法分析的同时执行与规则相关的语义动作,使得编译器能够在检查语法的同时完成特定任务。例如,在处理特定文法时,可以通过与文法规则关联的语义动作来实现特定功能,如...
它主要涉及三个核心过程:词法分析、语法分析和代码生成,而四元式在这个过程中起到重要作用。 首先,词法分析(Lexical Analysis)是编译器的第一步,它的任务是对源代码进行扫描,将源代码分解成一系列有意义的、...
语法制导翻译与中间代码生成是编译器设计中的关键步骤,主要涉及程序的静态语义审查、类型检查、控制流分析以及中间代码生成。在这个过程中,编译器不仅要确保程序符合语法规则,还要对其含义进行深入理解,以便生成...
5. **目标代码生成**:最后,三地址代码生成器需要将三地址代码转化为特定机器架构的目标代码,这通常涉及到指令选择和寄存器分配。 在实际项目中,我们可以根据提供的“编译原理 三地址代码生成器”文档进一步了解...
5. **优化**:对生成的三地址代码进行优化,如消除冗余计算、代码移动等,提高目标代码的效率。 6. **代码生成**:最后,将三地址代码翻译成特定机器的汇编代码或机器码。 五、应用与意义 了解并实现编译器的这一...
《编译原理 实验报告》 实验一主要涵盖了词法分析...词法分析器通过正规式和状态图解析源代码,而语法制导定义和三地址代码生成则涉及到语义分析和代码生成。理解这些概念对于深入学习编译原理和开发编译器至关重要。
采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。 三、实验的结果验证 1.输入是语法分析后提供的正确的单词串,输出为三地址指令形式的四元式序列。 给出语句串: begin_a:=2+3*...
此外,编译器还可能进行优化,例如对于 "x = x + 1" 这样的语句,编译器可能会生成更为高效的指令序列,避免不必要的重复读取和写入。这就是所谓的"副作用"概念,编译器需要理解并妥善处理。 在实际的编译过程中,...
本项目“基于C语言实现简单语言递归下降语法制导翻译”深入探讨了这一主题,主要关注如何使用C语言来设计和实现一个编译器的核心部分——语义分析和中间代码生成。 首先,我们要理解什么是递归下降解析。递归下降是...