Simple语言的定义(LL1文法)
编译原理课程设计_LL(1)文法的判定

课程设计报告课程:编译原理课程设计学号:姓名:班级:教师:时间:2015.05.20-2015.07.02计算机学院图4 输入LL(1)文法并测试图7 测试非LL(1)文法附录:程序代码#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/ char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/ int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0) return(0);for(i=0;;i++){if(p[i]==c) return(1); /*若在,返回1*/if(i==strlen(p)) return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1) c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/int j,k,m=0,n=3;char ch,temp[20];ch=c(); /*得到一个不是非终结符的符号*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果'|'后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0') temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);/*从temp所指向的内存单元顺序取m个字节复制到右部*/right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果'|'后的首符号和左部不同*/left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|') temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/******************************************* 分解不含有左递归的产生式********************************************/ void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|') temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/******************************************* 读入一个文法********************************************/char grammer(char *t,char *n,char *left,char right[50][50]){char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("请输入文法的非终结符号串:");scanf("%s",vn);//getchar(); /*取出缓冲区剩余的回车键,不要也可*/ i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("\n请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("\n请输入文法的开始符号:");scanf("%c",&s);//getchar();printf("\n请输入文法产生式的条数:");scanf("%d",&i);//getchar();for(j=1;j<=i;j++){printf("\n请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){printf("\nInput error!\n");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0]) recur(p[k]);else non_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){/*d是目标串s是源串,type=1,源串中的'^'并入目串;type=2,源串中的'^'不并入目串*/ int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='^');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j]) break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';break;}}}}}/*******************************************求所有能直接推出‘^’的符号********************************************/void emp(char c){ /*即求所有由'^'推出的符号*/char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}/*******************************************求某一符号能否推出‘^’********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1) return(1);for(i=0;;i++){if(i==count) return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1) return(1);else if(j==1&&in(right[i][0],termin)==1) return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1) mark=1;if(mark==1) continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count) continue;else if(result==1&&i<count) return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/printf("\nLeft error!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为'^',报错*/printf("\nRight error!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST集********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/char c,ch='^',temp[20];int j,k,m;c=v[i];emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c) continue;for(k=0;;k++)if(v[k]==right[j][0]) break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1]) break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}else break;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST集********************************************/ void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/{if(p[0]=='^'){if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0]) break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/{for(j=0;;j++)if(v[j]==p[0]) break;if(i>=0) merge(first[i],first1[j],2);else merge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1]) break;if(i>=0) merge(first[i],first1[m],2);else merge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0) merge(first[i],temp,1);else merge(TEMP,temp,1);}else if(_emp(p[k])==0) break;}}}/******************************************* 求各产生式左部的FOLLOW集********************************************/ void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c) break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j]) break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++) temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/ first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++) first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++) printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n_emp:");for(j=0;j<=strlen(v)-1;j++) printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++) FIRST(i,right[i]); /*求FIRST集*/for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW集*/ if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++) printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++) printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i]) break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/ length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i])) return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++) M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i]) break; /*m为产生式左部非终结符的序号*/ for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j]) break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/void syntax(){int i,j,k,m,n,p,q;char ch,S[50],str[50];printf("\n请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("\n该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("\n该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1]) break;for(k=0;;k++){if(termin[k]==ch) break;if(k==strlen(termin)){printf("\n词法错误!");return;}}if(M[i][k]==-1){printf("\n语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^') S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--) S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("S:%s str:",S);for(p=j;p<=strlen(str)-1;p++) printf("%c",str[p]);printf(" \n");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y') menu();}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++) printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++) printf("%c ",left[i]);if(validity==1) validity=judge();printf("\nvalidity=%d",validity);if(validity==1){ll=ll1();printf("\nll=%d",ll);if(ll==0) printf("\n该文法不是一个LL(1)文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);menu();}}}。
ll(1)文法分析课程设计

