编译原理之目标代码生成_编译原理目标代码生成实验-程序员宅基地

技术标签: 编译原理实验  c++语言  编译原理  目标代码生成  

所有的源码:https://github.com/yanguojun123/Compile

先上代码:

(其余后面完善)

 

#pragma once
#include<iostream>
#include<string>
#include <fstream>
#include <sstream>
#include<Windows.h>
#include "tree.h"
#include<stack>
bool success = 1;
using namespace std;
char ch;//字符变量,存放最新读进的源程序字符
char strToken[100];//字符数组,存放构成单词符号的字符串
int len = 0;//记录字符串的长度
string klabel[29] = { "+","-","*","/","=","#","<","<=",">",">=",",",";",":=","(",")",".","const","var","procedure","begin","end","odd","if","then","call"
,"while","do","read","write" };
string slabel[100] = {};
string  clabel[100] = {};
string  result[1000] = {};//保存所有单词的结果数组
int procedureId = 0;//记录当前的过程层数
int tableId = 0;//当前名字表的下标
int dx = 3;//当前层数的偏移地址
int ip = 0;//全局符号表的指针
int slen = 0;//标识符表的下标
int clen = 0;//常量表的下标
			 //判断是否为数字
const char *input;
int index = 0;
int codeId = 0;//代码的下标
bool isDigit()
{
	if (ch < 58 && ch >= 48)
		return true;
	else
		return false;
}
//判断是否为小写字母
bool issLetter()
{
	if (ch <= 122 && ch >= 97)
		return true;
	else
		return false;
}
bool isDigit(char ch1)
{
	if (ch1 < 58 && ch1 >= 48)
		return true;
	else
		return false;
}
//把字符串转化为数字
int strToint(string str)
{
	int len = str.length();
	int count = 0;
	for (int i = 0; i < len; i++)
	{
		if (str.at(i) <= 57 && str.at(i) >= 48)
			count = count + (str.at(i) - 48)*pow(10, len - i - 1);
		else
			return -1;
	}
	return count;
}
//把数字转化为字符串
//string intTostr(int num)
//{

