实验4 算符优先分析法.
算符优先文法实验报告

《编译原理》课程实验报告实验名称:算符优先文法姓名学号:地点:教师院系:计算机与通信工程学院专业:计算机科学与技术09-2一.实验目的设计、编制并调试一个算符优先法分析程序,加深对算符优先法分析原理的理解。
二.实验内容算术表达式的文法:(1).E → E +T | E -T | T(2).T → T * F | T / F | F(3).F → i |(E)转化后的文法:(1).E → E +T(2).E → E -T(3).E → T(4).T → T * F(5).T →T / F(6).T →F(7).F → i(8).F →(E)根据表达式的文法,首先计算每个非终结符的FIRSTVT和LASTVT:执行算法逐条扫描文法规则,从而构造出文法的算符优先关系表如图所示用算符优先分析法法对该文法进行分析,在每次归约成功后则输出四元式。
四元式形式如下:(op,arg1,arg2,result)其中op是运算符,arg1,arg2分别是第一和第二个运算对象,当op是一目运算时,常常将运算对象定义为arg1.例如,表达式-C和赋值语句X=a的四元式可分别表示为(i)(@,C,-,T)(j)(=,a,-,X)三.源代码:#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAXSIZE 64 //栈的大小#define N -10typedef char datatype; //以char作为栈中元素typedef struct //定义一个栈结构{datatype data[MAXSIZE];int top;}seqstack;seqstack OPR; //操作数栈OPRseqstack OPT; //申明操作符栈char *p; //全局变量指针,用来指向待分析字符串int matrix[7][7]={{N,-1,-1,-1,-1,N,1}, //算符优先矩阵{N,1,-1,-1,-1,1,1},{N,1,1,-1,-1,1,1},{1,1,1,N,N,1,1},{N,-1,-1,-1,-1,0,N},{N,1,1,N,N,1,1},{-1,N,N,-1,N,N,0}};int row,line; //全局变量,分别来表示算符优先矩阵的行和列int count=1;int compare(char m,char n){ //算符的优先级switch(m){case '=':row=0;break;case '+':row=1;break;case '*':row=2;break;case 'i':row=3;break;case '(':row=4;break;case ')':row=5;break;case '$':row=6;break;default: return -100;break;}switch(n){case '=':line=0;break;case '+':line=1;break;case '*':line=2;break;case 'i':line=3;break;case '(':line=4;break;case ')':line=5;break;case '$':line=6;break;default: return -100;break;}return matrix[row][line];}//定义对操作数栈的基本操作void OPRsetnull() //设置操作数栈空{OPR.top=-1;}bool OPRempty() //判断操作数栈是否为空{if(OPR.top>=0)return false;elsereturn true;}void OPRpush(char x) //往操作数栈push一个操作数i{printf("上溢!");else {OPR.top++;OPR.data[OPR.top]=x;}}datatype OPRpop() //从操作数栈中pop出一个操作数{if(OPRempty()){printf("下溢!");return NULL;}else{OPR.top--;return(OPR.data[OPR.top+1]);}}//定义对操作数栈的基本操作结束datatype OPRtop() //获取操作数栈的栈顶的操作数{if(OPRempty()){return NULL;}elsereturn(OPR.data[OPR.top]);}void OPTsetnull() //设置操作符栈空{OPT.top=-1;}bool OPTempty() //判断操作符栈是否为空{if(OPT.top>=0)return false;elsereturn true;}void OPTpush(char x) //往操作符栈push一个操作数{printf("上溢!");else{OPT.top++;OPT.data[OPT.top]=x;}}datatype OPTpop() //从操作数符中pop出一个操作数{if(OPTempty()){printf("下溢!");return NULL;}else{OPT.top--;return(OPT.data[OPT.top+1]);}}datatype OPTtop() //获取操作符栈的栈顶的操作数{if(OPTempty()){return NULL;}else return(OPT.data[OPT.top]);}//定义对操作符栈的基本操作结束void output(char opt,char op1,char op2,int num) //输出四元式{if(op1=='i'&&op2=='i') printf("(%c,%c,%c,t%d)\n",opt,op1,op2,num);if(op1!='i'&&op2=='i') printf("(%c,t%d,%c,t%d)\n",opt,op1,op2,num);if(op2!='i'&&op1=='i') printf("(%c,%c,t%d,t%d)\n",opt,op1,op2,num);if(op1!='i'&&op2!='i') printf("(%c,t%d,t%d,t%d)\n",opt,op1,op2,num); }void scan()//扫描语法分析程序{char opt;char op1,op2;if(*p=='$') OPTpush(*p);//将待分析的字符串的首字符$压栈p++;while(*p!='$')//循环直到待分析字符串尾{if(*p=='i') OPRpush(*p);//如果当前字符是操作数则入栈,只有i一种操作数else {opt=OPTtop();//否则是操作符与操作符栈顶的字符比较优先级P: switch(compare(opt,*p)){case -1: OPTpush(*p); break;//如果栈顶操作符优先级下,则将当前字符压栈case N: break;//若无优先级则说明待分析字符有误,不合语法规范//出现语法错误case 0: OPTpop(); break;//若操作符优先级相等则说明栈顶//符合当前操作符分别是左右括号//将栈顶的左括号出栈即可case 1: op1=OPRpop();//若栈顶操作符优先级高,则将操作符栈最上两个操作数出栈op2=OPRpop();output(opt,op1,op2,count);//输出四元式OPRpush(count); //并将生成的t的序数压栈(t1,t2等);count++;opt=OPTpop();//将已规约的输出的操作符出栈opt=OPTtop();//取栈顶操作符跳转到继续下一步。
实验四算符优先分析法分析器的设计