ll(1)文法分析课程设计一、课程目标知识目标:1. 学生能够掌握语文课本中基础文法知识,如句子成分、句型结构、标点符号的正确使用。
2. 学生能够理解和分析不同文学作品的文法特点,如散文、小说、诗歌等。
3. 学生能够通过具体实例,识别并改正常见的文法错误。
技能目标:1. 学生能够运用所学文法知识,进行句子仿写和创作,提高语言表达能力和写作技巧。
2. 学生能够通过分析文学作品中的文法技巧,提升阅读理解能力和文学鉴赏水平。
情感态度价值观目标:1. 学生能够增强对语文学习的兴趣,树立正确的语文学习观念。
2. 学生能够尊重和欣赏他人的语言表达,培养良好的沟通和合作意识。
3. 学生能够认识到文法知识在日常生活和未来学习中的重要性,提高自我修养和综合素质。
课程性质:本课程为语文文法分析课程,旨在帮助学生掌握语文基础知识,提高阅读和写作能力。
学生特点:学生处于中学阶段,具有一定的语文基础和阅读量,但对文法知识掌握不够系统,需要通过本课程进行巩固和提升。
教学要求:教师应结合课本内容,通过实例讲解、互动讨论、写作练习等多种教学手段,使学生能够扎实掌握文法知识,并应用于实际阅读和写作中。
同时,注重培养学生的情感态度价值观,提高学生的综合素养。
二、教学内容本课程教学内容主要包括以下几部分:1. 文法基础知识回顾:复习句子成分、句型结构、标点符号的正确使用等,参考课本第二章内容。
2. 不同文学作品的文法特点分析:- 散文:分析散文的句式、修辞手法等,以课本第三章为例。
- 小说:学习小说中的叙述方法、人物语言特点等,参考课本第四章。
- 诗歌:了解诗歌的韵律、象征手法等,结合课本第五章内容。
3. 常见文法错误识别与修改:针对学生在写作中常犯的文法错误,进行讲解和练习,纠正错误,提高写作水平。
4. 文法知识应用:- 句子仿写:根据所学文法知识,进行句子仿写,锻炼语言表达能力,参考课本第六章。
- 写作练习:结合课文内容,进行作文练习,提高写作技巧,参考课本第七章。
编译原理--LL(1)文法 算法代码

