首页 > 编程语言 >编译原理------一个简单语言的编译程序的设计与实现

编译原理------一个简单语言的编译程序的设计与实现

时间:2024-05-31 23:00:28浏览次数:23  
标签:cnt 语法分析 int 词法 编译 && ------ danci 编译程序

所完成功能

 1.词法分析 
2.语法分析
3.语义分析和中间代码生成
4.代码优化
5.目标代码生成

所实现语言的文法

采用下降分析方法,已将原来的文法改写成LL(1)文法。

  1. <程序> → <main关键字>(){<声明序列><语句序列>}
  2. <声明序列> → <声明语句><声明序列'> | ε
  3. <声明序列'> → <声明语句><声明序列'> | ε
  4. <声明语句> → <int关键字><标识符表>;
  5. <标识符表> → <标识符><标识符表'>
  6. <标识符表'> → ,<标识符><标识符表'> | ε
  7. <语句序列> → <语句><语句序列'>
  8. <语句序列'> → <语句><语句序列'> | ε
  9. <语句> → <if语句> | <while语句> | <for语句> || <复合语句> | <赋值语句>
  10. <if语句> → <if关键字> (<表达式>)<复合语句><else部分>
  11. <else部分> → <else关键字><复合语句> | ε
  12. <while语句> → <while关键字> (<表达式>)<复合语句>
  13. <for语句> → <for关键字> (<表达式>;<表达式>;<表达式>) <复合语句>
  14. <复合语句> → {<语句序列>}
  15. <赋值语句> → <标识符>=<表达式>
  16. <表达式> → <算数表达式> | <布尔表达式>
  17. <布尔表达式> → <算数表达式><关系运算符><算数表达式> | <算数表达式>
  18. <关系运算符> → > | < | >= | <= | == | !=
  19. <算数表达式> → <项><算数表达式'>
  20. <算数表达式'> → +<项><算数表达式'> | -<项><算数表达式'> | ε
  21. <项> → <因子><项'>
  22. <项'> → *<因子><项'> | /<因子><项'> | ε
  23. <因子> → <标识符> | <无符号整数> | (<算数表达式>)
  24. <标识符> → <字母><标识符'>
  25. <标识符'> → <字母><标识符'> | <数字><标识符'> | ε
  26. <无符号整数> → <数字><无符号整数'>
  27. <无符号整数'> → <数字><无符号整数'> | ε
  28. <字母> → a | b | ... | z | A | B | ... | Z
  29. <数字> → 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
  30. <main关键字> → main
  31. <if关键字> → if
  32. <else关键字> → else
  33. <while关键字> → while
  34. <for关键字> → for
  35. <int关键字> → int

总体概述:

1、词法分析器:该部分负责将输入的源代码文件转化为一个个字符串,将字符串中的内容逐个读取并存储到stringstream对象中,并使用while循环迭代读取其中的每个单词。识别关键字、标识符、常星、运算符等,并使用数组存储起来作为语法分析的输入。

2、语法分析器:语法分析器根据词法分析器生成的token,进行基本的语法分析,识别出语法结构,如声明语句、赋值语句、条件语句、循环语句等。然后采用递归下降解析来分析。

3、语义分析和优化︰在这个简单的程序中,包括一些简单的语义分析和优化,例如类型检查、常量折叠、构建DAG等。但其中没有完善其功能,只能部分实现。

4、目标代码生成:最后一个阶段是生成目标代码,根据经过优化的中间表示形式(如DAG)生成目标代码,即汇编语言代码

编译程序功能描述

该程序可以进行词法分析功能、语法分析功能、语义分析功能、DAG代码及优化功能和目标代码生成功能。

其中词法分析可以分析出关键字、边界符、标识符、数字和运算符。

语法分析可以推出采用了哪些文法进行推导代码。

语义分析可以处理赋值语句,生成相应的中间代码。此外,还可以通过拉链回填生成四元式。

优化方法可以输出DAG优化前和优化后的表达式。

目标代码生成,通过输入的寄存器个数,生成对应的汇编语言。

图1-1词法分析框图

部分函数如下图所示

语法分析

#include <bits/stdc++.h>
#include <fstream>
using namespace std;

