编译原理课程设计报告_算符优先分析法

合集下载

编译原理-实验3算符优先分析法

编译原理-实验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)

编译原算符优先分析实验报告 (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

编译原理_实验报告实验二__语法分析(算符优先) 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集找出它们之间的优先关系,构造算符优先矩阵。

然后,由此矩阵构造相应符号串的算符优先分析表并编写程序。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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 程序调试程序中调用了许多函数,编写代码时会出现调用的错误,使在程序运行时无法正确判断以致程序运行出错。

相关文档
最新文档