实验四算符优先分析法分析器的设计(6学时)
【目的】设计一个算符优先分析器,理解优先分析方法的原理。
【要求】使用算符优先分析算法分析下面的文法:
E’ →#E#
E →E+T | T
T →T*F | F
F →(E) | i
其中i可以看作是一个终结符,无需作词法分析。
具体要求如下:
1.如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的
变化情况;
2.如果输入符号串不是正确句子,则指示出错位置。
【方法】首先构造算符优先关系表,然后根据算符优先分析算法编写程序。
【实验环境和工具】本实验不限定现所使用的开发工具以及运行环境。
算符优先实验报告

算符优先实验报告《算符优先实验报告》引言算符优先是一种用于解决算术表达式中运算符优先级的算法,它可以帮助我们在计算表达式时确定运算符的优先级,从而得到正确的计算结果。
本实验旨在通过编写算符优先算法的程序,来深入理解算符优先的原理和应用。
实验目的1. 了解算符优先算法的原理和应用。
2. 掌握算符优先算法的程序设计方法。
3. 实现一个能够正确解析算术表达式并计算结果的程序。
实验内容1. 算符优先算法的原理和应用算符优先算法是一种基于文法的算法,它通过分析运算符之间的优先级和结合性来确定表达式的计算顺序。
在算符优先算法中,每个运算符都有一个优先级,高优先级的运算符先进行计算,低优先级的运算符后进行计算。
此外,算符优先算法还要考虑到运算符的结合性,即左结合或右结合。
2. 算符优先算法的程序设计方法为了实现算符优先算法,我们需要首先定义运算符的优先级和结合性,然后编写程序来解析表达式并按照算符优先规则进行计算。
在程序设计中,我们可以使用栈来辅助进行运算符的优先级判断和计算顺序的确定。
3. 实现一个能够正确解析算术表达式并计算结果的程序在本实验中,我们将编写一个简单的算符优先算法程序,该程序能够正确解析算术表达式并按照算符优先规则进行计算,最终得到正确的计算结果。
实验结果通过本次实验,我们成功实现了一个能够正确解析算术表达式并计算结果的程序。
该程序能够正确地处理不同优先级和结合性的运算符,并得到正确的计算结果。
这表明算符优先算法是一种有效的算法,能够帮助我们正确地处理算术表达式中的运算符优先级问题。
结论通过本次实验,我们深入理解了算符优先算法的原理和应用,并掌握了算符优先算法的程序设计方法。
算符优先算法是一种重要的算法,它在计算表达式时能够帮助我们确定运算符的优先级,从而得到正确的计算结果。
在今后的学习和工作中,我们将继续深入研究算符优先算法,并将其应用到更多的实际问题中。
算符优先分析法