vector<string> keywords = {"main", "if", "else", "for", "while", "int"};
vector<string> danci;
int cnt = 0;
int te = 0;
int m;
char fileadress[50] = "D://编译原理//分析结果存储//";
char name[30];
fstream ff;
void lalian();
void huitian();
bool isdigit(char ch) {
	return (ch >= '0' && ch <= '9');
}
bool ischaractor(char ch) {
	return ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'));
}
bool isboundary(char ch) {
	return (ch == '(' || ch == ')' || ch == '{' || ch == '}' || ch == ',' || ch == ';');
}
bool iskeyword(const string& s1) {
	return find(keywords.begin(), keywords.end(), s1) != keywords.end();
}
bool isoperator(char ch) {
	return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=' || ch == '!' || ch == '<' || ch == '>');
}

void cifa() {
	cout << "请输入文件名:";
	ff << "请输入文件名:";
//	char name[30];
	cin >> name;
//	gets(name);
	ff << name;
	strcat(fileadress, name);
	ff.open(fileadress, ios::out);
	ifstream myfile(name);
	if (!myfile.is_open()) {
		cout << "文件打开失败" << endl;
		ff << "文件打开失败" << endl;
	}
	cout << endl << "****************************" << endl;
	cout << "========词法分析如下========" << endl;
	cout << "****************************" << endl;
	ff << endl << "****************************" << endl;
	ff << "========词法分析如下========" << endl;
	ff << "****************************" << endl;
	string str, s, s1;
	stringstream ss;
	while (getline(myfile, str)) {
		if (str == "##")
			break;
		s1 += str;
	}
	ss << s1;
	s = "";
	myfile.close();
	while (ss >> s) {//ss将s逐个读取
		int len = s.length();//获取该字符串的长度
		for (int i = 0; i < len;) {
			if (isboundary(s[i])) {//判断是否为界符
				cout << "(boundary," << s[i] << ")" << endl;
				ff << "(boundary," << s[i] << ")" << endl;
				danci.push_back(string(1, s[i]));//把该界符存起来
				i++;
			} else if (isdigit(s[i])) {//判断是否为数字
				string s1 = "";
				while (isdigit(s[i])) {//把整个数字取完
					s1 += s[i++];
				}
				cout << "(integer," << s1 << ")" << endl;
				ff << "(integer," << s1 << ")" << endl;
				danci.push_back(s1);
			} else if (ischaractor(s[i]) ) {//判断单词
				string s1 = "";//单个读取,数字或者运算不止一个
				while (ischaractor(s[i]) ||  isdigit(s[i])) {
					s1 += s[i++];
				}
				if (iskeyword(s1)) {//判断是否为关键字
					cout << "(keyword," << s1 << ")" << endl;
					ff << "(keyword," << s1 << ")" << endl;
					danci.push_back(s1);
				} else {//不是关键字,则为标识符
					cout << "(identifier," << s1 << ")" << endl;
					ff << "(identifier," << s1 << ")" << endl;
					danci.push_back(s1);
				}
			} else if (isoperator(s[i])) {//判断是否为标识符
				if (i + 1 < len && s[i + 1] == '=') {
					cout << "(operator," << s[i] << s[i + 1] << ")" << endl;
					ff << "(operator," << s[i] << s[i + 1] << ")" << endl;
					danci.push_back(s.substr(i, 2));//存取两个字母
					i += 2;//若为==,则 i 要加 2
				} else {//不是 == 则单个存起来
					cout << "(operator," << s[i] << ")" << endl;
					ff << "(operator," << s[i] << ")" << endl;
					danci.push_back(string(1, s[i]));//存取一个字母
					i++;
				}
			}
		}
	}
}

语法分析

