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

编译原理课程设计报告_算符优先分析法编译原理课程设计报告选题名称: 算符优先分析法系(院): 计算机工程学院专业: 计算机科学与技术班级:姓名: 学号:指导教师:学年学期: 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 课题来源算符文法:即它的任一产生式的右部都不含两个相继的非终结符的文法。
编译原理实验4算符优先算法

一、实验目的与任务算术表达式和赋值语句的文法可以是(你可以根据需要适当改变):S→i=EE→E+E|E-E|E*E|E/E|(E)|i根据算符优先分析法,将赋值语句进行语法分析,翻译成等价的一组基本操作,每一基本操作用四元式表示。
二、实验涉及的相关知识点算符的优先顺序。
三、实验内容与过程如参考C语言的运算符。
输入如下表达式(以分号为结束):(1)a = 10;(2)b = a + 20;注:此例可以进行优化后输出(不作要求):(+,b,a,20)(3)c=(1+2)/3+4-(5+6/7);四、实验结果及分析(1)输出:(=, a,10,-)(2)输出:(=,r1,20,-)(+,r2,a,r1)(=,b,r2,-)(3)输出:(+,r1,1,2) (/,r2,r1,3) (/,r3,6,7) (+,r4,5,r3,) (+,r5,r2,4) (-,r6,r5,r4) (=,c,r6,-)五、实验有关附件(如程序、附图、参考资料,等)......h == '#') o][Peek(n0).No];if(r == '<') h == 'E'&& Peek(1).ch == '#' && Token[ipToken].ch == '#')return TRUE;elsereturn FALSE;}h){k = TRUE; h == 'E'){n ++;}return n;}词结束(遇到“#”号),无法移进,需要规约,返回:1词没有结束,需判断是否可以移进栈单词<=单词:移进后返回:2栈单词>单词:不能移进,需要规约,返回:1单词没有优先关系:出错,返回:-1int MoveIn(){SToken s,t; h = '#';Token[TokenNumber].No = O_NUL;return TRUE; h = '+';Token[TokenNumber].No = O_PLUS;GetChar();break;case '-':Token[TokenNumber].ch = '-';Token[TokenNumber].No = O_MINUS;GetChar();break;case '*':Token[TokenNumber].ch = '*';Token[TokenNumber].No = O_TIMES;GetChar();break;case '/':Token[TokenNumber].ch = '/';Token[TokenNumber].No = O_SLASH;GetChar();break;case '(':Token[TokenNumber].ch = '(';Token[TokenNumber].No = O_L_PAREN;GetChar();break;case ')':Token[TokenNumber].ch = ')';Token[TokenNumber].No = O_R_PAREN;GetChar();break;default:if(ch >= '0' && ch <= '9') h = 'i';Token[TokenNumber].No = O_IDENT;}else{return ! MakeErr("表达式中含有非法字符。
算符优先分析大学编译原理

6.1 自底向上优先分析概述
• 有两种优先分析法: 1。 简朴优先分析法:
求出文法全部符号(终止符,非终止符) 之间优先关系,按这种关系拟定规约过 程中旳句柄。 2。算符优先分析法:考虑算符之间优先关 系旳规约(非规范规约)
2
6.3 算符优先分析法
算符优先文法旳定义 算符优先关系表旳构造 算符优先分析算法 算符优先分析法旳不足
• 比规范归约快 • 可能造成把错误旳句子得到正确旳归约。
该措施仅合用于体现式旳语法分析
17
利用算符优先分析算法分析输入串
• 举例 p115: 分析输入串i+i#
• G’[E]: E→E+T|T T→T*F|F F→P↑F|P P→(E)|i
+ * ( ) i#
+>< << >< >
*> > < < > < >
第6章 自低向上优先分析
• 即移进-规约分析。思想: 对符号串自左向右扫描,将输入符号移入一种 后进先出栈中,边移入边分析,一旦栈顶符号 串形成某个句型旳句柄或可规约串时(该句柄 或可规约串相应某个产生式右部),就用该产 生式旳左部非终止符替代相应右部旳文法符号 串,即规约。反复这一过程,直到栈中只剩余 文法旳开始符号时则以为分析成功,即输入旳 符号串是文法旳句子。
E E+ T E +T F
T T* F i
E
E+T
E+T F
T
i
句型T+T+F旳素短语为:T+T
5
分析程序模型
输入串#
总控程序
输出
# 算符优先关系表 产生式
实验二 编译原理语法分析(算符优先)

实验二语法分析算符优先分析程序一.实验要求⑴选择最有代表性的语法分析方法算符优先法;⑵选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。
⑶实习时间为6学时。
二.实验内容及要求(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 "stdafx.h"#include "stdio.h"#include "stdlib.h"#include "iostream.h"int k;char a;int j;char q;int r;int r1;char st[10][30];char data[20][20];char s[100];char lable[20];char input[100];char string[20][10];char first[10][10];char last[10][10];int fflag[10]={0};int lflag[10]={0};int deal();int zhongjie(char c);int xiabiao(char c);void out(int j,int k,char *s);void firstvt(char c);void lastvt(char c);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]);first[i][0]=0;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();//输出每个非终结符的FIRSTVT集printf("每个非终结符的FIRSTVT集为:\n"); 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");}//输出每个非终结符的LASTVT集printf("每个非终结符的LASTVT集为:\n"); 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]='=';}//求FIRSTVT集void firstvt(char c) { 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;}}//求LASTVT集{void lastvt(char c)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(" ");}}//判断字符c是否是终极符int zhongjie(char c){int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return 1;}return 0;}//求字符c在算符优先关系表中的下标{int xiabiao(char c)int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return i;}return -1;}四、实验结果输入串为#(i+i)/i#存放于Read.txt文件中五、实验总结经过此次试验对算符优先分析的原理有了深入的理解,熟悉了算符分析的过程,掌握了算符优先分析的有关处理,能够使用一种高级语言构造算符优先的语法分析器。
编译原理算符优先分析算法

算符优先分析算法1.该实验实现算符优先分析算法,由于时间关系,尚未实现用程序计算FIRSTVT,LASTVT,因此本实验的各种非终结符及其之间的优先关系人为初始化。
本实验参考例4.12及其优先关系表。
2.算符优先关系表参考课本74页表4.4+ * id ( ) #+ > < < < > >* > > < < > >id > > > >( < < < < =) > > > ># < < < < =3.结果如图4.源代码# include<stdio.h># include<stdlib.h># include<string.h># define MAX 50 //定义最大长度为50,可以变化struct sst{char s[MAX];int ps;//栈顶终结符指针int top;//栈顶指针};struct inputst{char in[MAX];int pin;//当前字符指针};//定义算符及其优先关系表char ch[6] = {'+','*','i','(',')','#'};char chrelation[6][6]={'>','<','<','<','>','>','>','>','<','<','>','>','>','>','@','@','>','>','<','<','<','<','=','@','>','>','@','@','>','>','<','<','<','<','@','=', };char rela(char c1,char c2){int i = 0,j = 0;while(ch[i] != c1)i++;while(ch[j] != c2)j++;return chrelation[i][j];}int is_VN(char c1){//判断是否为非终结符int i = 0;while(i < 6){if(ch[i] == c1)return 0;i++;}return 1;}void main(){struct sst S;for(int i = 0;i < MAX;i++){S.s[i] = ' ';}S.s[0] = '#';S.ps = 0;S.top = 0;struct inputst input;printf("请输入需分析的字符串,以#结尾,最大长度为%d:\n",MAX);scanf("%s",input.in);printf("%s\n",input.in);input.pin = 0;printf("s栈优先关系当前符号输入流动作\n");int cursor;while(1){if(rela(S.s[S.ps],input.in[input.pin]) == '<' || rela(S.s[S.ps],input.in[input.pin]) == '=') { for(cursor = 0;cursor <= S.top;cursor++)printf("%c",S.s[cursor]);printf(" %c ",rela(S.s[S.ps],input.in[input.pin]));printf(" %c ",input.in[input.pin]);printf(" ");for(cursor = input.pin+1;cursor < strlen(input.in);cursor++)printf("%c",input.in[cursor]);if(S.s[S.ps] == '#' && S.s[S.top] == 'N' &&rela(S.s[S.ps],input.in[input.pin]) == '=') {printf(" 接受\n");return;}else{ printf(" 移进\n");S.top++;S.ps = S.top;S.s[S.top] = input.in[input.pin++];}}else if(rela(S.s[S.ps],input.in[input.pin]) == '>'){for(cursor = 0;cursor <= S.top;cursor++)printf("%c",S.s[cursor]);printf(" %c ",rela(S.s[S.ps],input.in[input.pin]));printf(" %c ",input.in[input.pin]);printf(" ");for(cursor = input.pin+1;cursor < strlen(input.in);cursor++)printf("%c",input.in[cursor]);if(S.ps >0 && S.ps < S.top){if( is_VN(S.s[S.ps-1]) && is_VN(S.s[S.ps+1])){S.s[S.ps-1] = 'N';S.top = S.ps-1;S.ps = S.top -1;}printf(" 归约\n");}else{S.s[S.top] = 'N';S.ps = S.top -1;printf(" 归约\n");}}else{for(cursor = 0;cursor <= S.top;cursor++)printf("%c",S.s[cursor]);printf(" %c ",rela(S.s[S.ps],input.in[input.pin]));printf(" %c ",input.in[input.pin]);printf(" ");for(cursor = input.pin+1;cursor < strlen(input.in);cursor++) printf("%c ",input.in[cursor]);printf(" 出错!");return;}}}5.问题不知如何用计算机程序得到FIRSTVT,LASTVT。
编译原理之OPG实验报告

编译原理之算符优先文法分析——**学院1105班安雨雅班级:11**学号:11****实验语法分析实验报告一、实验题目算符优先文法分析程序二、实验内容及要求(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕和文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式文法为:(OPG文件中还有其他文法可作为测试) B~BoT|TT~TaF|FF~nF|(B)|t|f(4)分析的句子为:ntofat#三、设计思想之重点:构造算符优先表:①求FirstVT集和LastVT集②判断是否是算符文法③判断是否是算符优先文法算符优先分析:I、求最左素短语II、根据算符优先分析表分析(“<”或”=”时移进;“>”时归约)四、程序源代码(C语言)#include "stdio.h"#include "string.h"#include "stdlib.h"#define STR_MAX 80 //串的最大长度#define MAX_NUM 100 //符号的最大个数#define MAX 32767 //文件中符号的最大个数#define N 20//栈的长度class stack{ //符号栈private:char s[N];int top;public:stack();void push(char);void pop();int TOP(); //返回top的值char *S(); //返回s的值};stack::stack(){ top=-1; }void stack::push(char ch) //进栈操作{ s[++top]=ch;s[top+1]='\0'; }void stack::pop() //出栈操作{ top--; }int stack::TOP() //返回top的值{ return top; }char * stack::S() //返回s的值{ return s; }char M[MAX_NUM][MAX_NUM];struct PRO{//产生式类型char left;char right[STR_MAX];};struct VNstru{char vn;char firstVT[MAX_NUM];char lastVT[MAX_NUM];};char SOUR[STR_MAX];//源文件名char OBJ[STR_MAX]; //目标文件名char ERR[STR_MAX]; //错误信息文件名FILE *INF; //源程序文件指针FILE *OUTF; //分析结果文件指针FILE *ERRF; //错误信息文件指针char OG[MAX]; //存放上下文无关文法int OGlen; //上下文无关文法长度VNstru VN[MAX_NUM]; //非终结符数组int VN_CNT; //非终结符个数char VT[MAX_NUM]; //终结符数组int VT_CNT; //终结符个数char S0; //开始符号PRO P[MAX_NUM]; //产生式数组int P_CNT; //产生式个数bool isIN(char ch,VNstru arr[]); //判别符号ch是否在arr数组中int isVN(char ch); //判别符号ch是否在VN数组中,存在则返回下标,否则返回-1 int isVT(char ch); //判别符号ch是否在VT数组中,存在则返回下标,否则返回-1 void getOG(); //从源文件取得OG文法串void getVN_VT_S_P(); //从OG文法提取VN,VT,S,Pvoid FirstVT(char ch,char firstVT[]); //求FirstVT[]集firstVT void LastVT(char ch,char lastVT[]); //求LastVT[]集lastVTbool O_G(); //判别是否是OG文法bool O_P_G(); //判别是否是OPG文法void leftphase(char str[],char substr[],char a); //求最左素短语substrvoid left_str(char w[],char subw[],int ip); //求剩余输入串subwbool isIN(char ch,VNstru arr[])//判别符号ch是否在arr数组中{for(int i=0;i<VN_CNT;i++)if(ch==arr[i].vn)return 1;return 0;}int isVN(char ch)//判别符号ch是否在VN数组中,存在则返回下标,否则返回-1 {for(int i=0;i<VN_CNT;i++){if(ch==VN[i].vn)return i;}return -1;}int isVT(char ch)//判别符号ch是否在VT数组中,存在则返回下标,否则返回-1 {for(int i=0;i<VT_CNT;i++){if(ch==VT[i])return i;}return -1;}void getOG()//从源文件取得OG文法串{OGlen=0;char ch;while(!feof(INF)){ch=fgetc(INF);if(ch!=' ')OG[OGlen++]=ch;}OG[OGlen]='\0';printf("The Grammar is :\n"); //将文法输出到屏幕puts(OG);fprintf(OUTF,"The Grammar is :\n");fputs(OG,OUTF); //将文法输出到文件}void getVN_VT_S_P()//从OG文法提取VN,VT,S,P{VN_CNT=0;VT_CNT=0;P_CNT=0;int newPF=0; //是否进入新产生式的标志int rightLen=0;char prech,ch,nextch;for(int i=0;i<OGlen;i++){if(i!=0) prech=OG[i-1]; //取文法文件中的前一个符号ch=OG[i]; //取文法文件中的当前符号nextch=OG[i+1]; //取文法文件中的下一个符号if(nextch=='~') //下一个符号是~,代表箭头{if(isVN(ch)==-1){ //当前符号不是已经识别到的VN VN[VN_CNT].vn=ch; //加入VNVN_CNT++;}P[P_CNT].left=ch; //记入新产生式的左部if(P_CNT==0)S0=ch; //第一条产生式的左部是开始符号i++; //跳过~}if(prech=='~'||prech=='|'){newPF=1; //进入新的产生式rightLen=0;}if(newPF==1){P[P_CNT].right[rightLen++]=ch;}if(nextch=='\n'||nextch=='|'){newPF=0; //一条产生式结束P_CNT++; //产生式个数加1P[P_CNT].left=P[P_CNT-1].left;i++; //跳过回车和|}}for(int j=0;j<OGlen;j++){ch=OG[j];if(ch!='~'&&ch!='|'&&ch!='\n'&&isVN(ch)==-1&&isVT(ch)==-1&&ch!=' ') VT[VT_CNT++]=ch;}VT[VT_CNT++]='#';VT[VT_CNT]='\0';//输出VNprintf("\nVN:\t");fprintf(OUTF,"\nVN:\t");for(int x=0;x<VN_CNT;x++){printf("%c",VN[x].vn);fprintf(OUTF,"%c",VN[x].vn);}//输出VTprintf("\nVT:\t%s\n",VT);fprintf(OUTF,"\nVT:\t%s\n",VT);//输出Sprintf("S0:\t%c\n\n",S0);fprintf(OUTF,"S0:%c\n\n",S0);//输出Pfor(int k=0;k<P_CNT;k++){printf("P[%d]:\t%c-->%s\n",k,P[k].left,P[k].right);fprintf(OUTF,"P[%d]:\t%c-->%s\n",k,P[k].left,P[k].right);}printf("\n");fprintf(OUTF,"\n");}//FIRSTVT(B)={b|B=>b...或B=>Cb...}int f=0;void FirstVT(char ch,char firstVT[])//求非终结符的FirstVT集,存至firstVT中{if(isIN(ch,VN))for(int i=0;i<P_CNT;i++){if(ch==P[i].left){int j=0;char a=P[i].right[j];//B->b...if(isVT(a)!=-1){firstVT[f++]=a;firstVT[f]='\0';}//B->Cb...if(isVN(a)!=-1 && isVT(P[i].right[j+1])!=-1){firstVT[f++]=P[i].right[j+1];firstVT[f]='\0';}//B->C,C->b...||Db...if(isVN(a)!=-1 && strlen(P[i].right)==1)FirstVT(a,firstVT);}}f=0; //f清零,便于重复调用此函数}//LASTVT(B)={a|B=>...a或B=>...aC}int l=0;void LastVT(char ch,char lastVT[])//求非终结符的LastVT集,存放至lastVT中{if(isIN(ch,VN))for(int i=0;i<P_CNT;i++){if(ch==P[i].left){int j=strlen(P[i].right)-1; //'j'记录右部的最后一个字符位置char a=P[i].right[j];//B->...a;if(isVT(a)!=-1){lastVT[l++]=a;lastVT[l]='\0';}//B->...aC;if(isVN(a)!=-1 && isVT(P[i].right[j-1])!=-1){lastVT[l++]=P[i].right[j-1];lastVT[l]='\0';}//B->C,C->...a||...aD;if(isVN(a)!=-1 && j==0)LastVT(a,lastVT);}}l=0;//l清零,便于重复调用此函数}bool O_G() //判别是否是OG文法[没有两个连续的非终结符,即形如A->...BC...的产生式] {//求所有非终结符的firstVT集for(int i=0;i<VN_CNT;i++){char fvt[STR_MAX];FirstVT(VN[i].vn,fvt);strcpy(VN[i].firstVT,fvt);printf("FirstVT(%c)={ ",VN[i]);fprintf(OUTF,"FirstVT(%c)={ ",VN[i]);for(int j=0;j<(int)strlen(fvt);j++){printf("%c ",fvt[j]);fprintf(OUTF,"%c ",fvt[j]);}printf("}\n");fprintf(OUTF,"}\n");}printf("\n");fprintf(OUTF,"\n");//求所有非终结符的lastVT集for(i=0;i<VN_CNT;i++){char lvt[STR_MAX];LastVT(VN[i].vn,lvt);strcpy(VN[i].lastVT,lvt);printf("LastVT(%c)={ ",VN[i]);fprintf(OUTF,"LastVT(%c)={ ",VN[i]);for(int j=0;j<(int)strlen(lvt);j++){printf("%c ",lvt[j]);fprintf(OUTF,"%c ",lvt[j]);}printf("}\n");fprintf(OUTF,"}\n");}//判别是否是OG文法for(i=0;i<P_CNT;i++){int j=0;while(P[i].right[j+1]!='\0'){char ch=P[i].right[j];char nextch=P[i].right[j+1];if(isVN(ch)!=-1 && isVN(nextch)!=-1)return 0;elsej++;}}return 1;}bool O_P_G()//判别是否是OPG文法 [不含空产生式或任意两个终结符a,b之间至多有一种(<,>,=)关系]{for(int m=0;m<MAX_NUM;m++) //初始化M数组for(int n=0;n<MAX_NUM;n++)M[m][n]=' ';for(int i=0;i<P_CNT;i++){int j=0;char prech=' ',ch=' ',nextch=' '; //当进入新的产生式时,要清空三字符的值;while(P[i].right[j]!='\0'){if(j!=0)prech=ch;ch=P[i].right[j];nextch=P[i].right[j+1];if(isVT(ch)!=-1 && isVT(nextch)!=-1) //A->..ab.. (a=b){if(M[isVT(ch)][isVT(nextch)]==' ') //当M[][]为空时赋号{M[isVT(ch)][isVT(nextch)]='=';j++;continue;}else//当有a,b有两种关系时返回{printf("\n%c,%c有两种关系!",ch,nextch);fprintf(ERRF,"\n%c,%c有两种关系!",ch,nextch);return 0;}}if(isVT(ch)!=-1 && isVN(nextch)!=-1) //A->..aB... (a<FirstVT[B]){FirstVT(nextch,VN[isVN(nextch)].firstVT);for(int m=0;VN[isVN(nextch)].firstVT[m]!='\0';m++){if(M[isVT(ch)][isVT(VN[isVN(nextch)].firstVT[m])]==' ')M[isVT(ch)][isVT(VN[isVN(nextch)].firstVT[m])]='<';else//当有a,b有两种关系时返回{printf("\n%c,%c有两种关系!",ch,VN[isVN(nextch)].firstVT[m]);fprintf(ERRF,"\n%c,%c有两种关系!",ch,VN[isVN(nextch)].firstVT[m]);return 0;}}j++;continue;}if(isVT(prech)!=-1 && isVN(ch)!=-1 && isVT(nextch)!=-1) //A->..aBb.. (a=b) {if(M[isVT(prech)][isVT(nextch)]==' ')M[isVT(prech)][isVT(nextch)]='=';else{printf("\n%c,%c有两种关系!",prech,nextch);fprintf(ERRF,"\n%c,%c有两种关系!",prech,nextch);return 0;}}if(isVN(ch)!=-1 && isVT(nextch)!=-1) //A->..Bb..(LastVT[B]>b){LastVT(ch,VN[isVN(ch)].lastVT);for(int m=0;VN[isVN(ch)].lastVT[m]!='\0';m++){if(M[isVT(VN[isVN(ch)].lastVT[m])][isVT(nextch)]==' ')M[isVT(VN[isVN(ch)].lastVT[m])][isVT(nextch)]='>';else//当有a,b有两种关系时返回{printf("\n%c,%c有两种关系!",VN[isVN(ch)].lastVT[m],nextch);fprintf(ERRF,"\n%c,%c有两种关系!",VN[isVN(ch)].lastVT[m],nextch);return 0;}}j++;continue;}elsej++;}//(while)}//(for)M[VT_CNT-1][VT_CNT-1]='='; //#=#for(int x=0;x<(int)strlen(VN[isVN(S0)].firstVT);x++) //# < FirstVT(S0);M[VT_CNT-1][isVT(VN[isVN(S0)].firstVT[x])]='<';for(x=0;x<(int)strlen(VN[isVN(S0)].lastVT);x++) //LastVT(S0) > #M[isVT(VN[isVN(S0)].lastVT[x])][VT_CNT-1]='>';return 1;}void leftphase(char str[],char substr[],char a) //求最左素短语,用substr储存{int slen=strlen(str);int begin,end=slen-1;for(int i=slen-1;i>0;i--){if(M[isVT(str[i])][isVT(a)]=='>'){if(M[isVT(str[i-1])][isVT(str[i])]=='<')begin=i;else{begin=i-1;continue;}}if(isVN(str[i]))continue;}int j=0;int b=begin; //必须将begin的值记录,因为while的循环条件与begin有关,否则会影响素短语的取值。
编译原理算符优先算法语法分析实验报告

年级专业_学号 _姓名成绩__________________数学与计算机学院编译原理实验报告实验题目算符优先分析法分析器的设计实验日期一、实验目的:设计一个算符优先分析器,理解优先分析方法的原理。
二、实验要求:设计一个算符优先分析器三、实验内容:使用算符优先分析算法分析下面的文法:E' T #E#E T E+T | TT T T*F | FF T P AF | PP T (E) | i其中i可以看作是一个终结符,无需作词法分析。
具体要求如下:1、如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的变化情况;2、如果输入符号串不是正确句子,则指示出错位置。
四、实验结果及主要代码:1•主要代码 void operatorp()char s[100];char a,Q;int k,j,i,l;string input,temp;cin>>input;"<<'\t'<<" 剩cout<<" 步骤 "<<'\t'<<" 栈 "<<'\t'<<" 优先关系 "<<'\t'<<" 当前符号余输入串 "<<'\t'<<" 移进或归约 "<<endl;k=1;s[k]='#';i=1;do{a=input[0];temp="";for(l=1;l<input.length();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<<i nput<<'\t'<<setw(15); //剩余输入串cout<<"接受"<<e ndl;i++;}else{cout<<?<<'\t'<<setw(10);; //优先关系cout<<a<<'\t'<<setw(15); //当前符号cout<<i nput<<'\t'<<setw(15); //剩余输入串cout<<"出错"<<e ndl;exit(O);}//出错}while(a!='#');2•实验结果优九关系 ■fri 利余输入串 当前符号 i*n few ■ *F ::\2O12\^i§J '^:S\^:SJFt?^=£-\0perator_preredAnce_rpdL4r+ion\cipFr i a J or^preced?nre,red 1! 話讲<2> <3> <4> <5> <6> <7> Pi*es £栈 t 11 tF IF* »F*i tF*F tF any key to continue H inn imtmt欢迎下载,谢谢观看!资料仅供参考学习。
编译原理课程设计算符优先分析法研究附源程序

1 课程设计的目的和要求 (1)1.1 课程设计的目的 (1)1.2 课程设计的要求 (1)2 系统描述 (1)2.1 自底向上分析方法的描述: (1)22算符优先文法的描述: (1)3)输入符号串,进行移进 -规约分析。
(2)3 概要设计 (2)3.1 设计思路 (2)3.2 系统功能结构 (3)3.3 技术路线或实现方法 (4)3.4 开发环境 (4)4详细设计 (4)4.1 模块划分 (4)4.2 主要算法的流程图 (6)4.3 数据分析与定义 (7)4.4 系统界面设计 (7)5测试方法和测试结果 (8)5.1 测试用例1 (8)5.2 测试用例2 (9)5.3 测试用例3 (10)5.4 测试用例4 (11)6 结论和展望 (12)结论 (12)展望 (12)学习编译技术课程的体会和对本门课程的评价 (12)7 参考文献 (12)8 源代码 (13)1课程设计的目的和要求1.1 课程设计的目的本次设计的时间为1周,目的是通过使用高级语言实现部分算法加强对编译技术和理论的理解。
设计的题目要求具有一定的规模,应涵盖本课程内容和实际应用相关的主要技术。
1.2 课程设计的要求1、文法使用产生式来定义;2、用大写字母和小写字母分别表示非终结符和终结符;产生式使用->;3、文法中的空字符串统一使用@表示;4、分别给出每一个非终结符的FIRSTVT集和LASTVT集;5、画出算符优先关系表6判定给定的文法是否是算符优先文法;7、给定符号串判定是否是文法中的句子,分析过程用分析表格的方式打印出来。
2系统描述本次实验使用windows vista操作系统下visual C++6.0平台,使用C语言,利用读文件方式将待分析的文法读入到程序中,通过定义数组和结构体作为具有一定意义或关系的表或栈,存放FIRSTVT、LASTVT、算符优先关系表的元素。
系统能够对由文件读入的文法进行分析,构造出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.。
编译原理课程设计报告 算符优先分析表

课程设计(论文)任务书软件学院学院软件工程专业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生成算符优先分析表。
编译原理算符优先分析程序设计

编译原理算符优先分析程序设计算符优先分析(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)```以上是一个简单的算符优先分析程序设计,实现了根据输入串和优先关系表进行分析的过程。
编译原理算符优先分析法

4.4.2 算符优先文法的定义
4.4.2 算符优先文法的定义
单击此处添加正文。
算符优先关系的定义
若S a…或S Ca…,则$ a 若S …a或S …aC,则a $
规定:
4.4.2 算符优先文法的定义
算符优先文法的定义 设有一个不含 规则的OG文法G, 如果任意两个终结符间至多有一种算符关系存在, 则称G是算符优先文法,也称OPG文法。 结论:算符优先文法是无二义的。
(非终结符对可归约串的识别没有影响,在归约时可用任意的N代替。)
当读到句子结束符$,栈中只剩下$N时,成功。
S栈
优先关系
当前符号
输入流
动作
$ $id $N $N+ $N+id $N+N $N
id + + id $ $ $
+id$ id$ id$ $
4.3 自下而上分析法的一般原理
1 自下而上语法分析概述
基本思想:用一个寄存文法符号的栈,将一个输入串反向归约至文法的开始符号。 特点:效率高、文法限制少。
1 自下而上语法分析概述
移进-归约过程实例。 例4.11 设有文法G[A]: A aBcDe B b B Bb D d 对输入串abbcde$的移进-归约分析过程
性质:
在算符文法中任何句型都不包含两个相邻的非终结符。 如Ab或bA出现在算符文法的句型 中,则 中任何含b的短语必含有A。
1 算符文法的定义
设有文法G,若G中没有形如U …VW…的规则,其中V和W为非终结符,则G称为算符文法,也称OG文法。
2 算符优先关系的定义 在OG中定义算符优先关系: (1)a b :含有P …ab…,或 P …aQb…的 规则。 (2)a b :含有P …aR…的规则,且R b…或 R Qb… (3)a b:含有P …Rb…的规则,且R …a或 R …aQ。
编译原理之算符优先分析

编译原理之算符优先分析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)二、设计原理 (1)三、设计思想 (2)四、设计要求 (3)五、设计流程图及程序 (4)六、运行结果及分析 (14)七、设计总结 (16)八、参考文献 (16)算符优先词法分析器一、设计目的算符优先算法是自底而上分析方法的一种。
所谓自底向上分析,也称移进—规约分析,粗略地说他的实现思想是对输入符号串自左向右进行扫描,并将输入符逐个移入一个后进先出的栈中,边移进边分析,一旦栈顶符号串形成某个句型的句柄或可规约串是,就用该产生式的左部非终结符代替相应右部的文法符号串,这称为一部规约。
重复这一过程直到规约到栈中只剩文法的开始符号是则为分析成功,也就确认输入串是文法的句子。
而算符优先分析的基本思想是只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系。
本课程设计的主要目的:1、通过本次课程设计,全面系统的了解编译原理程序构造的一般原理和基本实现方法,尤其是对自底向上的优先分析方法的认识和理解;2、提高对编译程序工作基本过程及其各阶段基本任务的分析技能;3、加强对编译程序的生成过程、构造工具及编译程序总流程框图的理解,巩固所学的课本知识。
二、设计原理算符优先分析法是一种有效的自底向上的分析方法。
自底向上分析方法面临的主要问题是如何确定可归约串,而算符优先分析法根据两个终结符号之间的优先关系比较,成功的解决了可归约串的问题。
算符优先分析法是采用最左素短语进行归约的,严格来讲不属于规范规约的范畴。
因此,在设计以前我们必须要知道什么是素短语和最左素短语。
所谓素短语就是指句型中具有这样性质的短语:至少含有一个终结符,且除了自身之外,不再含有任何更小的素短语的短语。
最左素短语,是指在句型的所有素短语中,处于句型最左边的素短语。
了解了素短语和最左素短语,那么如何构造这种算法呢?首先,根据非终结符的FIRSTVT集和LASTVT集找出它们之间的优先关系,构造算符优先矩阵。
然后,由此矩阵构造相应符号串的算符优先分析表并编写程序。
编译原理算符优先算法语法分析实验报告

编译原理算符优先算法语法分析实验报告实验报告:算符优先算法的语法分析一、实验目的本次实验旨在通过算符优先算法对给定的文法进行语法分析,实现对给定输入串的分析过程。
通过本次实验,我们能够了解算符优先算法的原理和实现方式,提升对编译原理的理解和应用能力。
二、实验内容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");}```五、实验结果经过实验,我们成功实现了算符优先算法的语法分析。
编译基本知识实验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;}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 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,非终结符falseif (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;elsereturn false;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;elsereturn false;}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、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理课程设计报告评分:签字:编译原理课程设计二——算符优先分析程序设计实验目的了解掌握算符优先分析的基本方法、内容;学会科学思考并解决问题,提高程序设计能力。
实验内容与要求用算符优先分析方法设计一个分析解释程序,对输入的赋值语句、输出语句、清除语句进行词法分析、语法分析、表达式求值并存储于指定变量中;若存在错误,提示错误相关信息。
文法表示: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为存放的值。
以及标志符表。
过程四:算符优先分析算法分析:1) 置栈底及输入串尾为# ,并设# < VT , VT > #;栈顶终结符为θ,输入字为 a ;2) 若θ<a 或θ = a 且a≠#,则a 移入栈中. 重复2);若θ >a, 则在栈中寻找最左素短语,归约为N ,并记录N的值重复2);若θ=a=#, 且栈中为#N,则分析成功;否则,输入串为非法字串.数据结构设计:构造堆栈结构存储分析句子typedef struct {SymbolTbl *elem;int n;int top;}Stack;堆栈相关操作int CreateStack(Stack &s, int n)//初始化void clearStack(Stack &s)//清空int empty(Stack &s)//判断是否为空void push(Stack &s,SymbolTbl t)//入栈void pop(Stack &s)//出栈主要函数:void Clear_Symbol_Tbl()//清空符号表void print_(Stack &s,int &point)//打印出堆栈和符号表的情况void suanfu_main()//算符优先分析测试分析测试用例a=5b=a+10测试结果#a=5#标识符表:1 a -1二元组表:0 12 -11 9 12 1 -13 10 54 12 -1当前堆栈情况:(12,-1) 当前符号表情况:(9,1) (1,-1) (10,5)这里是小于等于关系,入栈当前堆栈情况:(12,-1) (9,1)当前符号表情况:(1,-1) (10,5)这里是小于等于关系,入栈当前堆栈情况:(12,-1) (9,1) (1,-1)当前符号表情况:(10,5)这里是小于等于关系,入栈当前堆栈情况:(12,-1) (9,1) (1,-1) (10,5)当前符号表情况:此处将常量归约为N当前堆栈情况:(12,-1) (9,1) (1,-1) (13,5)当前符号表情况:此处将v=c归约为N当前堆栈情况:(12,-1) (13,5)当前符号表情况:当前堆栈情况:(12,-1) (13,5)当前符号表情况:归约成功结果为5coninue ? y or n y请输入句子,以#开始并且以#结束#b=a+10#标识符表:1 a 52 b -1二元组表:0 12 -11 9 22 1 -13 9 14 3 -15 10 106 12 -1当前堆栈情况:(12,-1)当前符号表情况:(9,2) (1,-1) (9,1) (3,-1) (10,10) 这里是小于等于关系,入栈当前堆栈情况:(12,-1) (9,2)当前符号表情况:(1,-1) (9,1) (3,-1) (10,10) 这里是小于等于关系,入栈当前堆栈情况:(12,-1) (9,2) (1,-1)当前符号表情况:(9,1) (3,-1) (10,10) 这里是小于等于关系,入栈当前堆栈情况:(12,-1) (9,2) (1,-1) (9,1)当前符号表情况:(3,-1) (10,10)此处将变量归约为N当前堆栈情况:(12,-1) (9,2) (1,-1) (13,5)当前符号表情况:(3,-1) (10,10)这里是小于等于关系,入栈当前堆栈情况:(12,-1) (9,2) (1,-1) (13,5) (3,-1)当前符号表情况:(10,10)这里是小于等于关系,入栈当前堆栈情况:(12,-1) (9,2) (1,-1) (13,5) (3,-1) (10,10)当前符号表情况:此处将常量归约为N当前堆栈情况:(12,-1) (9,2) (1,-1) (13,5) (3,-1) (13,10)当前符号表情况:此处将N+N归约为N当前堆栈情况:(12,-1) (9,2) (1,-1) (13,15)当前符号表情况:此处将v=c归约为N当前堆栈情况:(12,-1) (13,15)当前符号表情况:归约成功结果为15coninue ? y or n结论符合预期结果该赋值语句解释程序符合要求感想与收获赋值语句的词法分析包括了众多过程与步骤,通过完整的完成本次课程设计,我对构建算符优先表以及语法分析过程有了更深的理解与掌握。
同时在用代码实现的过程中我程序设计、程序优化、调试程序的能力也有较大提升。
代码#include<iostream>#include <iomanip>using namespace std;//单词种别码int zb_c(char a){switch (a) {case '=':return 1;case '?':return 2;case '+':return 3;case '-':return 4;case '*':return 5;case '/':return 6;case '(':return 7;case ')':return 8;case 'v':return 9;case 'c':return 10;case 'l':return 11;case '#':return 12;case 'N':return 13;default:return 0;}}char zbc[12] = { '=','?','+','-','*','/','(',')','v','c','l','#' };//是否为终结符int ISzj_code(char ch){if ((ch >= 97 && ch <= 122) || ch == '+' || ch == '*' || ch == '-' || ch == '/' || ch == '!' || ch == '(' || ch == ')' || ch == '#' || ch == '\?' || ch == '=')return 1;elsereturn 0;}char wenfa[4][30] = {{"S→v= E | E ? | l"},{"E→E + T | E - T | T"},{"T→T*F | T / F | F"},{"F→(E) | v | c"}};char First_VT[4][20];char Last_VT[4][20];char chc[4] = { 'S','E','T','F' };int Fzj(char a){switch (a){case 'S':return 0;case 'E':return 1;case 'T':return 2;case 'F':return 3;default:return -1;}}//求firstVTvoid get_firstVT(){int i, j;for ( i = 3;i >= 0;i--){int k = 0,flag = 1;for ( j = 2;wenfa[i][j] != '\0';j++){if (ISzj_code(wenfa[i][j]) && flag == 1){if (i == 0 && j == 3);else{First_VT[i][k++] = wenfa[i][j];flag = 0;}}if (wenfa[i][j] == '|')flag = 1;}if (i!=3){j = 0;while (First_VT[i + 1][j] != '\0')First_VT[i][k++] = First_VT[i + 1][j++];}First_VT[i][k] = '\0';}}void get_lastVT(){int i, j;for ( i = 3;i >= 0;i--){int k = 0, flag = 0;for ( j = 3;wenfa[i][j] != '\0';j++){if (ISzj_code(wenfa[i][j]) && flag == 1){Last_VT[i][k++] = wenfa[i][j];flag = 0;}if (!ISzj_code(wenfa[i][j]))flag = 1;}if (i!=3){j = 0;while (Last_VT[i+1][j] != '\0')Last_VT[i][k++] =Last_VT[i + 1][j++];}}}//打印fistVT与lastVT结果void printFistlast(){get_firstVT();for (int i = 0;i < 4;i++){cout << "FirstVT(" << chc[i] << "){";int j = 0;while (First_VT[i][j] != '\0')cout << First_VT[i][j++] << ",";cout << '}' << endl;}get_lastVT();for (int i = 0;i < 4;i++){cout << "LastVT(" << chc[i] << "){";int j = 0;while (Last_VT[i][j] != '\0')cout << Last_VT[i][j++] << ',';cout << '}' << endl;}}//优先关系表int priority[13][13] ;void prior(){int i, j,flag,p;for (i = 0;i < 13;i++)for (j = 0;j < 13;j++)priority[i][j] = -2;char ch1, ch2;//求等号for (i = 0;i < 4;i++){flag = 0;for (j = 3;wenfa[i][j] != '\0';j++){if (ISzj_code(wenfa[i][j])){flag++;if (flag == 1)ch1 = wenfa[i][j];if (flag == 2){ch2 = wenfa[i][j];priority[zb_c(ch1)][zb_c(ch2)] = 0;flag = 0;}}if (wenfa[i][j] == '|')flag = 0;}}//求小于for (i = 0;i < 4;i++){flag = 0;for (j = 3;wenfa[i][j] != '\0';j++){if (ISzj_code(wenfa[i][j])){flag = 1;ch1 = wenfa[i][j];}if (!ISzj_code(wenfa[i][j]) && flag == 1){ch2 = wenfa[i][j];if(ch2=='S'||ch2=='T'||ch2=='F'||ch2=='E'){int temp = Fzj(ch2);for ( p = 0;First_VT[temp][p] != '\0';p++){priority[zb_c(ch1)][zb_c(First_VT[temp][p])] = -1;}flag = 0;}if (wenfa[i][j] == '|')flag = 0;}}}//求大于for (i = 0;i < 4;i++){flag = 0;for (j = 3;wenfa[i][j] != '\0';j++){if (wenfa[i][j] == 'S' || wenfa[i][j] == 'T' || wenfa[i][j] == 'F' || wenfa[i][j] == 'E'){flag = 1;ch1 = wenfa[i][j];}if (ISzj_code(wenfa[i][j]) && flag == 1){ch2 = wenfa[i][j];int temp = Fzj(ch1);for (p = 0;Last_VT[temp][p] != '\0';p++){priority[zb_c(Last_VT[temp][p])][zb_c(ch2)] = 1;}flag = 0;}if (wenfa[i][j] == '|')flag = 0;}} for (i = 0;i <= 12;i++){priority[i][12] = 1;priority[12][i] = -1;}priority[12][12] = 0;}void print_prior(){int i;cout << setw(10);for (i = 0;i < 12;i++){cout << zbc[i];cout << setw(5);}cout << endl;for (int i = 1;i <= 12;i++){cout << zbc[i - 1]<<setw(5) ;for (int j = 1;j <= 12;j++)cout << priority[i][j]<< setw(5);cout << endl;}}typedef struct{int syn;//种别码int value;//数值或者标识符入口指针}SymbolTbl;#define LENGTH 10char ch;char *CODE[] = { "identifier","constant","keyword"/*保留字*/,"+","-","*","/","<","<=",">",">=","!=","==","=","(",")",",",":",";","{","}" };char *k[] = { "for","while","do","else","if","static","int","sizeof","break","continue" };//保留字char token[16];//存放处理后的字符串//标识符结构体typedef struct{char I[30];int value;}identifier;//变量表typedef struct{int cont[300];int len;}constnumber;//词法分析器void contacat()//连接字符{char * cht = &(ch);strcat_s(token, cht);}int letter()//判断是否为字母{return isalpha(ch);}int digit()//判断是否为数字{return isdigit(ch);}int reserve(char **k)//处理保留字int i;for (i = 0;i < LENGTH;i++){if (strcmp(token, k[i]) == 0)return (i + 1);}return 0;}identifier id[256];//标志符表int idscan = 1;int sysmbol(identifier *id)//处理标识符,查找符号表并存放位置若没有则添加{int i;for (i = 1;i <idscan;i++)if (strcmp(token,id[i].I) == 0)return i ;strcpy_s(id[idscan].I, token);id[idscan].value = -1;idscan++;return idscan-1;}int str_to_num()//数字字符串转化为整数{int i = 0;int k = token[i] - '0';for (i = 1;token[i] != '\0';i++){k = k * 10 + token[i] - '0';}return k;}int constant(constnumber *con)//存入常数表,并返回它在常数表中的位置{con->cont[con->len] = str_to_num();con->len++;return con->cont[con->len-1];}SymbolTbl symbol[100];void Insert_to_symboltbl(int syn, int value, int &point)//把二元组加入symbol表symbol[point].syn = syn;symbol[point].value = value;point++;}void WordAnalyze( constnumber *con, identifier *id, char sentence[],int &point,int &syn,int &sym_point)//词法分析{int entry,val;strcpy_s(token, "");//初始化为空字符串ch = sentence[point];if (ch == '#'&&point == 0){point++;ch = sentence[point];}if ((ch >= 'A'&&ch <= 'Z') || (ch >= 'a'&&ch <= 'z')) //分析标识符和保留字{//若字符为A~Z或0~9,则继续读取while (letter() || digit()){contacat();point++;ch = sentence[point];}//retract(fp, c);syn = 9;//代表找到了标识符if (strcmp(token, "clear") == 0){//代表找到了保留字“clear”syn = 11;Insert_to_symboltbl(syn, -1, sym_point);}if (syn == 9){entry = sysmbol(id);Insert_to_symboltbl(syn, entry, sym_point);}}else if (digit())//处理常数{while (digit()){contacat();point++;ch = sentence[point];}//retract(fp, c);val = constant(con);syn = 10;Insert_to_symboltbl(syn, val, sym_point);}else //分析符号{switch (ch){case'=':syn = 1; break;case'?':syn = 2; break;case'+':syn = 3; break;case'-':syn = 4; break;case'*':syn = 5; break;case'/':syn = 6; break;case'(':syn = 7; break;case')':syn = 8; break;case'#':syn = 12; break;default:printf("输入句子有误!\n");exit(0);break;}point++;Insert_to_symboltbl(syn, -1, sym_point);}}void Analyse_main()//初始化与结果输出{constnumber *con = (constnumber *)malloc(sizeof(constnumber));con->len = 0;char sentence[100] = "\0";int syn = -1,scan_point=0;int sym_point = 0;printf("请输入句子,以#开始并且以#结束\n");cin>>sentence;Insert_to_symboltbl(12, -1, sym_point);while (syn != 12){WordAnalyze(con, id, sentence, scan_point, syn,sym_point);}for (int m1 = 1;m1 < idscan;m1++){cout << m1<<" ";printf("%s ", id[m1].I);cout << id[m1].value<<" " << endl;}for (int m2 = 0;m2<sym_point;m2++){//符号表printf("\t%d %d %d\n", m2, symbol[m2].syn, symbol[m2].value);}}//算符优先分析typedef struct {SymbolTbl *elem;int n;int top;}Stack;int CreateStack(Stack &s, int n)//初始化{if (n < 0) return 0;s.n = n;s.top = -1;s.elem = (SymbolTbl*)malloc(sizeof(SymbolTbl)*n);if (!s.elem)return 0;return 1;}void clearStack(Stack &s)//清空{s.top = -1;}int empty(Stack &s)//判断是否为空{return s.top == -1;}void push(Stack &s,SymbolTbl t)//入栈{s.elem[++s.top] = t;}void pop(Stack &s)//出栈SymbolTbl t;t = s.elem[s.top--];}void Clear_Symbol_Tbl()//清空符号表{//将符号表的syn全部设置为0for (int i = 0;i<100;i++){symbol[i].syn = 0;//代表没定义symbol[i].value = -1;//指定为-1}}void print_(Stack &s,int &point)//打印出堆栈和符号表的情况{cout << endl;cout << "当前堆栈情况:";for (int i = 0;i <= s.top;i++)cout << "(" << s.elem[i].syn << "," << s.elem[i].value << ") ";cout << endl;cout << "当前符号表情况:";for(int j=point;symbol[j].syn!=12;j++)cout << "(" << symbol[j].syn << "," << symbol[j].value << ") ";cout << endl;}void error(){cout << "程序有错误";exit(0);}void suanfu_main()//算符优先分析{int symbol_scan=1;//符号表扫描指针,从1开始int stack_scan;//初始化一个堆栈Stack s;CreateStack(s, 50);SymbolTbl temp;temp.syn = 12;temp.value = -1;push(s, temp);print_(s, symbol_scan);stack_scan = s.top;int prior_stack, prior_symbol;while (1){prior_stack = s.elem[stack_scan].syn;prior_symbol = symbol[symbol_scan].syn;int prio = priority[prior_stack][prior_symbol];if (prio == -1 || (prio == 0 && prior_symbol != 12)){push(s, symbol[symbol_scan]);symbol_scan++;stack_scan = s.top;cout << "这里是小于等于关系,入栈";print_(s, symbol_scan);}else if (prio == 0 && s.elem[s.top].syn == 13 && prior_symbol == 12 && s.elem[s.top - 1].syn == 12) {cout << "归约成功" << endl;cout << "结果为" << s.elem[s.top].value << endl;break;}else if (prio == 1){stack_scan = s.top;while (prio == 1){int judge = s.elem[stack_scan].syn;if (judge == 9)//栈顶元素为变量{if (id[s.elem[stack_scan].value - 1].value == -1);else if (s.elem[stack_scan].value < 0){cout << "该变量未定义";exit(0);}else{temp.syn = 13;temp.value = id[s.elem[stack_scan].value].value;pop(s);push(s, temp);stack_scan = s.top - 1;if (stack_scan <0)error();prior_stack = s.elem[stack_scan].syn;prio = priority[prior_stack][prior_symbol];cout << "此处将变量归约为N" << endl;print_(s, symbol_scan);}}else if (judge == 10)//常量{temp.syn = 13;temp.value = s.elem[stack_scan].value;pop(s);push(s, temp);stack_scan = s.top - 1;if (stack_scan < 0)error();prior_stack = s.elem[stack_scan].syn;prio = priority[prior_stack][prior_symbol];cout << "此处将常量归约为N" << endl;print_(s, symbol_scan);}else if (judge == 1)//={if (s.elem[stack_scan - 1].syn == 9){id[s.elem[stack_scan - 1].value].value = s.elem[s.top].value;temp.syn = 13;temp.value = s.elem[s.top].value;pop(s);pop(s);pop(s);push(s, temp);stack_scan = s.top - 1;if (stack_scan < 0)error();prior_stack = s.elem[stack_scan].syn;prio = priority[prior_stack][prior_symbol];cout << "此处将v=c归约为N" << endl;print_(s, symbol_scan);}else{error();}}else if (judge == 3)//+{if (s.elem[stack_scan - 1].syn == 13 && s.elem[s.top].syn == 13){temp.syn = 13;temp.value = s.elem[stack_scan - 1].value + s.elem[s.top].value;pop(s);pop(s);pop(s);push(s, temp);stack_scan = s.top - 1;if (stack_scan < 0)error();prior_stack = s.elem[stack_scan].syn;prio = priority[prior_stack][prior_symbol];cout << "此处将N+N归约为N" << endl;print_(s, symbol_scan);}else{error( );}}else if(judge==4)//-{if (s.elem[stack_scan - 1].syn == 13 && s.elem[s.top].syn == 13){temp.syn = 13;temp.value = s.elem[stack_scan - 1].value - s.elem[s.top].value;pop(s);pop(s);pop(s);push(s, temp);stack_scan = s.top - 1;if (stack_scan < 0)error();prior_stack = s.elem[stack_scan].syn;prio = priority[prior_stack][prior_symbol];cout << "此处将N-N归约为N" << endl;print_(s, symbol_scan);}else{error( );}}else if (judge == 5)//*{if (s.elem[stack_scan - 1].syn == 13 && s.elem[s.top].syn == 13){temp.syn = 13;temp.value = s.elem[stack_scan - 1].value * s.elem[s.top].value;pop(s);pop(s);pop(s);push(s, temp);stack_scan = s.top - 1;if (stack_scan < 0)error();prior_stack = s.elem[stack_scan].syn;prio = priority[prior_stack][prior_symbol];cout << "此处将N*N归约为N" << endl;print_(s, symbol_scan);}else{error( );}}else if (judge == 6){if (s.elem[stack_scan - 1].syn == 13 && s.elem[s.top].syn == 13){temp.syn = 13;temp.value = s.elem[stack_scan - 1].value / s.elem[s.top].value;pop(s);pop(s);pop(s);push(s, temp);stack_scan = s.top - 1;if (stack_scan < 0)error();prior_stack = s.elem[stack_scan].syn;prio = priority[prior_stack][prior_symbol];cout << "此处将N/N归约为N" << endl;print_(s, symbol_scan);}elseerror( );}}else if (judge == 8)//){if (s.elem[stack_scan - 1].syn == 13 && s.elem[stack_scan-2].syn == 13) {temp.syn = 13;temp.value = s.elem[stack_scan - 1].value;pop(s);pop(s);pop(s);push(s, temp);stack_scan = s.top - 1;if (stack_scan < 0)error();prior_stack = s.elem[stack_scan].syn;prio = priority[prior_stack][prior_symbol];cout << "此处将N+N归约为N" << endl;print_(s, symbol_scan);}else{error( );}}else if (judge == 2)//? {if (s.elem[stack_scan - 1].syn == 13){temp.syn = 13;temp.value = s.elem[stack_scan - 1].value;pop(s);pop(s);push(s, temp);stack_scan = s.top - 1;if (stack_scan < 0)error();prior_stack = s.elem[stack_scan].syn;prio = priority[prior_stack][prior_symbol];cout << "此处将N?归约为N" << endl;print_(s, symbol_scan);}elseerror( );}}}}}}int main(){get_firstVT();get_lastVT();printFistlast();prior();print_prior();char a;while (1){Clear_Symbol_Tbl();Analyse_main();suanfu_main();cout << "coninue ? y or n";cin >>a;if (a == 'n')exit(0);}}。