算符优先分析算法

合集下载

编译原理-清华大学-第5章-自底向上优先分析法(2+1)

编译原理-清华大学-第5章-自底向上优先分析法(2+1)

第六章自底向上优先分析方法•教学要求:了解简单优先分折法,掌握算符优先分析法的关系表的构造以及分析过程。

•教学重点:算符优先表构造及算符优先分析法。

1自底向上分析法的基本思想•从输入串开始,朝着文法的开始符号进行最左归约,直到到达文法的开始符号为止。

•工作方式:“移进-归约”方式。

2分析程序模型1)初态时栈内仅有栈底符“#”,读头指针在最左单词符号上。

2)语法分析程序执行的动作:a)移进读入一个单词并压入栈内,读头后移;b)归约检查栈顶若干个符号能否进行归约,若能,就以产生式左部替代该符号串,同时输出产生式编号;c)识别成功移进-归约的结局是栈内只剩下栈底符号和文法开始符号,读头也指向语句的结束符;d)识别失败语法分析程序语法表a+b……#输出带#3例如:有文法如下(1)S→aAcBe(2)A→b(3)A→Ab(4)B→d问:语句abbcde是不是该文法的合法语句?4•例:设文法G(S):(1) S aAcBe(2) A b(3) A Ab(4) B d 试对abbcde进行“移进-归约”分析。

bbcde bbcde b cde de deabbcde eB cA a SB A a 5成功11接受2,3,4,1##S 10归约##aAcBe 9移进2,3,4e ##aAcB 8归约e ##aAc d 7移进de ##aAc 6移进2,3cde ##aA 5归约cde ##a Ab 4移进2bcde ##aA 3归约bcde ##a b 2移进bbcde ##a 1移进abbcde ##0动作输出带输入串栈步骤移进归约的分析过程G[S]:(1)S →aAcBe(2)A →b(3)A →Ab(4)B →d 6遇到的问题:(1)如何找出进行直接归约的简单短语?(2)找出的简单短语应直接归约到哪一个非终结符?关键:确定句柄.常用的分析方法:(1)优先分析法(2)LR分析法7b db ac eSA B A d b a c e S A B A d a c eSA B a c e A B S 没有语法树如何确定句柄?86.1 自底向上优先分析法概述•基本思想:利用文法符号中相邻符号之间的优先关系(谁先规约的优先关系)找出句柄。

编译原理实验报告5_语法分析程序的设计(2)

编译原理实验报告5_语法分析程序的设计(2)

实验5 语法分析程序的设计(2)一、实验目的通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析中算法优先分析方法。

二、实验内容设计一个文法的算法优先分析程序,判断特定表达式的正确性。

三、实验要求1、给出文法如下:G[E]E->T|E+T;T->F|T*F;F->i|(E);2、计算机中表示上述优先关系,优先关系的机内存放方式有两种1)直接存放,2)为优先关系建立优先函数,这里由学生自己选择一种方式;1、给出算符优先分析算法如下:k:=1; S[k]:=‘#’;REPEAT把下一个输入符号读进a中;IF S[k]∈V T THEN j:=k ELSE j:=k-1;WHILE S[j] a DOBEGINREPEATQ:=S[j];IF S[j-1]∈V T THEN j:=j-1 ELSE j:=j-2UNTIL S[j] Q把S[j+1]…S[k]归约为某个N;k:=j+1;S[k]:=N;END OF WHILE;IF S[j] a OR S[j] a THENBEGINk:=k+1;S[k]:=aENDELSE ERRORUNTIL a=‘#’1、根据给出算法,利用适当的数据结构实现算符优先分析程序;2、利用算符优先分析程序完成下列功能:1)手工将测试的表达式写入文本文件,每个表达式写一行,用“;”表示结束;2)读入文本文件中的表达式;3)调用实验2中的词法分析程序搜索单词;4)把单词送入算法优先分析程序,判断表达式是否正确(是否是给出文法的语言),若错误,应给出错误信息;5)完成上述功能,有余力的同学可以对正确的表达式计算出结果。

