实验四: 语义分析与中间代码生成

一、实验目的

通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法.

二、实验内容

采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。

三实验要求

  • 实验要求
  1. 文法:
  2. statement→begin expr end

expr  → expr + term 

| expr - term 

| term

term  → term * factor

 | term / factor 

| factor

factor ( expr ) | id | num

  1. 实现一遍扫描翻译

3、实验的输入和输出:

输入是语法分析提供的正确的单词串,输出为三地址指令形式的四元式序列。

例如:对于语句串

begin   a:=2+3*4;x:=(a+b)/c end#

输出的三地址指令如下:

t1=3*4

t2=2+t1

a=t2

t3=a+b

t4=t3/c

x=t4

四、实验步骤

算法思想

1设置语义过程

emit(char *result,char *arg1,char *op,char *ag2)

该函数功能是生成一个三地址语句送到四元式表中。

四元式表的结构如下:

struct {char result[8];

char ag1[8];

char op[8];

char ag2[8];

}quad[20];

(2)    char *newtemp()

该函数回送一个新的临时变量名,临时变量名产生的顺序为T1,T2,….

Char *newtemp(void)

{

    char *p;

    char m[8];

    p=(char *)malloc(8);

    k++;

    itoa(k,m,10);

    strcpy(p+1,m);

    p[0]=’t’;

    return(p);

}

2.主程序示意图如图c.10所示。

 

3.函数lrparser在原来语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。在实验中我们只对表达式、赋值语句进行翻译。

四、实验过程原始记录(数据、图表、计算等)

实验的输入和输出:

输入是语法分析提供的正确的单词串,输出为三地址指令形式的四元式序列。

例如:对于语句串

begin   a:=2+3*4;x:=(a+b)/c end#

输出的三地址指令如下:

t1=3*4

t2=2+t1

a=t2

t3=a+b

t4=t3/c

x=t4

五、实验过程和思路

思路:

编译器包含了词法分析、语法分析和代码生成三个阶段。

在词法分析阶段,通过读入字符并识别其类型,将输入的代码划分成一个个单词,并将每个单词的类型(关键字、标识符、数字等)保存在变量中。

在语法分析阶段,根据对应的文法规则,递归地调用各个函数进行语法分析。这里的文法规则包含了赋值语句、条件语句和循环语句。在语法分析过程中,还会借助生成四元式的方法,逐步构建出目标程序的中间代码。

在代码生成阶段,将语法分析阶段得到的四元式转换成目标程序的汇编代码。

主要是将输入的代码分析成语法树,然后生成对应的目标程序。

实验代码:

#include<stdio.h>#include <stdlib.h>#include<string.h>#include <conio.h>char prog[80], token[6];int count = 0;char ch;  /*当前读入单词*/int syn, p, m, n, sum, kk = 0, k = 0;  //p/*输入缓冲区指针*/int length = 0;    //输入字符长度int mark = 0;       /*标记注释//*/int mark2;// 用于/* */ 注释char* rwtab[6] = { "begin","if","then","while","do","end" };char* expression(void);struct {char result[8];char ag1[8];char op[8];char ag2[8];}quad[20];void emit(char* result, char* ag1, char* op, char* ag2){strcpy(quad[count].result, result);strcpy(quad[count].ag1, ag1);strcpy(quad[count].op, op);strcpy(quad[count].ag2, ag2);count++;return;}/*词法扫描程序:*/void scaner(){for (n = 0; n < 8; n++)token[n] = NULL;m = 0;ch = prog[p++];while (ch == ' ')ch = prog[p++];if ((ch <= 'z' && ch >= 'a') || (ch <= 'Z' && ch >= 'A')){while ((ch <= 'z' && ch >= 'a') || (ch <= 'Z' && ch >= 'A') || (ch <= '9' && ch >= '0')){token[m++] = ch;ch = prog[p++];}token[m++] = '\0';ch = prog[--p];syn = 10;for (n = 0; n < 6; n++)if (strcmp(token, rwtab[n]) == 0){syn = n + 1;break;}//break;}elseif ((ch <= '9' && ch >= '0')){sum = 0;while ((ch <= '9' && ch >= '0')){sum = sum * 10 + ch - '0';ch = prog[p++];}ch = prog[--p];syn = 11;}elseswitch (ch){case '<':m = 0; token[m++] = ch;ch = prog[p++];if (ch == '>'){syn = 21;token[m++] = ch;}elseif (ch == '='){syn = 22;token[m++] = ch;}else{syn = 20;ch = prog[--p];}break;case '>':token[m++] = ch;ch = prog[p++];if (ch == '='){syn = 24;token[m++] = ch;}else{syn = 23;ch = prog[--p];}break;case ':':token[m++] = ch;ch = prog[p++];if (ch == '='){syn = 18;token[m++] = ch;}else{syn = 17;ch = prog[--p];}break;case '+':syn = 13; token[0] = ch; break;case '-':syn = 14; token[0] = ch; break;case '*':syn = 15;token[m++] = ch;ch = prog[p++];if (ch == '/'){mark2 = 1;return scaner();}ch = prog[--p];break;case '/':syn = 16;token[m++] = ch;ch = prog[p++];if (ch == '/'){mark = 0;while (mark == 0){scaner();}p++;//mark=0;}else if (ch == '*'){mark = 1;syn = 30;   ///**/token[m++] = '*';mark2 = 0;while (mark2 == 0){scaner();}p++;//mark2=0;}ch = prog[--p];break;case ':=':syn = 18; token[0] = ch; break;case '<>':syn = 21; token[0] = ch; break;case '<=':syn = 22; token[0] = ch; break;case '>=':syn = 24; token[0] = ch; break;case '=':syn = 25; token[0] = ch; break;case ';':syn = 26; token[0] = ch; break;case '(':syn = 27; token[0] = ch; break;case ')':syn = 28; token[0] = ch; break;case '\n':syn = 29;token[0] = ch;mark = 1;return scaner();break;case '#':syn = 0; token[0] = ch; break;case '\0':syn = 1000; token[0] = '\0'; break;default:syn = -1;}}char* newtemp(void){char* p;char m[8];p = (char*)malloc(8);k++;itoa(k, m, 10);strcpy(p + 1, m);p[0] = 't';return(p);}//factor分析函数char* factor(){char* fplace;fplace = (char*)malloc(12);strcpy(fplace, " ");if (syn == 10){strcpy(fplace, token);scaner();}else if (syn == 11){itoa(sum, fplace, 10);scaner();}elseif (syn == 27)   //(   27{scaner();fplace = expression();if (syn == 28)scaner();else{printf("缺少')' 出错!\n");kk = 1;}}else{printf("表达式错误!\n");kk = 1;}return (fplace);}//term分析函数char* term(void){char* tp, * ep2, * eplace, * tt;tp = (char*)malloc(12);/*分配空间*/ep2 = (char*)malloc(12);eplace = (char*)malloc(12);tt = (char*)malloc(12);strcpy(eplace, factor());while (syn == 15 || syn == 16){if (syn == 15){tt[0] = '*';tt[1] = '\0';}else if (syn == 16){tt[0] = '/';tt[1] = '\0';}scaner();strcpy(ep2, factor());strcpy(tp, newtemp()); //tp为临时变量emit(tp, eplace, tt, ep2); //将三地址代码送到四元式表strcpy(eplace, tp);//factor();}return (eplace);}//expression表达式分析函数char* expression(){char* tp, * ep2, * eplace, * tt;tp = (char*)malloc(12);/*分配空间*/ep2 = (char*)malloc(12);eplace = (char*)malloc(12);tt = (char*)malloc(12);strcpy(eplace, term());/*调用term分析产生表达式计算的第一项eplace*/while (syn == 13 || syn == 14){if (syn == 13){tt[0] = '+';tt[1] = '\0';}else if (syn == 14){tt[0] = '-';tt[1] = '\0';}scaner();strcpy(ep2, term());/*/调用term分析产生表达式计算的第二项ep2/*/strcpy(tp, newtemp());/*/调用newtemp产生临时变量tp存储计算结果/*/emit(tp, eplace, tt, ep2);/*/生成四元式送入四元式表/*/strcpy(eplace, tp);}return (eplace);}//statement语句分析函数int statement(){//scaner();int schain = 0;char tt[8], eplace[8];if (syn == 10){strcpy(tt, token);scaner();if (syn == 18)  //:= 18{scaner();strcpy(eplace, expression());emit(tt, eplace," "," ");schain = 0;//expression();}else{printf("赋号值错误!\n");kk = 1;}}else{printf("语句错误\n");//kk=1;}return (schain);}//语句串分析int yucu(){int schain = 0;schain = statement();while (syn != 6 && p != length - 1 && syn != 0){if (syn != 26)scaner();while (syn == 26)     //26==;{scaner();if (syn != 0 && syn != 6){schain = statement();}}}return (schain);}//递归下降分析程序int lrparser(){int schain = 0;scaner();if (syn != 1){printf("begin错误\n");kk = 1;}elsescaner();schain = yucu();if (syn == 6){scaner();if (kk == 0)printf("sucess");}else {if (kk != 1)kk = 1;printf("缺少end\n");}return (schain);}void readFile() {int i = 0;char temp[255];/*ifstream fin("data.txt");*/FILE* fp = fopen("data.txt", "r");while ((temp[i] = fgetc(fp)) != EOF){prog[i++] = temp[i];}length = i;}int main(){int i;p = 0;readFile();printf("\nplease intput string:");do{ch = getchar();prog[p++] = ch;} while (ch != '#');length = p;//将程序保存在prog字符数组中p = 0;printf("词法分析:\n");do{scaner();if (syn < 1000/*&&syn!=100&&syn!=101*/){printf("(%d,%s)\n", syn, token);}} while (syn < 1000);printf("\n\n");printf("语法分析:\n");p = 0;//scaner();lrparser();printf("\n");printf("\n三地址指令如下:\n");for (i = 0; i < count; i++){printf("%s=", quad[i].result); //t1=  //x=printf("%s", quad[i].ag1);     //a    //t1printf("%s", quad[i].op);      //+printf("%s ", quad[i].ag2);     //bprintf("\n");}getch();}