华中师范大学计算机科学系算符优先分析法学号:2009210580姓名:王晔成绩:一实验目的设计、编制并调试一个算符优先分析算法,加深对此分析法的理解二实验过程2.1实验过程先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。
分析过程从头开始,并重复进行;若读来的是运算符θ2则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。
1 若f(θ1)<=g(θ2),则θ2进算符栈,并继续顺序往下扫描,分析过程从头开始2 如f(θ1)>g(θ2),则产生对操作数栈顶的若干项进行θ1运算的中间代码,并从运算符栈顶移去θ1,并从操作数栈顶移去若干项,然后把执行θ1的结果压入操作数栈。
接着以运算符栈新的项目与θ2进行上述优先数的比较,即重复(1)(2),3 重复(1)(2)直到“$”与“$”配对为止。
关键代码#include <stdio.h>#include <string.h>#include <ctype.h>char calculator_stack[100],prog[1000];int operator_stack[100];int c_top=0,o_top=0,p;char ch;int f[255]={0};int g[255]={0};void Init(){f['*']=f['/']=5;f['+']=f['-']=3;f['$']=0;g['*']=g['/']=4;g['+']=g['-']=2;g['$']=0;}int main(){int i,sum=0,oper1,oper2,result;Init();calculator_stack[c_top++]='$';p=0;printf("请输入正确的代码,以#结束:\n"); do{ch=getchar();prog[p++]=ch;}while(ch!='#');prog[p]=0;printf("%s\n",prog);p=0;bool flag;for(i=0;prog[i];i++){if(isalpha(prog[i])){flag=1;continue;}else if(isdigit(prog[i])){if(flag)continue;else{sum=sum*10+prog[i]-'0';if(!isdigit(prog[i+1])){operator_stack[o_top++]=sum;sum=0;}flag=0;}}else if(prog[i]==' ' || prog[i]=='\t' || prog[i]=='\n'){flag=0;continue;}else if(prog[i]=='#')break;else{flag=0;if(prog[i]=='*' || prog[i]=='/' || prog[i]=='+' || prog[i]=='-' ||prog[i]=='$') {if(prog[i]!='$' && f[calculator_stack[c_top-1]]<=g[prog[i]]) calculator_stack[c_top++]=prog[i];else{while(1){oper2=operator_stack[--o_top];oper1=operator_stack[--o_top];ch=calculator_stack[c_top-1];if(ch=='*')result=oper1*oper2;else if(ch=='/'){if(oper2==0){printf("除零错误!\n");return 0;}result=oper1/oper2;}else if(ch=='+')result=oper1+oper2;else if(ch=='-')result=oper1-oper2;printf("%d = %d %c %d\n",result,oper1,ch,oper2); operator_stack[o_top++]=result;calculator_stack[--c_top];if(prog[i]=='$' && calculator_stack[c_top-1]=='$') return 0;if(f[calculator_stack[c_top-1]]<=g[prog[i]]){calculator_stack[c_top++]=prog[i];break;}}}}}}return 0;}。
算符优先分析报告法设计与实现

算符优先分析法设计与实现一、实验目的加深对语法分析器工作过程的理解;加强对算符优先分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
二、实验内容在实验1的基础上,用算符优先分析法编制语法分析程序,语法分析程序的实现可以采用任何一种编程语言和工具。
三、实验要求:1.对语法规则有明确的定义;2.编写的分析程序能够对实验一的结果进行正确的语法分析;3.对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程;四、实验步骤1.定义目标语言的语法规则;2.求解预测分析方法需要的符号集和分析表;3.依次读入实验一的分析结果,根据预测分析的方法进行语法分析,直到源程序结束;4.对遇到的语法错误做出错误处理。
五、实验报告要求详细说明你的程序的设计思路和实现过程。
实验报告要求用文法的形式对语法定义做出详细说明,说明语法分析程序的工作过程,说明错误处理的实现。
算符优先分析器(综合性实验)一、实验目的掌握 FirstVT和 LastVT集的算法,算符优先分析表的构造算法及其分析过程,并掌握中间代码产生过程。
二、实验内容算术表达式和赋值语句的文法可以是(可以根据需要适当改变):S→i=EE→E+TE→E-TE→TT→T*FT→T/FT→FF→(E)F→i根据算符优先分析法,将赋值语句进行语法语义分析,翻译成等价的一组基本操作,每一基本操作用四元式表示。
三、实验过程和指导1、构造FirstVT和LastVT集合给定一个上下文无关文法,根据算法设计一个程序,求文法中每个非终结符的 FirstVT 集和LastVT 集。
算符描述如下:/*求 FirstVT 集的算法*/PROCEDURE insert(P,a);IF not F[P,a] thenbeginf[p,a] = true; (P,a)进栈end;Procedure FirstVT;Beginfor 对每个非终结符 P和终结符 a doF[P,a] = falsefor 对每个形如 P→a…或 P→Qa…的产生式 doInsert(P,a)while stack 非空begin栈顶项出栈,记为(Q,a)for 对每条形如 P→Q…的产生式 doinsert(P,a)end;end.2、构造算符优先分析表依据文法和求出的相应FirstVT和 LastVT 集生成算符优先分析表。
编译原理 算符优先分析实验报告

