一、实验目的
1.熟悉LL(1)语法分析的基本原理,语法分析的过程,以及语法分析中要注意的一些问题。
2. 复习高级语言及线性表、栈、图等典型数据结构,进一步加强用高级语言来解决实际问题的能力。
二、实验内容
编程实现下面的功能:
输入一个上下文无关文法,按照教材5.2节算法,求出各个非终结符能否推出ε,存储并显示结果。
1.计算能推出空的非终结符。
原理部分摘自清华大学出版社出版的《编译原理》一书
第一步:求能推出#的非终结符
结果如下图:
是否=>#
S
否
T
否
N
是
推导步骤:
(1)初值:“未定”
(2)扫描:
①先删除右部有终结符(只要有就删除)的产生式,若某符号的产生式全部被删除光了,则定义“否”(这里S直接可以定义否)
这个时候产生式剩下:
T->SN
N->,SN
N->#
②若某产生式右部为#,则该非终结符标“是”,并删除该终结符相关的所有产生式; (这里N可以定义为“是”,并N在左部的所有产生式)
这个时候产生式剩下:
T->SN
(3)扫描右部的每一个符号
①右部“是”对应的非终结符都要被删除(在经历(2)中的扫描产生的“是”的非终结符,这里是指N ; 这里的删除值得是删除单个字符,),若这使得某个某个产生式右部为空,则该产生式左部的符号,可以直接标“是”,然后删除该符号的相关产生式
例子:
经历扫描前还剩下 T->SN
之后删除N
T->S
(4)扫描右部的每一个符号
同上,右部如果对应为“否”的符号,则删除整个产生式(注意:区别上面的(3)上面是先删除单个字符,这里是直接删除整个产生式),若这使得产生式左部相关符号的所有的产生式都被删除,则标记“否”
S标记为“否”,则删除T->S,这时,关于T的所有产生式都被删除,这时T被标记“否”
得下图(也就是上文的图标):
是否=>#
S
否
T
否
N
是
#include<bits/stdc++.h>
using namespace std;
/*
未知-1
非空1
空0
*/
/*
在1
不在0
*/
int zjf(char c)
{
if(c>='A'&&c<='Z')
{
return 0;
}
else if(c=='@')
{
return 0;
}
else if(c==','||c=='.'||c==':'||c=='?')
{
return 0;
}
else
{
return 1;
}
}
int zj(string s)
{
for(int i=0; i<s.size(); i++)
{
if(zjf(s[i]))
{
return 1;
}
}
return 0;
}
string delchar(char c,string s)
{
string str= "";
for(int i=0;i<s.size();i++)
{
if(s[i]!=c)
str+=s[i];
}
return str;
}
int main()
{
int n;
map<string,int>ma;
set<char> se;
cout<<"输入文法产生式的个数(<=50):";
cin>>n;
string s[51];
cout<<"输入各产生式(每行一条,空用'@'表示):"<<endl;
for(int i=0; i<n; i++)
{
cout<<"("<<i+1<<"):";
cin>>s[i];
ma[s[i]]=1;
se.insert(s[i][0]);
}
set<char>::iterator it;
int k=0;
char a[51];
for(it=se.begin(); it!=se.end(); it++) //使用迭代器进行遍历
{
a[k++]=*it;
}
map<char,int> m;
for(int i=0; i<k; i++)
{
m[a[i]]=-1;
// cout<<m[a[i]]<<" ";
}
//(1)
for(int i=0; i<k; i++)
{
int cnt=0,cnt1=0;
for(int j=0; j<n; j++)
{
if(zj(s[j].substr(3)))
{
ma[s[j]]=0;
}
if(zj(s[j].substr(3))&&s[j][0]==a[i])
{
cnt++;
}
if(s[j][0]==a[i])
{
cnt1++;
}
}
if(cnt1==cnt)
{
m[a[i]]=1;
}
}
//(2)
for(int i=0; i<n; i++)
{
if(ma[s[i]]==1)
{
if(s[i].substr(3)=="@")
{
m[s[i][0]]=0;
}
}
}
for(int i=0; i<n; i++)
{
if(m[s[i][0]]==0)
{
ma[s[i]]=0;
}
}
// (3)
while(1)
{
int flag=0;
for(int i=0; i<n; i++)
{
if(ma[s[i]]==1)
{
char de[51];
int kk=0;
for(int j=3; j<s[i].size(); j++)
{
if(m[s[i][j]]==0)
{
de[kk++]=s[i][j];
}
}
for(int w=0;w<kk;w++)
{
s[i]=s[i].substr(0,3)+delchar(de[w],s[i].substr(3));
ma[s[i]]=1;
}
// cout<<s[i]<<endl;
if(s[i].size()==3)
{
m[s[i][0]]=0;
ma[s[i]]=0;
flag=1;
}
}
}
for(int i=0; i<n; i++)
{
for(int j=3; j<s[i].size(); j++)
{
if(ma[s[i]]==1)
{
ma[s[i]]=0;
int ff=0;
for(int k=0; k<n; k++)
{
if(ma[s[k]]==1)
{
if(s[i][0]==s[k][0])
{
ff=1;
}
}
}
if(ff==0)
{
m[s[i][0]]=1;
flag=1;
}
}
}
}
if(flag==0)
break;
}
for(int i=0; i<k; i++)
{
cout<<a[i]<<"-> "<<m[a[i]]<<endl;
}
}
/*
S->a
S->^
S->(T)
T->SN
N->,SN
N->@
*/