//}
//判断是否为小写字母
bool issLetter(char ch1)
{
	if (ch1 <= 122 && ch1 >= 97)
		return true;
	else
		return false;
}
//判断是否为大写字母
bool islLetter()
{
	if (ch <= 90 && ch >= 65)
		return true;
	else
		return false;
}
//将下一输入字符读到ch中
void GetChar()
{
	ch = input[index];
	index++;

}
//判断ch中是否是空白,若是,则调用GetChar直至读入下一个非空白的字符
void GetBC()
{
	while (ch == 32)
		GetChar();
}
//将ch中的字符连接到strToken之后
void concat()
{
	strToken[len] = ch;
	len++;
}
//对strToken中的字符串查找保留字表,若他是一个保留字则返回则返回他的编码,否则返回0值
int Reserve()
{

	for (int i = 0; i < 29; i++)
	{
		/*const char *p = klabel[i].data();
		if (strcmp(p,strToken)==0)
		{
		return i;
		}*/
		if (klabel[i] == strToken)
			return i;
	}
	return -1;
}
//将搜索指示器回调一个字符位置
void Retract()
{
	index--;
	ch = 32;
}
//将strToken中的标识符插入到符号表
int insertId()
{
	slabel[slen] = strToken;
	slen++;
	return slen - 1;
}
//将strToken中的常数插入到常数表
int insertConst()
{
	clabel[clen] = strToken;
	clen++;
	return clen - 1;
}
string readFileIntoString(char * filename)
{
	ifstream ifile(filename);
	//将文件读入到ostringstream对象buf中
	ostringstream buf;
	char ch;
	while (buf&&ifile.get(ch))
		buf.put(ch);
	//返回与流对象buf关联的字符串
	return buf.str();
}
//检测是否已经存在此标识符
int isexists(string str)
{
	for (int i = 0; i < slen; i++)
		if (str == slabel[i])
			return 1;

	return 0;
}
//检测是否已经存在此常量
int  isexistc(string con)
{
	for (int i = 0; i < clen; i++)
		if (con == clabel[i])
			return 1;
	return -1;
}
int isexists()
{
	for (int i = 0; i < slen; i++)
		if (strToken == slabel[i])
			return i;

	return -1;
}
//检测是否已经存在此常量
int  isexistc()
{
	for (int i = 0; i < clen; i++)
		if (strToken == clabel[i])
			return i;
	return -1;
}
//名字表的结构体
struct symble
{
	string name;
	string kind;
	int addr;
	int attribute;//val/value 
}symlabel;
//判断是否退出
symble table[20];
//在符号表里查找某个标识符
int findSymble(string str)
{
	for (int i = 0; i < tableId; i++)
	{
		if (table[i].name == str)
			return i;
	}
	return -1;
}
//在符号表里根据地址查找变量的名字
string findSymble(int addr1)
{
	for (int i = 0; i < tableId; i++)
	{
		if (table[i].addr == addr1)
			return table[i].name;
	}
	return "";
}
//目标指令的结构体:
struct tarInstruc
{
	string funcCode=" ";
	int levelDiff = 0;
	int displacement = 0;
	string content = " ";
};
tarInstruc code[200];
//从关键字表查找关键字的下标
int findKlabel(string str)
{
	for (int i = 0; i < 29; i++)
	{
		if (str == klabel[i])
			return i+1;
	}
	return -1;
}
//添加code,运算类型
void codeAdd(string str,int lev,int place,string con)
{
	code[codeId].funcCode = str;
	code[codeId].levelDiff = lev;
	code[codeId].displacement = place;
	code[codeId].content = con;
	codeId++;
}
//添加code,非运算
void codeAdd(string str, int lev, int place)
{
	code[codeId].funcCode = str;
	code[codeId].levelDiff = lev;
	code[codeId].displacement = place;
	codeId++;
}
//主程序
void lex(string file1)
{
	int code, value, num = 0;
	/*cout << "请输入单词长度"<<endl;
	cin >> num;
	cout << "请输入单词:"<<endl;
	cin >> input;*/
	//char filename[] = "test.txt";
	//const char *file = readFileIntoString(filename).data();
	std::ifstream in(file1);
	std::ostringstream tmp;
	tmp << in.rdbuf();
	std::string str = tmp.str();
	cout << str << endl;
	for (int i = 0; i < str.length(); i++)//如果输入中有大写字母,则转换为小写字母
		if (str.at(i) <= 90 && str.at(i) >= 65)
			str.at(i) = str.at(i) + 32;
	const char *file = str.data();
	input = file;

	while (input[index] != 0)
	{
		len = 0;
		//strcpy(strToken,"");
		memset(strToken, 0, sizeof(strToken));
		//cout << strToken << endl;
		//Sleep(1000);
		GetChar();
		GetBC();
		if (issLetter())//判断是否是字母
		{
			while (issLetter() || isDigit())
			{
				concat();
				GetChar();
			}
			Retract();
			result[ip] = strToken;
			ip++;
			code = Reserve();
			if (code == -1)//不在关键字表里,即为标识符
			{
				
				int index1 = isexists();//检测此标识符是否存在
				if (index1 != -1)
					cout << "(" << strToken << ",id," << index1 << ")" << endl;
				else
				{
					value = insertId();
					cout << "(" << strToken << ",id," << value << ")" << endl;//输出标识符的三元组

				}//cout << strToken<<endl;
			}
			else
			{
				cout << "(" << klabel[code] << "," << klabel[code] << ",-)" << endl;//输出关键字的二元组
			}
		}
		else if (isDigit())//如果是数字,即为常量
		{
			while (isDigit())
			{
				concat();
				GetChar();
			}
			Retract();
			result[ip] = strToken;
			ip++;
			int index2 = isexistc();
			if (index2 != -1)
				cout << "(" << strToken << ",int," << index2 << ")" << endl;
			else
			{
			
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_38247544/article/details/85076074

智能推荐

CPO-CNN-LSTM分类预测,【24新算法】冠豪猪算法CPO优化卷积神经网络-长短期记忆网络多特征分类预测-程序员宅基地

文章浏览阅读161次。CPO-CNN-LSTM分类预测,【24新算法】冠豪猪算法CPO优化卷积神经网络-长短期记忆网络多特征分类预测

非Root或Administrator账户下运行Nginx_nginx用什么用户启动-程序员宅基地

文章浏览阅读1.4k次。这样,就可以在CentOS系统中使用普通用户身份来管理和启动Nginx服务了。请注意,对于其他需要管理员权限才能完成的操作(如修改系统文件等),还需要使用sudo命令或者切换到管理员账户进行操作。下载并安装Nginx,保证Nginx可执行文件所在的路径对普通用户具有可读、可执行的权限。安装过程中,在指定 Nginx 配置文件路径时要特别注意,确保可访问并正确填写。启动Nginx服务。是您实际安装Nginx时配置文件存放的路径。_nginx用什么用户启动

【解决】无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core]_无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[h-程序员宅基地

文章浏览阅读6.8k次。问题描述:无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core]在调用<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>时出现异常调用tomcat服务器时,页面出错:原因分析:首先确认导入的jar包是否正确经过多次导包还是老样子,在网上也找了挺多方法,但都不凑效解决方案:方案一:重新导入jar包如果是jar包缺失_无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[h

matlab2019a的help文档不显示的解决_matlab没安装帮助文档-程序员宅基地

文章浏览阅读1k次。仅作为学习记录,大佬请跳过。关键词:在help文档里的——预设齿轮按钮——安装到本地即可显示感谢CSDN的一位优秀博主文章:https://blog.csdn.net/weixin_44331401/article/details/97013548..._matlab没安装帮助文档

Linux环境下安装pandoc_linux安装pandoc-程序员宅基地

文章浏览阅读7.3k次,点赞6次,收藏17次。概述本篇文章主要讲解:pandoc的安装及其一些注意事项使用pandoc将md文件转PDF,HTML文件指令介绍pandoc进阶(用指令对图片的设定)本文为我个人安装及使用pandoc过程中对遇到的一些问题及使用心得的总结,仅供参考。pandoc简介Pandoc 是一个命令行工具,用于将文件从一种标记语言转换为另一种标记语言。标记语言使用标签来标记文档的各个部分。常用的标记语言包..._linux安装pandoc

Spring Cloud Eureka项目切换注册中心到Nacos_eureka切换nacos-程序员宅基地

文章浏览阅读1.9k次,点赞2次,收藏7次。Spring Cloud 项目平滑将注册中心迁移到Nacos上1.问题概述由于项目升级,需要将Eureka注册中心改为阿里的Nacos作为注册中心项目环境1、Java 使用的 JDK-1.82、Spring Boot 使用的 Spring Boot-2.1.4.RELEASE3、Spring Cloud 使用的是 Greenwich.RELEASE2.方案设计2.1 业务应用多注册到Nacos和EurekaSpring Cloud应用默认不支持启动时双向注册,但是阿里商业版上云edas_eureka切换nacos

随便推点

优动漫PAINT-超简单灌木教程-程序员宅基地

文章浏览阅读93次。超简单灌木教程~零基础神马的都能神还原哦!优动漫PAINT下载:http://wm.makeding.com/iclk/?zoneid=18597想要Get到更多有关优动漫的信息包括软件下载,可关注优动漫PAINT中文官网哦!转载于:https://www.cnblogs.com/danzi/p/8527177.html..._优动漫边缘上色

Netty 1-程序员宅基地

文章浏览阅读716次,点赞24次,收藏27次。Channel与BufferJava NIO系统的核心通道(Channel)和缓冲区(Buffer)。通道表示打开到 IO 设备(例如:文件、套接字)的连接。若需要使用 NIO 系统,需要获取用于连接 IO 设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理简而言之,通道负责传输,缓冲区负责存储常见的Channel有以下四种,其中FileChannel主要用于文件传输,其余三种用于网络通信Buffer有以下几种,其中使用较多的是ByteBufferByteBuffer。

VS 设置 C# 以下划线 _ 开头命名全局字段_visual studio 命名规则以_开头给-程序员宅基地

文章浏览阅读2.1k次,点赞3次,收藏5次。VS 设置 C# 以下划线 _ 开头命名全局字段设置方法之前在某位大神的博客有看到这个设置方法,换电脑以后再找那个文章却找不到了,按回忆找到了设置方法,故写出来分享给大家。private readonly SearchResult _searchResult;设置方法以2019企业版为例,找到:工具 - 选项 - 文本编辑器 - C# - 代码样式 - 命名点击“管理命名样式”,然后再点左下角加号,新建一个命名规范,标题可以自己拟定,设置“必填前缀”为“_”,选择“camel 事例名称”,确_visual studio 命名规则以_开头给

测试用例设计--经典面试_面试测试用例设计-程序员宅基地

文章浏览阅读184次。在开始设计测试用例前,需要了解项目产品需求,只有对需求深入了解后,才能进一步进行测试用例设计。(1)水杯有很多,有瓷水杯,纸杯,保温杯,不绣钢杯等,水杯具体需求是哪种杯子?下面以测试【纸杯】为例。(2)水杯具有的特性要求: 杯子的容量:要求最大能装多少升水(满杯),空杯,半杯杯子的型状:圆型,上面口大,下面小。 杯子的材料:纸杯 ..._面试测试用例设计

【mysql】mysql中字符长度的问题_mysql mutipolygen 字符大小-程序员宅基地

文章浏览阅读1.6k次。只适用mysql5.0以上的版本: 1.一个汉字占多少长度与编码有关: UTF-8:一个汉字=3个字节 GBK:一个汉字=2个字节2.varchar(n)表示n个字符,无论汉字和英文,Mysql都能存入n个字符,仅是实际字节长度有所区别3.MySQL检查长度,可用SQL语言: select LENGTH(fieldname) f_mysql mutipolygen 字符大小

【项目构建】java: -source 1.5 中不支持switch 中存在字符串_-source 1.5 中不支持 switch 中存在字符串-程序员宅基地

文章浏览阅读502次,点赞20次,收藏3次。使用maven进行项目构建时报错,信息如下。_-source 1.5 中不支持 switch 中存在字符串