编译原理实验二之语法分析(算数表达式的扩充)

一、实验目的:

掌握LR分析表的设计方法和语义加工程序的扩充

二、实验内容及原理

算术表达式文法扩充如下:

E→E+E|E-E|E*E|E/E|(E)|I

试根据该文法重新设计LR分析表,并修改语义加工程序,最后验证修改的结果。

实验要求:

参照算术表达式LR分析表的设计方法,设计扩充后的算术表达式LR分析表,并对原语义加工程序修改,加入新添的内容。

三、实验过程原始数据记录

主要结构:

//定义状态栈

vector<int> status;

//定义符号栈

vector<char> sign;

//定义输入的字符串

vector<char> inputStr;

//定义产生式数组

string formula[100] = { " ","E->E+E","E->E-E","E->E*E","E->E/E","E->(E)","E->i" };

//定义分析表

class {

public:

    string str;

}st[20][20];

主要函数:

//初始化LR文法分析表

void Init()

//读入字符

int getChar(char ch)

//对栈容器进行输出

string Output_vec(int i);

//总控,对输入的字符串进行分析

void LRanalyse();

结果截图:

四、实验总结

        通过这个实验,我对LR(1)分析法算法的原理和实现有了更清晰的认识。在实验中,我逐步理解了LR(1)分析法中的项目集、项目、核心项目以及项目的闭包等概念,掌握了构建LR(1)分析表的基本方法和步骤。通过实验的过程,我深入理解了文法的FIRST集和FOLLOW集的计算方法,以及如何利用这些集合来确定项目的移进和规约操作,从而构建出LR(1)分析表。这样,我对编译原理中语法分析的过程和实现有了更深入的了解。实验中,我需要根据给定的文法和LR(1)分析表,设计和实现一个可以进行语法分析的编译器。在这个过程中,我需要考虑如何将文法转化为计算机可以理解和处理的形式,如何利用数据结构和算法来实现语法分析的过程。在实验的过程中,我遇到了一些困难,需要仔细思考和分析,不断尝试和调试。

五、实验代码

#include <iostream>
#include <vector>
#include <iomanip>
#include <cstring>
#include <sstream>
#include <unordered_map>
#include <stack>

using namespace std;

vector<char>inputStr;  //输入字符
vector<char>sign;  //定义符号栈
vector<int>status;  //定义状态栈
unordered_map<int, vector<pair<char, int>>>state;
char symbol[10] = { '+', '-', '*', '/', '(', ')', 'i', '#' ,'A','E' };
//定义产生式数组
string formula[100] = { " ","E->E+E","E->E-E","E->E*E","E->E/E","E->(E)","E->i" };
class {
public:
    string str;
}st[20][20];


int getChar(char ch) {
	for (int i = 0; i < 10; i++) {
		if (symbol[i] == ch)return i;
	}
	return -1;
}

//LR文法分析表
void Init() {
    for (int i = 0; i < 20; i++) {
        for (int j = 0; j < 20; j++) {
            st[i][j].str = "-1";
        }
    }
    state[0].push_back({ 'E',1 }); state[0].push_back({ '(',2 }); state[0].push_back({ 'i',3 });
    state[1].push_back({ '+',4 }); state[1].push_back({ '-',5 }); state[1].push_back({ '*',6 }); state[1].push_back({ '/',7 });
    state[2].push_back({ 'E',8 }); state[2].push_back({ '(',2 }); state[2].push_back({ 'i',3 });
    state[4].push_back({ 'E',9 }); state[4].push_back({ '(',2 }); state[4].push_back({ 'i',3 });
    state[5].push_back({ 'E',10 });state[5].push_back({ '(',2 }); state[5].push_back({ 'i',3 });
    state[6].push_back({ 'E',11 });state[6].push_back({ '(',2 }); state[6].push_back({ 'i',3 });
    state[7].push_back({ 'E',12 });state[7].push_back({ '(',2 }); state[7].push_back({ 'i',3 });
    state[8].push_back({ '+',4 }); state[8].push_back({ '-',5 }); state[8].push_back({ '*',6 });
    state[8].push_back({ '/',7 }); state[8].push_back({ ')',13 }); state[9].push_back({ '+',4 });
    state[9].push_back({ '-',5 }); state[9].push_back({ '*',6 }); state[9].push_back({ '/',7 });
    state[10].push_back({ '+',4 });state[10].push_back({ '-',5 });state[10].push_back({ '*',6 });
    state[10].push_back({ '/',7 });state[11].push_back({ '+',4 });state[11].push_back({ '-',5 });
    state[11].push_back({ '*',6 });state[11].push_back({ '/',7 });state[12].push_back({ '+',4 });
    state[12].push_back({ '-',5 });state[12].push_back({ '*',6 });state[12].push_back({ '/',7 });
    st[0][4].str = "s2";st[0][6].str = "s3";st[0][9].str = "s1";st[1][0].str = "s4";
    st[1][1].str = "s5";st[1][2].str = "s6";st[1][3].str = "s7";st[1][7].str = "acc";
    st[2][4].str = "s2";st[2][6].str = "s3";st[2][9].str = "s8";
    st[3][0].str = "r6";st[3][1].str = "r6";st[3][2].str = "r6";st[3][3].str = "r6";st[3][5].str = "r6";st[3][7].str = "r6";
    st[4][4].str = "s2";st[4][6].str = "s3";st[4][9].str = "s9";
    st[5][4].str = "s2";st[5][6].str = "s3";st[5][9].str = "s10";
	st[6][4].str = "s2"; st[6][6].str = "s3"; st[6][9].str = "s11";
	st[7][4].str = "s2"; st[7][6].str = "s3"; st[7][9].str = "s12";
	st[8][0].str = "s4"; st[8][1].str = "s5"; st[8][2].str = "s6"; st[8][3].str = "s7"; st[8][5].str = "s13";
	st[9][0].str = "r1"; st[9][1].str = "r1"; st[9][2].str = "r1"; st[9][3].str = "r1"; st[9][5].str = "r1"; st[9][7].str = "r1";
	st[10][0].str = "r2"; st[10][1].str = "r2"; st[10][2].str = "r2"; st[10][3].str = "r2"; st[10][5].str = "r2"; st[10][7].str = "r2";
	st[11][0].str = "r3"; st[11][1].str = "r3"; st[11][2].str = "r3"; st[11][3].str = "r3"; st[11][5].str = "r3"; st[11][7].str = "r3";
	st[12][0].str = "r4"; st[12][1].str = "r4"; st[12][2].str = "r4"; st[12][3].str = "r4"; st[12][5].str = "r4"; st[12][7].str = "r4";
	st[13][0].str = "r5"; st[13][1].str = "r5"; st[13][2].str = "r5"; st[13][3].str = "r5"; st[13][5].str = "r5"; st[13][7].str = "r5";
}


