精华内容
下载资源
问答
  • ①掌握中间代码生成的基本方法。 ②掌握语法制导翻译模式。 ③完成算术表达式的中间代码生成程序。 重点及难点:掌握语法制导翻译模式的核心思想和工作原理,在此基础上完成基于算数表达式的中间代码生成程序的设计...

    基本要求:
    ①掌握中间代码生成的基本方法。
    ②掌握语法制导翻译模式。
    ③完成算术表达式的中间代码生成程序。
    重点及难点:掌握语法制导翻译模式的核心思想和工作原理,在此基础上完成基于算数表达式的中间代码生成程序的设计和调试运行。

    一、 算符优先分析法

    算符优先分析法是一种简单且直观的自下而上分析方法,它特别适合于分析程序语言中的各类表达式,并且宜于手工实现。所谓算符优先分析,就是依照算术表达式的四则运算过程来进行语法分析,即这种分析方法要预先规定运算符(确切地说是终结符)之间的优先关系和结合性质,然后借助于这种关系来比较相邻运算符的优先级,以确定句型的“可归约串”来进行归约。因此,算符优先分析法不是一种规范归约,在整个归约过程中起决定性作用的是相继两个终结符的优先关系。
    附加语义的方法是采用语法制导翻译的方法,语法制导翻译的方法就是为每个产生式配上一个翻译子程序(称语义动作或语义子程序),并在语法分析的同时执行这些子程序。语义动作是为产生式赋予具体意义的手段,它一方面指出了一个产生式所产生的符号串的意义,另一方面又按照这种意义规定了生成某种中间代码应做哪些基本动作。在语法分析过程中,当一个产生式获得匹配(对于自上而下分析)或用于归约(对于自下而上分析)时,此产生式相应的语义子程序就进入工作,完成既定的翻译任务。

    二.算符优先分析法程序源代码

    #include<string.h>
    #include<stdio.h>
    #include<math.h>
    
    int nxq = 100;
    char a[20], optr[10], s, op;
    int i, j, k, opond[10], x1, x2, x3;
    
    int operand(char c) {
    	if ((c >= 48) && (c <= 57)) {
    		return(1);
    	}
    	else {
    		return(0);
    	}
    }
    
    int f(char c) {
    	switch (c) {
    	case'+':return(4);
    	case'-':return(4);
    	case'*':return(6);
    	case'/':return(4);
    	case'(':return(2);
    	case')':return(6);
    	case'#':return(0);
    	default:printf("error!\n");
    	}
    }
    
    int g(char c) {
    	switch (c) {
    	case'+':return(3);
    	case'-':return(3);
    	case'*':return(5);
    	case'/':return(5);
    	case'(':return(7);
    	case')':return(2);
    	case'#':return(0);
    	default:printf("error!\n");
    	}
    }
    
    void get() {
    	s = a[i];
    	i = i + 1;
    }
    
    int main() {
    	printf("please input your exoression:\n");
    	i = 0;
    	do {
    		i = i + 1;
    		scanf_s("%c", &a[i]);
    	} while (a[i] != '#');
    	i = 1;
    	j = k = 1;
    	optr[j] = '#';
    	get();
    	while (!((optr[j] == '#') && (s == '#'))) {
    		if (operand(s)) {
    			opond[k] = s - 48;
    			k = k + 1;
    			get();
    		}
    		else if (f(optr[j]) > g(s)) {
    			op = optr[j];
    			j = j - 1;
    			x1 = opond[k - 2];
    			x2 = opond[k - 1];
    			k = k - 2;
    			switch (op) {
    			case'+':x3 = x1 + x2;break;
    			case'*':x3 = x1 * x2;break;
    			case'-':x3 = x1 - x2;break;
    			case'/':x3 = x1 / x2;break;
    			}			
    			opond[k] = x3;
    			k++;
    			printf("%d (%c,%d,%d,%d)\n", nxq++,op, x1, x2, x3);
    		}
    		else if (f(optr[j]) < g(s)) {
    			j = j + 1;
    			optr[j] = s;
    			get();
    		}
    		else if (f(optr[j]) == g(s)) {
    			if (optr[j] == '(' ||optr[j]== ')') {
    				j = j - 1;
    				get();
    			}
    			else {
    				printf("error!\n");
    			}
    		}
    		else {
    			printf("error!\n");
    		}
    	}
    	return 0;
    }
    
    展开全文
  • 阅读更多1 控制流语句及其SDT1.1 控制流语句的基本文法$$P \to S \\S \to S_1S_2 \\S \to id = E; | L = E; \\S \to\;...S_1$$1.2 控制流语句的代码结构布尔表达式$B$被翻译成由跳转指令构成的跳转代码...

    阅读更多

    1 控制流语句及其SDT

    1.1 控制流语句的基本文法$$

    P \to S \\

    S \to S_1S_2 \\

    S \to id = E; | L = E; \\

    S \to\;if\;B\;then \;S_1\;|\;if\;B\;then\;S_1\;else\;S_2\;|\;while\;B\;do\;S_1

    $$

    1.2 控制流语句的代码结构

    布尔表达式$B$被翻译成由跳转指令构成的跳转代码,非终结符$B$包含如下继承属性

    $S.next$:是一个地址,该地址中存放了紧跟在$S$代码之后的指令(S的**后继指令**)的**标号**

    $B.true$:是一个地址,该地址中存放了当$B$为**真**时控制流转向的**指令的标号**

    $B.false$:是一个地址,该地址中存放了当$B$为**假**时控制流转向的**指令的标号**

    用指令的标号标识一条三地址指令

    1.3 控制流语句的语义动作$newlabel()$:生成一个用于存放标号的新的临时变量$L$,返回变量地址

    $label(L)$:将**下一条**三地址指令的标号赋给$L$

    1.4 控制流语句的SDT

    1.4.1 $if-then-else$语句的SDT

    4024bbf9bb93c0885e45a4f6465f2be9.png

    1.4.2 $if-then$语句的SDT

    495c3d4c7da77144d7fa9aa0cd55395b.png

    1.4.3 $while-do$语句的SDT

    8e69a1775848f53b781e984ae02ff8a7.png

    2 布尔表达式及其SDT

    2.1 布尔表达式的基本文法$$

    B \to B\;or\;B \\

    |\;B\;and\;B \\

    |\;not\;B \\

    |\;(B)\; \\

    |\;E\;relop\;E \\

    |\;true \\

    |\;false

    $$

    优先级:not > and > or

    relop(关系运算符):, >=,==, !=

    在跳转代码中,逻辑运算符&&、|| 和!被翻译成跳转指令。运算符本身不出现在代码中,布尔表达式的值是通过代码序列中的位置来表示的

    faa59d882700b99db9f8f7f47998bf2e.png

    2.2 布尔表达式的SDT

    46907f81b0c4d83ddbf5244a7acfe9b7.png

    2.2.1 $B \to B_1\;or\;B_2$ 的SDT

    29a4eab2e646d077816e6da20fcde38b.png

    2.2.2 $B \to B_1\;and\;B_2$ 的SDT

    225e4ae38d3ae4e24d3c3e581569c294.png

    3 控制流翻译的例子

    3.1 控制流语句的SDT

    d68ecda358938fc1a262db2773d9e8c7.png

    3.2 SDT的通用实现方法

    任何SDT都可以通过下面的方法实现:首先建立一棵语法分析树,然后按照从左到右的深度优先顺序来执行这些动作

    b6a88d2caf05095abc0ea40363b4bb21.png

    首先生成$L_1$用于存放$S.next$

    执行完$S$后,才能确定$L_1$的值

    96ea2908ae12ab62de0420243523e67c.png

    生成$L_2$用于存放$S.begin$

    确定$S.begin$的值,即$L_2=1$,即下一条三地址指令的标号

    生成$L_3$用于存放$B.true$

    将$B.false$绑定为$S.next$(这里用到绑定一词,当$S.next$最终确定后,$B.false$才会确定,因此这里只是绑定关系,而非最终确定$B.false$的值)

    将$B$生成两条三地址指令$1.\;if\;a < b\;goto\;L_3$

    $2.\;goto\;L_1$

    确定$B.true$的值,即$L_3=3$,即下一条三地址指令的标号

    将$S_3.next$绑定为$S.begin$

    0fb9475dbc7c2db211c7bb0eef3d604d.png

    $S_3$展开为$if\;B\;then\;S_1\;else\;S_2$

    生成$L_4$用于存放$B1.true$

    生成$L_5$用于存放$B1.false$

    将$B_1$生成两条三地址指令$3.\;if\;c < d\;goto\;L_4$

    $4.\;goto\;L_5$

    确定$B1.true$的值,即$L_4=5$,即下一条三地址指令的标号

    $S_1.next$**绑定为**$S_3.next$

    将$S_1$生成三地址指令$5.\;t_1 = y+z$

    $6.\;x = t_1$

    生成三地址指令$7.\;goto\;S_3.next$,即$7.\;goto\;S.begin$

    确定$B1.false$的值,为即$L_5=8$,即下一条三地址指令的标号

    将$S_2.next$绑定为$S_3.next$

    将$S_2$生成三地址指令$8.\;t_2 = y-z$

    $9.\;x = t_2$

    生成三地址指令$10.\;goto\;S.begin$

    确定$S.next$的值,即$L_1=11$,即下一条三地址指令的标号

    8f9a59e3be16a0676eb1a392160e6996.png

    88baea0c9bff91f7cc1cb45ef4ae73d3.png

    4 参考《MOOC-编译原理-陈鄞》

    展开全文
  • 通常,我们的中间代码都是一种三地址码。可以理解为只有个变量以内的表达式。 对于三地址码,我们可以进行代码优化,例如想上述的代码可以优化成: 对于优化后的中间代码,我们可以方便的将其翻译成汇编代码。 ...

    学完编译原理已经一年了,也有半年被因为学其他东西而没空继续深入学习编译原理。

    现在终于有机会继续学习了。

    首先回顾下,编译原理考试第一题的答案。就是翻译的步骤。

    a1a23ad77f1a28af9db7c514b2cb6655.png

    对于编译,第一步是词法分析。也就是分出一个个Token。

    例如,像一行赋值语句:a[index] = 4 + 2 ,我们可以将其拆成一个个基本元素,每种元素都有自己的类型。如下所示:

    74b2355865c54f40f02cca8c97c87947.png

    这些Token将作为编译过程中最基本的元素。

    标识符(identifier) a, index

    左方括号(left bracket) [

    右方括号(right bracket) ]

    等号(assignment) =

    加号(plus) +

    数字(number) 4, 2

    当这些Token它们组合在一起,就成了句子。在这个时候,我们就可以进行语法分析了。

    我们可以将其组织成一棵抽象的语法树。根节点就是抽象的表达式,因为这个一句话就是一个表达式。然后可以分割为赋值表达式的3个元素,然后逐级分割,到了叶子就是基本的词法单元Token了。

    9e8d28e087eb67a2253b8843d063125f.png

    在做完语法分析后,我们就要进行语义分析。为什么要语义分析呢?我们要根据语义来标记这棵语法树,让其变成标记树,然后才好根据这棵树生成中间代码。

    4c9063c8e29d2aa249c233dd8d3f0425.png

    通常,我们的中间代码都是一种三地址码。可以理解为只有三个变量以内的表达式。

    02b377a9bba903c49f4c1ba33dbeadbb.png

    对于三地址码,我们可以进行代码优化,例如想上述的代码可以优化成:

    635c1812e32be01ac435a67a9d478646.png

    对于优化后的中间代码,我们可以方便的将其翻译成汇编代码。

    我们假设变量a的类型是占4个字节。于是可以翻译成下述汇编

    63af10dea8ccbdde51b50bbe50418571.png

    于是关于代码生成的部分就完成了。

    展开全文
  • PL0语言编译器的中间代码生成课程设计报告 ( 2016--2017年度第一学期)名称:编译技术课程设计题目: PL/0语言编译器的中间代码生成院系:控制与计算机工程班级:信安1401学号: 1141290105 学生姓名:黄竞昶指导教师...

    PL0语言编译器的中间代码生成

    课程设计报告 ( 2016--2017年度第一学期)名称:编译技术课程设计题目: PL/0语言编译器的中间代码生成院系:控制与计算机工程班级:信安1401学号: 1141290105 学生姓名:黄竞昶指导教师:徐欢设计周数:一周成绩:日期:2016年 12 月29日1 课程设计的目的和要求1.1 课程设计的目的本次设计的时间为1周,目的是通过使用高级语言实现部分算法加强对编译技术和理论的理解。设计的题目要求具有一定的规模,应涵盖本课程内容和实际应用相关的主要技术。1.2 课程设计的要求1、要求用递归子程序法/或预测分析法实现对表达式、各种说明语句、控制语句进行语法分析。2、若语法正确,则用语法制导翻译法进行语义翻译:对说明语句,要求将说明的各符号记录到相应符号表中;对可执行语句,应产生出四元式中间代码并填写到三地址码表中;3、若语法错误,要求指出出错性质和出错位置(行号)。出错处理应设计成一个出错处理子程序。2 系统描述PL/0的编译程序和目标程序的解释执行程序都是用JAVA语言书写的,因此PL/0语言可在配备JAVA语言的任何机器上实现。本次课设开发平台即为JAVA。用递归子程序法实现了对表达式、各种说明语句、控制语句进行语法的分析。其中,对各个变量符号保存到了符号表中。对可执行语句,转化成四元式中间代码进行输出。本程序中,通过出错处理子程序,也进行了语法的错误的记录,并且输出了出错的行号和出错原因。该程序的输入是打开test文件,通过文件输入流读入,输出有生成的中间代码、符号表内容、错误分析三部分内容,分别用java界面控件显示出来。2.1 文法的描述在计算机科学中,文法是编译原理的基础,是描述一门程序设计语言和实现其编译器的方法。文法的描述多用BNF(巴克斯范式),而另一个重要的概念:正则表达式,也是文法的另一种形式。PL/0文法的EBNF表示:::= .::= [][][]::= const{,};::= =::= {}::= {|}::= var{, };::= {;}::= procedure;::= ||||||| ::= := ::= [+|-]{}::= {}::= || ‘ ( ’ ‘ ) ’::= +|-::= *|/::= |odd::= =|<>||>=::= ifthen::= whiledo ::= call ::= begin{;}end::= read ‘ ( ’{, } ‘ ) ’::= write ‘ ( ’{, } ‘ ) ’::= a|b|c|d…..x|y|z ::= 0|1|2|3…...8|93 概要设计3.1 概要设计(体现系统的设计思路和主要功能)首先在源程序相同的目录下创建一个txt文档,并在文档中输入需要编译的程序即if-else语句,然后定义一个输入流文件,利用这个流文件中的open函数打开我需要编译的txt文件,在调用初始化各种变量的初始化函数。接着开始进行词法分析,词法分析程序的主要任务是对构成源程序的字符串从左到右的扫描,逐个字符地读入源程序字符并按照构词规则切分成一个一个具有独立意义的单词。并确定其属性(如保留字、标识符、运算符、界限符和常量等)。再把它们转换成长度统一的标准形式—属性字。词法分析是编译过程中的第一个阶段,在语法分析前进行。也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。单词的分类(五类):1. 关键字:由程序语言定义的具有固定意义的标识符。也称为保留字或基本字。2. 标识符:用来表示程序中各种名字的字符串。3. 常数:常数的类型一般有整型、实型、布尔型、文字型。4. 运算符:如+、-、*、/

    展开全文
  • 中间语言 后缀式
  • 《PL0语言编译器的中间代码生成》由会员分享,可在线阅读,更多相关《PL0语言编译器的中间代码生成(14页珍藏版)》请在人人文库网上搜索。1、课程设计报告( 2016-2017年度第一学期)名 称: 编译技术课程设计 题 目: ...
  • (1)通过上机实验,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法范畴变换为某种中间代码的语义翻译方法。 (2)掌握目前普遍采用的语义分析方法─语法制导翻译技术。 (3)给出 PL/0 文法规范,要求...
  • 第8章 静态语义分析和中间代码生成 中间代码生成 中间代码 一种介于源语言和目标语言的中间语言形式,有: 逆波兰表示 三元式表示 四元式表示 树形表示 逆波兰表示 逆波兰表示法即为后缀表示法,而默认我们使用的...
  •   三地址码是一种平台无关的中间代码(类似汇编,但没到 x86、MIPS 那么具体),特点是:1、变量和 label 无需换成具体的地址,能区分清楚就行(例如嵌套作用域的同名变量要区分开);2、寄存器无限量,不需要考虑...
  • 静态语义分析和中间代码生成8.1 中间语言8.1.1 概述8.1.2 逆波兰式(后缀式)1) 定义2) 计算方式3) 表达式 => 后缀式8.1.3 图表示法1) 有向无环图2) 举例8.1.4 三地址代码1) 概述2) 四元式3) 三元式4) 间接三元式...
  • 三地址码转换成控制流程图
  • C语言编译器lex和yacc编写的...运行环境要求:flex bison g++11 python3中间代码生成windows命令行输入:flex compiler.lbison -vdty compiler.yg++ -std=c++11 -o compiler tree.cpp Praser.cpp innerCode.cpp tool...
  • AX(AX)* X->Y(MY)* Y->I|N|(S) A->+|- M->*|/ C->=|#|<||>|>= 本次的代码主要是在【编译原理】c++实现自下而上语法分析器的基础上,伴随着归约的过程,增加了生成四元式的过程,也就是一边归约一边生成中间代码。...
  • 为了便于优化处理,作为中间代码,设一张指示器表(间接码表) 四元式 四元式主要由四部分组成: (OP,arg1,arg2,result) 其中,OP是运算符,argl、arg2分别是第一和第二个运算对象,result是编译
  • Simulink代码生成技术详解 17.1基于模型的设计 基于模型设计是一种流程,较之传统软件开发流程而言,使开发者能够更快捷、更高效地进行开发。适用范围包括汽车电子信号处理、控制系统、通信行业和半导体行业。 V...
  • LLVM 目标无关代码生成器1 介绍:LLVM 目标无关代码生成器由 6 个主要的组件组成:1.1 代码生成1.2 代码生成器的高层设计1.3 使用 TableGen 来描述目标平台2 目标描述类2.1 TargetMachine 类2.2 DataLayout 类2.3 ...
  • 字节解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节指令 它是唯一一个在 JVM 规范中没有规定任何 OutOfMemoryError 情况的区域 :使用PC寄存器存储字节指令地址有什么用呢?为什么使用PC...
  • 大厂技术高级前端Node进阶点击上方程序员成长指北,关注公众号回复1,加入高级Node交流群设计稿(UI视图)转代码是前端工程师日常不断重复的工作,这部分工作复杂度较低但工作占...
  • 中间添加rewrite节点: [Nginx] 在Nginx低版本中,是不支持PATHINFO的,但是可以通过在Nginx.conf中配置转发规则实现: location / { // …..省略部分代码 if (!-e $request_filename) { rewrite ^(.*)$ /index....
  • 假如我们现在使用的是CLI模式,直接在SAPI/cli/php_cli.c文件中找到main函数, 默认情况下PHP的CLI模式的行为模式为... 顺着这条执行的线路,可以看到一个PHP文件在经过词法分析,语法分析,编译后生成中...
  • 一、Swagger介绍Swagger是一个规范和...这个解释简单点来讲就是说,swagger是一款可以根据restful风格生成的接口开发文档,并且支持做测试的一款中间软件。二、使用swagger优势1、对于后端开发人员来说不用再手写Wik...
  • 首先高级语言被编译成一种称作IL的中间语言,与高级语言相比,IL更像是机器语言,然而,IL却包含一些抽象概念(比如:类、异常),这也是这种语言被称为中间语言的原因。IL被打包在DLL或EXE文件中,而DLL和EXE在.NET中...
  • 通过反汇编等手段查看编译器生成的代码,原本想着看能不能设置好编译参数,使得编译器可以输出书本中的中间代码,可惜的是暂时还没找到,还一度以为只能通过强行分析汇编码。经过一周的摸索,总算弄出了一个可以接受...
  • 作者简介ZiLin Wang,前端开发者,函数式编程爱好者,最近沉迷于低代码平台和WebAssembly;Ivan Zhang,擅长前端打杂,最近专注于Sketch插件和DesignOp...
  • tp 生成小程序

    2021-01-19 16:57:17
    ​​​​​​Tp生成小程序二维码(带参数),前端解析 注:小程序要进行上线,然后微信开发工具的appid和上线后的appid要一致,否则无法解析出来参参数。 需要 小程序appid 然后小程序秘钥 可以自设头像也可以不...
  • /** * 本类测试生成XML格式的文件 * @author guanshun * */ public class CreateXMLFile { Book[] books = new Book[] { new Book("1","唐诗百首"), new Book("2","Think in Java"), new Book("3","神雕侠侣"), ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 119,991
精华内容 47,996
关键字:

中间代码生成三地址码