好久不更新了,U盘格式化了,之前的代码都丢了,诶,好久了才想起来有个CSDN还没更新过,以后会坚持更新的,这次先挂上LLI文法吧,之后补上之前总结的算法,之后的内容大都是跟着课堂的,然后再根据自己跟大佬自学的东西,进行更新吧
——————————————————————————————————————————
这是实验要求:
编写程序,实现下列功能:
——————————————————————————————————————————
1、判断各非汇总结符是否可以推出空
(1)将各非终结符出示状态置为“未知”
(2)按顺序扫描各产生式右部。分为下面几种情况:
a、若遇到符号“ε”,检查左部非终结符状态,若不是“空”,将其置为“空”,继续扫描下一产生式;
b、若遇到终结符,检查左部非终结符状态,若为“未知”,将其置为“非空”,继续扫描下一产生式;
c、若遇到非终结符,检查该非终结符状态,若为“未知”,则跳过当前产生式,扫描下一产生式;若为“非空”,检查左部非终结符状态,若为“未知”,将其置为“非空”,继续扫描下一产生式;
若为“空”,继续扫描本产生式的下一符号;
d、若遇到“\0”,检查左部非终结符状态,若不是“空”,将其置为“空”,继续扫描下一产生式;
e、若上述a,b,c,d过程引起了非终结符状态的改变,则跳到(2)处继续循环,否则跳出循环,判断结束。
2、求非终结符的first集
扫描以要求first集的非终结符为左部的各产生式的右部,分为下面几种情况:
A、若遇到终结符,将该终结符加入左部非终结符的first集,继续扫描下一产生式;
B、若遇到符号“ε”,将“ε”加入左部非终结符的first集,继续扫描下一产生式;
C、若遇到非终结符,将该非终结符的 first集— {ε} 加入左部非终结符的first集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;若不为空,则继续扫描下一产生式;
D、若遇到“\0”,将“ε”加入左部非终结符的first集,继续扫描下一产生式;
3、求某一非终结符的FOLLOW集
(1)在产生式右部找到该非终结符,扫面它后面的符号,分为下面几种情况:
A、若是终结符,则将该终结符加入该非终结符的folow集;
B、若是非终结符,将该非终结符的 first集— {ε} 加入该非终结符的folow集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;
C、若是“\0”,则将该产生式的左部非终结符的follow集加入它的follow集。
(2)在产生式的右部继续查找该非终结符,若找到,转(1)步。
4、求某产生式的select集
扫描产生式的右部,分为下面几种情况:
(1) 若是终结符,则将该终结符加入该产生式的select集;
(2) 若是“ε”,将左部非终结符的follow集加入该产生式的select集;
(3) 若是非终结符,将该非终结符的 first集— {ε} 加入该产生式的select集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;
(4) 若是“\0”,则将该产生式的左部非终结符的follow集加入该产生式的select集。
———————————————————————————————————————————
程序是用C++实现的,2维数组存储文法,这种简单的操作就不说了,first,follow,select,这些集合,都是要求不重复的,在程序实现的时候也是使用各种大循环来实现,所以,选择用set容器来存储这些集合,set有排序和去除重复的功能,具体的迭代器取值啥的,百度结合set的用法即可。
———————————————————————————————————————————
之后就是输入字符串,并进行分析,这时候我们先构造预测分析表,下面的程序按7即可,之后利用栈的思想,逐一分析,这里我用的是string字符串的用法,没用栈,栈取值比较麻烦,所以用的string,上代码吧
我的代码如果想执行8,必须先执行7!!!!!!!!
如果想再输入文法或者字符串的时候,请在运行一下,我懒得赋初值了。。。。。。
专业有大佬写了300,400行,用的map,map我也用不好,就数组吧,500多行。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef struct
{
char p[50][10];
int length;
}G;
typedef struct
{
char p1[20];
int length;
}zhong1;
typedef struct
{
char p2[20];
int empty[20];
int length;
}fei1;
sets[50];
sets1[50];
sets2[50];
G g;
char biao[100];
zhong1 zhong;
fei1 fei;
int v[100];
void init();
void chushi();
void chuli();
void panduan();
void input();
char meau();
void first();
void follow();
void select();
void biaoo();
void chuanchuan();
int dian(char b);
void panduan_select();void chuanchuan();
string bb[100][100];
char meau()
{
char ch;
system("cls");
printf("\n\n\n\n");
printf("\t\tLL(1)语法分析演示程序\n");
printf("\n\t 1.输入LL(1)文法\n");
printf("\n\t 2.显示输入的LL(1)文法\n");
printf("\n\t 3.判定非终结符是否为空\n");
printf("\n\t 4.输出非终结符的First集\n");
printf("\n\t 5.输出非终结符的Follow集\n");
printf("\n\t 6.输出产生式的Sellect集\n\t");
printf("\n\t 7.产生预测分析表\n\t");
printf("\n\t 8.输入字符串并分析字符串\n\t");
printf("\n\t 9.退出\n\t");
printf("\n\t请输入你想要做的操作:");
fflush(stdin);
scanf("%c",&ch);
return ch;
}
int feii(char c)
{
int i;
for(i=0;i>g.length;
cout<<"请输入产生式,空用@表示"<>g.p[i];
}
chuli();first();follow();select();
}
void chushi()
{
g.length=8;
strcpy(g.p[0],"E->TX");
strcpy(g.p[1],"X->+TX");
strcpy(g.p[2],"X->@");
strcpy(g.p[3],"T->FY");
strcpy(g.p[4],"Y->*FY");
strcpy(g.p[5],"Y->@");
strcpy(g.p[6],"F->i");
strcpy(g.p[7],"F->(E)");
chuli();first();follow();select();
}
void chuli()
{
int i,j,k;
for(i=0;i='A'&&g.p[i][j]<='Z')
{
for(k=0;k')
{
for(k=0;k'Z'||g.p[i][j]<'A')&&g.p[i][j]!='\0')
{
if(fei.empty[feii(g.p[i][0])]==-1)
{
fei.empty[feii(g.p[i][0])]=0;
s=1;
}
break;
}
else if(g.p[i][j]<='Z'&&g.p[i][j]>='A')
{
if(fei.empty[feii(g.p[i][j])]==-1)break;
else if(fei.empty[feii(g.p[i][j])]==0)
{
if(fei.empty[feii(g.p[i][0])]==-1)
{
fei.empty[feii(g.p[i][0])]=0;
s=1;
}
break;
}
}
}
if(g.p[i][j]=='\0')
{
if(fei.empty[feii(g.p[i][0])]!=1)
{
fei.empty[feii(g.p[i][0])]=1;
s=1;
}
}
}
if(s==0)break;
}
}
int dian(char b)
{
int n;
for(int k=0;k'Z'||g.p[i][j]<'A')&&g.p[i][j]!='\0')
{
s[dian(g.p[i][0])].insert(g.p[i][j]);break;
}
else if(g.p[i][j]<='Z'&&g.p[i][j]>='A')
{
m=dian(g.p[i][0]);n=dian(g.p[i][j]);
set::iterator it1;
for(it1=s[n].begin();it1!=s[n].end();it1++)
{
if(*it1!='@')
s[m].insert(*it1);
}
if(fei.empty[n]==0)break;
if(fei.empty[n]==1)continue;
}
if(g.p[i][j]=='\0')
{
s[dian(g.p[i][0])].insert('@');break;
}
}
}
}
}
void follow()
{
s1[0].insert('#');
int i,j,m,n,n1,d;
for(int z=0;z='A')
{
for(d=j+1;d'Z'||g.p[i][d]<'A')&&g.p[i][d]!='\0')
{
s1[dian(g.p[i][j])].insert(g.p[i][d]);break;
}
else if(g.p[i][d]<='Z'&&g.p[i][d]>='A')
{
m=dian(g.p[i][j]);n=dian(g.p[i][d]);
set::iterator it2;
for(it2=s[n].begin();it2!=s[n].end();it2++)
{
if(*it2!='@')
s1[m].insert(*it2);
}
if(fei.empty[n]==1)break;
}
else if(g.p[i][d]=='\0')
{
m=dian(g.p[i][j]);n=dian(g.p[i][0]);
set::iterator it3;
for(it3=s1[n].begin();it3!=s1[n].end();it3++)
{
s1[m].insert(*it3);
}
}
}
}
}
}
}
}
void select()
{
int i,j,w,n;
for(i=0;i'Z'||g.p[i][j]<'A')&&g.p[i][j]!='\0'&&g.p[i][j]!='@')
{
s2[i].insert(g.p[i][j]);
break;
}
else if(g.p[i][j]=='@'||g.p[i][j]=='\0')
{
n=dian(g.p[i][0]);
set::iterator it5;
for(it5=s1[n].begin();it5!=s1[n].end();it5++)
s2[i].insert(*it5);
}
else if(g.p[i][j]<='Z'&&g.p[i][j]>='A')
{
n=dian(g.p[i][j]);
set::iterator it6;
for(it6=s[n].begin();it6!=s[n].end();it6++)
{
if(*it6!='@')
s2[i].insert(*it6);
}break;
}
}
}
}
void panduan_select()
{
int f=0,i,j;
for(i=0;i ANS;
set_intersection(s2[i].begin(),s2[i].end(),s2[j].begin(),s2[j].end(),inserter(ANS,ANS.begin()));
if(!ANS.empty()){
f=1;
}
}
}
}
if(f==1)cout<<"这不是LL(1)文法!!!\n\n";
else
cout<<"这是LL(1)文法\n\n";
}
void biaoo()
{
for(int i=0;i::iterator it6;
for(int i=0;i>n1;
int k1=1,i=0,f=0,ff=0;
if(n1[n1.size()-1]!='#'){
cout<<"请以#结尾"<0;i--)
zuizuo1+=n[i];
zuizuo3+=zuizuo2;
zuizuo3+=zuizuo1;
}
if(n1[0]=='#')
{
int k4=zhongg('@');
if(n[n.size()-1]=='#')
{
cout<<"接受\t"<";continue;
}
}
}
else if(n[n.size()-1]==n1[0])
{
zuizuo2+=n1[0];
cout<";continue;
}
else
{
cout<';j--)n+=n2[j];zuizuo3+="->";continue;
}
}
else
{cout<<"分析出错!!!"<='1'&&ch<='9')
{
if(ch=='1')
{ system("cls");
cout<<"1是输入新文法,2是用初始定义的文法"<>cc;
if(cc==1){
input();panduan();
}
else
{chushi();
panduan();
}
}
else if(ch=='2')
{
system("cls");
for(int k=0;k::iterator it;
for(int i=0;i::iterator it4;
for(int i=0;i::iterator it7;
for(int i=0;i
——————————————
啊哈,有啥不懂的,评论问。
恰饭去了。。