/* LL(1)文法<古城童话>$为空字; 输入0,表示结束测试案例:案例1.(编译原理P76的LL(1)文法,E'改成了A,T'改成了B);E->TA A->+TA|$ T->FB B->*FB|$ F->(E)|i 0案例2. (First和Follow有非空交集)S->Ab A->a|B|$ B->b|$ 0*/#include <iostream>#include <string>using namespace std;const int MAX=100;int FirstNum=0,FollowNum=0; // First集合Follow集的数目string SaveStr[MAX]; //预存输入的字符串string TerStr="#"; //保存终结字符串int FlagError1=0; //左递归错误标志struct Assemble{int FlagLast,FlagFirst; //首尾标志int Position ; //字符串的位置char Data;Assemble *Next;};Assemble *First[MAX]; //定义Fist集Assemble *Follow[MAX]; //定义Follow集int IsNonterminal(char Cur) //判断是否为非终结符{if(Cur<='Z'&&Cur>='A')return 1;return 0;}int IsTerminal(char Cur) //判断是否为终结符{if(IsNonterminal(Cur)||Cur=='|')return 0;return 1 ;}int Exist(Assemble* L,char Cur,int Flag) //L的集合里面是否有Cur字符{ //Flag为1表示First,为0表示Followif(!L) return 0;Assemble *P;for(P=L->Next;P;P=P->Next)if(P->Data==Cur)return Flag ? P->Position:1 ;return 0;}int IsEmptyStr(char Cur) //字符串里面是否有${for(int i=0;i<FirstNum;i++)if(SaveStr[i][0]==Cur){ if(SaveStr[i].find('$')==-1)return 0;return 1;}}void HideSame(Assemble* &L) //消除相同的字符{Assemble *P,*Pa;for(P=L->Next;P->Next;P=P->Next)for(Pa=P->Next;Pa;Pa=Pa->Next)if(P->Data==Pa->Data) Pa->Data=3;}Assemble* FindAddFirst(char Cur) //查找要添加的First集{for(int i=FirstNum-1;i>=0;i--)if(First[i]->Data==Cur) return First[i];return NULL;}Assemble* FindAddFollow(char Cur) //查找要添加的Follow集{for(int i=0;i<FollowNum;i++)if(Follow[i]->Data==Cur) return Follow[i];return NULL;}void CreatFirst(Assemble* &L,string Str) //创建Firs集{Assemble *P=L,*Pa;int FlagLeft=0,Pos=3,j,i;L->FlagLast=0;for(i=3;Str[i];i++){int FlagGo=1,FlagLa=1;char Ch=L->Data;if(Ch==Str[3]||Str[i-1]=='|'&&Str[i]==Ch) FlagError1=1; //含有左递归while(i<Str.length()&&Str[i]!='|'){if(IsNonterminal(Str[i]))FlagGo=(IsEmptyStr(Str[i])? 1:0);Pa=new Assemble;Pa->Data=Str[i];Pa->Position=Pos;P->Next=Pa;P=Pa;if(!FlagGo||IsTerminal(Str[i])){ FlagLa=0; break; }i++;}if(!FlagLa)while(Str[i]&&Str[i]!='|')i++;else { L->FlagLast=1; }Pos=i+1;}P->Next=NULL;}void CreatFollow(string Str) //创建Follow集{int i,j,Num;for(i=3;Str[i];i++){Num=-1;if(IsNonterminal(Str[i])){ for(j=0;j<FollowNum;j++)if(Follow[j]->Data==Str[i]){ Num=j; break; }if(Num<0){Follow[FollowNum]= new Assemble;Follow[FollowNum]->Data=Str[i];Follow[FollowNum]->Next=NULL;Num=FollowNum++;}int FlagGo=0,FlagLa=0;Assemble *Pa,*Pb,*P=Follow[Num];for(j=i+1;Str[j]&&Str[j]!='|';j++){Pa=new Assemble;Pa->FlagLast=0;for(;P->Next;P=P->Next);FlagGo=Exist(FindAddFirst(Str[j]),'$',1)? 1:0;Pa->Data=Str[j];P->Next=Pa;Pa->Next=NULL;if(!FlagGo){ FlagLa=1; break; } //是否继续添加}if(!FlagLa) //非终结符位于末尾{for(;P->Next;P=P->Next);Pb=new Assemble;Pb->FlagLast=1;Pb->Data=Str[0];Pb->Next=P->Next;P->Next=Pb;}}}}void InitFollow(int Num) //初始化Follow集{for(int i=0;i<Num;i++){if(!i){Follow[FollowNum]=new Assemble;Follow[FollowNum]->Data=SaveStr[0][0];Follow[FollowNum]->Next=new Assemble;Follow[FollowNum]->Next->Data='#';Follow[FollowNum++]->Next->Next=NULL;}CreatFollow(SaveStr[i]);}}//增添Follow集,Num=1,增添First集,Num=0,增添Follow集void AddFollow(Assemble* &L, Assemble* Head,int Num){Assemble *Pa,*Pb,*Pc;for(Pc=Head->Next;Pc;Pc=Pc->Next){ for(Pa=L->Next;Pa;Pa=Pa->Next)if(Pa->Data==Pc->Data)break;if(!Pa){if(Pc->Data=='$'&&Num) continue;Pb=new Assemble;Pb->Data=Pc->Data;Pb->Next=L->Next;L->Next=Pb;}}}void GetFollow(Assemble* &L) //得到Follow集{Assemble *P,*Head;for(P=L->Next;P;P=P->Next)if(IsNonterminal(P->Data)){if(P->FlagLast) //位于末尾,增添Follow集{Head=FindAddFollow(P->Data);AddFollow(L,Head,0);}else //不位于末尾,增添First集{Head=FindAddFirst(P->Data);AddFollow(L,Head,1);}}}int GetFirst(Assemble* &L) //得到First集{Assemble *P,*Pa,*Pb,*Pc,*Head;for(P=L->Next;P;P=P->Next)if(IsNonterminal(P->Data)){Head=FindAddFirst(P->Data);if(!Head)return 0;for(Pc=Head->Next;Pc;Pc=Pc->Next)if(Pc->Data=='$'&&!L->FlagLast)continue;Pb=new Assemble;Pb->Data=Pc->Data;Pb->Position=P->Position;Pb->Next=L->Next;L->Next=Pb;}}}void KeepTerStr(string Str) //保存终结符{for(int i=3;Str[i];i++)if(IsTerminal(Str[i])&&Str[i]!='$'){if(TerStr.find(Str[i])==-1)TerStr+=Str[i];}}void ShowLL1(Assemble *L,int num)//输出LL(1)文法{Assemble *P=L,*Head;int i,npos;string Str=SaveStr[num];cout<<First[num]->Data<<"\t";for(i=0;TerStr[i];i++){if(npos=Exist(L,TerStr[i],1)){cout<<First[num]->Data<<"->";if(npos==1)npos=3;while(Str[npos]!='|'&&npos<Str.length()){cout<<Str[npos];npos++;}}else if(Exist(L,'$',0)){Head=FindAddFollow(First[num]->Data);if(Exist(Head,TerStr[i],0))cout<<First[num]->Data<<"->"<<"$";cout<<"____";}else cout<<"____";cout<<"\t ";}cout<<"\n\n";}int IsError2()//测试是否有左因子{string AddStr,Str;for(int i=0;i<FirstNum;i++){AddStr="";Str=SaveStr[i];for(int j=0;Str[j];j++)if(j==3||Str[j-1]=='|'){if(AddStr.find(Str[j])!=-1) return 1;AddStr+=Str[j];}}return 0;}Assemble* IsError3(char &Ch) //测试First和Follow是否有非交集{Assemble *P,*Pa,*Head;for(int i=0;i<FirstNum;i++){for(P=First[i]->Next;P;P=P->Next){Head=FindAddFollow(First[i]->Data);if(P->Data!='$'&&IsTerminal(P->Data)&&P->Data!=3)for(Pa=Head->Next;Pa;Pa=Pa->Next)if(Pa->Data==P->Data){ Ch=First[i]->Data; return P; }}}return NULL;}int ShowForm() //显示LL(1)文法的终结符{Assemble *P;char Cur;if(FlagError1){ cout<<"\n文法中含有左递归...!\n"; return 1; }if(IsError2()){ cout<<"\n文法中含有左因子...!\n"; return 1; }if(P=IsError3(Cur)){ printf("\n文法中First(%c)和Follow(%c)有非空交集%c...!\n",Cur,Cur,P->Data);return 1;}cout<<"\nLL(1)分析表:\n\n";for(int i=0;TerStr[i];i++)cout<<"\t "<<TerStr[i];cout<<endl;for(int i=0;i<FirstNum;i++)ShowLL1(First[i],i);}void GetFistrFollow(int Num){int i,j;FirstNum=Num;for(i=0;i<Num;i++){First[i]=new Assemble;First[i]->Data=SaveStr[i][0];CreatFirst(First[i],SaveStr[i]); //创建First集}for(j=0,i=FirstNum-1;i>=0;i--,j++) //得到First集{GetFirst(First[i]);GetFirst(First[j]);}InitFollow(Num); //初始化Follow集for(i=0;i<FollowNum;i++)GetFollow(Follow[i]); //得到Follow集}int main(){int i,j,Num=0;cout<<"请输入文法产生式(以输入0结束):\n";while(cin>>SaveStr[Num]&&SaveStr[Num][0]!='0') {KeepTerStr(SaveStr[Num]);Num++;}GetFistrFollow(Num); //获得First集合Follw集ShowForm(); //输出LL(1)文法表system("pause");}。
ll1 slr1 lrk文法