void yuju() {
	if (danci[cnt] == "if") {
		cout << "<语句> → <if语句>" << endl;
		ff << "<语句> → <if语句>" << endl;
		ifyuju();
	} else if (danci[cnt] == "while") {
		cout << "<语句> → <while语句>" << endl;
		ff << "<语句> → <while语句>" << endl;
		whileyuju();
	} else if (danci[cnt] == "for") {
		cout << "<语句> → <for语句>" << endl;
		ff << "<语句> → <for语句>" << endl;
		foryuju();
	} else if (danci[cnt][0] >= 'a' && danci[cnt][0] <= 'z' || danci[cnt][0] >= 'A' && danci[cnt][0] <= 'Z') {
		cout << "<语句> → <赋值语句>" << endl;
		ff << "<语句> → <赋值语句>" << endl;
		fuzhiyuju();
	} else {
//		cout << danci[cnt] << endl;
		error();
	}
}
void yujuxulie1() {
	if (danci[cnt][0] >= 'a' && danci[cnt][0]  <= 'z' || danci[cnt][0]  >= 'A' && danci[cnt][0]  <= 'Z') {
		cout << "<语句序列'> → <语句><语句序列'>" << endl;
		ff << "<语句序列'> → <语句><语句序列'>" << endl;
		yuju();
		yujuxulie1();
	}

}
void yujuxulie() {
	if (danci[cnt + 1] == "}") {
		cout << "<语句序列> → ε" << endl;
		ff << "<语句序列> → ε" << endl;
	} else  {
		cout << "<语句序列> → <语句><语句序列'>" << endl;
		ff << "<语句序列> → <语句><语句序列'>" << endl;
		yuju();
		yujuxulie1();
	}

}
void intkeyword() {
	if (danci[cnt] == "int") {
		cnt++;
		cout << "<int关键字> → int" << endl;
		ff << "<int关键字> → int" << endl;
	} else {
		error();
	}
}
void biaoshifubiao1() {
	if (danci[cnt] == ",") {
		cnt++;
		cout << "<标识符表'> → ,<标识符><标识符表'>" << endl;
		ff << "<标识符表'> → ,<标识符><标识符表'>" << endl;
		biaoshifu();
		biaoshifubiao1();
	} else {
		cout << "<标识符表'> → ε" << endl;
		ff << "<标识符表'> → ε" << endl;
	}
}
void biaoshifubiao() {
	te = 0;
	cout << "<标识符表> → <标识符><标识符表'> " << endl;
	ff << "<标识符表> → <标识符><标识符表'> " << endl;
	biaoshifu();
	biaoshifubiao1();
}
void shengmingyuju() {
	cout << "<声明语句> → <int关键字><标识符表>;" << endl;
	ff << "<声明语句> → <int关键字><标识符表>;" << endl;
	intkeyword();
	biaoshifubiao();
	if (danci[cnt] == ";") {
		cnt++;
	}

}
void shengmingxulie() {
	if (danci[cnt] == "int") {
		cout << "<声明序列> → <声明语句><声明序列'>" << endl;
		ff << "<声明序列> → <声明语句><声明序列'>" << endl;
		shengmingyuju();
		shengmingxulie1();
	} else {
		cout << "<声明序列> → ε" << endl;
		ff << "<声明序列> → ε" << endl;
	}
}
void mainkeyword() {
	if (danci[cnt] == "main") {
		cnt++;
		cout << "<main关键字> → main" << endl;
		ff << "<main关键字> → main" << endl;
	} else {
		error();
	}

}
void yufa() {
	cout << endl << "****************************" << endl;
	cout << "========语法分析如下========" << endl;
	cout << "****************************" << endl;
	cout << endl;
	ff << endl << "****************************" << endl;
	ff << "========语法分析如下========" << endl;
	ff << "****************************" << endl;
	cnt = 0;//从0开始
	if (danci[cnt] == "main") {//若等于main,则进入下一步分析
		cout << "<程序> → <main关键字>(){<声明序列><语句序列>}" << endl;
		ff << "<程序> → <main关键字>(){<声明序列><语句序列>}" << endl;
		mainkeyword();
		if (danci[cnt] == "(") {//匹配左括号(
			cnt++;
			if (danci[cnt] == ")") {//匹配右括号(
				cnt++;
				if (danci[cnt] == "{") {//匹配左大括号{
					cnt++;
					if (danci[cnt] == "int") {
						shengmingxulie();//匹配int,进入声明序列分析
						yujuxulie();//进入语句序列分析
						if (danci[cnt] == "}") {
							cnt++;//匹配左大括号}
						} else {//语法错误,抛出错误信息
							error();
						}
					} else {//语法错误,抛出错误信息
						error();
					}
				} else {//语法错误,抛出错误信息
					error();
				}
			} else {//语法错误,抛出错误信息
				error();
			}
		} else {//语法错误,抛出错误信息
			error();
		}//语法错误,抛出错误信息
	} else {
		error();
	}

}
..........待续

