预测分析表的构造
编译原理语法分析(3)_ 习题
来消除左递归。由此,将产生式B→Bb|d改造为 B→dB′ B′→bB′| ε
其次,应通过提取公共左因子的方法来消除G[A]中的回 溯,即将产生式A→aABl|a改造为 A→aA′ A′→ABl | ε
最后得到改造后的文法为 G[A′]:A→aA′ A′→ABl | ε B→dB′ B′→bB′| ε
S ( L) L, S S ( L)
S a
图4-5 句型(S,(a))的语法树
(2) 由图4-5可知: 短语:S、a、(a)、S,(a)、(S,(a)); 直接短语:a、S; 句柄:S; 素短语:素短语可由图4-5中相邻终结符之间的优 先关系求得,即:
#⋖ (⋖,⋖ (⋖a⋗)⋗)⋗# 因此,素短语为a。
D
D
TL
TL
int a L′
int L , c
, b L′
L, b
, c L′
a (a)
(b)
图4-6 两种文法为int a,b,c构造的分析树 (a) 文法G(D); (b) 文法G′(D)
3.9 考虑文法G[S]: S→(T) | a+S | a T→T,S | S
消除文法的左递归及提取公共左因子,然后对每 个非终结符写出不带回溯的递归子程序。
优先关系表构造方法: ① 对P→…ab…或P→…aQb…,有ab; ② 对P→…aR…而b∈FIRSTVT(R),有a⋖b; ③ 对P→…Rb…而a∈LASTVT(R),有a⋗b。 解之无①。 由②得:E→…+T,即+⋖FIRSTVT(T),有+⋖*,+⋖i;
T→…*P,即*⋖FIRSTVT(P),有*i。 由③得:E→E+…,即LASTVT(E)⋗+,有+⋗+,*⋗+, i⋗+;
编译原理-第4章 语法分析--习题答案
第4章语法分析习题答案1.判断(1)由于递归下降分析法比较简单,因此它要求文法不必是LL(1)文法。
(× )LL(1)文法。
(× )(3)任何LL(1)文法都是无二义性的。
(√)(4)存在一种算法,能判定任何上下文无关文法是否是LL(1) 文法。
(√)(× )(6)每一个SLR(1)文法都是LR(1)文法。
(√)(7)任何一个LR(1)文法,反之亦然。
(× )(8)由于LALR是在LR(1)基础上的改进方法,所以LALR(× )(9)所有LR分析器的总控程序都是一样的,只是分析表各有不同。
(√)(10)算符优先分析法很难完全避免将错误的句子得到正确的归约。
(√)2.文法G[E]:E→E+T|TT→T*F|FF→(E)|i试给出句型(E+F)*i的短语、简单短语、句柄和最左素短语。
答案:画出语法树,得到:短语: (E+F)*i ,(E+F) ,E+F ,F ,i简单短语: F ,i句柄: F最左素短语: E+F3.文法G[S]:S→SdT | TT→T<G | GG→(S) | a试给出句型(SdG)<a的短语、简单短语、句柄和最左素短语。
答案:画出语法树,得到:短语:(SdG)<a 、(SdG) 、SdG 、G 、a简单(直接)短语:G 、a句柄:G最左素短语:SdG4.对文法G[S]提取公共左因子进行改写,判断改写后的文法是否为LL(1)文法。
S→if E then S else SS→if E then SS→otherE→b答案:提取公共左因子;文法改写为:S→if E then S S'|otherS'→else S|E→bLL(1)文法判定:① 文法无左递归② First(S)={if,other}, First(S')={else, }First(E)={b}Follow(S)= Follow(S')={else,#}Follow(E)={then}First(if E then S S')∩First(other)=First(else S)∩First( )=③First(S')∩Follow(S')={else}不为空集故此文法不是LL(1)文法。
first集follow集求解算法及构造预测分析表
构造预测分析表源程序:#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,m=0,n=3,k;char temp[20],ch;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);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("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%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!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_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("\nerror1!");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("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/ char c,temp[20];int j,k,m;c=v[i];char ch='@';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);}elsebreak;}}}}}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);elsemerge(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);elsemerge(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);elsemerge(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("\n各非终结符导出的first集:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\n能导空的非终结符集合:%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;char S[50],str[50];printf("请输入该文法的句型:");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("该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("该符号串是文法的句型."); 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("词法错误!");return;}}if(M[i][k]==-1){printf("语法错误!");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("\n开始符号为:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\n所有符号集为:%s",v);printf("\n非终结符集合:{%s",non_ter);printf("}");printf("\n终结符集合:{%s",termin); printf("}");printf("\n文法所有右边表达式依次是:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\n文法所有左边开始符依次是:"); 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该文法不是一个LL1文法!"); else{printf("\n该文法是一个LL(1)文法!");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();}}运行结果:。
编译原理笔记10 自上而下分析-预测分析程序与LL(1)文法
预测分析程序与LL(1)文法一、预测分析程序1.带预测分析的PDA:1)在PDA中加入预测分析之后,可以消除自上而下分析中出现回溯的现象,此时PDA可以改造为:2)注:a、改造后,整个分析过程都在预测分析程序控制下工作。
B、预测分析程序用了一个预测分析表,它是预测分析程序分析时的主要依据。
3)预测分析表:预测分析表是一矩阵M[A,a],其中行标A是非终结符,列标a是终结符或串结束符;矩阵元素M[A,a]是存放A的一个候选式,指出当前栈顶符号为A 且面临读入符号为a时应选的候选式;或者存放“出错标志”,指出A不该面临读入符号a。
2.预测分析程序算法描述设栈顶符号为X,读入符号为a,则1)若X=a=‘#’,则表示识别成功,退出分析程序;2)若X=a=‘#’,则表示匹配,弹出栈顶符号X,读头前进一格,让读头指向下一个符号,以读入下一个符号;若X是终结符,但X<>a,则调用error处理;3)若X属于非终结符,则查预测分析表M。
若M[X,a]中存放着关于X的产生式,则弹出X,且将相应产生式右部以自右向左的顺序压入栈,在输出带上记下产生式编号;若M[X,a]中存放着出错标记,则调用相应Error处理。
二、求串α的终结首符集和非终结符A的随符集a) 求串α的终结首符集First(α)i. 定义:假定α是文法G的一个符号串,α属于星闭包,则First(α)={a | α广义推导出a......a,a属于终结符}注:1)若α推导出空串,那么空串就属于First(α)。
2)First(α)集合是α的所有可能推导出的开头终结符或空串所组成的集合。
ii. 算法具体步骤:b) 求非终结符A的随符集Follow(A)i. 定义:假定S是文法G的开始符号,对于G的任何非终结符A,定义:ii. 算法1. 对文法开始符号S,将‘#’加入到Follow(S)中;2. 若B->αAβ是文法G的一个产生式,则将First(β)-空串加入到Folow(A)中;3. 若B->αA是文法G的一个产生式,或B->αAβ是文法G的一个产生式,且β推导出空串,则将Follow(B)加入到Follow(A)中;注:这里的文法必须消除左递归且提取了左因子后的文法。
编译原理考试试题与答案(汇总)
对输入串ab#给出分析过程为:
一、是非题:
1.一个上下文无关文法的开始符,可以是终结符或非终结符。 ( )
2.一个句型的直接短语是唯一的。 ( )
3.已经证明文法的二义性是可判定的。 ( )
4.每个基本块可用一个DAG表示。 ( )
5.每个过程的活动记录的体积在编译时可静态确定。 ( )
1.编译程序是对高级语言程序的解释执行。(× )
2.一个有限状态自动机中,有且仅有一个唯一的终态。(×)
3.一个算符优先文法可能不存在算符优先函数与之对应。(√ )
4.语法分析时必须先消除文法中的左递归。(×)
5.LR分析法在自左至右扫描输入串时就能发现错误,但不能准确地指出出错地点。(√)
6.逆波兰表示法表示表达式时无须使用括号。(√ )
2.考虑文法G[S]:
S → (T) | a+S | a
T → T,S | S
消除文法的左递归及提取公共左因子。
解:消除文法G[S]的左递归:
S→(T) | a+S | a
T→ST′
T′→,ST′| ε
提取公共左因子:
S→(T) | aS′
S′→+S | ε
T→ST′
T′→,ST′| ε
3.试为表达式w+(a+b)*(c+d/(e-10)+8)写出相应的逆波兰表示。
8.一个过程相应的DISPLAY表的内容为(现行活动记录地址和所有外层最新活动记录的地址)
10.常用的两种动态存贮分配办法是(栈式)动态分配和(堆式)动态分配。
11.一个名字的属性包括( 类型)和(作用域 )。
12.常用的参数传递方式有(传地址),(传值),(传名)
对下面的文法G
7. F’过程 过程 Procedure F Begin if sym=‘*’ then begin advance; F’ end else if sym in [ a, b, (, ), ^, +, # ] then return else error; end
E TE‘ E’ +E|ε | T FT‘ T’ T|ε | F PF‘ F’ *F‘|ε | P (E)|a|b|^ | | |^
P91 习题 习题2 2、对下面的文法 : 、对下面的文法G: E TE‘ E’ +E|ε | T FT‘ T’ T|ε | F PF‘ F’ *F‘|ε | P (E)|a|b|^ | | |^ (1)计算这个文法的每个非终结符的 )计算这个文法的每个非终结符的FIRST集和 集和 FOLLOW集。 集 (2)证明这个文法是 (1)的。 )证明这个文法是LL( ) (3)构造它的预测分析表。 )构造它的预测分析表。 (4)构造它的递归下降分析程序。 )构造它的递归下降分析程序。
E TE‘ E’ +E|ε | T FT‘ T’ T|ε | F PF‘ F’ *F‘|ε |
P (E)|a|b|^ | | |^ FOLLOW(E)={ ) , # } FOLLOW(E’)=FOLLOW(E)={ ) , # } FOLLOW(T)=FIRST(E’)\ ε ∪FOLLOW(E)={+, ) , # } FOLLOW(T’)=FOLLOW(T)=={+, ) , # } FOLLOW(F)=FIRST(T’)\ ε ∪FOLLOW(T)={ (,a,b,^ , +, ) , # } FOLLOW(F’)=FOLLOW(F)={(, a , b , ^ , +, ) , # } FOLLOW(P)=FIRST(F’)\ ε ∪FOLLOW(F)={*,( ,a, b ,^,+ , ) ,# }
预测分析程序
1
#ET
i1*i2+i3# E→TE
2
#ETF i1*i2+i3# T→FT
3
#ETi i1*i2+i3# F→i
i
+
*
(
)
#
E E→TE
E→TE
E
E→+TE
E→ E→
T T→FT
T→FT
T
T→ T→*FT
T→ T→
F F→i
F→ (E)
12
步骤 符号栈 输入串 所用产生式
3
#ETi i1*i2+i3# F→i
把X逐出STACK栈顶,把产生式的右部符号
串按反序一一推进STACK栈(若右部符号为
,则意味不推什么东西进栈)。在把产生式
推导
的右部符号推进栈的同时应做这个产生式相 应的语义动作。
• 若M[X,a]中存放着“出错标志”,则调用
出错诊察程序ERROR。
8
预测分析程序的总控程序
BEGIN
首先把‘#’然后把文法开始符号推进STACK栈;
2. 若A→B是一个产生式,则把FIRST()\{}加 至FOLLOW(B)中;
3. 若A→B是一个产生式,或AB是一个
产生式而 (即FIRST()),
则把FOLLOW(A)加至FOLLOW(B)中。
25
例4.6 对于文法G(E)
E→TE E→+TE | T→FT T→*FT | F→(E) | i
= X, XVT∪VN = X1X2…Xn, XiVT∪VN
22
构造任何符号串的FIRST集合
对文法G的任何符号串=X1X2…Xn构造 集合FIRST()
编译原理_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)、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表示所有产生式的集合。
实验5-LL(1)语法分析程序的设计与实现(C语言)
实验五LL(1)文法识别程序设计一、实验目的通过LL(1)文法识别程序的设计理解自顶向下的语法分析思想。
二、实验重难点FIRST集合、FOLLOW集合、SELECT集合元素的求解,预测分析表的构造。
三、实验内容与要求实验内容:1.阅读并理解实验案例中LL(1)文法判别的程序实现;2.参考实验案例,完成简单的LL(1)文法判别程序设计。
四、实验学时4课时五、实验设备与环境C语言编译环境六、实验案例1.实验要求参考教材93页预测分析方法,94页图5.11 预测分析程序框图,编写表达式文法的识别程序。
要求对输入的LL(1)文法字符串,程序能自动判断所给字符串是否为所给文法的句子,并能给出分析过程。
表达式文法为:E→E+T|TT→T*F|FF→i|(E)2.参考代码为了更好的理解代码,建议将图5.11做如下标注:/* 程序名称: LL(1)语法分析程序 *//* E->E+T|T *//* T->T*F|F *//* F->(E)|i *//*目的: 对输入LL(1)文法字符串,本程序能自动判断所给字符串是否为所给文法的句子,并能给出分析过程。
/********************************************//* 程序相关说明 *//* A=E' B=T' *//* 预测分析表中列号、行号 *//* 0=E 1=E' 2=T 3=T' 4=F *//* 0=i 1=+ 2=* 3=( 4=) 5=# *//************************************/#include"iostream"#include "stdio.h"#include "malloc.h"#include "conio.h"/*定义链表这种数据类型参见:*/struct Lchar{char char_ch;struct Lchar *next;}Lchar,*p,*h,*temp,*top,*base;/*p指向终结符线性链表的头结点,h指向动态建成的终结符线性链表节点,top和base分别指向非终结符堆栈的顶和底*/char curchar; //存放当前待比较的字符:终结符char curtocmp; //存放当前栈顶的字符:非终结符int right;int table[5][6]={{1,0,0,1,0,0},{0,1,0,0,1,1},{1,0,0,1,0,0},{0,1,1,0,1,1},{1,0,0,1,0,0}};/*存放预测分析表,1表示有产生式,0表示无产生式。
编译原理课程设计-LL(1)语法分析器的构造
LL(1)语法分析器的构造摘要语法分析的主要任务是接收词法分析程序识别出来的单词符由某种号串,判断它们是否语言的文法产生,即判断被识别的符号串是否为某语法部分。
一般语法分析常用自顶向下方法中的LL分析法,采用种方法时,语法分程序将按自左向右的顺序扫描输入的的符号串,并在此过程中产生一个句子的最左推导,即LL是指自左向右扫描,自左向右分析和匹配输入串。
经过分析,我们使用VC++作为前端开发工具,在分析语法成分时比较方便直观,更便于操作。
运行程序的同时不断修正改进程序,直至的到最优源程序。
关键字语法分析文法自顶向下分析 LL(1)分析最左推导AbstractGrammatical analysis of the main tasks was to receive lexical analysis procedure to identify the words from a website, string, and judge whether they have a grammar of the language, that is, judging by the series of symbols to identify whether a grammar part. General syntax analysis commonly used top-down methods of LL analysis, using methods, Grammar hours will be from the procedures of the order left-to-right scanning input string of symbols, and in the process produced one of the most left the sentence is derived, LL is scanned from left to right, From left to right analysis and matching input strings. After analysis, we use VC + + as a front-end development tool for the analysis of syntax ingredients more convenient visual, more easy to operate. Operational procedures at the same time constantly improving procedures, until the source of optimal .Key WordsGrammatical analysis grammar Top-down analysis LL (1) AnalysisMost left Derivation目录摘要 (1)引言 (3)第一章设计目的 (4)第二章设计的内容和要求 (5)2.1 设计内容 (5)2.2 设计要求 (5)2.3 设计实现的功能 (5)第三章设计任务的组织和分工 (6)3.1 小组的任务分工 (6)3.2 本人主要工作 (6)第四章系统设计 (9)4.1 总体设计 (9)4.2 详细设计 (9)第五章运行与测试结果 (22)5.1 一组测试数据 (22)5.2 界面实现情况 (23)第六章结论 (27)课程设计心得 (28)参考文献 (29)致谢 (30)附录(核心代码清单) (31)引言编译器的构造工具是根据用户输入的语言的文法,编译器的构造工具可以生成程序来处理以用户输入的文法书写的文本。
编译原理教程课后习题答案——第三章
第三章语法分析3.1 完成下列选择题:(1) 文法G:S→xSx|y所识别的语言是。
a. xyxb. (xyx)*c. xnyxn(n≥0)d. x*yx*(2) 如果文法G是无二义的,则它的任何句子α。
a. 最左推导和最右推导对应的语法树必定相同b. 最左推导和最右推导对应的语法树可能不同c. 最左推导和最右推导必定相同d. 可能存在两个不同的最左推导,但它们对应的语法树相同(3) 采用自上而下分析,必须。
a. 消除左递 a. 必有ac归b. 消除右递归c. 消除回溯d. 提取公共左因子(4) 设a、b、c是文法的终结符,且满足优先关系a b和bc,则。
b. 必有cac. 必有bad. a~c都不一定成立(5) 在规范归约中,用来刻画可归约串。
a. 直接短语b. 句柄c. 最左素短语d. 素短语(6) 若a为终结符,则A→α·aβ为项目。
a. 归约b. 移进c. 接受d. 待约(7) 若项目集Ik含有A→α·,则在状态k时,仅当面临的输入符号a∈FOLLOW(A)时,才采取“A→α·”动作的一定是。
a. LALR文法b. LR(0)文法c. LR(1)文法d. SLR(1)文法(8) 同心集合并有可能产生新的冲突。
a. 归约b. “移进”/“移进”c.“移进”/“归约”d. “归约”/“归约”【解答】(1) c (2) a (3) c (4) d (5) b (6) b (7) d (8) d3.2 令文法G[N]为G[N]: N→D|NDD→0|1|2|3|4|5|6|7|8|9(1) G[N]的语言L(G[N])是什么?(2) 给出句子0127、34和568的最左推导和最右推导。
【解答】(1) G[N]的语言L(G[N])是非负整数。
(2) 最左推导:NNDNDDN DDDDDD D0DDD01DD012D0127NNDDD3D34NNDNDDD DD5DD56D568最右推导:NNDN7ND7N27ND27N127D1270127NNDN4D434NNDN8ND8N68D685683.3 已知文法G[S]为S→aSb|Sb|b,试证明文法G[S]为二义文法。
编译原理知识点参考
第三章3.1 对于词法分析器的要求1.词法词法分析的任务:从左至右逐个字符地对源程序进行扫描,产生一个个单词符号。
词法分析器(Lexical Analyzer) 又称扫描器(Scanner):执行词法分析的程序。
2.程序语言的单词符号:关键字、标识符、常数、运算符、界符。
3.输出的单词符号的表示形式:(单词种别,单词自身的值)Eg:while (i>=j) i--;输出单词符号:< while, - >< (, - >< id, 指向i的符号表项的指针><>=, - >< id, 指向j的符号表项的指针>< ), - >< id, 指向i的符号表项的指针>< --, - >< ;, - >4.词法分析器作为一个独立子程序:结构简洁、清晰和条理化,有利于集中考虑词法分析一些枝节问题。
5.词法分析器3.2 词法分析器的设计1.词法分析器2.输入、预处理:输入串放在输入缓冲区中。
预处理子程序:剔除无用的空白、跳格、回车和换行等编辑性字符;区分标号区、捻接续行和给出句末符等扫描缓冲区(指向开始位置,向前搜索确定终点)3.单词符号的识别、超前搜索:(1)基本字识别Eg:DO99K=1,10 DO 99 K = 1,10IF(5.EQ.M)GOTO55 IF (5.EQ.M) GOTO 55DO99K=1.10IF(5)=55需要超前搜索才能确定哪些是基本字(2)标识符(3)常数(4)算符和界符4.状态转换图(有限方向图)<1>结点代表状态<2>状态之间用箭弧连结,箭弧上的标记(字符)代表射出结状态下可能出现的输入字符或字符类。
<3>一个状态转换图可用于识别(或接受)一定的字符串。
5.语法分析的状态转换图6.状态转换图的实现思想:每个状态结对应一小段程序。
语法设计——基于LL(1)文法的预测分析表法
语法设计——基于LL(1)⽂法的预测分析表法实验⼆、语法设计——基于LL(1)⽂法的预测分析表法⼀、实验⽬的通过实验教学,加深学⽣对所学的关于编译的理论知识的理解,增强学⽣对所学知识的综合应⽤能⼒,并通过实践达到对所学的知识进⾏验证。
通过对基于LL(1)⽂法的预测分析表法DFA 模拟程序实验,使学⽣掌握确定的⾃上⽽下的语法分析的实现技术,及具体实现⽅法。
通过本实验加深对语词法分析程序的功能及实现⽅法的理解。
⼆、实验环境供Windows系统的PC机,可⽤C++/C#/Java等编程⼯具编写三、实验内容1、⾃⼰定义⼀个LL(1)⽂法⽰例如(仅供参考) G[E]:E →TE' E' → +TE' | εT →FT' T' → *FT' | ε F → i | ( E )2、构造其预测分析表,如3、LL(1)⽂法的预测分析表的模型⽰意图4、预测分析控制程序的算法流程5、运⾏结果,⽰例如下四、实验⽅式与要求1、设计的下推⾃动机具有通⽤性,上机编程实现;2、实验报告格式要求书写要点:概要设计(总体设计思想);详细设计(程序主流程、⾃动机的存储格式、关键函数的流程图);结果分析(输⼊与输出结果、存在问题及有待改进善的地⽅、实验⼼得);3、实验报告限4页内。
设计思路:我就讲解⼀下核⼼部分代码,⾸先,进栈函数在 298 ⾏处左右,我们⽤ ArrayList 去定义⼀个动态数组 analyzeProduces ,我们定义了⼀个栈 analyzeStatck ,⽽这个栈在我们在定义 Analyzer 类中初始化化过了,所以在创建 analyzeStatck 中⾸先会进⾏初始化操作, push 了⼀个 # ,所以 analyzeStatck 栈中会存在 # 这个字符(以这个 # 作为标记),然后302 ⾏,我们向 analyzeStack 中推⼊开始符号,也就是我们在主函数设置的字符 E ,然后打印出开始符号以及⼀些格式要求(步骤,符号栈,输⼊串,产⽣式等等),设置 index 的值来记录⾛过的步骤次数。
编译原理-清华大学-第4章-自顶向下语法分析方法(3+1)
(2)一个文法提取了左公共因子后,只解决 了相同左部产生式右部的FIRST集不相交问 题,当改写后的文法不含空产生式,且无左 递归时,则改写后的文法是LL(1)文法,否 则还需用LL(1)文法的判别方式进行判断才 能确定是否为LL(1)文法。
• FIRST(Ap)={a,c} • FIRST(Bq)={b,d}
2、非终结符A后跟符号FOLLOW集的定义:
• 定义:设 G = (VT ,VN , S , P) 是上下文无关文 法,A∈VN , S是开始符号。 FOLLOW(A)={a|S * …Aa… ,a∈VT} 若S *…A,则规定 #∈FOLLOW(A)
(3)反复使用规则(2)直到每个非终结符的 FOLLOW集不再增大
S→AB S→bC A→ε A→b B→ε B→aD C→AD C→b D→aS D→c
FOLLOW(S)={#}∪FOLLOW(D) FOLLOW(A)=( FIRST(B)-{ε} )∪
FOLLOW(S) ∪ FIRST(D) FOLLOW(B)=FOLLOW(S) FOLLOW(C)=FOLLOW(S) FOLLOW(D)=FOLLOW(B)∪FOLLOW(C)
• 1表示:只需向右看1个输入符号便可决定 如何推导(即选择哪个产生式进行推导)。
• 类似也可以有LL(K)文法:需向前查看K个 输入符号才可确定选用哪个产生式。
• 文法G[S]是否是LL(1)文法: S→aA S→d A→bAS A→ε
SELECT(S→aA) ={a} SELECT(S→d)={d} SELECT(A→bAS)={b} SELECT(A→ε)={a,d,#} SELECT(S→aA)∩SELECT(S→d)={a}∩{d}=Φ SELECT(A→bAS)∩SELECT(A→ε)={b}∩{a,d,#}=Φ
编译原理_第1~5章习题课解答
I1 {b,c,d} {c,d,e} {c,d,e} {c,d,e} {c,d,e,g} {c,d,e}
④.DFA
I
I00
{a}
0 ΦC 0
{b,c,d}A 1 B {c,d} 1 0 E
{c,d}
1{c,dD}
{c,d,e} {c,d,f}
{c,d1,f}
1
{c,d}
{c,d,e,g}
{c,d,f}
L3={anbnambm| m,n≥0} G3(S): S→AB A→aAb|ε B→aBb|ε
L4={1n 0m 1m 0n| n,m≥0}
可以看成是两部分: 中间部分是 0m 1m : A→ 0A1 | ε
剩下两边的部分就是: S→ 1S0 | A 所以G4[S]可以写为: S→ 1S0 | A A→ 0A1 |ε
1
1
2
0
最小化: {0,1},{2}
{0,1}0={1} {0,1}1={2} {2}0={0},{2}1= ∅ ⊆ {2}或{0,1} 所以{0,1}不可分,用狀態0代表它們
0
0
0
2
1
15、给定右线性文法G:求一个与G等价的左线性文法。
S → 0S | 1S | 1A | 0B A → 1C | 1 B → 0C | 0 C→ 0C | 1C | 0 | 1
{0 {0,1 {1
}
}
}
{0,1 {0,1 {1}
}
}
{1 {0} φ
}
012 112 2 0φ
④.最小化
Π0=({0,1},{2})
{0,1}a={1} {0,1}b={2} 因此,不能再分
(b)
ba
编译原理复习题(含考试)
编译原理复习题(含考试)————————————————————————————————作者:————————————————————————————————日期:*编译原理复习题一.简答题:1) 什么是句子? 什么是语言?解答:句子——设G 是一个给定的文法,S 是文法的开始符号,如果S x (其中x ∈V T *),则称x 是文法的一个句子。
语言——语言是句子的集合。
或——设G[S]是给定文法,则由文法G 所定义的语言L(G)可描述为:L(G)={x │Sx,x ∈V T *} 。
2) DFA 与NFA 有何区别 ?解答:DFA 与NFA 的区别表现为两个方面:一是NFA 可以有若干个开始状态,而DFA 仅只有一个开始状态。
另一方面,DFA 的映象M 是从K ×∑到K ,而NFA 的映象M 是从K ×∑到K 的子集,即映象M 将产生一个状态集合(可能为空集),而不是单个状态。
3) 自顶向下的语法分析方法的基本思想是什么?解答:从文法的开始符号开始,根据给定的输入串并按照文法的产生式一步一步的向下进行直接推导,试图推导出文法的句子,使之与给定的输入串匹配。
4) 自底向上的语法分析方法的基本思想是什么?解答:从给定的输入串(终结符串)开始,根据文法的规则一步一步的向上进行直接归约,试图归约到文法的开始符号。
5) 一个上下文无关文法G 包括哪四个组成部分?解答:一组非终结符号,一组终结符号,一个开始符号,以及一组产生式。
6) 在自底向上的语法分析方法中,分析的关键是什么?解答:关键是寻找句柄。
7) 在自顶向下的语法分析方法中,分析的关键是什么? 解答:关键是选择候选式。
8)什么是属性文法?答:是在上下文无关文法的基础上,为每个文法符号(含终结符和非终结符)配备若干个属性值,对文法的每个产生式都配备了一组属性计算规则(称为语义规则)。
在语法分析过程中,完成语义规则所描述的动作,从而实现语义处理。
编译原理习题(含解答)_
5. 写出表达式(a+b*c)/(a+b)-d的逆波兰表示和三元式序列。 解:逆波兰表示: abc*+ab+/d- 三元式序列: ① (*,b,c) ② (+,a,①) ③ (+,a,b) ④ (/,②,③) ⑤ (-,④,d) 五、计算题(10分) 1.构造下述文法 G[S] 的自动机: S->A0 A->A0|S1|0 该自动机是确定的吗?若不确定,则对它确定化。 解:由于该文法的产生式S->A0,A->A0|S1中没有字符集VT的输入,所 以不是确定的自动机。 要将其他确定化,必须先用代入法得到它对应 的正规式。把S->A0代入产生式A->S1有: A=A0|A01|0=A(0|01)|0=0(0|01)*。 代入S->A0有该文法的正规式: * 0(0|01) 0,所以, 改写该文法为确定的自动机为:
由于状态A有3次输入0的重复输入,所以上图只是NFA,下可知DFA为: 1 0 0 C B A 0
综合练习二
一、选择题(请在前括号内选择最确切的一项作为答案划一个勾,多划 按错论)(每个4分,共40分) 1.通常一个编译程序中,不仅包含词法分析,语法分析,中间代码生 成,代码优化,目标代码生成等五个部分,还应包括_ C_ __。 A.模拟执行器 B.解释器 C.表格处理和出错处理 D.符号执行器 2.文法 G[N]=({b},{N,B},N ,{N→b│bB,B→bN}),该文法所 描述的语言是_ C_ __。 A.L(G[N])={bi│i≥0} B.L(G[N])={b2i│i≥0} C.L(G[N])={b2i+1│i≥0} D.L(G[N])={b2i+1│i≥1} 3.一个句型中的最左_ _B_ __称为该句型的句柄。 A.短语 B.简单短语 C.素短语 D. 终结符号 4.设 G 是一个给定的文法,S是文法的开始符号,如果 S->x( 其中 x∈V*), 则称 x 是文法 G 的一个__ B ___。 A.候选式 B.句型 C.单词 D.产生式 5.文法 G[E] : E→T∣E + T T→F∣T ﹡ F F→a∣ ( E ) 该文法句型 E + F ﹡ (E + T) 的简单短语是下列符号串中的__ B ___。 ① (E + T) ②E + T ③F ④ F ﹡ (E + T) A.① 和 ③ B.② 和 ③ C.③ 和 ④ D.( ) ③ 6.若一个文法是递归的,则它所产生的语言的句子__ A ___。 A.是无穷多个 B.是有穷多个 C.是可枚举的 D.个数是常量 7.词法分析器用于识别_ C____。 A.句子 B.句型 C.单词
Excel中的数据透视表和透视图的预测分析
Excel中的数据透视表和透视图的预测分析预测分析是数据分析中的重要环节,有助于我们通过已有的数据和趋势预测未来的走向。
在Excel中,数据透视表和透视图是强大的预测分析工具,它们可以帮助人们更好地利用数据进行决策和规划。
本文将介绍Excel中数据透视表和透视图的预测分析功能,并探讨其在实际应用中的价值。
首先,我们来了解数据透视表的预测分析功能。
数据透视表是Excel中一种用于汇总和分析大量数据的工具,它可以快速生成多维度的汇总报表。
通过数据透视表,我们可以对数据进行分类、汇总和比较,分析数据的变化趋势和规律,并根据这些趋势和规律进行预测分析。
在使用数据透视表进行预测分析时,首先需要选择要分析的数据范围,并将其创建为数据透视表。
然后,我们可以根据需要选择要分析的字段,并将其拖放到行标签、列标签和值区域中。
通过添加筛选器和排序功能,我们可以进一步深入分析数据,并找出其中的关联性和规律。
通过对数据透视表进行适当的调整和筛选,我们可以获得对未来数据变化趋势的初步预测。
除了数据透视表,Excel中的透视图也是一种强大的预测分析工具。
透视图是基于数据透视表创建的图表,它以更直观和可视化的方式展示数据的分析结果和预测趋势。
通过透视图,我们可以更清晰地观察数据的变化和趋势,并根据这些趋势进行更精准的预测分析。
在创建透视图时,我们可以选择不同类型的图表,如柱状图、折线图、饼图等,以便更好地呈现数据的特点和规律。
通过对透视图进行样式和格式的调整,我们可以使图表更加美观、清晰,增加数据分析的可读性和说服力。
同时,透视图还支持交互式操作,我们可以通过更改图表的参数和设置,实时观察数据的变化效果,提高预测分析的准确性。
数据透视表和透视图在预测分析中有着广泛的应用。
例如,在销售业务中,我们可以使用数据透视表和透视图分析销售额、销售量等指标的变化趋势,根据这些趋势预测未来的销售情况,从而做出相应的决策和规划。
在金融领域,数据透视表和透视图可以帮助我们分析市场行情、股票价格等数据,预测股市的涨跌和波动,为投资决策提供参考。
预测分析算法的设计与实现
预测分析算法的设计与实现程序代码:""""855202050/*产生式右部结构*/{;*;};{;; /*右部长度*/*; /*右部结点头指针*/};[ + 1]; /*非终结符集*/;[ + 1]; /*终结符集*/;P[];;[ + 1];;[]; /*要分析的符号串*/{;()*输出分析表*/( *);();();();( r);(){;();();();();();();("所得集为:");();("所得集为:");();();();= 'y';('y' ){("\n是否继续进行句型分析?(y / n):"); = ();('y' 'n' ){("\n(y / n)? ");= ();}('y' ){i;();("请输入符号串(以#结束) : "); = ();i = 0;('#' i < ){[i] = ;();}("输入出错!\n");}}();}(){;= 0;= 0;= 0;(i = 0; i <= ; )[i] = '\0';(i = 0; i <= ; )[i] = '\0';(i = 0; i < ; ){P[i] = ;P[i] = ;P[i] = 0;}= 0;(i = 0; i <= ; )}}( ){n;n = 0; /* ?*/( [n] '\0' [n]);('\0' [n])100 + n;n = 0; /* ?*/( [n] '\0' [n]);('\0' [n])n;-1;}/*输出或的内容*/(* ){k = 0;('\0' [k]){(" ", []);}("\n");}/*输入非终结符*/(){{[] = '\0';}n = 0;(('#' ) (n < )){(' ' '\n' -1 ()) {[] = ;;}= ();}[n] = '#'; /*以"#"标志结束用于判断长度是否合法*/ k = n;('#' ){( '#' ( = ())){('#' ( = ()));("\n符号数目超过限制!\n");= 1;;}{("输入正确确认?():");}("", );}('n' ){("录入错误重新输入!\n");= 1;}{= 0;}}}/*输入终结符*/(){= 1;;;(){("\n请输入所有的终结符,注意:"); ("以#号结束:\n");= ' ';n = 0;/*初始化数组*/(n < ){[] = '\0';}n = 0;(('#' ) (n < )){(' ' '\n' -1 ()){[] = ;;}= ();}[n] = '#';k = n;('#' ){( '#' ( = ())){('#' ( = ()));("\n符号数目超过限制!\n");= 1;;}}[k] = '\0';();= ' ';('y' 'n' ){('\n' ){("输入正确确认?():");}("", );}('n' ){("录入错误重新输入!\n");= 1;}{= 0;}}}/*产生式输入*/(){;i = 0, ;("请输入文法产生式的个数:");("", );= ;(); /*消除回车符*/("\n请输入文法的个产生式,并以回车分隔每个产生式:", ); ("\n");(i < ){("第个:", i);/*初始化*/(n =0; n < ; )[n] = '\0';/*输入产生式串*/= ' ';n = 0;('\n' ( = ()) n < ){(' ' )[] = ;}[n] = '\0';(()){*, *;P[i] = ([0]);= (*)(());> = ([3]);> = ;P[i] = ;n = 4;('\0' [n]){= (*)(());> = ([n]);> = ;> = ;= ;;}P[i] = n - 3;;}("输入符号含非法在成分,请重新输入!\n"); }}/*判断产生式正确性*/( * ){n;(100 > ([0]))('-' [1]);('>' [2]);(n = 3; '\0' [n]; n ) {(-1 ([n]));};}( U){;(i = 0; i < ; ){(P[i] U){* ;= P[i];j = 0;(j < P[i]){(100 > >){(U, >);;}{( [> - 100]){(>);}(U, >);((>));}{= >;}};}(j >= P[i]) /*当产生式右部都能推出空时*/ (U, -1);}}}/*加入集*/( U, ){*, *;; /*用于处理*/= ;= ;( < 100){= [U - 100];( ){(> );{= ;= >;}}( ){= ( *)(( ));> = ;( [U - 100]){[U - 100] = ;}{> = ; /*指向集的最后一个元素*/ }= >;}}{= [ - 100];( ){= >;(-1 ){(U, );}= >;}}}( ){( < 100);*;= [ - 100];( ){(-1 >);};}( V){i;* ;(100 V) /*当为初始符时*/(V, -1, 0 );(i = 0; i < ; ){= P[i];( > V)= >;( ){= >;( ){( [P[i] - 100] P[i] V) {(P[i]);}(V, P[i], 0);}{( (>)){(V, >, 1);= >;}( ){( [P[i] - 100] P[i] V) {(P[i]);}(V, P[i], 0);}{(V, >, 1);}}}}}( V, , ){*, *;;= ;= ;( < 100) /*为终结符时*/ {= [V - 100];( ){(> );{= ;= >;}}( ){= ( *)(( ));> = ;> = ;( [V - 100]){[V - 100] = ;}{> = ; /*指向集的最后一个元素*/ }= >;}}{(0 ){= [ - 100];( ){= >;(V, , 0);= >;}}{= [ - 100];( ){= >;(-1 ){(V, , 1);}= >;}}}}/*输出或集*/( **){i;*;i = 0;( [i]){= [i];("\:\t", [i]); ( ){(-1 >){(" ", [>]); }(" #");= >;};}("\n");}/*计算和*/(){i;i = 0;('\0' [i]){( [i])(100 + i);;}i = 0;('\0' [i]){( [i])(100 + i);;}}/*构造预测分析表*/(){i;*;*;(i = 0; i < ; ){= P[i];( (>)){= [> - 100];( ){(-1 >)[P[i] - 100][>] = i; = >;}= >;}( ){= [P[i] - 100];( ){(-1 >)[P[i] - 100][>] = i;[P[i] - 100][] = i; = >;}}{(100 <= >) /*不含空的非终结符*/ {= [> - 100];( ){[P[i] - 100][>] = i;= >;}}/*终结符或者空*/{(-1 >){= [P[i] - 100];( ){(-1 >)[P[i] - 100][>] = i;/*当含有#号时*/[P[i] - 100][] = i;= >;}}/*为终结符*/{[P[i] - 100][>] = i;}}}}}/*输出分析表*/(){;("构造预测分析表如下:\n");("\\t");(i = 0; i < ; ){("\t", [i]);}("#\t\n");("- - -\ - -\t");(i = 0; i <= ; )("- - -\t");("\n");(i = 0; i < ; ){("\\t", [i]);(j = 0; j <= ; ){(-1 [i][j])("R()\t", [i][j]);("\t");}("\n");}}( *){; /*r表使用的产生式的序号*/("\的分析过程:\n", );("步骤\t分析符号栈\t当前指示字符\t使用产生式序号\n"); = 0;= 0;("\t");();("\t\\t\ -\n", []);('#' []){(100 > []){([] ([])){();;;("\t", );();("\t\\t\t出栈、后移\n", []); }{("不匹配!", [], []);("此串不是此文法的句子!\n"); ;}}/*当为非终结符时*/{r = [[] - 100][([])];(-1 r){(r);;("\t", );();("\t\\t\\n", [], r);}{("此串不是此文法的句子!\n"); ;}}}('#' []){(0 '#' []){;("\t", );();("\t\\t\t分析成功!\n", []);("是给定文法的句子!\n", );}{( > 0){(100 > []){("此串不是此文法的句子!\n");;}{r = [[] - 100][];(-1 r){(r); /*产生式右部代替左部,指示器不移动*/ ;("\t", );();(0 '#' []){("\t\\t\t分析成功!\n", []);("是给定文法的句子!\n", );}("\t\\t\\n", [], r);}{("此串不是此文法的句子!\n");;}}}}}/*初始化栈与符号串*/(){i;/*分析栈的初始化*/(i = 0; i < ; )[i] = '\0';[0] = -1; /*#(-1)入栈*/[1] = 100; /*初始符入栈*/ = 1;}/*显示符号栈中内容*/(){i;(i = 0; i <= ; ){(100 <= [i])("", [[i] - 100]);{(-1 [i])("", [[i]]);("#");}}}/*栈顶出栈*/(){;}( r){*;();= P[r];(-1 >);P[r];(i = 0; i < P[r]; ) {[ - i] = >*逆序入栈*/ = >;}}运行结果演示:。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
表达式文法的预测分析表 i + * ( ) →TE' →TE' →+TE' →ε →FT' →FT' →ε →*FT' →ε →i →(E)
# →ε →ε
结论:一个文法G的预测分析表 的预测分析表M不含多 结论:一个文法 的预测分析表 不含多 重定义入口, 该文法为LL(1)文法 文法. 重定义入口 当且仅当 该文法为 文法
第四章 4.1 语法分析器的功能 4.2 自上而下分析面临的问题 4.3 LL(1)分析法 分析法 4.4 递归下降分析程序构造 4.5 预测分析程序 4.6 LL(1)分析中的错误处理 分析中的错误处理
4.5 预测分析程序 4.5.2 预测分析表的构造
(1)
计算FIRST集 集 计算 (2) 计算 计算FOLLOW集 集 (3) 计算 计算SELECT集* 集
E E' T T' F
G': E → TE' E'→ +TE'|ε T → FT' T'→ *FT'|ε F → (E) | i 推出 FIRST FOLLOW ε 集 集 N (,i ),# Y + ,ε ),# N (,i +,),# Y * ,ε +,),# N (,i *,+,),#
SELECT集合 集合 E→TE' (,i E'→+TE' + E'→ε ),# T → FT' ( , i T'→ *FT' * T'→ ε +,),# F → (E) ( F→ i i
构造预测分析表 对每个终结符或"#", 用a表示 表示. 对每个终结符或 表示 • 若a∈SELECT(A→α) , ∈ 放入M[A,a]中 把A→α放入放入 中 • 把所有无定义的 把所有无定义的M[A,a] 标上出错标记 或 标上出错标记(或 空白) 空白 • 产生式的左部可以不写入表中
E E' T T' F