实验四、算符优先分析算法
姓名:
学号:
班级:
指导老师:
时间:
计算机与信息技术学院
程序功能描述
实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。
G[E]:E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
说明:终结符号i 为用户定义的简单变量,即标识符的定义。
(1)构造该算符优先文法的优先关系矩阵或优先函数;(2)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;(3)算符优先分析过程应能发现输入串出错。
(4)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。
备注:程序中判断该输入串是否为该文法定义的算术表达式的结果,若是则输出“accept”,若不是则输出“error”。
该二元式序列要以“#”为结尾。
主要数据结构描述
程序结构描述
程序测试:
测试1:(i+i*i)
输出:
输入二:i+i*ii
输出:
学习总结
算符优先文法关键点就在于判断各个终结符号的优先级,构造算符优先矩阵是个难点,程序里面没有实现,而是直接定义了优先矩阵,这是需要完善的地方,试试能不能在程序中动态地构造优先矩阵。
另外对于算符优先文法,失败的条件是比较两个非终结符的优先关系,若优先关系表中为空,就返回error.。
算符优先_实验报告

一、实验目的1. 理解算符优先分析法的原理和过程。
2. 掌握算符优先分析法的实现方法。
3. 通过实验加深对自底向上语法分析方法的理解。
二、实验内容1. 算符优先分析法原理介绍算符优先分析法是一种自底向上的语法分析方法,它通过比较相邻算符的优先次序来识别句型中的句柄,进而执行归约。
该方法的核心是确立文法的终结符之间的优先关系。
2. 实验步骤(1)判断文法是否为OG文法:OG文法要求所有产生式右部至少有一个终结符。
(2)判断文法是否为OPG文法:计算FIRSTVT集、LASTVT集,并构建算符优先矩阵。
(3)对句子进行分析:根据分析表判断句子是否为文法的句子。
(4)实现程序:从文件和键盘读取输入,将结果输出到指定文件和屏幕,并具有一致性。
3. 实验数据(1)文法:g[e]:e->e+t|t(2)测试句子:12+t, t+12, 12+13t, 12+t13三、实验过程1. 判断文法是否为OG文法根据给定的文法,我们可以看到所有产生式右部至少有一个终结符,因此该文法为OG文法。
2. 判断文法是否为OPG文法,并构建算符优先矩阵(1)计算FIRSTVT集FIRSTVT(e) = {t}FIRSTVT(t) = {t}(2)计算LASTVT集LASTVT(e) = {t}LASTVT(t) = {t}(3)构建算符优先矩阵| + - ( ) t e $+ > - - - > > -- > - - - > > -> > > > > > >( > > > > > > >) - - - - - - -t - - - - - - -e - - - - - - -$ - - - - - - -3. 对句子进行分析(1)分析句子“12+t”根据分析表,我们可以得到以下分析过程:12+t -> 12+t -> 12+t -> t -> t(2)分析句子“t+12”根据分析表,我们可以得到以下分析过程:t+12 -> t+12 -> t+12 -> t+12 -> t+12 -> t -> t (3)分析句子“12+13t”根据分析表,我们可以得到以下分析过程:12+13t -> 12+13t -> 12+13t -> 12+13t -> 12+13t -> t -> t(4)分析句子“12+t13”根据分析表,我们可以得到以下分析过程:12+t13 -> 12+t13 -> 12+t13 -> 12+t13 -> 12+t13 -> t13 -> t13 -> t13 -> t -> t四、实验结果1. 测试句子“12+t”分析结果:正确2. 测试句子“t+12”分析结果:正确3. 测试句子“12+13t”分析结果:正确4. 测试句子“12+t13”分析结果:正确五、实验总结通过本次实验,我们深入了解了算符优先分析法的原理和实现方法。
算符优先实验报告