ll1 slr1 lrk文法
LR(1)文法范围最大,而LR(0)文法范围最小。
同时也说明了四种文法分析过程的强弱,即LR(1)文法分析最强,而LR(0)文法分析最弱。
那为什么没有LL(1)文法呢?因为它和上面的四种文法是不同的。
LL(1)分析法是自上而下的分析法。
LR(0),LR(1),SLR(1),LALR(1)是自
下而上的分析法。
自上而下:从开始符号出发,根据产生式规则推导给定的句子。
用的是推导。
自下而上:从给定的句子规约到文法的开始符号。
用的是归约。
下面就主要来讲解他们的不同点,LL(1)单独讲,其他四种文法
分析过程基本有三大步:写出自动机(即LR(0)或LR(1)项集族,后面都称作自动机)-> 构造文法分析表-> 进行文法分析过程。
其中后两步都是类似或者说几乎完全一样的,第一步中的自动机有两种: LR(0)自动机和LR(1)自动机。
LR(0) 和SLR文法分析用的是LR(0)自动机,LR(1)和LALR文法分析用的是LR(1)自动机。
而LR(1)自动机构造方法和LR(0)自动机的构造方法相同,只是多增加了向前搜索符号。
编译原理-LL(1)文法源代码(实验三)

一、实验目的及要求1.掌握LL(1)分析法的基本原理;2.掌握LL(1)分析表的构造方法;3.用LL(1)分析法分析高级语言表达式。
4、了解LL(1)分析器的工作过程。
文法:无二义性的算术表达式的文法(1)把词法分析作为语法分析的子程序实现(5分)(2)独立的语法分析程序(4分)(3)对表达式文法消除左递归、构造LL(1)分析表(4)LL(1)分析表可以直接输入(4分),也可以用程序实现(5分)(5)给一个表达式,给出分析过程(分析栈、输入串、所用规则)(4分)(6)生成一个棵语法树(5分)用二叉树的形式表示出来二、实验内容及原理1、实验原理(1)、LL(1)文法的定义LL(1)分析法属于确定的自顶向下分析方法。
LL(1)的含义是:第一个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式(规则)进行推导。
LL(1)文法的判别需要依次计算FIRST集、FOLLOW集和SELLECT集,然后判断是否为LL(1)文法,最后再进行句子分析。
需要预测分析器对所给句型进行识别。
即在LL(1)分析法中,每当在符号栈的栈顶出现非终极符时,要预测用哪个产生式的右部去替换该非终极符;当出现终结符时,判断其与剩余输入串的第一个字符是否匹配,如果匹配,则继续分析,否则报错。
LL(1)分析方法要求文法满足如下条件:对于任一非终极符A的两个不同产生式A→α,A→β,都要满足下面条件:SELECT(A→α)∩SELECT(A→β)=∅(2)、预测分析表构造LL(1)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推导。
它的行对应文法的非终极符,列对应终极符,表中的值有两种:一是产生式的右部的字符串,一是null。
若用M表示LL(1)分析表,则M可表示如下:M: VN×VT→P∪{Error}M(A, t) = A→α,当t∈select(A→α) ,否则M(A, t) = Error其中P表示所有产生式的集合。
SIMPLE语言定义

