编译原理课程设计报告_算符优先分析法
编译原理-实验3算符优先分析法
实验3《算符优先分析法设计与实现》实验学时: 2 实验地点:实验日期:一、实验目的加深对语法分析器工作过程的理解;加强对算符优先分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
二、实验内容在实验1的基础上,用算符优先分析法编制语法分析程序,语法分析程序的实现可以采用任何一种编程语言和工具。
三、实验方法先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。
分析过程从头开始,并重复进行;若读来的是运算符θ2则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。
四、实验步骤1.定义目标语言的语法规则;2.求解预测分析方法需要的符号集和分析表;3.依次读入实验一的分析结果,根据预测分析的方法进行语法分析,直到源程序结束;4.对遇到的语法错误做出错误处理。
五、实验结果六、实验结论#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];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;}七、实验小结通过本次试验我知道了算符文法的形式,对给定的算符文法能构造算符优先关系分析表,并判别所给文法是否为算符优先文法。
编译原算符优先分析实验报告 (2)
编译原理实验报告——算符优先文法分析指导教师:***学号:**********姓名:***【实验名称】算符优先文法分析【实验目的】掌握算符优先分析法的原理,利用算符优先分析法将赋值语句进行语法分析,翻译成等价的四元式表示。
【实验内容】1.算术表达式的文法可以是:(1)S->#E# (2)E->E+T (3)E->T (4)T->T*F (5)T->F (6)F->P^F (7)F->P (8)P->(E) (9)P->i2.根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确。
【设计思想】(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立算符优先关系表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用算符优先文法分析算法进行表达式处理:根据优先关系表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
【流程图】【源码】#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <stack>using namespace std;struct Node1{char vn;char vt;char s[10];}MAP[20];//存储分析预测表每个位置对应的终结符,非终结符,产生式int k;//用R代表E',W代表T',e代表空char G[10][10]={"E->TR","R->+TR","R->e","T->FW","W->*FW","W->e","F->(E)","F->i"};//存储文法中的产生式char VN[6]={'E','R','T','W','F'};//存储非终结符char VT[6]={'i','+','*','(',')','#'};//存储终结符char SELECT[10][10]={"(,i","+","),#","(,i","*","+,),#","(","i"};//存储文法中每个产生式对应的SELECT集char Right[10][8]={"->TR","->+TR","->e","->FW","->*FW","->e","->(E)","->i"};stack <char> stak,stak1,stak2;bool compare(char *a,char *b){int i,la=strlen(a),j,lb=strlen(b);for(i=0;i<la;i++)for(j=0;j<lb;j++){if(a[i]==b[j])return 1;}return 0;}char *Find(char vn,char vt){int i;for(i=0;i<k;i++){if(MAP[i].vn==vn && MAP[i].vt==vt)return MAP[i].s;}return "error";}char * Analyse(char * word){char p,action[10],output[10];int i=1,j,l=strlen(word),k=0,l_act,m;while(!stak.empty())stak.pop();stak.push('#');stak.push('E');printf("_________________________________________________________________________ _______\n");printf("\n 对符号串%s的分析过程\n",word);printf(" 步骤栈顶元素剩余输入串推到所用产生式或匹配\n");p=stak.top();while(p!='#'){printf("%7d ",i++);p=stak.top();stak.pop();printf("%6c ",p);for(j=k,m=0;j<l;j++)output[m++]=word[j];output[m]='\0';printf("%10s",output);if(p==word[k]){if(p=='#'){printf(" 接受\n");return "SUCCESS";}printf(" “%c”匹配\n",p);k++;}else{strcpy(action,Find(p,word[k]));if(strcmp(action,"error")==0){printf(" 没有可用的产生式\n");return "ERROR";}printf(" %c%s\n",p,action);int l_act=strlen(action);if(action[l_act-1]=='e')continue;for(j=l_act-1;j>1;j--)stak.push(action[j]);}}if(strcmp(output,"#")!=0)return "ERROR";}int main (){freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);char source[100];int i,j,flag,l,m;printf("\n为了方便编写程序,用R代表E',W代表T',e代表空\n\n");printf("该文法的产生式如下:\n");for(i=0;i<8;i++)printf(" %s\n",G[i]);printf("\n该文法的SELECT集如下:\n");for(i=0;i<8;i++){printf(" SELECT(%s) = { %s }\n",G[i],SELECT[i]);}//判断是否是LL(1)文法flag=1;for(i=0;i<8;i++){for(j=i+1;j<8;j++){if(G[i][0]==G[j][0]){if(compare(SELECT[i],SELECT[j])){flag=0;break;}}}if(j!=8)break;}if(flag)printf("\n有相同左部产生式的SELECT集合的交集为空,所以文法是LL(1)文法。
编译原理_实验报告实验二__语法分析(算符优先) 2
华北水利水电学院编译原理实验报告一、实验题目:语法分析(算符优先分析程序)(1)选择最有代表性的语法分析方法算符优先法;(2)选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。
二、实验内容(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(4) 分析的句子为:(i+i)*i和i+i)*i三、程序源代#include<stdlib.h>#include<stdio.h>#include<string.h>#include<iostream.h>#define SIZE 128char priority[6][6]; //算符优先关系表数组char input[SIZE]; //存放输入的要进行分析的句子char remain[SIZE]; //存放剩余串char AnalyseStack[SIZE]; //分析栈void analyse();int testchar(char x); //判断字符X在算符优先关系表中的位置void remainString(); //移进时处理剩余字符串,即去掉剩余字符串第一个字符int k;void init()//构造算符优先关系表,并将其存入数组中{priority[0][2]='<';priority[0][3]='<';priority[0][4]='>';priority[0][5]='>';priority[1][0]='>';priority[1][1]='>';priority[1][2]='<';priority[1][3]='<';priority[1][4]='>';priority[1][5]='>';priority[2][0]='>';priority[2][1]='>';priority[2][2]='$';//无优先关系的用$表示priority[2][3]='$';priority[2][4]='>';priority[2][5]='>';priority[3][0]='<';priority[3][1]='<';priority[3][2]='<';priority[3][3]='<';priority[3][4]='=';priority[3][5]='$';priority[4][0]='>';priority[4][1]='>';priority[4][2]='$';priority[4][3]='$';priority[4][4]='>';priority[4][5]='>';priority[5][0]='<';priority[5][3]='<';priority[5][4]='$';priority[5][5]='=';}void analyse()//对所输入的句子进行算符优先分析过程的函数{FILE *fp;fp=fopen("li","a");int i,j,f,z,z1,n,n1,z2,n2;int count=0;//操作的步骤数char a; //用于存放正在分析的字符char p,Q,p1,p2;f=strlen(input); //测出数组的长度for(i=0;i<=f;i++){a=input[i];if(i==0)remainString();if(AnalyseStack[k]=='+'||AnalyseStack[k]=='*'||AnalyseStack[k]=='i'||Analy seStack[k]=='('||AnalyseStack[k]==')'||AnalyseStack[k]=='#')j=k;elsej=k-1;z=testchar(AnalyseStack[j]);//从优先关系表中查出s[j]和a的优先关系if(a=='+'||a=='*'||a=='i'||a=='('||a==')'||a=='#')n=testchar(a);else //如果句子含有不是终结符集合里的其它字符,不合法{printf("错误!该句子不是该文法的合法句子!\n");break;}if(p=='$'){printf("错误!该句子不是该文法的合法句子!\n");return;}if(p=='>'){ for( ; ; ){Q=AnalyseStack[j];if(AnalyseStack[j-1]=='+'||AnalyseStack[j-1]=='*'||AnalyseStack[j-1]=='i'||AnalyseStack[j-1]=='('||AnalyseStack[j-1]==')'||AnalyseStack[j-1]=='#')j=j-1;elsej=j-2;z1=testchar(AnalyseStack[j]);n1=testchar(Q);p1=priority[z1][n1];if(p1=='<') //把AnalyseStack[j+1]~AnalyseStack[k]归约为N{count++;printf("(%d) %s\t%10c\t%5c%17s\t 归约\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"归约");k=j+1;i--;AnalyseStack[k]='N';int r,r1;r=strlen(AnalyseStack);for(r1=k+1;r1<r;r1++)AnalyseStack[r1]='\0';break;}else}}else{if(p=='<') //表示移进{count++;printf("(%d) %s\t%10c\t%5c%17s\t 移进\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"移进");k=k+1;AnalyseStack[k]=a;remainString();}else{if(p=='='){z2=testchar(AnalyseStack[j]);n2=testchar('#');p2=priority[z2][n2];if(p2=='='){count++;printf("(%d) %s\t%10c\t%5c%17s\t 接受\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"接受");printf("该句子是该文法的合法句子。
编译原理 算符优先分析实验报告
实验四、算符优先分析算法
姓名:
学号:
班级:
指导老师:
时间:
计算机与信息技术学院
程序功能描述
实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。
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.。
编译原理课程设计报告 算符优先分析表
课程设计(论文)任务书软件学院学院软件工程专业07-1班一、课程设计(论文)题目算符优先分析表生成模拟二、课程设计(论文)工作自2010年6月20 日起至 2010 年6月25日止。
三、课程设计(论文) 地点:四、课程设计(论文)内容要求:1.本课程设计的目的1、使学生增进对编译原理的认识,加强用程序设计语言实现编译算法能力。
2、进一步培养学生编译器设计的思想,加深对编译原理和应用程序的理解,针对编译过程的重点和难点内容进行编程,独立完成有一定工作量的程序设计任务,同时强调好的程序设计风格,并综合使用程序设计语言、数据结构和编译原理的知识,熟悉使用开发工具VC6.0 或JA V A。
2.课程设计的任务及要求1)基本要求:动态模拟算法的基本功能是:(1)输入一个给定文法,及FIRSTVT和LASTVT集;(2)输出算符优先分析表生成算法;(3)输出算法优先分析表构造过程的过程。
2)课程设计论文编写要求1)要按照书稿的规格打印誊写课设报告;2)报告分为封面、课程设计任务书(本文档)分析、总结和附录;3)报告正文包括以下部分:①问题描述:题目要解决的问题是什么;②分析、设计、实现:解决问题的基本方法说明,包括主要算法思想,算法的流程图,程序中主要函数或过程的功能说明;④运行结果分析:分析程序的运行结果是否正确以及出现的问题;⑤总结:遇到的主要问题是如何解决的、对设计和编码的回顾讨论和分析、进一步改进设想、经验和体会等;⑥附录,包括源程序清单和运行结果。
学生签名:2009 年6 月25 日课程设计(论文)评审意见(1)编译器思想的正确性(20分):优()、良()、中()、一般()、差();(2)程序实现的正确性(20分):优()、良()、中()、一般()、差();(3)程序功能的完善程度(20分):优()、良()、中()、一般()、差();(4)学生的态度(20分):优()、良()、中()、一般()、差();(5)课程设计报告(20分):优()、良()、中()、一般()、差();(6)格式规范性、设计态度及考勤是否降等级:是()、否()评阅人:职称:教授2010 年6月28 日目录一、课设题目 (4)二、概要设计 (5)三、详细设计 (7)四、运行结果……………………………………………………五、总结…………………………………………………………六、附录…………………………………………………………一、课设题目1、问题描述设计一个给定文法和对应FIRSTVT和LASTVT集,能依据依据文法和FIRSTVT和LASTVT生成算符优先分析表。
算符优先_实验报告
一、实验目的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”分析结果:正确五、实验总结通过本次实验,我们深入了解了算符优先分析法的原理和实现方法。
编译原理算符优先分析程序设计
编译原理算符优先分析程序设计算符优先分析(Operator Precedence Parsing)是一种基于文法的自下而上的语法分析方法,用于构造一个将输入串转化为语法分析树的分析器。
它通过根据每一个终结符号和非终结符号之间的优先级关系,来判断是否可以进行规约操作。
算符优先分析的基本思想是,为每一个终结符和非终结符分配一个优先级,然后根据这些优先级来决定如何进行规约操作。
一般来说,基本的终结符都有一个固定的优先级,而非终结符的优先级则由其所对应的产生式右部中的终结符优先级来决定。
算符优先分析的核心在于构造一个优先级关系表,用于指导规约过程。
这个表一般由产生式构造得到,每个终结符和非终结符对应一行和一列,表中的每个元素表示两个符号之间的优先级关系。
算符优先分析的步骤如下:1.根据给定的文法,确定每个终结符号和非终结符号的优先级。
2.构造优先关系表,填入每两个符号之间的优先关系。
3.初始化分析栈和输入栈,将栈底符号设为文法开始符号,并将输入串入栈。
4.重复以下步骤,直到分析完成:a.查找栈顶和当前输入符号之间的优先关系。
b.如果栈顶符号的优先级较低或相等,则进行规约操作,将栈顶的符号替换为相应的非终结符号。
c.如果栈顶符号的优先级较高,则进行移进操作,将当前输入符号移入栈中。
d.如果找不到优先关系,则出现错误,分析失败。
算符优先分析的优点是简单明了,且规约过程中不需要回溯,效率较高。
然而,由于它只适用于算符优先文法,而不是所有的上下文无关文法,因此适用范围有限。
在实际编程中,我们可以通过编写算符优先分析程序来对给定的文法进行分析。
程序可以根据文法自动生成优先关系表,然后根据输入串和优先关系表进行分析。
下面是一个简单的算符优先分析程序设计:```python#定义终结符和非终结符的优先级priority = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 0, ')': 0}#构造优先关系表def build_table(:table = {}for symbol1 in priority.keys(:row = {}for symbol2 in priority.keys(:if symbol1 == '(' and symbol2 == ')':row[symbol2] = 'r'elif symbol1 == ')' and symbol2 == '(':row[symbol2] = 'e'elif priority[symbol1] > priority[symbol2]:row[symbol2] = '>'elif priority[symbol1] < priority[symbol2]:row[symbol2] = '<'else:row[symbol2] = 'e'table[symbol1] = rowreturn table#算符优先分析程序def operator_precedence_parsing(table, input_str): input_stack = list(input_str)input_stack.append('#')analysis_stack = ['#']while len(analysis_stack) > 0:top = analysis_stack[-1]if top in priority.keys( and input_stack[0] in priority.keys(:relation = table[top][input_stack[0]]if relation == '>':analysis_stack.popprint('Reduce by', top)elif relation == '<':analysis_stack.append(input_stack.pop(0)) print('Shift', analysis_stack[-1])elif relation == 'e':analysis_stack.popinput_stack.pop(0)print('Error')returnelse:print('Error')returnelse:print('Error')return#测试代码table = build_tableinput_str = input('Please enter a valid expression: ')operator_precedence_parsing(table, input_str)```以上是一个简单的算符优先分析程序设计,实现了根据输入串和优先关系表进行分析的过程。
算符优先词法分析器_编译原理完整课程设计
目录一、设计目的 (1)二、设计原理 (1)三、设计思想 (2)四、设计要求 (3)五、设计流程图及程序 (4)六、运行结果及分析 (14)七、设计总结 (16)八、参考文献 (16)算符优先词法分析器一、设计目的算符优先算法是自底而上分析方法的一种。
所谓自底向上分析,也称移进—规约分析,粗略地说他的实现思想是对输入符号串自左向右进行扫描,并将输入符逐个移入一个后进先出的栈中,边移进边分析,一旦栈顶符号串形成某个句型的句柄或可规约串是,就用该产生式的左部非终结符代替相应右部的文法符号串,这称为一部规约。
重复这一过程直到规约到栈中只剩文法的开始符号是则为分析成功,也就确认输入串是文法的句子。
而算符优先分析的基本思想是只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系。
本课程设计的主要目的:1、通过本次课程设计,全面系统的了解编译原理程序构造的一般原理和基本实现方法,尤其是对自底向上的优先分析方法的认识和理解;2、提高对编译程序工作基本过程及其各阶段基本任务的分析技能;3、加强对编译程序的生成过程、构造工具及编译程序总流程框图的理解,巩固所学的课本知识。
二、设计原理算符优先分析法是一种有效的自底向上的分析方法。
自底向上分析方法面临的主要问题是如何确定可归约串,而算符优先分析法根据两个终结符号之间的优先关系比较,成功的解决了可归约串的问题。
算符优先分析法是采用最左素短语进行归约的,严格来讲不属于规范规约的范畴。
因此,在设计以前我们必须要知道什么是素短语和最左素短语。
所谓素短语就是指句型中具有这样性质的短语:至少含有一个终结符,且除了自身之外,不再含有任何更小的素短语的短语。
最左素短语,是指在句型的所有素短语中,处于句型最左边的素短语。
了解了素短语和最左素短语,那么如何构造这种算法呢?首先,根据非终结符的FIRSTVT集和LASTVT集找出它们之间的优先关系,构造算符优先矩阵。
然后,由此矩阵构造相应符号串的算符优先分析表并编写程序。
编译原理课程设计--基于算符优先分析方法的表达式语法分析器
基于算符优先分析方法的表达式语法分析器年级: 2007班级:级计算机科学与技术 4班组长:刘思佳组员:欧垚毛群晖袁小仨徐碧红邓文杰孙苗苗顿硕伍小军曾洁孙梁吉顺昌指导老师:段明秀二〇一五年七月一日目录前言 (1)第1章课程设计计划 (4)1.1员与工作分配 (4)1.2课程计划 (4)1.3资源需求 (4)第2章功能需求分析 (5)2.1 功能需求清单 (5)第3章设计、分析与编码 (6)3.1 总体设计 (6)3.1.1 模块划分 (6)3.1.2程序分包 (6)3.2 详细设计 (7)3.2.1 类图 (7)3.3 程序流程图 (9)3.4 分析与编码实现 (10)3.4.1表达式文法G[E’]构造算符优先关系表 (10)3.4.2 根据算符优先表用栈结构来实现算符优先分析 (11)3.4.3 辅助工具类设计 (18)第4章测试用例及程序截图 (21)4.1第一版测试 (21)4.1第二版测试 (25)4.2 第三版测试...................................................................................... 错误!未定义书签。
第5章用户使用说明.. (32)5.1 使用步骤 (32)附录1. 参考文献 (33)附录2. 总结 (33)前言1.摘要编译原理是计算机专业的一门重要专业课,旨在介绍编译程序构造的一般原理和基本方法。
内容包括语言和文法、词法分析、语法分析、语法制导翻译、中间代码生成、存储管理、代码优化和目标代码生成。
编译原理是计算机专业设置的一门重要的专业课程。
虽然只有少数人从事编译方面的工作,但是这门课在理论、技术、方法上都对学生提供了系统而有效的训练,有利于提高软件人员的素质和能力。
算符优先分析法是一种简单直观、特别方便于表达式分析,易于手式实现的方法。
算符优先法只考虑算符(广义为终结符号)之间的优先关系,它是一种自底向上的归约过程,但这种归约未必严格按照句柄归约。
编译原理 算符优先分析程序设计
编译原理课程设计报告评分:签字:编译原理课程设计二——算符优先分析程序设计实验目的了解掌握算符优先分析的基本方法、内容;学会科学思考并解决问题,提高程序设计能力。
实验内容与要求用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。
文法表示:S→v=E|E?|clearE→E+T|E-T|TT→T*F|T/F|FF→(E)|v|c单词种别码设计:= 1? 2+ 3- 4* 5/ 6(7)8v 9c 10clear 11# 12N 13实验环境系统环境为windows系统,编译环境为VS2015,编程语言为C++。
实验过程过程一:构建firstVT()和lastVT()算法分析:对于firstVT()构建,对于每个非终结符F的产生式,第一个终结符或者‘|’后的第一个终结符应该在其firstVT()集合内,且若非终结符T能推出非终结符F则firstVT(T)包含first(F)。
lastVT()的构造类似,对于每个非终结符F的产生式,非终结符后的第一个终结符都属于lastVT (F), 且若非终结符T能推出非终结符F则lastVT(T)包含first(F)。
算法实现主要函数:void get_firstVT()//求firstVT();void get_lastVT()//求lastVT();结果:FirstVT(S){=,?,l,+,-,*,/,(,v,c,}FirstVT(E){+,-,*,/,(,v,c,}FirstVT(T){*,/,(,v,c,}FirstVT(F){(,v,c,}LastVT(S){=,?,l,+,-,*,/,),v,c,}LastVT(E){+,-,*,/,),v,c,}LastVT(T){*,/,),v,c,}LastVT(F){),v,c,}过程二:构建优先符号表算法分析:(1)在产生式中两个相邻的终结符优先顺序相等(2)对于小于关系,首先扫描终结符a标记flag=1,再扫描到非终结符Q,此时判断若flag=1,则对所有b∈FristVT{Q},a<b.(3)对于大于关系,首先扫描非终结符Q在前标记flag=1,再扫描终结符a在后此时判断若flag=1,对所有b∈LastVT{Q},b>a.算法结果:其中-2表示不会出现,1表示>,-1表示<,0表示=.字母l表示clear.过程三:词法分析算法分析:详见课程设计一算法主要函数:int letter()//判断是否为字母int digit()//判断是否为数字int str_to_num()//数字字符串转化为整数int reserve(char **k)//处理保留字int sysmbol(identifier *id)//处理标识符,查找符号表并存放位置若没有则添加int constant(constnumber *con)//存入常数表,并返回它在常数表中的位置void WordAnalyze( constnumber *con, identifier *id, char sentence[],int &point,int &syn,int &sym_point)//词法分析void Insert_to_symboltbl(int syn, int value, int &point)//把二元组加入symbol表算法结果:得到语句的所有单词二元组symbolTBL表,存放种别码syn及其值val,其中对于种别码为9的变量val为标志符的入口标志,对于种别码为10的的常量val为存放的值。
C.4-算符优先分析法-实验报告
学号
成绩
实 验 报 告
实验题目:算符优先分析法
课程名称:编译原理
主讲教师:
班 级:
实验日期:
提交日期:
1、
实验目的:
采用算符优先分析法对表达式(不包含括号运算)进行分析,并给出四元式。
二、实验内容
在实验1、2的基础上,用算符优先分析法编制语法分析程序。
分析过程:先在算符栈置“$”,然后开始顺序扫描表达式,若读来的单词符号是操作数,这直接进操作数栈,然后继续读下一个单词符号。分析过程从头开始,并重复进行;若读来的是运算符θ2 则将当前处于运算符栈顶的运算符θ1的入栈优先数f与θ2的比较优先函数g进行比较。
结果
四、我的感想
这次试验可以说是前两个试验的综合了,程序中也很多用到了前两次的代码。对于我自己来说,最难的部分在于将这些思想转换成代码实现出来,很大一部分在于自己平时没有多打代码以及就是对算符优先分析的思想理解得还不够透彻。在写main函数时,因为要调用很多函数,刚开始写的时候陷入了死循环,以及栈函数的各种调用发生错误,说明自己思路还不够清晰。因为这次实验是在考完试后做的,之前对算符优先分析以及四元式的理解不够明白,在这个实验实现成功后,自己能够透彻地了解,知道了算符文法的形式,对给定的算符文法能构造算符优先关系分析表,并判别所给出的文法是否为算符优先文法。同时我也算符优先文法的优缺点以及实际应用中的局限性。
三、程序的改写:
因为这次的实验与前面两次的实验有很大的重合,所以会用到很多之前两次的代码。首先,定义函数:
其中本次需要写的函数有:入栈优先函数f,比较优先函数g,compare,middle,栈函数以及主函数。
1.入栈优先函数f
书上已经给出了入栈优先函数的表,根据输入的符号赋予数值,以便后面方便比较。
编译原理之算符优先分析
编译原理之算符优先分析1.算符优先分析:1.1定义是⼀种简单直观、⼴泛使⽤、便于⼿⼯实现的⾃下⽽上的语法分析⽅法。
1.2原理定义算符之间的某种优先关系,寻找“归约串”,并进⾏归约1.3相关知识拓展1.3.1 算符⽂法:产⽣式的右部不包含两个相继的⾮终结符,即不包含形如:.....QR.....1.3.2 算符优先⽂法:任何终结符对(a,b)⾄多⼀种优先级关系。
1.3.3 构造优先关系表步骤:(1)写出FIRSTVT、LASTVTFIRSTVT(P)={a|P->a.....或P->Qa......}LASTVT(P)={a|P->.....a或P->......aQ} (2)列表,根据优先级填表 1.确定同⼀产⽣式的末尾终结符之间⽆优先关系 2.确定=,再使⽤FIRSTVT、LASTVT1.4 算符优先分析算法 素短语:⾄少包含⼀个终结符且不包含更⼩的终结符,如p*p或 i 最左素短语:最左侧的素短语 缺点:跳过了所有单⾮产⽣式所对应的归约步骤。
(单⾮产⽣式:形如:P->Q ,右部只有⼀个⾮终结符的产⽣式)1.5 构造优先函数使⽤构造优先函数代替优先表f:表⼊栈优先函数、g:表⽐较优先函数1.6 举例S→a|Λ|(T) T->T,S|S(1)基本了解:FIRSTVT(P)={a|P->a.... or Qa....}; LASTVT(P)={a|P->...a or P->....aQ}所以对于:S→a|Λ|(T) 则FIRSTVT(S)={a,Λ,(}对于:S→a|Λ|(T) 则LASTVT(S)={a,Λ,)}对于:T->T,S|S 则FIRSTVT(T)={, ,a,Λ,(}对于:T->T,S|S 则LASTVT(T)={, ,a,Λ,)}(2)优先关系aΛ(),a>>Λ>>(<<<=<)>>,<<<>>,<<<>>由于G[S]中任何终结符对(a,b)之多只有⼀种关系成⽴,所以,G[S]为算符优先⽂法。
编译原理实验4 算符优先语法分析
归约时找最左素短语
栈底
串头
可归约串
串尾
#…aj-1 aj aj+1 … ai-1 ai ai+1…
优先关系: ⋖
=·
⋗
串头与串尾之间为可归约串(素短语), 包括其间的及左右两边的非终结符。
核心问题
• 分析栈的数据结构、出栈操作、入栈操作 • 分析表的存储结构、读取操作
步骤1
• 判断给定的文法是否是OPG文法
步骤3:构造算符优先分析表
优先关系:
设G是一个不含 产生式的算符文法,令 a、b是任意两个VT , P、Q、R ∈ VN ,则:
(1) ab 当且仅当文法G中含有形如P …ab…或P …aQb…的产生式 (2) a<b 当且仅当G中含有形如P …aR…的产生式,R而Rb… 或R Qb… (3) a>b 当且仅当G中含有形如P …Rb…的产生式,R而R…a 或R …aQ
步骤6
• 完成主分析程序
符号栈的初始化
for( 从左到右扫描输入符号串 ) {
i = 获取当前的输入符号 j = 获取栈顶的终结符号 switch(table[i][j]) //比较优先关系 { case 9: // 语法错误 case 0: // 移进 case -1: // 移进 case 1: // 归约 } }
{ k = k+1 ; S[ k ] = a ;
} else error( ); } while ( a != ‘#’ ) ; // end of do
// 判断符号栈是否出现成功标志 or 出错
在正确的情况下,算法工作完毕时符号栈将呈现 #N,输入 符号为# 。
步骤7
• 测试语法分析的结果
分析过程
编译原理 实验3 算符优先分析
编译原理实验3 算符优先分析一、实验目的通过设计编制调试构造FIRSTVT集、LASTVT集和构造算符优先表、对给定符号串进行分析的程序,了解构造算符优先分析表的步骤,对文法的要求,生成算符优先关系表的算法,对给定的符号串进行分析的方法。
二、实验内容1. 给定一文法G,输出G的每个非终结符的FIRSTVT集和LASTVT集。
2. 构造算符优先表。
3. 对给定的符号串进行分析,包含符号栈,符号栈栈顶符号和输入串当前符号的优先级,最左素短语和使用的产生式和采取的动作。
三、程序思路在文法框内输入待判断文法产生式,格式E->a|S,注意左部和右部之间是“->”,每个产生式一行,ENTER键换行。
文法结束再输入一行G->#E#1. 先做文法判断,即可判断文法情况。
2. 若是算符优先文法,则在优先表栏显示优先表。
3. 写入要分析的句子,按回车即可。
4. 在分析过程栏,可以看到整个归约过程情况四、实验结果FunctorFirst.h#include<afx.h>#include<iostream>#include<fstream>#include<string>using namespace std;#define rightlength 20#define product_num 20 // 产生式最多个数#define num_noterminal 26 // 非终结符最多个数#define num_terminal 26 // 终结符最多个数struct Production{char Left;char Right[rightlength];int num;};struct VT{bool vt[num_noterminal][num_terminal];};struct Stack{char P;char a;};class CMyDlg{public:CMyDlg();void InputRule();CString showLastVT();CString showFirstVT();CString shownoTerminal(char G[]);CString showTerminal(char g[]);CString showLeftS(char S[], int j, int k);void InitAll();CString showSentence(CString sen, int start);CString showStack(char S[], int n);void Initarry(char arry[], int n);CString ProdtoCStr(Production prod);int selectProd(int i, int j, char S[]);void preFunctor(CString sen);void insertFirstVT(Stack S[], int &sp, char P, char a);void insertLastVT(Stack S[], int &sp, char P, char a);void ShowPreTable();void createPreTable();char pretable[num_terminal][num_terminal];bool like_Q(Production prod, char Q);void createLastVT();bool likeQ_(Production prod, char Q);bool likeQa_(Production prod);bool like_aQ(Production prod);bool like_a(Production prod);bool likea_(Production prod);bool Dignose(char c);int findg(char c);int findG(char c);void createFirstVT();void createTerminal();void createnoTerminal();void buildProduction(CString s);bool test(CString s);void parse(); // 语法分析CString gram; // 存放文法;Production production[product_num];VT FirstVT;VT LastVT;int locProduct; // 已有产生式个数char G[num_noterminal];char g[num_terminal];int i_G;int i_g;CString m_sen;};FunctorFirst.cpp#include"FunctorFirst.h"CMyDlg::CMyDlg(){}bool CMyDlg::test(CString s) // 测试是否是算符优先文法{bool t = 1;for (int i = 0;i < s.GetLength() - 1;i++)if (s[i] > 64 && s[i] < 91 && s[i + 1]>64 && s[i + 1] < 91){t = 0;break;}return t;}void CMyDlg::InputRule(){string infile;string line;cout <<" 请输入语法文件的路径:";cin >> infile;cout << endl;ifstream input(infile.c_str());if (!input){cout << endl <<"###打不开文件,请确认输入的路径有效###"<< endl;cout <<"请再次运行本程序"<< endl << endl;exit(0);}while (getline(input, line)){if (test(line.c_str()) == 0){cout << endl <<"这不是算符优先文法!"<< endl;exit(0);}buildProduction(line.c_str());}cout << endl <<"这是算符优先文法!"<< endl;input.close();}void CMyDlg::buildProduction(CString s){int i = 0;int j = 0;int k = 0;for (k = 0;k < s.GetLength();k++) // 得到左部{if (s[k] != ' '){production[locProduct].Left = s[k];break;}}for (i = k + 1;i < s.GetLength();i++){if (s[i - 1] == '-'&&s[i] == '>')break;}int temp = i;for (i = temp + 1;i < s.GetLength();i++){if (s[i] != '|'){if (s[i] != ' '){production[locProduct].Right[j] = s[i];j++;production[locProduct].num = j;}}else{locProduct++;production[locProduct].Left = production[locProduct - 1].Left;j = 0;}}locProduct++;}void CMyDlg::createnoTerminal() // 建立非终结符索引{i_G = 0; // 最后一个位置的下一个下标int j = 0;for (int i = 0;i < locProduct;i++){for (j = 0;j < i_G;){if (production[i].Left != G[j])j++;elsebreak;}if (j > i_G - 1){G[i_G] = production[i].Left;i_G++;}}}void CMyDlg::createTerminal() // 建立终结符索引{i_g = 0; // 最后一个位置的下一个下标int j = 0;for (int i = 0;i < locProduct;i++){for (int k = 0;k < production[i].num;k++){char temp = production[i].Right[k];if (Dignose(temp)){for (j = 0;j < i_g;){if (temp != g[j])j++;elsebreak;}if (j > i_g - 1){g[i_g] = temp;i_g++;}}}}}void CMyDlg::createFirstVT() // production已完成,创建FirstVT{int i, j;Stack S[100];int sp = 0;for (i = 0;i < i_G;i++) // 初始化FirstVTfor (j = 0;j < i_g;j++)FirstVT.vt[i][j] = false;for (i = 0;i < locProduct;i++){if (likea_(production[i]))insertFirstVT(S, sp, production[i].Left, production[i].Right[0]);if (likeQa_(production[i]))insertFirstVT(S, sp, production[i].Left, production[i].Right[1]);}while (sp > 0){sp--;char Q = S[sp].P;char a = S[sp].a;for (i = 0;i < locProduct;i++){if (likeQ_(production[i], Q))insertFirstVT(S, sp, production[i].Left, a);}}}void CMyDlg::createLastVT() // 创建Last集{int i, j;Stack S[100];int sp = 0;for (i = 0;i < i_G;i++) // 初始化FirstVT for (j = 0;j < i_g;j++)LastVT.vt[i][j] = false;for (i = 0;i < locProduct;i++){if (like_a(production[i]))insertLastVT(S, sp, production[i].Left,production[i].Right[production[i].num - 1]);if (like_aQ(production[i]))insertLastVT(S, sp, production[i].Left,production[i].Right[production[i].num - 2]);}while (sp > 0){sp--;char Q = S[sp].P;char a = S[sp].a;for (i = 0;i < locProduct;i++){if (like_Q(production[i], Q))insertLastVT(S, sp, production[i].Left, a);}}}int CMyDlg::findG(char c) // 定位c在G中的下标{int i = 0;for (i = 0;i < i_G;i++)if (c == G[i])break;return i;}int CMyDlg::findg(char c) // 定位c在g中的下标{int i = 0;for (i = 0;i < i_g;i++)if (c == g[i])break;return i;}bool CMyDlg::Dignose(char c) // 判断c 是终结符还是非终结符,终结符true,非终结符 false{if (c > 64 && c < 91)return false;elsereturn true;}bool CMyDlg::likea_(Production prod){if (Dignose(prod.Right[0]))return true;elsereturn false;}bool CMyDlg::like_a(Production prod) // 形如P->…a型产生式{if (Dignose(prod.Right[prod.num - 1]))return true;else}bool CMyDlg::like_aQ(Production prod) // 形如P->…aQ型产生式{if (prod.num < 1)return false;else{if (Dignose(prod.Right[prod.num - 2]) && (!Dignose(prod.Right[prod.num - 1])))return true;elsereturn false;}}bool CMyDlg::likeQa_(Production prod){if (prod.num < 1)return false;else{if (Dignose(prod.Right[1]) && (!Dignose(prod.Right[0])))return true;elsereturn false;}}bool CMyDlg::likeQ_(Production prod, char Q){if (prod.Right[0] == Q)return true;elsereturn false;}bool CMyDlg::like_Q(Production prod, char Q){if (prod.Right[prod.num - 1] == Q)return true;else}void CMyDlg::createPreTable() // 创建优先表{// 初始化优先表pretableint i, j;for (i = 0;i < i_g;i++)for (j = 0;j < i_g;j++)pretable[i][j] = ' '; // 表错误for (j = 0;j < locProduct;j++){for (i = 0;i < production[j].num - 1;i++){char xi, xi1, xi2;xi = production[j].Right[i];xi1 = production[j].Right[i + 1];xi2 = production[j].Right[i + 2];if (Dignose(xi) && Dignose(xi1))pretable[findg(xi)][findg(xi1)] = '=';if (i < production[j].num - 2 && Dignose(xi) && Dignose(xi2) && (!Dignose(xi1)))pretable[findg(xi)][findg(xi2)] = '=';if (Dignose(xi) && (!Dignose(xi1))){int N = findG(xi1);for (int k = 0;k < i_g;k++)if (FirstVT.vt[N][k] == true)pretable[findg(xi)][k] = '<';}if ((!Dignose(xi)) && Dignose(xi1)){int N = findG(xi);for (int k = 0;k < i_g;k++)if (LastVT.vt[N][k] == true)pretable[k][findg(xi1)] = '>';}}}}void CMyDlg::ShowPreTable() // 显示相关集合和优先表{CString str = "";str = str +"终结符"+ showTerminal(g) +"\r\n";str = str +"非终结符"+ shownoTerminal(G) +"\r\n";str = str +"First集合:\r\n"+ showFirstVT();str = str +"Lasst集合:\r\n"+ showLastVT();str = str +" | ";int i, j;for (i = 0;i < i_g;i++)str = str + g[i] +" | ";str = str +"\r\n";for (j = 0;j < i_g;j++)str = str +"…………";str +="\r\n";for (i = 0;i < i_g;i++){str = str + g[i] +" | ";for (j = 0;j < i_g;j++)str = str + pretable[i][j] +" | ";str +="\r\n";for (j = 0;j < i_g;j++)str = str +"…………";str +="\r\n";}cout << str.GetBuffer(1000);}void CMyDlg::insertFirstVT(Stack S[], int &sp, char P, char a) {if (FirstVT.vt[findG(P)][findg(a)] == false){FirstVT.vt[findG(P)][findg(a)] = true;S[sp].P = P;S[sp].a = a;sp++;}}void CMyDlg::insertLastVT(Stack S[], int &sp, char P, char a){if (LastVT.vt[findG(P)][findg(a)] == false){LastVT.vt[findG(P)][findg(a)] = true;S[sp].P = P;S[sp].a = a;sp++;}}void CMyDlg::preFunctor(CString sen) // 算符优先分析过程实现{bool tagbreak = true;char S[100];int k = 0;S[k] = '#';int i = 0; // 表下次读入位置int j = 0;//char a;CString show = "";CString temp = "";temp.Format("%-15s %s %15s %-15s%-10s%-15s\r\n\r\n", "符号栈", "关系", "输入串", "最左素短语", "使用产生式", "下步动作");show = show + temp;temp ="";CString s_stack, s_sentence, s_lefts, s_prod, s_action;char s_presymbol;do{a = sen[i];if (Dignose(S[k]))j = k;elsej = k - 1;while (pretable[findg(S[j])][findg(a)] == '>'){s_stack = showStack(S, k);s_presymbol = pretable[findg(S[j])][findg(a)];s_sentence = showSentence(sen, i);char Q;do{Q = S[j];if (Dignose(S[j - 1]))j = j - 1;elsej = j - 2;} while (pretable[findg(S[j])][findg(Q)] == '>' ||pretable[findg(S[j])][findg(Q)] == '=');int n = selectProd(j + 1, k, S);if (n > -1 && n < locProduct){s_lefts = showLeftS(S, j + 1, k);k = j + 1;S[k] = production[n].Left;s_prod = ProdtoCStr(production[n]);s_action ="归约";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';}else{s_stack = showStack(S, k);s_presymbol = 'n';s_prod ="出错";s_sentence = showSentence(sen, i);s_action ="无法归约";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n",s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';tagbreak = false;break;}}if (!tagbreak)break;if (pretable[findg(S[j])][findg(a)] == '<' ||pretable[findg(S[j])][findg(a)] == '='){s_stack = showStack(S, k);s_presymbol = pretable[findg(S[j])][findg(a)];s_sentence = showSentence(sen, i);s_action ="入栈";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;k = k + 1;S[k] = a;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';}else{s_stack = showStack(S, k);s_presymbol = 'n';s_prod ="出错";s_sentence = showSentence(sen, i);s_action ="出错";temp.Format("%-15s %c %15s %-15s %-10s %-15s\r\n", s_stack, s_presymbol, s_sentence, s_lefts, s_prod, s_action);show = show + temp;s_stack ="";s_sentence ="";s_lefts ="";s_prod ="";s_action ="";s_presymbol = ' ';break;}i++;} while (a != '#');show = show +"完成";cout << show.GetBuffer(1000) << endl << endl;}void CMyDlg::parse(){string sen;cout << endl << endl <<" 请输入分析的句子:";cin >> sen;cout << endl << endl;m_sen = sen.c_str();}int CMyDlg::selectProd(int i, int j, char S[]) // 查找产生式{int n = -1;int k = 0;for (k = 0;k < locProduct;k++){if (j - i == production[k].num - 1){int si = i;for (int m = 0;m < production[k].num;m++){if (S[si] == production[k].Right[m] || ((!Dignose(S[si])) &&(!Dignose(production[k].Right[m]))))si++;elsebreak;}if (si == j + 1){n = k;break;}}}return n;}CString CMyDlg::ProdtoCStr(Production prod){CString str = "";str = str +prod.Left +"->";for (int i = 0;i < prod.num;i++)str = str +prod.Right[i];return str;}void CMyDlg::Initarry(char arry[], int n)//初始化数组{for (int i = 0;i < n;i++)arry[i] = ' ';}CString CMyDlg::showStack(char S[], int n)//显示符号栈,n表栈大小{CString str = "";for (int i = 0;i <= n;i++)str = str +S[i];return str;}CString CMyDlg::showSentence(CString sen, int start){CString str = "";for (int i = start;i < sen.GetLength();i++)str = str +sen[i];return str;}void CMyDlg::InitAll(){gram ="";i_G = 0;i_g = 0;locProduct = 0;}// 以下是为了便于显示,将数组型转换成CString型CString CMyDlg::showLeftS(char S[], int j, int k) {CString str = "";for (int i = j;i <= k;i++)str = str +S[i];return str;}CString CMyDlg::showTerminal(char g[]){CString str = "{";for (int i = 0;i < i_g;i++)str = str +g[i] +" ";return str +"}";}CString CMyDlg::shownoTerminal(char G[]){CString str = "{";for (int i = 0;i < i_G;i++)str = str +G[i] +" ";return str +"}";}CString CMyDlg::showFirstVT(){CString str = "";for (int i = 0;i < i_G;i++){str = str +"FirstVT( "+ G[i] +" )={ ";for (int j = 0;j < i_g;j++){if (FirstVT.vt[i][j])str = str + g[j] +' ';}str = str +" }\r\n";}return str;}CString CMyDlg::showLastVT(){CString str = "";for (int i = 0;i < i_G;i++){str = str +"LastVT( "+ G[i] +" )={ ";for (int j = 0;j < i_g;j++){if (LastVT.vt[i][j])str = str + g[j] +' ';}str = str +" }\r\n";}return str;}FFmain.cpp#include"FunctorFirst.h"void main(){CMyDlg ff;ff.gram ="";ff.locProduct = 0; // 已有产生式个数ff.InputRule();ff.createnoTerminal(); // 建立非终结符索引ff.createTerminal(); // 建立终结符索引ff.createFirstVT(); // 建立FirstVTff.createLastVT(); // 建立LastVTff.createPreTable(); // 建立优先表ff.ShowPreTable();ff.parse();if (ff.m_sen[ff.m_sen.GetLength() - 1] != '#') ff.m_sen = ff.m_sen +'#';ff.preFunctor(ff.m_sen);}。
编译原理算符优先算法语法分析实验报告
编译原理算符优先算法语法分析实验报告实验报告:算符优先算法的语法分析一、实验目的本次实验旨在通过算符优先算法对给定的文法进行语法分析,实现对给定输入串的分析过程。
通过本次实验,我们能够了解算符优先算法的原理和实现方式,提升对编译原理的理解和应用能力。
二、实验内容1.完成对给定文法的定义和构造2.构造算符优先表3.实现算符优先分析程序三、实验原理算符优先算法是一种自底向上的语法分析方法,通过构造算符优先表来辅助分析过程。
算符优先表主要由终结符、非终结符和算符优先关系组成,其中算符优先关系用1表示优先关系,用2表示不优先关系,用0表示无关系。
算符优先分析程序的基本思路是:根据算符优先关系,依次将输入串的符号压栈,同时根据优先关系对栈内符号进行规约操作,最终判断输入串是否属于给定文法。
四、实验步骤1.定义和构造文法在本次实验中,我们假设给定文法如下:1)E->E+T,T2)T->T*F,F3)F->(E),i2.构造算符优先表根据给定文法,构造算符优先表如下:+*()i#+212112*222112(111012222122i222222#1112203.实现算符优先分析程序我们可以用C语言编写算符优先分析程序,以下是程序的基本框架:```c#include <stdio.h>//判断是否为终结符int isTerminal(char c)//判断条件//匹配符号int match(char stack, char input)//根据算符优先关系表进行匹配//算符优先分析程序void operatorPrecedence(char inputString[]) //定义栈char stack[MAX_SIZE];//初始化栈//将#和起始符号入栈//读入输入串//初始化索引指针//循环分析输入串while (index <= inputLength)//判断栈顶和输入符号的优先关系if (match(stack[top], inputString[index])) //栈顶符号规约} else//符号入栈}//计算新的栈顶}//判断是否成功分析if (stack[top] == '#' && inputString[index] == '#')printf("输入串符合给定文法!\n");} elseprintf("输入串不符合给定文法!\n");}```五、实验结果经过实验,我们成功实现了算符优先算法的语法分析。
编译原理算符优先算法语法分析实验报告
数学与计算机学院编译原理实验报告年级专业学号姓名成绩实验题目算符优先分析法分析器的设计实验日期一、实验目的:设计一个算符优先分析器,理解优先分析方法的原理。
二、实验要求:设计一个算符优先分析器三、实验内容:使用算符优先分析算法分析下面的文法:E’→#E#E →E+T | TT →T*F | FF →P^F | PP →(E) | i其中i可以看作是一个终结符,无需作词法分析。
具体要求如下:1、如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的变化情况;2、如果输入符号串不是正确句子,则指示出错位置。
四、实验结果及主要代码:1.主要代码void operatorp(){char s[100];char a,Q;int k,j,i,l;string input,temp;cin>>input;cout<<"步骤"<<'\t'<<"栈"<<'\t'<<"优先关系"<<'\t'<<"当前符号"<<'\t'<<"剩余输入串"<<'\t'<<"移进或归约"<<endl;k=1;s[k]='#';i=1;do{a=input[0];temp="";for(l=1;l<();l++)temp+=input[l];input=temp;if(svt(s[k])) j=k;else j=k-1;while (search(s[j],a)=='>'){cout<<'('<<i<<')'<<'\t'; //步骤temp="";for(l=1;l<k+1;l++)temp+=s[l];cout<<temp<<'\t'; //栈cout<<'>'<<'\t'<<setw(10); //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串i++;for(;;){Q=s[j];if(svt(s[j-1])) j=j-1;else j=j-2;if(search(s[j],Q)=='<'){cout<<"归约"<<endl;//归约break;}}temp="";for(l=j+1;l<k+1;l++)temp+=s[l];for(l=0;l<6;l++)if(temp==key[l]){k=j+1;s[k]=v[l];break;}}cout<<'('<<i<<')'<<'\t'; //步骤temp="";for(l=1;l<k+1;l++)temp+=s[l];cout<<temp<<'\t'; //栈if(search(s[j],a)=='<'){cout<<'<'<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串cout<<"移进"<<endl;i++;k=k+1;s[k]=a;} //移进else if(search(s[j],a)=='Y'){cout<<'='<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串cout<<"接受"<<endl;i++;}else{cout<<''<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<input<<'\t'<<setw(15); //剩余输入串cout<<"出错"<<endl;exit(0);}//出错}while(a!='#');}2.实验结果。
编译原理 第05章_算符优先分析法
S)中不存在形如A…BC…的产生式,则称之为算符文
即:如果文法G中不存在具有相邻非终结符的产生式,
符文法,如果该文法中的任何终结符号对a,b之间,在三种
关系中最多只有一种成立,则称该文法为算符优先文法。
(1)求文法中每个非终结符P的首终结符集合FIRSTVT(P)
①定义:FIRSTVT(P)={a|P+a…或者P+Qa…,a ∈VT,P,Q
FOR
THEN
FIRSTVT(Xi+1)中的每个a DO THEN
置 Xi≮a;
IF Xi为非终结符而Xi+1为终结符
FOR
置 END;
LASTVT(Xi)中的每个a DO
a≯Xi+1;
4、直观算法优先算法:
(1)直观算符优先法的下推自动机:
两个工作栈:①算符栈OPTR:用于存放运算符
②算量栈OPND:用于存放运算量
E
E T F i + T T * F F i i
第5章 算符优先分析法
②算符优先分析法每一次归约时,可归约串中至少有一个终结符。
i+i*i# E+i*i# E+T*i# E+T*F# E+T# E#
E E i + T T * F i i
第5章 算符优先分析法
(3)最左素短语:
素短语是指至少含有一个终结符,并且除它自身 之外不再含有更小的素短语。 最左素短语指处于句型最左边的那个素短语。 最左素短语具备三个条件:
i+i-i*(i+i)
①矩阵元素M(a,b)表示a在前,b在后时,a与b之间的优先关系。
②矩阵元素M(a,b)的取值:≮,≯,≡ 。
编译原理第六章算符优先分析法
编译原理第六章算符优先分析法第六章算符优先分析法课前索引【课前思考】◇什么是⾃下⽽上语法分析的策略?◇什么是移进-归约分析?◇移进-归约过程和⾃顶向下最右推导有何关系?◇⾃下⽽上语法分析成功的标志是什么?◇什么是可归约串?◇移进-归约过程的关键问题是什么?◇如何确定可归约串?◇如何决定什么时候移进,什么时候归约?◇什么是算符⽂法?什么是算符优先⽂法?◇算符优先分析是如何识别可归约串的?◇算符优先分析法的优缺点和局限性有哪些?【学习⽬标】算符优先分析法是⾃下⽽上(⾃底向上)语法分析的⼀种,尤其适应于表达式的语法分析,由于它的算法简单直观易于理解,因此,也是学习其它⾃下⽽上语法分析的基础。
通过本章学习学员应掌握:◇对给定的⽂法能够判断该⽂法是否是算符⽂法◇对给定的算符⽂法能够判断该⽂法是否是算符优先⽂法◇对给定的算符⽂法能构造算符优先关系表,并能利⽤算符优先关系表判断该⽂法是否是算符优先⽂法。
◇能应⽤算符优先分析算法对给定的输⼊串进⾏移进-归约分析,在分析的每⼀步能确定当前应移进还是归约,并能判断所给的输⼊串是否是该⽂法的句⼦。
◇了解算符优先分析法的优缺点和实际应⽤中的局限性。
【学习指南】算符优先分析法是⾃下⽽上语法分析的⼀种,它的算法简单、直观、易于理解,所以通常作为学习其它⾃下⽽上语法分析的基础。
为学好本章内容,学员应复习有关语法分析的知识,如:什么是语⾔、⽂法、句⼦、句型、短语、简单短语、句柄、最右推导、规范归约基本概念。
【难重点】◇通过本章学习后,学员应该能知道算符⽂法的形式。
◇对⼀个给定的算符⽂法能构造算符优先关系分析表,并能判别所给⽂法是否为算符优先⽂法。
◇分清规范句型的句柄和最左素短语的区别,进⽽分清算符优先归约和规范归约的区别。
◇算符优先分析的可归约串是句型的最左素短语,在分析过程中如何寻找可归约串是算符优先分析的关键问题。
对⼀个给定的输⼊串能应⽤算符优先关系分析表给出分析(归约)步骤,并最终判断所给输⼊串是否为该⽂法的句⼦。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理课程设计报告_算符优先分析法编译原理课程设计报告选题名称: 算符优先分析法系(院): 计算机工程学院专业: 计算机科学与技术班级:姓名: 学号:指导教师:学年学期: 7>2012 ~ 2013 学年第 1 学期2012年 12 月 04 日设计任务书课题名称算符优先分析法设计目的通过一周的课程设计,对算符优先分析法有深刻的理解,达到巩固理论知识、锻炼实践能力、构建合理知识结构的目的。
实验环境Windows2000以上操作系统,Visual C++6.0编译环境任务要求1.判断文法是否为算符优先文法,对相应文法字符串进行算符优先分析;2.编写代码,实现算符优先文法判断和相应文法字符串的算符优先分析;3.撰写课程设计报告;4提交报告。
工作进度计划序号起止日期工作内容1 理论辅导,搜集资料2 ~编写代码,上机调试3 撰写课程设计报告4 提交报告指导教师(签章):年月日摘要:编译原理是计算机专业重要的一门专业基础课程,内容庞大,涉及面广,知识点多。
本次课程设计的目的正是基于此,力求为学生提供一个理论联系实际的机会,通过布置一定难度的课题,要求学生独立完成。
我们这次课程设计的主要任务是编程实现对输入合法的算符优先文法的相应的字符串进行算符优先分析,并输出算符优先分析的过程。
算符优先分析法特别有利于表达式的处理,宜于手工实现。
算符优先分析过程是自下而上的归约过程,但这种归约未必是严格的规范归约。
而在整个归约过程中,起决定作用的是相继连个终结符之间的优先关系。
因此,所谓算符优先分析法就是定义算符之间的某种优先关系,并借助这种关系寻找句型的最左素短语进行归约。
通过实践,建立系统设计的整体思想,锻炼编写程序、调试程序的能力,学习文档编写规范,培养独立学习、吸取他人经验、探索前言知识的习惯,树立团队协作精神。
同时,课程设计可以充分弥补课堂教学及普通实验中知识深度与广度有限的缺陷。
关键字:编译原理;归约;算符优先分析;最左素短语;目录1 课题综述 11.1 课题来源 11.2课题意义 11.3 预期目标 11.4 面对的问题 12 系统分析 22.1 基础知识 22.2 解决问题的基本思路 52.3 总体方案 53 系统设计 63.1 算法实现 63.2 流程图74 代码编写85 程序调试116 运行与测试12总结13致谢14参考文献151 课题综述1.1 课题来源算符文法:即它的任一产生式的右部都不含两个相继的非终结符的文法。
如果G是一个不含空字符的算法文法,那么只要它的任一对终结符都只满足,,的关系的一种,则称G是一个算符优先文法。
1.2课题意义算符优先文法在规约过程中只考虑终结符之间的优先关系确定句柄,而与非终结符无关,只需知道把当前句柄规约为某一非终结符,不必知道该非终结符的名字是什么,这样也就去掉了单非终结符的规约,因为若只有一个非终结符时无法与句型中该非终结符的左部及右部的串比较优先关系。
也就无法确定该非终结符为句柄。
1.3 预期目标编写程序,实现文法的算符优先判断,并对输入的符合算符优先文法的字符串进行算符优先分析。
首先对输入的表达式求FIRSTVT集和LASTVT集,然后根据优先级关系构造算符优先关系表,最后进行算符优先分析的过程。
过实践,建立系统设计的整体思想,锻炼编写程序、调试程序的能力,学习文档编写规范,培养独立学习、吸取他人经验、探索知识的习惯。
1.4 面对的问题如何通过自底向上的方法分析表达式,构造文法的优先矩阵,以及如何运用该优先矩阵完成移入和归约的过程,从而完成整个文法的分析。
1.5 需解决的关键技术本次课程设计中的关键是:扫描和语法分析函数,它使用一个用于存放文法符号的先进后出栈,并利用有限关系可以确定最左素短语是否已形成来决定分析器的动作。
如果当前栈顶的终结符号和带输入符号之间优先关系是或则表示栈顶符号串未形成最左素短语,此时分析器将移进输入符号。
如果当前栈顶的终结符号和待输入符号之间的优先关系是,则表示已找到最左素短语的尾,在从栈顶开始,按优先关系在栈内向左寻找最左素短语的头,然后分析器将归约最左素短语。
如果出现两个终结符号之间不存在优先关系,则表示存在语法错误。
以及如何编写、调试、修改代码。
还要了解一个题目有许多种解决方法。
锻炼我们的思维能力。
2 系统分析2.1 基础知识算符优先分析法的基本思想仿照算术表达式的四则运算过程算符优先分析的基本思想是只规定算符广义为终结符之间的优先关系,也就是只考虑终结符之间的优先关系,不考虑非终结符之间的优先关系。
在归约过程中只要找到可归约串就归约,并不考虑归约到那个非终结符名,算符优先分析的可归约串不一定是规范句型的句柄,所以算符优先归约不是规范归约。
算符优先分析的可归约串是当前符号栈中的符号和剩余的输入符号构成句型的最左素短语。
先关系的定义设G是一个不含ε产生式的算符文法,a和b是任意两个终结符,A、B、C 是非终结符,算符优先关系、、定义如下:① ab 当且仅当G中含有形如A→…ab…或A→…aBb…的产生式② ab 当且仅当G中含有形如A→…aB …的产生式,且Bb…或BCb…③ ab当且仅当G中含有形如A→…Bb …的产生式,且B…a 或B…aC以上三种关系也可由下列语法树来说明:① a b 则存在语法子树如图2.1 a其中δ为ε或为B,这样a, b在同一句柄中同时归约所以优先级相同。
② a b 则存在语法子树如图2.1 b其中δ为ε或为C。
a,b不在同一句柄中,b先归约,所以a的优先级低于b。
③ a b 则存在语法子树如图2.1 c 。
图2.1 由语法树结构决定优先性先文法的定义设有一文法G,如果G中没有形如A→…BC…的产生式,其中B和C为非终结符,则称G为算符文法 Operater Grammar 也称OG文法。
例如:表达式文法E→E+E|E*E| E |i其中任何一个产生式中都不包含两个非终结符相邻的情况,因此该文法是算符文法。
设有一不含ε产生式的算符文法G,如果对任意两个终结符对a,b之间至多只有、和三种关系中的一种成立,则称G是一个算符优先文法。
Operator Precedence Grammar 即OPG文法。
由以上内容我们可计算出给定的算符文法中任何两个终结符对 a,b 之间的优先关系,其算法如下:首先定义如下两个集合:FIRSTVT B b|B b…或 B Cb…LASTVT B a|B…a 或 B …aC三种优先关系的计算为a 关系:可直接查看产生式的右部,对如下形式的产生式A→…ab… , A→…aBb…有a b 成立。
b 关系:求出每个非终结符B的FIRSTVT B ,在如下形式的产生式A→…aB…中,对每一 b∈FIRSTVT B ,有ab成立。
c 关系:计算每个非终结符B的LASTVT B ,在如下形式的产生式A→…Bb…中,对每一a∈LASTVT B ,有ab成立。
最左素短语的定义设有文法G[S],其句型的素短语是一个短语,它至少包含一个终结符,并除自身外不包含其它素短语,最左边的素短语称最左素短语。
例如,若表达式文法G[E]为:E→E+T|TT→T*F|FF→P↑F|PP→ E |i图2.2 句型T+T*F+i的语法树若有句型#T+T*F+i#,它的语法树如图2.2。
其短语有:T+T*F+i 相对于非终结符E的短语T+T*F 相对于非终结符E的短语T 相对于非终结符E的短语T*F 相对于非终结符T的短语i 相对于非终结符P,F,T的短语由以上内容知i和T*F为素短语,T*F为最左素短语。
也为算符优先分析的可归约串。
由算符优先分析算法可知一个算符优先文法的最左素短语满足如下条件:ai-1 ai ai+1 ... aj aj+1上述句型#T+T*F+i#写成算符分析过程的形式为:#N1a1N2a2N3a3a4#其中a1 +, a2 *, a3 +, a4 ia1 a2 因+ *a2 a3 因* +由此 N2a2N3 即T*F为可归约串,也就是前面分析的最左素短语。
2.2 解决问题的基本思路根据课程设计的要求,程序应具有如下功能:对输入的文法进行分析并判断是否为算符优先文法。
如果是算符优先分析文法则再进一步输入符合该算符优先文法的字符串,并对该字符串进行算符优先分析,同时输出算符优先分析的过程。
2.3 总体方案启动VC++,新建源程序并进行编程,程序的功能模块图如图2-1所示。
图2-1系统功能结构图函数功能:Main 函数:调用主函数,运行程序;FIRSTVT 函数:构造FIRSTVT表;LASTVT 函数:构造LASTVT表;OpPrioTable 函数:构造算符优先关系表;InputAnalyse 函数:分析输入串是否为文法中的句子,并给出规约过程。
3 系统设计3.1 算法实现算符优先分析法的具体过程如下:1、首先先输入文件的路径,在readfile char sen[][col] 函数中,将需要分析的文法通过输入流文件打开函数open 复制到sen[row][col]中。
2、然后利用FIRSTVT 构造产生式sen[row][col]的FIRSTVT表。
先找出形如A- …a…(a为第一个终结符)的产生式,把(A,a)压入Operator栈中。
从Operator栈顶抛出项(A,a),填入first表相应位置。
在找出形如B- A…的产生式,把(B,a)压入Operator栈中。
循环直到Operator栈为空,此时FIRSTVT 表构造完毕。
3、然后把产生式右部翻转,调用FIRSTVT函数求出LASTVT表。
4、接着调用OpPriotable()构造算符优先关系表opTable。
先把产生式中所有终结符填入opTable表第一行和第一列,然后利用产生式和FIRSTVT表LASTVT表分别找出满足关系、关系、关系的算符填表。
若相应位已有关系,说明两个终结符之间至少有两种优先关系,该文法不是算符优先文法。
5、最后调用InputAnalyse()对输入串进行分析。
初始化分析栈S,依次判断当前输入符a和分析栈中离栈顶最近的终结符S[ j ]的关系,若S[ j ] a ,则a移近,若S[ j ] a ,则往前找到第一个S[ j ] a,将S[ j -1]到栈顶S[ k ]规约,若S[ j ] a ,如果S[ j ] #,则接受,如果S[ j ]! #,则移进。
直到接受或者出错,算符优先分析结束。
3.2 流程图图3-1 程序流程图4 代码编写在这次课程设计过程中,我主要负责的是FIRSTVT、 LASTVT集的构造部分,代码如下。
//FIRSTVT表和LASTVT表中表项(非终结符)的初始化void ItemInit char sen[][col],char first[][col],char last[][col],int sen_len,int &frist_lenint i;frist_len 1;first[0][0] sen[0][0];last[0][0] sen[0][0];for i 1;i sen_len;i++if TerminalJud sen[i][0] false && ItemJud first,frist_len,sen[i][0] false //k是当前first和last表的长度first[frist_len][0] sen[i][0];last[frist_len][0] sen[i][0];frist_len++;void FirstVt char sen[][col],char first[][col],int sen_len,int frist_len // frist_len 是 first 表的行数 sen_len是产生式的个数StackElement DFS,record[SIZE];stack Operator; //创建存放(A,a)的栈InitStack Operator ;int i,j,r 0;for i 0;i sen_len;i++ //第一次扫描,将能直接得出的first (A,a)放进栈中for j 3;sen[i][j]! '\0';j++if TerminalJud sen[i][j] true //遇到的第一个终结符压入int exist 0;DFS.nonterm sen[i][0];DFS.term sen[i][j];for int i1 0;i r;i++if record[i1].nonterm sen[i][0]&&record[i1].term sen[i][j]exist 1;break;record[r].nonterm sen[i][0];record[r].term sen[i][j];if exist 0Insert Operator,DFS ;//A-aB A-aC A,a 压栈两次?record[r].nonterm sen[i][0];record[r].term sen[i][j];r++;break;int location[col]; //辅助数组,用来记录first表中放入终结符的位置for i 0;i frist_len;i++location[i] 1;while !ifEmpty Operatorint exist 0; //标志位,记录即将入栈的元素是否已经存在StackElement IDElement,DElement;DElement Pop Operator ; //弹出栈顶元素for i 0;i frist_len;i++if first[i][0] DElement.nontermint n location[i];first[i][n] DElement.term; //将终结符填入相应的first表中location[i]++;break;for j 0;j sen_len;j++if sen[j][3] DElement.nonterm //找出能推出当前非终结符的产生式的左部IDElement.nonterm sen[j][0];IDElement.term DElement.term;//判断将要放进栈里的元素曾经是否出现过,若没有,才压入栈for int r0 0;r0 r;r0++ //r记录record数组中的元素个数if record[r0].nonterm IDElement.nonterm && record[r0].term IDElement.termexist 1;break;if exist 0Insert Operator,IDElement ;record[r].nonterm IDElement.nonterm;record[r].term IDElement.term;r++;//if//for//whilevoid LastVt char sen[][col],char last[][col],int sen_len,int frist_len //firstvt表与lastvt表行数一样 first_len表示last 表的行数int i,j,i1,j1;char c,record[row][col] '\0' ;for i 0;i sen_len;i++for j 0;sen[i][j]! '\0';j++record[i][j] sen[i][j];j j-1;for i1 3,j1 j;i1 j1;i1++,j1-- //做翻转,就可以用求first的方法求lastc record[i][i1];record[i][i1] record[i][j1];record[i][j1] c;//forFirstVt record,last,sen_len,frist_len ;5 程序调试程序中调用了许多函数,编写代码时会出现调用的错误,使在程序运行时无法正确判断以致程序运行出错。