四、实验环境PC微机DOS操作系统或 Windows 操作系统Turbo C 程序集成环境或 Visual C++ 程序集成环境五、实验步骤1、分析文法中终结符号的优先关系;2、存放优先关系或构造优先函数;3、利用算符优先分析的算法编写分析程序;4、写测试程序,包括表达式的读入和结果的输出;5、程序运行效果,测试数据可以参考下列给出的数据。

算符优先文法最左素短语的一种判断算法

算符优先文法最左素短语的一种判断算法

算符优先文法最左素短语的一种判断算法
本文旨在介绍计算符优先文法最左素短语的一种判断算法,以帮助读者更加了
解此领域的知识。

计算符优先文法最左素短语算法(简称LP)是一种基于自动机的判断文法的
算法,它的任务是判断一个表达式的最左子程序中的符号是否为最左素短语。

LP算法根据文法产生式的属性构造一个状态转换图(简称状态图),根据该
状态图建立一个有限状态自动机(简称FSM),并根据FSM的状态变化进行判断。

状态转换图由状态和转换组成,它标识自动机在文法分析中所承担的每一个状态,转换总是于每个字符符号有关,其中转换是由当前状态和当前符号所确定的,并且一个特定的转换总是指向一个特定的状态。

LP算法在判断最左素短语时,首先根据文法和符号列表构造状态转换图和FSM,然后比较非终结符号和终结符号,如果当前输入的符号是非终结符号,则进行转换,如果当前输入的符号是终结符号,则停止判断并进行下一个符号的判断。

如果所有的符号都被判断完毕,则表明此表达式的最左子程序是最左素短语。

总的来说,计算符优先文法最左素短语的一种判断算法的基本思路是构造状态
转换图,根据文法构造FSM,并根据FSM进行状态转换和符号判断,最终来确定表
达式的最左子程序是否是最左素短语。

LP算法为文法分析和程序设计提供了高效
的算法,使文法分析更加简单易懂,从而为程序设计提供了更多可能性。

3.4 自下而上分析方法

3.4 自下而上分析方法
8
d aAbB
2014-10-5
分析过程的特点
1. 从输入串的开头依次读入(移进)单词。 2. 一旦发现可归约串(在上例中是句柄)就立即 归约。 3. 根据句柄对分析树进行修剪子树,剪去子树 的叶子。 4. 若最终能归约成文法的开始符号,则分析成 功。 5. 由于总是将句型的最左边的可归约串替换成 非终结符号,该归约方法通常得到是最右推 导的逆过程。

2014-10-5
2
自顶向下分析算法的基本思想为: 若Z S
G[Z] +
则 S L(G[Z])
否则 S L(G[Z])
存在主要问题: 左递归问题 回溯问题
主要方法: • 递归子程序法 • LL(1)分析法
自底向上分析算法的基本思想为: 若Z S
G[Z] +
则 S L(G[Z])
2014-10-5 20
假定G是一个不含ε产生式的算符文法, 对任一对终结符a,b, 定义 (1) a≐b当且仅当文法G中含有形如 P→…ab… 或 P→…aQb…的产生式; (2) a⋖b当且仅当G中含有形如 P→…aR…的产生式, + + 而R b… 或 R Qb…; (3) a⋗b当且仅当G中含有形如 P→…Rb…的产生式, + + 而R …a 或 R aQ。
3)算符优先分析的特点:

仿效四则运算过程,预先规定相邻终结符 之间的优先关系,然后利用这种优先关系 来确定句型的“句柄” ,并进行规约。
输入串 # 符号栈 # 分析程序 (优先关系矩阵)
18
4)分析器结构:
2014-10-5
概 述:

所谓算符优先分析,就是预先规定运算 符(确切地说是终结符)之间的优先关系和 结合性质,借助于这种优先关系来比较 相邻运算符的优先级,以确定句型的可 归约串并进行归约。 注意:算符优先分析不是规范归约。

算符优先分析算法(c语言)

算符优先分析算法(c语言)

编译原理实验一实验目的设计、编制并调试一个算符优先分析算法,加深对此分析法的理解二实验过程先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。

分析过程从头开始,并重复进行;若读来的是运算符θ2则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。

2.2 各种单词符号对应的种别码2.3 算符优先程序的功能完成一个交互式面向对象的算符优先分析程序,而一个交互式面向对象的算符优先分析程序基本功能是:(1)输入文法规则(2)对文法进行转换(3)生成每个非终结符的FirstVT和LastVT(4)生成算符优先分析表(5)再输入文法符号(6)生成移进规约步骤三设计源码算符优先分析器#include "stdio.h"#include "stdlib.h"#include "iostream.h"char data[20][20]; //算符优先关系char s[100]; //模拟符号栈schar lable[20]; //文法终极符集char input[100]; //文法输入符号串char string[20][10]; //用于输入串的分析int k;char a;int j;char q;int r; //文法规则个数int r1;int m,n,N; //转化后文法规则个数char st[10][30]; //用来存储文法规则char first[10][10]; //文法非终结符FIRSTVT集char last[10][10]; //文法非终结符LASTVT集int fflag[10]={0}; //标志第i个非终结符的FIRSTVT集是否已求出int lflag[10]={0}; //标志第i个非终结符的LASTVT集是否已求出int deal(); //对输入串的分析int zhongjie(char c); //判断字符c是否是终极符int xiabiao(char c); //求字符c在算符优先关系表中的下标void out(int j,int k,char *s); //打印s栈void firstvt(char c); //求非终结符c的FIRSTVT集void lastvt(char c); //求非终结符c的LASTVT集void table(); //创建文法优先关系表void main(){int i,j,k=0;printf("请输入文法规则数:");scanf("%d",&r);printf("请输入文法规则:\n");for(i=0;i<r;i++){scanf("%s",st[i]); //存储文法规则,初始化FIRSTVT集和LASTVT集*/first[i][0]=0; /*first[i][0]和last[i][0]分别表示st[i][0]非终极符的FIRSTVT集和LASTVT集中元素的个数*/ last[i][0]=0;}for(i=0;i<r;i++) //判断文法是否合法{for(j=0;st[i][j]!='\0';j++){if(st[i][0]<'A'||st[i][0]>'Z'){printf("不是算符文法!\n");exit(-1);}if(st[i][j]>='A'&&st[i][j]<='Z'){if(st[i][j+1]>='A'&&st[i][j+1]<='Z'){printf("不是算符文法!\n");exit(-1);}}}}for(i=0;i<r;i++){for(j=0;st[i][j]!='\0';j++){if((st[i][j]<'A'||st[i][j]>'Z')&&st[i][j]!='-'&&st[i][j]!='>'&&st[i][j]!='| ')lable[k++]=st[i][j];}}lable[k]='#';lable[k+1]='\0';table();printf("每个非终结符的FIRSTVT集为:\n"); //输出每个非终结符的FIRSTVT集for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<first[i][0];j++){printf("%c ",first[i][j+1]);}printf("\n");}printf("每个非终结符的LASTVT集为:\n"); //输出每个非终结符的LASTVT集for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<last[i][0];j++){printf("%c ",last[i][j+1]);}printf("\n");}printf("算符优先分析表如下:\n");for(i=0;lable[i]!='\0';i++)printf("\t%c",lable[i]);printf("\n");for(i=0;i<k+1;i++){printf("%c\t",lable[i]);for(j=0;j<k+1;j++){printf("%c\t",data[i][j]);}printf("\n");}printf("请输入文法输入符号串以#结束:");scanf("%s",input);deal();}void table(){char text[20][10];int i,j,k,t,l,x=0,y=0;int m,n;x=0;for(i=0;i<r;i++){firstvt(st[i][0]);lastvt(st[i][0]);}for(i=0;i<r;i++){text[x][y]=st[i][0];y++;for(j=1;st[i][j]!='\0';j++){if(st[i][j]=='|'){text[x][y]='\0';x++;y=0;text[x][y]=st[i][0];y++;text[x][y++]='-';text[x][y++]='>';}else{text[x][y]=st[i][j];y++;}}text[x][y]='\0';x++;y=0;}r1=x;printf("转化后的文法为:\n");for(i=0;i<x;i++) //输出转化后的文法规则串{printf("%s\n",text[i]);}for(i=0;i<x;i++) /*求每个终结符的推导结果(去掉"->"后的转化文法,用于最后的规约)*/ {string[i][0]=text[i][0];for(j=3,l=1;text[i][j]!='\0';j++,l++)string[i][l]=text[i][j];string[i][l]='\0';}for(i=0;i<x;i++){for(j=1;text[i][j+1]!='\0';j++){if(zhongjie(text[i][j])&&zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+1]);data[m][n]='=';}if(text[i][j+2]!='\0'&&zhongjie(text[i][j])&&zhongjie(text[i][j+2])&&!zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+2]);data[m][n]='=';}if(zhongjie(text[i][j])&&!zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j+1])break;}m=xiabiao(text[i][j]);for(t=0;t<first[k][0];t++){n=xiabiao(first[k][t+1]);data[m][n]='<';}}if(!zhongjie(text[i][j])&&zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j])break;}n=xiabiao(text[i][j+1]);for(t=0;t<last[k][0];t++){m=xiabiao(last[k][t+1]);data[m][n]='>';}}}}m=xiabiao('#');for(t=0;t<first[0][0];t++){n=xiabiao(first[0][t+1]);data[m][n]='<';}n=xiabiao('#');for(t=0;t<last[0][0];t++){m=xiabiao(last[0][t+1]);data[m][n]='>';}data[n][n]='=';}void firstvt(char c) //求FIRSTVT集{int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(fflag[i]==0){n=first[i][0]+1;m=0;do{if(m==2||st[i][m]=='|'){if(zhongjie(st[i][m+1])){first[i][n]=st[i][m+1];n++;}else{if(zhongjie(st[i][m+2])){first[i][n]=st[i][m+2];n++;}if(st[i][m+1]!=c){firstvt(st[i][m+1]);for(j=0;j<r;j++){if(st[j][0]==st[i][m+1])break;}for(k=0;k<first[j][0];k++)int t;for(t=0;t<n;t++){if(first[i][t]==first[j][k+1])break;}if(t==n){first[i][n]=first[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');first[i][n]='\0';first[i][0]=--n;fflag[i]=1;}}void lastvt(char c) //求LASTVT集{int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(lflag[i]==0){n=last[i][0]+1;m=0;do{if(st[i][m+1]=='\0'||st[i][m+1]=='|'){if(zhongjie(st[i][m])){last[i][n]=st[i][m];}else{if(zhongjie(st[i][m-1])){last[i][n]=st[i][m-1];n++;}if(st[i][m]!=c){lastvt(st[i][m]);for(j=0;j<r;j++){if(st[j][0]==st[i][m])break;}for(k=0;k<last[j][0];k++){int t;for(t=0;t<n;t++){if(last[i][t]==last[j][k+1])break;}if(t==n){last[i][n]=last[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');last[i][n]='\0';last[i][0]=--n;lflag[i]=1;}}int deal(){int i,j;int x,y;int z; //输入串的长度k=1;s[k]='#'; //栈置初值for(i=0;input[i]!='\0';i++); //计算输入串的长度z=i--;i=0;while((a=input[i])!='\0'){if(zhongjie(s[k]))j=k;elsej=k-1;x=xiabiao(s[j]);y=xiabiao(a);if(data[x][y]=='>'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("规约\n");do{q=s[j];if(zhongjie(s[j-1]))j=j-1;else j=j-2;x=xiabiao(s[j]);y=xiabiao(q);}while(data[x][y]!='<');int m,n,N;for(m=j+1;m<=k;m++){for(N=0;N<r1;N++)for(n=1;string[N][n]!='\0';n++){if(!zhongjie(s[m])&&!zhongjie(string[N][n])){if(zhongjie(s[m+1])&&zhongjie(string[N][n+1])&&s[m+1]==string[N][n+1]){s[j+1]=string[N][0];break;}}elseif(zhongjie(s[m]))if(s[m]==string[N][n]){s[j+1]=string[N][0];break;}}}k=j+1;if(k==2&&a=='#'){out(1,k,s);printf("%c",a);out(i+1,z,input);printf("结束\n");printf("输入串符合文法的定义!\n");return 1; //输入串符合文法的定义}}elseif(data[x][y]=='<'||data[x][y]=='='){ //移进out(1,k,s);printf("%c",a);out(i+1,z,input);printf("移进\n");k++;s[k]=a;i++;}else{printf("\nflase");return 0;}}printf("\nflase");return 0;}void out(int j,int k,char *s){int n=0;int i;for(i=j;i<=k;i++){printf("%c",s[i]);n++;}for(;n<15;n++){printf(" ");}}int xiabiao(char c) //求字符c在算符优先关系表中的下标{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return i;}return -1;}int zhongjie(char c) //判断字符c是否是终极符{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return 1;}return 0;}四实验结果。