SIMPLE语言定义一、字符集定义1.<字符集> →<字母>│<数字>│<单界符>2.<字母> →A│B│…│Z│a│b│…│z3.<数字> →0│1│2│…│94.<单界符> →+│-│*│/│=│<│>│(│)│[│]│:│. │; │, │'二、单词集定义5.<单词集> →<保留字>│<双界符>│<标识符>│<常数>│<单界符>6.<保留字> →and│array│begin│bool│call│case│char│constant│dim│do│else│end│false│for│if│input│integer│not│of│or│output│procedure│program│read│real│repeat│set│stop│then│to│true│until│var│while│write7.<双界符> →<>│<=│>=│:= │/*│*/│..8.<标识符> →<字母>│<标识符> <数字>│<标识符> <字母>9.<常数> →<整数>│<布尔常数>│<字符常数>10.<整数> →<数字>│<整数> <数字>11.<布尔常数> →true│false12.<字符常数> →' 除{'} 外的任意字符串'三、数据类型定义13.<类型> →integer│bool│char四、表达式定义14.<表达式> →<算术表达式>│<布尔表达式>│<字符表达式>15.<算术表达式> →<算术表达式> + <项>│<算术表达式> - <项>│<项>16.<项> →<项> * <因子>│<项> / <因子>│<因子>17.<因子> →<算术量>│- <因子>18.<算术量> →<整数>│<标识符>│(<算术表达式> )19.<布尔表达式> →<布尔表达式> or <布尔项>│<布尔项>20.<布尔项> →<布尔项> and <布因子>│<布因子>21.<布因子> →<布尔量>│not <布因子>22.<布尔量> →<布尔常量>│<标识符>│(<布尔表达式> )│<标识符> <关系符> <标识符>│<算术表达式> <关系符> <算术表达式> 23.<关系符> →<│<>│<=│>=│>│=24.<字符表达式> →<字符常数>│<标识符>五、语句定义25.<语句> →<赋值句>│<if句>│<while句>│<repeat句>│<复合句>26.<赋值句> →<标识符> := <算术表达式>27.<if句>→if <布尔表达式> then <语句>│if <布尔表达式> then <语句> else <语句> 28.<whilet句> →while <布尔表达式> do <语句>29.<repeat句> →rpeat <语句> until <布尔表达式>30.<复合句> →begin <语句表> end31.<语句表> →<语句> ;<语句表>│<语句>六、程序定义32.<程序> →program <标识符> ;<变量说明> <复合语句> .33.<变量说明> →var <变量定义>│ε34.<变量定义> →<标识符表> :<类型> ;<变量定义>│<标识符表> :<类型> ;35.<标识符表> →<标识符> ,<标识符表>│<标识符>七、SIMPLE语言单词编码八、实验一:设计SAMPLE语言的词法分析器检查要求:a)启动程序后,先输出作者姓名、班级、学号(可用汉语、英语或拼音);b)请求输入测试程序名,键入程序名后自动开始词法分析并输出结果;c)输出结果为单词的二元式序列(样式见样板输出1和2);d)要求能发现下列词法错误和指出错误性质和位置:非法字符,即不是SAMPLE字符集的符号;字符常数缺右边的单引号(字符常数要求左、右边用单引号界定,不能跨行);注释部分缺右边的界符*/(注释要求左右边分别用/*和*/界定,不能跨行)。
LL(1)文法分析.