//对栈容器进行输出
string Output_vec(int i) {
	char buf[100];
	int count = 0;
	//输出状态栈
	if (i == 0) {
		string str;
		for (vector<int>::iterator it = status.begin(); it != status.end(); it++) {
			int c = *it;
			str += to_string(c);
		}
		return str;
	}
	else if (i == 1) {
		for (vector<char>::iterator it = sign.begin(); it != sign.end(); it++) {
			buf[count++] = *it;
		}
	}
	else {
		for (vector<char>::iterator it = inputStr.begin(); it != inputStr.end(); it++) {
			buf[count++] = *it;
		}
	}
	buf[count] = '\0';
	string str(buf);
	return str;
}

//总控,对输入的字符串进行分析
void LRanalyse() {
	int step = 1;
	sign.push_back('#');
	status.push_back(0);
	cout << setw(10) << "步骤" << setw(10) << "状态栈" << setw(10) << "符号栈" << setw(10) << "输入串" << setw(25) << "动作说明" << endl;
	int s = 0;
	int oldstatus;
	char ch = inputStr.front();
	int c = getChar(ch);
	if (c == -1) {
		cout << "error" << endl;
		return;
	}
	while (st[s][getChar(ch)].str != "acc") {
		string sstr = st[s][getChar(ch)].str;
		int s1 = 0;
		for (int i = 1; i < sstr.size(); i++) {
			s1 = s1 * 10 + (sstr[i] - '0');
		}
		s = s1;
		if (sstr == "-1") {
			cout << "error" << endl;
			return;
		}
		if (sstr.substr(0, 1) == "s") {
			cout << setw(10) << step << setw(10) << Output_vec(0) << setw(10) << Output_vec(1) << setw(10) << Output_vec(2) << setw(10) 
				<< "A" << "CTION[" << status.back() << "," << ch << "]=S" << s << "," << "状态" << s << "入栈" << endl;
			sign.push_back(ch);
			inputStr.erase(inputStr.begin());
			status.push_back(s);
		}
		else if (sstr.substr(0, 1) == "r") {
			string formu = formula[s];
			int strlen = formu.size();
			int popnum = strlen - 3;
			int i = 0;
			for (vector<int>::reverse_iterator it = status.rbegin(); it != status.rend(); it++) {
				i++;
				if (i == popnum + 1) {
					oldstatus = *it;
					break;
				}
			}
			int r = s;
			for (int i = 0; i < state[oldstatus].size(); i++) {
				if (state[oldstatus][i].first == 'E') {
					s = state[oldstatus][i].second;
				}
			}
			cout << setw(10) << step << setw(10) << Output_vec(0) << setw(10) << Output_vec(1) << setw(10) << Output_vec(2) << setw(10) 
				<< "r" << r << (string)":" + formula[r] + (string)"归约,GOTO{" << oldstatus << "," << 'E' << ")=" << s << "入栈" << endl;
			for (int i = 0; i < popnum; i++) {
				status.pop_back();
				sign.pop_back();
			}
			status.push_back(s);
			sign.push_back('E');
		}
		step++;
		s = status.back();
		ch = inputStr.front();
	}
	cout << setw(10) << step << setw(10) << Output_vec(0) << setw(10) << Output_vec(1) << setw(10) << Output_vec(2) << setw(10) 
		<< "A" << "cc:分析成功" << endl;
}

int main() {
	Init();
	string s;
	cout << "------------请输入字符串(+,-,*,/,E,i,(,),#)------------" << endl;
	cin >> s;
	for (int i = 0; i < s.size(); i++)inputStr.push_back(s[i]);
	if (inputStr.back() != '#')inputStr.push_back('#');
	LRanalyse();
}

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冬天的枫树

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值