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

技术标签: 编译原理实验  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

智能推荐

智慧校园全场景解决方案分析及方案架构_智慧校园中控架构开发软件有哪些-程序员宅基地

文章浏览阅读384次,点赞7次,收藏9次。智慧校园全场景解决方案是借助AIoT智能物联能力打造智慧绿色校园,助力实现校园周界安防、智慧通行、设备运维、能耗管理等场景功能智慧校园全场景解决方案,打造安全、便捷、绿色的智慧校园。_智慧校园中控架构开发软件有哪些

演示Win10输入法设置方法编程_win10 输入法 中英文模式api-程序员宅基地

文章浏览阅读82次。库,我们可以编写代码来模拟按键和鼠标操作,从而实现自动设置Windows 10的输入法。这种方法可以节省时间和精力,尤其是在需要频繁更改输入法设置的情况下。运行代码后,您将看到Windows 10的设置窗口打开,并自动导航到语言设置,然后将输入法更改为中文简体拼音。在本文中,我将向您展示如何使用编程方式来设置Windows 10的输入法。现在,我们已经编写了设置输入法的代码。保存代码文件,并在命令提示符或终端中运行它。库来模拟按下键盘快捷键,以设置输入法。一旦安装完成,我们可以开始编写代码。_win10 输入法 中英文模式api

女人手掌中间有条竖线_手心有一条竖线代表什么-程序员宅基地

文章浏览阅读1.5k次。每个人都有属于自己的手相,有些人的手相是属于典型的、一般的手相特征,没有太多值得说的地方;而另一些人,他们的手相之中,却有一些别人所没有的手相特征,但却真实的出现在了自己的手掌中。比如说,对于手心里有一条竖线的人,他们的命格会是怎样的呢?一起来手相图解看看吧!1、事业发展:前途坎坷对于手心有一条竖线的人,他们的事业线一定会因此而出现中断,与此相交。而在事业发展方面,事业线的分叉代表了遇到的困难程度..._女生右手手掌中间的竖线代表什么

python getattr和getattribute_python __getattr__和__getattribute__ 区别-程序员宅基地

文章浏览阅读70次。当我们访问一个对象的不存在的属性的时候,默认都会报错例如:class Count(object):def __init__(self, mymin, mymax):self.mymin = myminself.mymax = mymaxobj1 = Count(1, 10)print(obj1.mymin)print(obj1.mymax)print(obj1.current)AttributeE..._getattribute方法报错不存在属性

换一种思路实现Java里String类的contains方法_stringcontains和for循环-程序员宅基地

文章浏览阅读2.3k次。换一种思路实现Java里String类的contains方法_stringcontains和for循环

低效能程序员的行为与思维_程序员思维固化的表现-程序员宅基地

文章浏览阅读95次。排过序不写单元测试。 不主动学习,不看书。 总是拿没时间作为借口。 不会做任务拆解,也没有记录拆解的任务。 做事没耐心。 不 Review 自己的代码,做过的事情,犯的错误。 从不了解架构,不了解设计(设计就是架构)。 不了解敏捷开发,更没有想了解的意愿,也不会去实施。Scrum Standup 、Kanban Board 是能提高工作效率的。 喜欢埋怨别人,说在公司学不到技术,也不积极主动学习。 认为重复的 CRUD 很无趣,总想着换个工作能好点。 对每天做的事情不做记录。这里不是_程序员思维固化的表现

随便推点

java虚拟机栈和本地方法栈_本地方法栈存放什么数据-程序员宅基地

文章浏览阅读803次。Java 内存可以粗糙的区分为堆内存(Heap)和栈内存 (Stack),其中栈就是现在说的虚拟机栈,或者说是虚拟机栈中局部变量表部分。new了一个class类的过程:往栈里丢了一个英文的名字,在堆里实例化了一个类,名字指向这个类。与程序计数器一样,Java 虚拟机栈也是线程私有的,它的生命周期和线程相同,描述的是。栈:栈内存,主管程序的运行,生命周期与线程同步。Java 栈可用类比数据结构中栈,Java 栈中保存的主要内容是栈帧,栈:8大基本数据类型,对象的引用,实例的方法。栈运行的原理:栈帧。_本地方法栈存放什么数据

Expression expected.Vetur(1109) 报错_ts1109: expression expected.-程序员宅基地

文章浏览阅读5.9k次。这里发现报错,关闭vscode重启也还是有问题。后面发现其实是typescript定义类型的语法,是因为我将代码写在<script></script>里面,使用ts语法需要表明lang="ts"即将代码写在<script lang="ts"></script>将不会报错..._ts1109: expression expected.

基于8ASK调制解调误码率matlab仿真_matlab ask-程序员宅基地

文章浏览阅读1k次,点赞23次,收藏22次。在数字通信系统中,幅度键控(ASK)是一种通过改变载波信号的幅度来传输数字信息的调制方式。8ASK,即8幅度键控,是ASK的一种变体,它使用8个不同的幅度级别来表示数字信息。8ASK (Amplitude Shift Keying) 调制是一种幅度移键调制技术,它通过改变载波信号的幅度来传输数据,同时保持频率和相位不变。在8ASK中,有8个不同的幅度级别,每个级别代表3比特的信息(因为2^3=8)。这种调制方式能够在相同的带宽条件下传输更多的数据,但与此同时,它对信号的幅度噪声也更加敏感。_matlab ask

auto.js autojs pro9 云控使用意图Intent跳转详细过程,实现通过意图跳转_intent拦截者app-程序员宅基地

文章浏览阅读1k次,点赞12次,收藏13次。Intent记录 意图跳转_intent拦截者app

pycharm光标消失,无法编辑_pycharm光标不见了-程序员宅基地

文章浏览阅读1.7k次。pycharm在debug时光标消失,无法编辑代码区。点击这个小扳手即可解决。_pycharm光标不见了

Java如何使用排序_java什么叫自然顺序-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏2次。在开发中,需要对一组对象进行排序,是非常常见的需求。排序可以让数据更加有序,便于查找和操作。在Java中,排序可以使用Collections类或Arrays类提供的方法可以通过Comparable自然排序和Comparator定制排序进行实现。_java什么叫自然顺序

推荐文章

热门文章

相关标签