后续代码,私信联系,不免费

整体代码基本完善,有些功能未全能覆盖,在此作出声明!!!

标签:cnt,语法分析,int,词法,编译,&&,------,danci,编译程序
From: https://blog.csdn.net/qq_63933556/article/details/139334959

相关文章

  • 204页 | MES项目需求案例方案:效率+精细化+品质+数据互联(免费下载)
     【1】关注本公众号,转发当前文章到微信朋友圈【2】私信发送MES项目需求案例方案【3】获取本方案PDF下载链接,直接下载即可。如需下载本方案PPT/WORD原格式,请加入微信扫描以下方案驿站知识星球,获取上万份PPT/WORD解决方案!!!感谢支持!!!......
  • OSPF重发布
    OSPFA-->B[r2]ospf1[r2-ospf-1]import-routerip默认进入路由为类型2,种子度量为1;重发布进入的LSA为5类/7类,优先级为150;类型1:显示总度量=种子度量+沿途累加类型2:仅显示种子度量,但选路时比较的是总度量=种子度量+沿途累加类型1选路时由于类型2;[r2-ospf-1]import-r......
  • Verilog设计实现七段数码管译码器的设计
    七段数码管常用于计时器、拨码开关输入、班级和学号等信息的显示,通过控制不同的段亮灭,可以实现各种数字和字符的显示。七段数码管通常由a-g七个段组成,每一段对应一个LED。为了显示不同的数字,需要控制这些LED的亮灭。图1七段数码管为了控制这些LED的亮灭,需要设计一个显示译......
  • Verilog设计实现7人投票表决器
    使用verilog实现七人投票表决器。要求若超过四人含四人投票赞成,则表决通过。设计模块://定义模块test6,声明输出端口pass和输入端口votemoduletest6(outputpass,//输出端口,表示投票结果是否通过inputvote//输入端口,一个7位的向量,每位表示......
  • Verilog设计实现两个8位二进制数相乘
    乘法器的基本原理可以通过多种方法实现,例如移位相加法、查找表法等。在Verilog中,我们可以使用内建的乘法运算符“*”来实现乘法功能。首先明确计算的范围。8位2进制1111_1111=255,所以两个8位二进制数的取值范围是0-255。考虑最大值255*255=65025=(1111_1110_0000_0001)2。所......
  • Java循环结构while
    1.while是最基本的循环,它的结构为        while(布尔表达式){            //循环内容                }2.只要布尔表达式为true,循环就会一直执行下去3.我们大多数情况是会让循环停止下来的,我们需要一个让表达式时......
  • Java If选择结构
    1.if单选择结构    if(布尔表达式){        //如果布尔值表达式为true将执行的语句    }2.if双选择结构    if(布尔表达式){        //如果布尔表达式的值为true        }else{        ......
  • vue3 组件级权限控制
    权限控制程度分为:1.页面级2.组件级3.代码级1.页面级这是大部分前端遇到的级别。依靠路由守卫,如果没有权限,就看不到菜单,就进不到页面。不会给页面带来侵入性。什么是侵入性,就是写页面组件的时候,还要考虑权限。2.组件级有没有权限都可以看到页面组件,但是不同权限的人,......
  • windows安装redis
    1、下载: Releases·microsoftarchive/redis(github.com)   2、解压Redis安装包 3、注册RedisWindows服务进入Redis安装包目录,执行如下的命令,安装服务redis-server.exe--service-installredis.windows.conf--service-nameredisserver1--loglevelverbose......
  • Apache历理 贝锐花生壳的下载及使用
    下载地址:https://hsk.oray.com/使用方法如下:第一步:进入贝锐花生壳的内网穿透的页面第二步:选择映射协议映射协议https第三步:输入外网域名,默认端口443第四步:输入内网域名:192.168.1.160,默认端口80第五步:提交后诊断映射通过就可正常访问效果图:......