构造预测分析表
在确定的自顶向下分析方法中,又有递归子程序法和预测分 析方法,我们采用的是预测分析的方法。一个预测分析器 由三部分组成: (1)预测分析程序 (2)先进后出栈 (3)预测分析表 其中,只有预测分析表与文法有关。分析表可用矩阵M 表示。M(A,a)中的下标A表示非终结符,a为终结符 或括号,矩阵元素M(A,a)中的内容是一条关于A的产 生式,表明当用非终结符A往下推导时,面临输入符A时, 所应采取的候选产生式,元素内容无产生式时,则表明出 错。为便于辨认,我们令M数组为 Analyze数组。
算法介绍
1、在对输入序列进行LL(1)文法分析之前,首先要对文法进行判 别,看文法是不是LL(1)文法。这个文法应该满足无二义性,无 左递归,无公因子。具体的判别过程是,求出能推出ε的非终结 符,求出FIRST集,求出FOLLOW集,求出SELLECT集,看相 同左部的产生式的SELLECT集是否有交集,有就不是LL(1)文 法。 2、如果输入文法不是LL(1)文法,可以进行转换,转换一般有两 种方法:提取左公因子法和消除左递归法。 3、构造预测分析表,设二维矩阵M。
4、预测分析。
人员分工
• 负责MFC界面制作,程序总控,各个非终结 符能否推出ε的计算,判断是否LL(1),以及人员 分工。 • 消除左递归的实现 • 提取公因子的实现 • 求FIRST集 • 求FOLLOW集 • 求SELLECT集 • 构造预测分析表,分析输入的句子
程序流程
程序开始 InitAndConvertPt(); //读入文法、消除左递归、提取公因子 InitArray(); //初始化N[ ]数组 VnRefresh(Pt); //构造非终结符集 VtRefresh(Pt);//构造终结符集 Create_N_Table(); //判断哪些非终结符可以推出空,存入N[ ]
SIMPLE算法解析

