前言
编译原理课程实验的实验课内容—构造自底向上LR(0)的语法分析程序。通过本次实验,可以熟练掌握对于LR(0)分析表的构造方法。
1.1实验目的
(1)掌握 LR(0)分析表的构造方法。
(2)掌握设计、编制和调试典型的语法分析程序,进一步掌握常用的语法分析方法。
(3)理解语法分析在编译程序中的作用。
1.2 实验任务
编写一个程序对输入的源代码进行语法分析,并打印分析结果。
自己编写一个基于 LR(0)方法的语法分析程序。语言不限,文法不限。 此时可根据自己的实际情况,选择以下一项实现分析算法中分析表的构造:
(1)直接输入根据已知文法构造的 LR(0)分析表;
(2)输入已知文法的项目集规范族和转换函数,由程序自动生成 LR(0)分析表;
(3)输入已知文法,由程序自动生成 LR(0)分析表。
1.3 实验内容
1.3.1 输入格式:
你的程序输入是一个包含待分析词法单元序列的文本 文件,程序需要能够接收一个输入文件名作为参数,以获得相应的输出结果。
1.3.2 输出格式:
你的程序需要输出语法分析过程(包括 LR(0)分析表和分析过程表,并能够保 存 LR(0)分析表)和相应的分析结果(即此串是否为 LR(0)文法的句子)
1.3.3 样例
对输入串的分析:
1.4 程序
1.4.1 程序流程图
1.4.2 算法描述
本次LR(0)分析表采用的是课本P136页表6.3的LR(0)分析表。程序的整体设计思路上,首先分为几个主要的函数来实现查找LR(0)分析表,对确定的输入串进行LR(0)分析过程。 同时,还要有出错判断的提示,这个我计划放在对输入串的分析过程中一并实现,另一个是保存当前的LR(0)分析表,这个功能放在输出LR(0)分析表的函数中实现。
1.4.3 程序源码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<string>
#include<sstream>
#include<fstream>
using namespace std;
char LR0[50][50][100] = { {"S2" ,"S3" ,"null", "null" ,"null" ,"1" ,"null" ,"null"},
{"null" ,"null" ,"null", "null" ,"acc " ,"null" ,"null" ,"null"},
{"null" ,"null" ,"S4" , "S10" ,"null" ,"null" ,"6" ,"null"},
{"null" ,"null" ,"S5" , "S11" ,"null" ,"null" ,"null" ,"7" },
{"null" ,"null" ,"S4" , "S10" ,"null" ,"null" ,"8" ,"null"},
{"null" ,"null" ,"S5" , "S11" ,"null" ,"null" ,"null" ,"9" },
{"r1" ,"r1" ,"r1" , "r1" ,"r1" ,"null" ,"null" ,"null"},
{"r2" ,"r2" ,"r2" , "r2" ,"r2" ,"null" ,"null" ,"null"},
{"r3" ,"r3" ,"r3" , "r3" ,"r3" ,"null" ,"null" ,"null"},
{"r5" ,"r5" ,"r5" , "r5" ,"r5" ,"null" ,"null" ,"null"},
{"r4" ,"r4" ,"r4" , "r4" ,"r4" ,"null" ,"null" ,"null"},
{"r6" ,"r6" ,"r6" , "r6" ,"r6" ,"null" ,"null" ,"null"},
};
char L[200] = "abcd#EAB";
int del[10] = { 0,2,2,2,1,2,1 };
char head[20] = { 'S','E','E','A','A','B','B' };
stack<int>con;
stack<char>cmp;
char cod[300] = "0";
int cindex = 0;
char sti[300] = "#";
int sindex = 0;
int findL(char b)
{
for (int i = 0; i <= 7; i++)
{
if (b == L[i])
{
return i;
}
}
return -1;
}
void error(int x, int y)
{
printf("第%d行%c列为空!", x, L[y]);
}
int calculate(int l, char s[])
{
int num = 0;
for (int i = 1; i < l; i++)
{
num = num * 10 + (s[i] - '0');
}
return num;
}
void analyze(string str, int len)
{
int cnt = 1;
printf("步骤 状态栈 符号栈 输入串 ACTION GOTO\n");
int LR = 0;
while (LR <= len)
{
printf("(%d) %-10s%-10s", cnt, cod, sti);
cnt++;
for (int i = LR; i < len; i++)
{
cout << str[i];
}
for (int i = len - LR; i < 10; i++)cout<<" ";
int x = con.top();
int y = findL(str[LR]);
if (strcmp(LR0[x][y], "null") != 0)
{
int l = strlen(LR0[x][y]);
if (LR0[x][y][0] == 'a')
{
printf("acc \n");
return;
}
else if (LR0[x][y][0] == 'S')
{
printf("%-10s \n", LR0[x][y]);
int t = calculate(l, LR0[x][y]);
con.push(t);
sindex++;
sti[sindex] = str[LR];
cmp.push(str[LR]);
if (t < 10)
{
cindex++;
cod[cindex] = LR0[x][y][1];
}
else
{
int k = 1;
cindex++;
cod[cindex] = '(';
while (k < l)
{
cindex++;
cod[cindex] = LR0[x][y][k];
k++;
}
cindex++;
cod[cindex] = ')';
}
LR++;
}
else if (LR0[x][y][0] == 'r')
{
printf("%-10s", LR0[x][y]);
int t = calculate(l, LR0[x][y]);
int g = del[t];
while (g--)
{
con.pop();
cmp.pop();
sti[sindex] = '\0';
sindex--;
}
g = del[t];
while (g > 0)
{
if (cod[cindex] == ')')
{
cod[cindex] = '\0';
cindex--;
for (;;)
{
if (cod[cindex] == '(')
{
cod[cindex] = '\0';
cindex--;
break;
}
else
{
cod[cindex] = '\0';
cindex--;
}
}
g--;
}
else
{
cod[cindex] = '\0';
cindex--;
g--;
}
}
cmp.push(head[t]);
sindex++;
sti[sindex] = head[t];
x = con.top();
y = findL(cmp.top());
t = LR0[x][y][0] - '0';
con.push(t);
cindex++;
cod[cindex] = LR0[x][y][0];
printf("%-10d\n", t);
}
}
else
{
error(x, y);
cout << endl;
cout << "程序分析结束,遇到语法错误!" << endl;
exit(0);
}
}
}
void chart()
{
string file = ("文法.txt");
ifstream input(file);
string grammar;
cout << "文法如下:" << endl;
while (!input.eof())
{
getline(input, grammar);
cout << grammar << endl;
}
input.close();
cout << endl;
file = ("LR(0).txt");
ofstream output(file, ios::trunc);
cout << "LR(0)分析表:" << endl;
output << "LR(0)分析表:" << endl;
cout << "---------------------------------------------------------------------" << endl;
printf("-\ta\tb\tc\td\t#\tE\tA\tB\n");
output << "-\ta\tb\tc\td\t#\tE\tA\tB\n";
for (int i = 0; i <= 11; i++)
{
cout << "---------------------------------------------------------------------" << endl;
printf("%d", i);
output << i;
for (int j = 0; j <= 8; j++)
{
printf("\t%s", LR0[i][j]);
output << "\t" << LR0[i][j];
}
cout << endl;
output << endl;
}
cout <<"---------------------------------------------------------------------"<< endl;
output.close();
}
int main()
{
chart();
con.push(0);
cmp.push('#');
string str;
cout << "读取的字符串为:" << endl;
string file = ("测试样例1.txt");
ifstream input(file);
input >> str;
cout << str << endl;
input.close();
int len = str.length();
analyze(str, len);
return 0;
}
(寒假打算发一下的,结果后来一直拖到现在,忽然想起,还是赶快发一下)
参考博客:https://blog.csdn.net/wys5wys/article/details/85128812
|