如有帮助,求三连 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/229047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ list常用操作

目录 一、介绍 二、list的常用操作 1、构造 2、迭代器 3、元素访问 4、容量操作 一、介绍 std::list文档链接 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个…

3rd 库(x86, linux)的编译,源码目录

著名的C/C框架和第三方库-CSDN博客 Ubuntu下protobuf的port_def.inc文件找不到问题//test ok-CSDN博客 protobuf入门教程(四)&#xff1a;repeated限定修饰符//test ok-CSDN博客 protobuf 3.17.0交叉编译//test ok-CSDN博客 protobuf-2.6.1安装//test ok-CSDN博客 【zmq】z…

独立看门狗 IWDG

看门狗介绍 "看门狗"通常指的是计算机科学和信息技术领域中的一种技术或设备&#xff0c;用于监控系统的运行状态&#xff0c;并在系统出现故障或异常情况时采取相应的措施。这种技术或设备起到类似于守卫的作用&#xff0c;确保系统的稳定性和可靠性。 在计算机系统…

RealBasicVSR高清处理视频

autodl做了镜像&#xff1a;高清RealBasicVSR 首先在剪映将视频剪好导出&#xff0c;最多是720像素的&#xff0c;不然后面超分的时候会爆显存。剪映视频也最好是双数帧数结尾的&#xff0c;不然超分的时候单数图片会报错->RuntimeError: non-empty 3D or 4D input tensor …

beebox靶场A1 low 命令注入通关教程(上)

一&#xff1a;html注入 get HTML注入&#xff0c;就是当用户进行输入时&#xff0c;服务器没有对用户输入的数据进行过滤或转义&#xff0c;导致所有输入均被返回前端&#xff0c;网页解析器会将这些数据当作html代码进行解析,这就导致一些恶意代码会被正常执行。 首先进行简…

DC电源模块的设计与制造技术创新

BOSHIDA DC电源模块的设计与制造技术创新 DC电源模块的设计与制造技术创新主要涉及以下几个方面&#xff1a; 1. 高效率设计&#xff1a;传统的DC电源模块存在能量转换损耗较大的问题&#xff0c;技术创新可通过采用高效率的电路拓扑结构、使用高性能的功率开关器件和优化控制…

【Linux应用编程笔记】输入设备

系列文章目录 【Linux应用编程笔记】GPIO 本系列使用的开发板为正点原子阿尔法IMX6ULL开发板&#xff0c;及根据正点原子所的提供教程学习 文章目录 系列文章目录【Linux应用编程笔记】GPIO 做什么&#xff1f;一、编写流程1、input子系统2、读取数据的流程3、解析数据应用编…

面向对象三大特征——继承