SIMPLE算法解析SIMPLE(SIMulated Programming Language)是一种简单且易于理解的编程语言,用于教学和演示。
它并不是一种专门用于实际项目的编程语言,而是一个面向初学者的工具,旨在帮助他们理解编程原理。
下面对SIMPLE算法进行解析。
1.基本概念:2.源码实例:下面是一个简单的SIMPLE程序示例,用于计算前n个自然数的和:```JMP10LADA,0LADB,1ADDA,BLADB,1SUBC,BJMNC,4OUTAHLT```该程序分为以下几个部分:3.程序解析:a.第一行"JMP10"是跳转指令,将程序的执行跳转到标号为10的地址。
这里是用来跳过下面的数据段。
b. 第二行 "LAD A, 0" 将寄存器A的值设置为0。
LAD是 load 的缩写,意味着将一个数据加载到寄存器中。
c.第三行"LADB,1"将寄存器B的值设置为1d.第四行"ADDA,B"将寄存器A和B中的值相加,并将结果存入寄存器A中。
e.第五行"LADB,1"将寄存器B的值重新设置为1f.第六行"SUBC,B"用寄存器B的值去减寄存器C的值,并将结果存放在寄存器C中。
寄存器C的值在程序开始时,会被设置为n,即要计算前n个数的和。
g.第七行"JMNC,4"是一个条件分支指令,如果寄存器C的值小于等于0,那么跳转到标号为4的地址(即结束程序)。
h.第八行"OUTA"输出寄存器A中的值。
i.最后一行"HLT"是停止指令,表示程序执行结束。
4.程序执行:程序的执行从第一行开始,依次执行每条指令。
在上面的示例中,开始时会跳过第一行,直接执行第二行到第八行的指令。
其中,第四行和第六行是循环结构的关键,它们重复执行直到寄存器C的值小于等于0。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Simple语言的定义(select集)1.<字符集> -> <字母>2. <字符集> -> <数字>3. <字符集> -> <单界符>4.<字母> -> A | B|…….| Z | a | b | ……….| z5. <数字> -> 0 | 1 | 2 |……| 96.<单界符> -> ' | ( | ) | * | + | , | - | . | / | : | ; | < | = | > | [ | ]| _7.<单词集> -> <保留字>8.<单词集> -> <双界符>9.<单词集> -> <标识符>10. <单词集> -> <常数>11.<单词集> -> <单界符>12.<保留字> -> and | array | begin | bool | call | case | char | constant | do | else | end | false | for | if | input | integer | not | of | or | output | real | repeat |set | then | to | true | until | main | void | while |program| procedure|read|write13. <双界符> -> <> | <= | >= | -> | /* | */ | ..14.<标识符> -> <字母><标识符>’15. <标识符>’-><数字><标识符>’16.<标识符>’-> <字母><标识符>’17.<标识符>’-> ε18.<常数>-> <整数>19.<常数>-><布尔常数>20.<常数>-><字符常数>21.<常数>-><常数标识符>22.<常数>-><实数>23.<整数>-> <数字>24.<布尔常数>-> true | false25.<字符常数>-> ‘除{'}外的任意字符(包括空字符)’26.<实数>-><整数>.<整数>27.<常数标识符>-><标识符>28.<类型>-> <简单类型>29.<类型>-> <复合类型>30.<简单类型>-> integer | char | real | bool31.< 复合类型> -> array[<索引>]of<简单类型>32. <索引> -> <整数><索引>’33. <索引> -> <整数>···<整数><索引>’34. <索引>’ -> ,<整数><索引>’35. <索引>’ -> ,<整数>···<整数><索引>’36. <索引>’ -> ε37. <表达式> -> <算术表达式>38. <表达式> -> <布尔表达式>39. <表达式> -> <字符表达式>40. <算术表达式> -> +-<项><算术表达式>’41. <算术表达式> -> <项><算术表达式>’42. <算术表达式>’ -> +-<项><算术表达式>’43. <算术表达式>’ ->ε44. <项> -> <因子><项>’45. <项>’ -> * <因子><项>’|/<因子><项>’|ε46. <因子> -> <算术量>47. <因子> -> (<算术表达式>)48.<算术量> -> <标识符>49. <算术量> -> <整数>50. <布尔表达式> -> <布尔项><布尔表达式>’51. <布尔表达式>’-> or <布尔项><布尔表达式>’52. <布尔表达式>’-> ε53. <布尔项> -> <布因子><布尔项>’54. <布尔项>’-> and<布因子><布尔项>’55. <布尔项>’->ε56. <布因子> -> <布尔量>57. <布因子> -> not<布因子>58. <布尔量> -> <布尔常数>59. <布尔量> -> <标识符>60. <布尔量> ->(<布尔表达式>)<标识符><关系符><标识符>61. <布尔量> ->(<算术表达式>)<关系符>(<算术表达式>)62. <字符表达式> -> <字符常数>63. <字符表达式> -> <标识符>64.<关系符> -> < | <> | <= | >= | > | =65. <语句> -> <说明句>66. <语句> -> <执行句>67. <说明句> -> <常数说明>68. <说明句> -> <变量说明>69. <说明句> -> <过程说明>70.<常数说明> -> constant<常数定义>71. <常数说明> ->ε72. <常数定义> -> <标识符>=<常数>;<常数定义>73. <常数定义> -> <标识符>=<常数>;74. <变量说明> -> var<变量定义>75. <变量说明> -> ε76. <变量定义> -> <标识符表>:<类型>;77. <变量定义> -> <标识符表>;<类型>;<变量定义>78.<标识符表> -> <标识符>,<标识符表>79. <标识符表> -> <标识符>80. <执行句> -> <简单句>81. <执行句> -> <结构句>82. <简单句> -> <赋值句>83. <简单句> -> <调用语句>84. <简单句> -> <读语句>85. <简单句> -> <写语句>86. <赋值句> -> <变量>-><表达式>87. <变量> -> <单变量>88. <变量> -> <索引变量>89. <单变量> -> <标识符>90. <索引变量> -> <标识符>[<表达式表>]91. <表达式表> -> <表达式>,<表达式表>92. <表达式表> -> <表达式>93.<调用语句> -> call<标识符>(<实参表>)94. <实参表> -> <表达式>,<实参表>95. <实参表> -> <表达式>96. <读语句> -> read(<输入变量表>)97. <输入变量表> -> <变量>98. <输入变量表> -> <变量>,<输入变量表>99. <写语句> -> write(<表达式表>)100. <结构句> -> <复合句>101. <结构句> -> <if句>102. <结构句> -> <while句>103. <结构句> -> <for句>104. <结构句> -> <repeat句>105. <复合句> -> begin<语句表>end106. <if句> -> if<布尔表达式>then<执行句>107. <if句> -> if<布尔表达式>then<执行句>else<执行句> 108. <while句> -> while<布尔表达式>do<执行句>109. <repeat句> -> repeat<执行句>until<布尔表达式>110. <for句> -> for<变量>=<表达式>to<表达式>do<><执行句> 111. <过程说明> -> procedure<标识符>(<形参表>)<分程序>112. <过程说明> ->ε113. <形参表> -> <变量>:<简单类型>114. <形参表> -> <变量>:<简单类型>,<形参表>115. <分程序> -> <常数说明><变量说明><过程说明><复合句> 116. <程序> -> program<标识符><分程序>。