第六章 语法分析-自下而上分析法

第六章 语法分析-自下而上分析法

一、自下而上语法分析的基本问题 1.归约: 如何判断栈顶符号的可归约性以及如何归约,是 自下而上分析的中心问题。 2.短语和句柄
如果S ⇒ αAβ and A ⇒γ,则称γ是句型 αγβ的相对于变量A的短语 * 如果S ⇒αAβ and A⇒γ,则称γ是句型 αγβ的相对于变量A的直接(简单)短语 最左直接短语叫做句柄
e
abbcde
一、自下而上语法分析的基本问题 (3)自下而上分析的关键问题
似乎移进-归约过程很简单,其实不然,在上面第5步,如果用 规则2(P → b)进行归约而不是用规则3(P → Pb)进行归约,结果 会怎么样呢? 上面的归约过程是从文法的句子abbcde开始,每一步都是把最 左直接短语(句柄)替换为相应产生式的左部符号(在步骤5时 栈顶为#aPb,此时是将b归约为P还是将Pb归约为P?由于此时对 于句型aPbcde(即栈内容+输入缓冲区内容)来说Pb是句柄,故 将Pb归约为P)。也就是说,自底向上分析的关键问题是在分析 中如何确定句柄(准确地说为可归约串),即如果知道何时在 栈顶符号串中已形成了某句型的句柄,那么就可以确定何时进 行归约。对此,不同的分析方法有不同的解决办法。这里主要 介绍算符优先及LR分析方法。
例: 移进—归约分析(Shift-reduce parsing)
要点:建立符号栈,用来纪录分析的历史和现状, 并根据所面临的状态,确定下一步动作是移 进还是归约。
输入串 # 符号栈 #
S.R.P
输入串 # 符号栈 #
S.R.P
分析过程:把输入符号串按自左向右顺序一一地 移进符号栈(一次移一个),检查栈中符号,当在栈 顶的若干符号形成当前句型的句柄时,就根据规则进 行归约,将句柄从符号栈中弹出,并将相应的非终结 符号压入栈内(即规则的左部符号),然后再检查栈 内符号串是否形成新的句柄,若有就再进行归约,否 则移进符号。分析一直进行到读到输入串的右界符为 止。最后,若栈中仅含有左界符号和识别符号,则表 示分析成功,否则失败

算符优先分析法

算符优先分析法

G[E]: E→E+E|E-E|E*E|E/E|EE|(E)|-E|id


由于该文法是一个二义文法,它的句子往往有不同的规范推导和 归约,实际运算会得到不同结果,但按传统的习惯规定优先级和 结合律进行归约,优先级从高到低为:乘幂运算符,乘、除运算符, 加、减运算符;同级运算符服从左结合原则;有括号时,先括号 内后括号外。 则文法的句子id+id-id*(id+id)的归约过程为:

N1…Ni-1<· Ni …… Nj · >Nj+1…Nn
2.
句型中Ni„„Nj是句柄,语法分析程序可以通过寻找 Ni-1<· Ni和Nj· >Nj+1这两个关系来确定句柄的头尾,从 而确定句柄进行归约。
帮助理解 abce # 控制程序 # ce # b a #
G[S]: S→aBe B→bc bce # 控制程序 e #
知识点



算符优先分析法的算法简单、直观、易于理解,所以通常作为学 习其它自下而上语法分析的基础。 需复习有关语法分析的知识有:什么是语言、文法、句子、句型、 短语、简单短语、句柄、最右推导、规范归约基本概念。 本章重难点 算符文法的形式。 对一个给定的算符文法能构造算符优先关系分析表,并能判别所 给文法是否为 算符优先文法。 分清规范句型的句柄和最左素短语的区别,进而分清算符优先归 约和规范归约的区别。(在分析过程中如何寻找可归约串) 对一个给定的输入串能应用算符优先关系分析表给出分析(归约) 步骤,并最终判断所给输入串是否为该文法的句子。
输出带
2
2,3
2,3,4
2,3,4,1
S
a
A A b b
c
B e d

算符优先实验报告

算符优先实验报告

算符优先实验报告算符优先实验报告引言算符优先是一种用于描述和分析算术表达式的语法分析方法。

在本次实验中,我们将通过编写一个算符优先分析器来深入理解算符优先算法的原理和应用。

实验目的1. 了解算符优先算法的基本原理和概念;2. 掌握算符优先算法的具体实现方法;3. 实现一个简单的算符优先分析器,用于分析和判断输入的算术表达式是否符合文法规则。

实验过程1. 算符优先的基本原理算符优先算法是一种自底向上的语法分析方法,用于判断算术表达式中运算符的优先级关系。

它通过构建一个算符优先关系表来实现对表达式的分析和判断。

2. 算符优先的概念和定义算符优先表是一个二维表格,行和列分别表示算术表达式中的运算符。

表格中的每个元素表示两个运算符之间的优先关系,可以是大于、小于或等于。

根据这个表格,我们可以判断两个相邻的运算符之间的优先级关系。

3. 算符优先分析器的实现为了实现一个算符优先分析器,我们首先需要构建算符优先表。

算符优先表的构建需要根据文法规则和运算符的优先级来确定。

在本次实验中,我们假设算术表达式中只包含加法和乘法运算符,并且加法运算符的优先级高于乘法运算符。

4. 算符优先分析的过程算符优先分析的过程可以分为两个步骤:扫描和规约。

在扫描过程中,我们从左到右扫描输入的算术表达式,并将扫描到的运算符和操作数依次入栈。

在规约过程中,我们根据算符优先表中的优先关系,将栈中的符号进行规约,直到最终得到一个唯一的非终结符号。

实验结果与分析通过实验,我们成功实现了一个简单的算符优先分析器,并对不同的算术表达式进行了分析和判断。

实验结果表明,算符优先分析器能够准确地判断算术表达式的语法正确性,并且能够正确地处理运算符的优先级关系。

结论算符优先算法是一种常用的语法分析方法,能够有效地判断算术表达式的语法正确性。

通过本次实验,我们深入理解了算符优先算法的原理和应用,并成功实现了一个简单的算符优先分析器。

这对我们进一步学习和应用语法分析方法具有重要的意义。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

数学与计算机学院编译原理实验报告年级09软工学号姓名成绩专业软件工程实验地点主楼指导教师湛燕实验项目算符优先关系算法实验日期2012.6.6一、实验目的和要求设计一个算符优先分析器,理解优先分析方法的原理。

重点和难点:本实验的重点是理解优先分析方法的原理;难点是如何构造算符优先关系。

二、实验内容使用算符优先分析算法分析下面的文法:E’→ #E#E → E+T | TT → T*F | FF → P^F | PP → (E) | i其中i可以看作是一个终结符,无需作词法分析。

具体要求如下:1、如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的变化情况;2、如果输入符号串不是正确句子,则指示出错位置。

三、程序设计全局变量有一下几个:static string input;//记录输入串char s[20];//栈int top=-1;//栈顶指针有三个函数:int analyze(string input);//分析输入的串是否符合标准void process();//进行归约的函数int main()input是一个全局变量,记录输入串,用analyze(input)分析输入的是不是符合标准的字符串,(例如“i+i*i^(i+i)”)如果不符合标准,提示用户重新输入。

进行归约的函数主要思想是:先构造优先关系矩阵,有“<”,“>”,“=”和空格四种关系。

Char a 记录栈中最高位的终结符,如果栈中是#E+E,则 a 的赋值是“+”,如果形如“#E+”或“#E+i”则a 赋值“+”或“i”。

charnowchar 记录当前的字符。

a 与 nowchar 按照算符优先关系矩阵找出优先关系。

如果优先关系是“<”,则进行移进;如果优先关系是“>”,则进行归约;如果是“=”,则去掉括号或分析成功。

五、代码和截图自己编写代码如下:#include <iostream>#include <string>using namespace std;static string input;//输入串char s[20];//栈int top=-1;//栈顶指针char VT[7]={'+','*','^','i','(',')','#'};//终结符static char matrix[7][7]={'>','<','<','<','<','>','>','>','>','<','<','<','>','>','>','>','<','<','<','>','>','>','>','>',' ',' ','>','>','<','<','<','<','<','=',' ','>','>','>',' ',' ','>','>','<','<','<','<','<',' ','='}; //优先关系矩阵,不存在优先关系时为空格int analyze(string input);//分析输入的串是否符合标准void process();//规约int main(){//cout<<"输入一个符号串!"<<endl;int flag=1;while(flag==1){cout<<"输入一个符号串!"<<endl;cin>>input;if(analyze(input)==0)flag=1;elseflag=0;}cout<<"***********************************************************"<<endl;cout<<" 表达式文法算符优先关系表"<<endl;cout<<endl;for(inti=0;i<8;i++){cout<<" "<<VT[i];}cout<<endl;cout<<endl;for(i=0;i<7;i++){cout<<VT[i];for(int j=0;j<7;j++){cout<<" ";cout<<matrix[i][j];}cout<<endl;}//cout<<<<endl;cout<<"***********************************************************"<< endl;cout<<"对输入串"<<input<<"的算符优先分析过程如下:"<<endl;process();cout<<""<<endl;//cout<<" 栈"<<" 优先关系"<<" 当前符号"<<" 剩余输入串"<<" 移进或规约"<<endl;cout<<""<<endl;cout<<""<<endl;cout<<""<<endl;return 1;}int analyze(string input)//分析输入的串是否符合标准{//cout<<input[0]<<input[1]<<input[2]<<input[3]<<endl;intlen = input.length();//获得输入串长度//cout<<len<<endl;int flag=0;//char t;////char temp;for(inti=0;i<len;i++){if((input[len-1]!='i')&&(input[len-1]!=')')) {flag=1;break;}//cout<<input[len-1]<<endl;switch(input[i]){case '(':if(i==0){}else if(input[i-1]=='^'||'+'||'*'){}elseflag=1;break;case ')':if(input[i-1]=='i'){}elseflag=1;break;case '*':if(input[i-1]=='i'||')'){}//cout<<i<<flag<<endl;elseflag=1;break;case '^':if(input[i-1]=='i'||')'){}//cout<<i<<flag<<endl;elseflag=1;break;case '+':if(input[i-1]=='i'||')'){}//cout<<i<<flag<<endl;elseflag=1;break;case 'i':{if(input[len-1]=='i')flag=1;else{}}//cout<<i<<flag<<"输入的是正确的字符串!"<<endl;break;default://cout<<flag<<endl;flag=1;break;}}//int flag=0;if(flag==0){cout<<"输入的是正确的句子!"<<endl;return 1;}else{cout<<"输入的是错误的句子!"<<endl;return 0;}}void process()//规约{//cout<<s<<endl;//cout<<top;int row;//列int line;//行s[++top]='#';//input="i+i*(i+i)";//cout<<input<<endl;input=input+'#';////cout<<input<<endl;//char temp;inti=0;int k=0;int g;char a;//char nowchar;//++top;//s[top]=input[i];//cout<<s[top-1]<<endl;//cout<<input[i]<<endl;//cout<<s[top]<<endl;int flag=0;char nowchar;//记录当前字符cout<<endl;cout<<"栈"<<" 优先关系"<<" 当前符号"<<" 剩余输入串"<<" 移进或归约"<<endl;nowchar=input[0];while(flag==0)//s[2]!='#'{ //k++;if(s[top]=='E')a=s[top-1];elsea=s[top];for(int n=0;n<7;n++)//记录行{if(a==VT[n])line=n;}for(n=0;n<7;n++)//记录列{if(nowchar==VT[n])row=n;}char compare;for(int m=0;m<7;m++)for(n=0;n<7;n++){if((line==m)&&(row==n))compare=matrix[m][n];}int j;//i=top;///cout<<"******"<<compare<<"******"<<endl;switch(compare){case '<':{//cout<<" ";for(j=0;j<=top;j++)cout<<s[j];//cout<<"@"<<a;//cout<<line<<row;cout<<"&&&"<<s[top]<<a<<c ompare;//cout<<"(栈)";cout<<" <";cout<<" "<<input[i]<<" ";for(j=strlen(s);j<input.length ();j++)cout<<input[j];cout<<" 移进";//<<10-strlen(s)s[++top]=input[i];//移进if(nowchar=='#'){}elsenowchar=input[strlen(s)-1];//cout<<nowchar;cout<<endl;//cout<<"(剩余输入串)"<<endl;//cout<<endl;i++;break;}case '>'://cout<<" ";for(j=0;j<=top;j++)cout<<s[j];//cout<<"@"<<a;///cout<<"&&&"<<s[top]<<a; cout<<" >";cout<<" "<<input[i]<<" ";//cout<<" ";for(j=strlen(s);j<input.length ();j++)cout<<input[j];//cout<<" "<<endl;cout<<endl;if(s[top]=='E'){top=top-2;s[top]='E';}else if(s[top]==')'){top=top-2;s[top]='E';}elses[top]='E';//归约//cout<<s[top];//if((s[top]=='E')||(s[top]==')'))//i++;if(nowchar=='#'){}elsenowchar=input[strlen(s)-1];cout<<" 归约"<<endl;break;case '=':if(s[top-1]=='('){top=top-1;//a=s[top];s[top]='E';nowchar='#';}//if(s[top-1]=='(')// {//nowchar='#';// }else//cout<<"规约成功"<<endl;{cout<<"#E# 接受"<<endl;flag=1;}break;}//cout<<s[j];}//}如果输入的句子是错误的,提示错误,并要求重新输入。

相关文档
最新文档