一、实验目的:
掌握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();
}