目录 1. 概述 2. 继承的限制 2.1 单继承 2.2 访问修饰符 2.3 . final 3. 重写 4. super 4.1super的作用 4.2访问父类的成员和被重写方法 4.3调用父类的构造器 1. 概述 多个类中存在相同属性和行为时&#xff0c;将这些内容抽取到单独一个类中&#xff0c;那么就无需在…

C++类与对象 (上)

目录 前言&#xff1a; 类和对象的理解 类的引入 类的定义与使用方式 访问限定符 类的两种定义方式 成员变量的命名规则 类的作用域 类的实例化 类对象模型 计算类对象的大小 类对象的存储方式 this指针 前言&#xff1a; C语言是面向过程的&#xff0c;关注的是过…

基于Java SSM框架实现智能停车场系统项目【项目源码+论文说明】

基于java的SSM框架实现智能停车场系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个智能停车场管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述…

svg文本转为对应图片的base64编码

转换脚本&#xff08;node&#xff09; npm init -y npm install express sharp body-parser const express require(express); const bodyParser require(body-parser); const sharp require(sharp);const app express(); const port 5000;// 配置body-parser以接受JSON格…

【Linux基础命令使用】

文章目录 一. 操作系统和文件及文件路径介绍二. 基础指令介绍三. 结束语 一. 操作系统和文件及文件路径介绍 什么是操作系统&#xff1f;操作系统是一款进行软硬件资源管理的软件为什么要进行软硬件资源管理&#xff1f;对上提供良好的稳定的运行服务----工具Linux指令和图形化…

图扑物联助力打造现代化绿色智慧港口

“智慧港口”是以现代化基础设施设备为基础&#xff0c;以云计算、大数据、物联网、移动互联网、智能控制等新一代信息技术与港口运输业务深度融合为核心&#xff0c;以港口运输组织服务创新为动力&#xff0c;以完善的机制、法律法规、标准规范、发展政策为保障。能够在更高层…

数字签名介绍

数字签名的意义&#xff1a;防止抵赖、保证信息没有被更改过。 假如A公司要发一份合同给B公司&#xff0c;过程如下&#xff1a; 1 A公司使用一个单向散列函数算法&#xff08;比如使用MD5&#xff09;对合同计算一个摘要&#xff0c;得到摘要S(A)&#xff0c;再使用A的私钥对摘…

信息学奥赛一本通1085:球弹跳高度的计算详解+代码

目录 题目 【题目描述】 【输入】 【输出】 【输入样例】 【输出样例】 详解 代码 题目链接&#xff1a;信息学奥赛一本通1085&#xff1a;球弹跳高度的计算 题目 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 100308 通过数: 55941 【题目描述】 一球…

Element 介绍

Element 介绍 Vue 快速入门 Vue 常见组件 表格 分页组件 其他自己去看吧 链接: 其他组件

设计模式——装饰模式(结构型)

引言 装饰模式是一种结构型设计模式&#xff0c; 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。 假设你正在开发一个提供通知功能的库&#xff0c; 其他程序可使用它向用户发送关于重要事件的通知。 库的最初版本基于 通知器Notifier类&#xff0c;…

C语言——谁考了第k名(编程题目)

目录 一、题目描述&#xff1a; 二、输入格式&#xff1a; 三、输出格式&#xff1a; 四、输出样例&#xff1a; 五、输出样例&#xff1a; 六、代码呈现&#xff1a; 一、题目描述&#xff1a; 在一次考试中&#xff0c;每个学生的成绩都不相同&#xff0c;现知道了每个…

Oracle RAC环境下redo log 文件的扩容

环境&#xff1a; 有一个2节点RAC每一个节点2个logfile group每一个group含2个member每一个member的大小为200M 目标&#xff1a;将每一个member的大小有200M扩充到1G。 先来看下redo log的配置&#xff1a; SQL> select * from v$log;GROUP# THREAD# SEQUENCE# …

JUC并发编程 06——Synchronized与锁升级

一.Java对象内存布局和对象头 在HotSpot虚拟机里&#xff0c;对象在堆内存中的存储布局可以划分为三个部分&#xff1a;对象头(Header) 、实例数据 (Instance Data) 和 对文填充 (Padding)。 对象内部结构分为&#xff1a;对象头、实例数据、对齐填充&#xff08;保证8个字节的…