算符优先分析实验报告一、程序功能实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。
G[S]:S->#E#E->E+T|TT->T*F|FF->P^F | PP->(E)|i二、主要数据结构char VT[]定义符号表;struct type{char origin; char array[5]; int length;}定义产生式类型;table[][]定义优先关系矩阵。
三、程序结构int locate(char s[],char c) 辅助函数,在一个字符串中查找某特定字符;int Find(type G[],char s[],int m,int n) 查找与已搜索出的短语对应的产生式,返回该产生式的序号;void doScan()对输入串进行分析的主控函数;void print(char s[],int k,int tag,char str[],int i,char action[])输出分析过程的函数。
在find()和doScan()中调用locate()函数,在doScan()中调用find()和print()函数,在main()中调用doScan()函数。
流程图:Y成功四、程序测试测试句子:i+i*i结果:测试句子:(i+i)*i结果:五、实验总结本实验重点解决算符优先矩阵的构造和算符优先算法的实现,我认为难点是构造优先矩阵,这个就需要掌握方法多练习,优先算法只需将PPT上的流程图一步一步地转化为代码就可以了。
总体来说,本实验比较简单。
THANKS !!!致力为企业和个人提供合同协议,策划案计划书,学习课件等等打造全网一站式需求欢迎您的下载,资料仅供参考。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验名称:实验任务:对下述描述算符表达式的算符优先文法G[E],给出算符优先分析的实验结果。
实验容:有上下无关文法如下:E->E+T|E-T|TT->T*F|T/F|FF->(E)|i说明:优先关系矩阵的构造过程:(1) = 关系由产生式 F->(E) 知‘(’=‘)’FIRSTVT集及LASTVT集FIRSTVT(E)={ +,-,*,/,(,i }FIRSTVT(F)={ (,i }FIRSTVT(T)={ *,/,(,i }LASTVT(E)={ +,-,*,/,),i }LASTVT(F)={ ),i }LASTVT(T)={ *,/,),i }(2) < 关系+T 则有:+ < FIRSTVT(T)-T 则有:- < FIRSTVT(T)*F 则有:* < FIRSTVT(F)/F 则有:/ < FIRSTVT(F)(E 则有:( < FIRSTVT(E)(3) > 关系E+ 则有: LASTVT(E) > +E- 则有: LASTVT(E) > -T* 则有: LASTVT(T) > *T/ 则有: LASTVT(T) > /E) 则有: LASTVT(E) > )(4)请大家画出优先关系矩阵终结符之间的优先关系是唯一的,所以该文法是算符优先文法。
程序的功能描述:程序由文件读入字符串(以#结束),然后进行算符优先分析,分析过程中如有错误,则终止程序并报告错误位置,最终向屏幕输出移近——规约过程。
(5)依据文法和求出的相应FirstVT和 LastVT 集生成算符优先分析表。
算法描述如下:for 每个形如 P->X1X2…Xn的产生式dofor i =1 to n-1 dobeginif Xi和Xi+1都是终结符 thenXi = Xi+1if i<= n-2, Xi和Xi+2 是终结符, 但Xi+1 为非终结符thenXi = Xi+2if Xi为终结符, Xi+1为非终结符 thenfor FirstVT 中的每个元素 a doXi < aif Xi为非终结符, Xi+1为终结符 thenfor LastVT 中的每个元素 a doa > Xi+1end(6)构造总控程序算法描述如下:stack S; k = 1; //符号栈S的使用深度S[k] = ‘#’REPEAT把下一个输入符号读进a中;If S[k] VT thenj = kelsej = k-1;While S[j] > a doBeginRepeatQ = S[j];if S[j-1] VT thenj = j-1elsej = j-2until S[j] < Q;把S[j+1]…S[k]归约为某个N,并输出归约为哪个符号;K = j+1;S[k] = N;end of whileif S[j] < a or S[j] = a thenbegin k = k+1; S[k] = a endelse error //调用出错诊察程序until a = ‘#’(7)代码如下:#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; //转化后文法规则个数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])&&!zhong jie(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];n++;}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;}实验结果:。