实验3 算符优先分析算法的设计与实现
算符优先文法实验报告

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

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

算符优先语法分析设计原理与实现技术XXX 1028XXX 计科1XXX 班功能描述能够有效识别以下算符优先文法E T E+T | E-TT T T*F | T/F | FF T (E) | i所描述算术表达式.主要数据结构描述程序结构描述设计方法2. 根据算符优先矩阵算数表达式的词法分析结果进行语法分析,分析算法为:数据结构:符号栈S ---存放所有读进的符号(计数i)K ---符号栈使用深度a ---工作单元R, Q ---变量分析算法:先找最左素短语的尾部(>)再找最左素短语的头部(<)以分析表达式i+i*i为例,详细过程如下:■算符优先关系矩阵例:舖入串i+i*i 的界苻优先分析过程(査界替优先关系矩体)1#N + N**<i■11# N + N*'■ 1#1#N + N J* N+<*># 接受# N + N#<+>## N结论:汁详iJt 文法的命法句子函数原型功能描述void in it()各种初始化操作,主要是建立符号与整 数、整数与行列号、整数与符号之间的映 射,也包括各全局变量的初始化void isVt(i nt )判断某整数所代表的符号是否是终结符##<i# i#<i>-l- #N#<+# N + +<i# N + i +<i>* # N+ N+<*分析栈优先关系号或’#'void comp(i nt a, int b) r比较两整数所代表的字符的优先关系—void adva nce() 从输入文件中读入一个词bool parser() 算符优先分析函数,根据算符优先矩阵进行语法分析int main (i nt argc, char *argv[]) 主函数,参数argv[1]代表输入文件函数调用关系程序执行图S(l)=#;i=l;k=Q;k~k+1: R=siiLrQ=SG); j=j-ij=j-i l| t=i 11i=讦丄;S(i)=R程序测试测试用例一:(a+b*c)+d+e+a*c/b 首先调用实验一的词法分析程序,得到如下分析结果:(19, '(')(12, 'a')(14, '+')(12, 'b')(16, '*')(12, 'c')(20, ')')(14, '+')(12, 'd')(14, '+')(12, 'e')(14, '+')(12, 'a')(16, '*')(12, 'c')(17, '/')(12, 'b')在以此分析结果作为本程序实验结果的输入,得到如下分析结果:taw Cf'v/indov^5\system32\cmd.exe该结果显示了详细的分析过程,且表明该表达式是一个符合该文法的表达式测试用例二:(a+b*c)+d*-a*c+(a+b同样调用实验--的词法分析程序,得到如下结果:(19, '(')(12, 'a')(14, '+')(12, 'b')(16, '*')(12, 'c')(20, ')')(14, '+') (12, 'd') (16, '*') (15, '-') (12, 'a') (16, '*') (12, 'c') (14, '+') (19, '(') (12, 'a') (14, '+') (12, 'b')以此分析结果作为本实验程序的输入,得到如下语法分析结果:实验结果表明,在分析过程中出现了错误,分析过程未完成,该样例是一个非法的表达式.学习总结按算符优先关系所确定的应被规约的子串恰好是当前举行的最左素短语.尽管算符优先分析也属于自底向上语法分析的范畴,但却不是严格的从左至右的规范分析,每步所得的句型自然也不是一个规范句型.采用上述策略进行算符优先分析时,尽管我们也指出了每一最左素短语应规约到的非终结符号,然而每次在查找最左素短语时,起主导作用的是终结符号间的优先关系,两终结符号之间究竟是哪个非终结符号无关宏旨.// operator_prior.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <stdio.h>#include <ctype.h>#include <map>#include <vector>#include <string>#define ID 12#define ADD 14#define SUB 15#define MUL 16#define DIV 17#define LP 19#define RP 20#define EOI 31#define SHARP 32#define EQ 0#define BT 1#define LT 2#define UD 3#define N_Base 1000 using namespace std;FILE *fp;int lookahead, yylineno;bool success;map<int, int> intToint; map<char, int> charToint; map<int, char> intTochar; string grammer[8] = {"E+T", "E-T", "T","T*F", "T/F", "F","(E)", n:n};int prior_matrix[9][9] = {{BT, BT, LT, LT, LT, BT, LT, BT},{BT, BT, LT, LT, LT, BT, LT, BT},{BT, BT, BT, BT, LT, BT, LT, BT},{BT, BT, BT, BT, LT, BT, LT, BT},{LT, LT, LT, LT, LT, EQ, LT, UD},{BT, BT, BT, BT, UD, BT, UD, BT},{BT, BT, BT, BT, UD, BT, UD, BT},{LT, LT, LT, LT, LT, UD, LT, EQ}};void init() {success = true;yylineno = 0;intToint[ADD] = 0; intToint[SUB] = 1;intToint[MUL] = 2; intToint[DIV] = 3;intToint[LP] = 4; intToint[RP] = 5;intToint[ID] = 6; intToint[SHARP] = 7;charToint['+'] = ADD; charToint['-'] = SUB;charToint['*'] = MUL; charToint['/'] = DIV;charToint['('] = LP; charToint[')'] = RP;charToint['i'] = ID;intTochar[ADD] = '+'; intTochar[SUB] = '-';intTochar[MUL] = '*'; intTochar[DIV] = '/';intTochar[LP] = '('; intTochar[RP] = ')';intTochar[ID] = 'i'; intTochar[SHARP] = '#';intTochar[N_Base] = 'N';}bool isVt(int a) {if (a >= N_Base) return false;else return true;}int comp(int a, int b) { int x = intToint[a];int y = intToint[b]; return prior_matrix[x][y]; }void advance() {if (fscanf(fp, "(%d", &lookahead) == EOF) { lookahead = SHARP;} else {char ch;do {ch = fgetc(fp);if (ch == '\n' || ch == EOF) break; } while (true);} yylineno++;}void parser() {int stack[100], top = 0;int i, j, k, ii, jj;stack[top++] = SHARP;advance();do {for (i = 0; i < top; i++) {printf("%c", intTochar[stack[i]]);}printf("\t%c\n", intTochar[lookahead]);for (i = top - 1; i >= 0; i--) { if (isVt(stack[i])) break;}int res = comp(stack[i], lookahead);if (res == LT || res == EQ) { stack[top++] = lookahead; advance();} else if (res == BT) {int temp = stack[i]; for (j = i - 1; j >= 0; j--) {if (isVt(stack[j])) {if (comp(stack[j], temp) == LT) {break;} else {temp = stack[j];}}}for (k = 0; k < 8; k++) {if ((int)grammer[k].length() == top - 1 - j) {ii = j + 1;jj = 0;do {if (grammer[k].at(jj) >= 'A' && grammer[k].at(jj) <= 'Z'){ if (isVt(stack[ii])) break;} else {if (charToint[grammer[k].at(jj)] != stack[ii]) break;}ii++;jj++;} while (ii < top && jj < (int)grammer[k].length());if (ii >= top) break;}}if (k >= 8) {success = false;return ;}top = j + 1;stack[top++] = N_Base;} else {success = false;return ;}if (stack[0] == SHARP && stack[1] == N_Base&& stack[2] == SHARP) { printf("#N#\n"); break;}} while (true);success = true;}int main(int argc, char *argv[]) {if (argc == 2) {fp = fopen(argv[1], "r");init();parser();if (success) printf("This is a legal expression."); else printf("Thisis a illegal expression.");} else {printf(" 参数错误!\n");}return 0;。
编译原理算符优先分析算法

算符优先分析算法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。
实验三_算符优先分析算法的设计与实现

实验三 算符优先分析算法的设计与实现(8学时)一、 实验目的根据算符优先分析法,对表达式进行语法分析,使其能够判断一个表达式是否正确。
通过算符优先分析方法的实现,加深对自下而上语法分析方法的理解。
二、 实验要求1、输入文法。
可以是如下算术表达式的文法(你可以根据需要适当改变):E→E+T|E-T|TT→T*F|T/F|FF→(E)|i2、对给定表达式进行分析,输出表达式正确与否的判断。
程序输入/输出示例:输入:1+2;输出:正确输入:(1+2)/3+4-(5+6/7);输出:正确输入:((1-2)/3+4输出:错误输入:1+2-3+(*4/5)输出:错误三、实验步骤1、参考数据结构char *VN=0,*VT=0;//非终结符和终结符数组char firstvt[N][N],lastvt[N][N],table[N][N];typedef struct //符号对(P,a){char Vn;char Vt;} VN_VT;typedef struct //栈{VN_VT *top;VN_VT *bollow;int size;}stack;2、根据文法求FIRSTVT集和LASTVT集给定一个上下文无关文法,根据算法设计一个程序,求文法中每个非终结符的FirstVT 集和LastVT 集。
算符描述如下:/*求 FirstVT 集的算法*/PROCEDURE insert(P,a);IF not F[P,a] thenbeginF[P,a] = true; //(P,a)进栈end;Procedure FirstVT;Beginfor 对每个非终结符 P和终结符 a doF[P,a] = falsefor 对每个形如 P a…或 P→Qa…的产生式 doInsert(P,a)while stack 非空begin栈顶项出栈,记为(Q,a)for 对每条形如 P→Q…的产生式 doinsert(P,a)end;end.同理,可构造计算LASTVT的算法。
算符优先分析法

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

算符优先分析器设计1实验目的(1)掌握算符优先分析法——一种自底向上的语法分析方法的思想。
(2)能识别算符优先分析法中的可规约串——最左素短语。
(3)领会算符优先关系表转换成优先函数的方法。
2实验内容和实验要求根据形式化算法,编制程序实现一个算符优先分析器,能对常见的算术表达式语句进行分析。
要求实现以下功能:1) 组织算术表达式的输入;2) 组织算符优先关系表或者优先函数的输入;3) 若输入的符号串是一个算术表达式语句,则输出一个分析树骨架(既每一步规约用到的最左素短语),否则输出一个错误信息。
3待分析的语法描述E->E+T|TT->T*F|FF->(E)| I4算法描述4.1算府分析法基本方法实现算法,转化成某种高级语言程序,实现一个算符优先分析器。
其中要用到分析栈和输入缓冲器,本实验采用的方法是一种自底向上的语法分析方法,所以是在词法分析的基础上进行的。
对于表达式结果的计算,要在算法中引入内部变量来保存结果,另外在分析过程中,除了移进、规约、接受、报错等动作外,还要引入计算的动作。
4.2实现方法(1)首先定义char precede(char a,char c),在这里规定算符(终结符之间)的优先规则,在分析文法的时候便于调用。
(2)再定义 isn(char c),判断是否为非终结符,返回值为1和0,用于循环调用。
(3)主函数,总控算法:1.定义栈堆Stack中的变量,以及控制指针(用于存发归约或者待形成最左素短语的符号串)。
2.用string工作单元存放当前输入的字符,归约成功的标志是当读入的输入字符是句子的结束符号#号时,即栈中只是剩下#T的时候(栈Stack中只剩下开始标志# 和终结符号T的时候)使用判断是否栈顶指针指向的是#,若不是,则继续顺序扫描子过程。
从输入符号串中依次读入字符到string中,调用char precede(char a,char c)中进行分析是否要归约,还是要移进输入符,再栈S中形成最左素短语。
编译原理 算符优先分析实验报告

实验四、算符优先分析算法
姓名:
学号:
班级:
指导老师:
时间:
计算机与信息技术学院
程序功能描述
实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程。
G[E]:E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
说明:终结符号i 为用户定义的简单变量,即标识符的定义。
(1)构造该算符优先文法的优先关系矩阵或优先函数;(2)输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;(3)算符优先分析过程应能发现输入串出错。
(4)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果。
备注:程序中判断该输入串是否为该文法定义的算术表达式的结果,若是则输出“accept”,若不是则输出“error”。
该二元式序列要以“#”为结尾。
主要数据结构描述
程序结构描述
程序测试:
测试1:(i+i*i)
输出:
输入二:i+i*ii
输出:
学习总结
算符优先文法关键点就在于判断各个终结符号的优先级,构造算符优先矩阵是个难点,程序里面没有实现,而是直接定义了优先矩阵,这是需要完善的地方,试试能不能在程序中动态地构造优先矩阵。
另外对于算符优先文法,失败的条件是比较两个非终结符的优先关系,若优先关系表中为空,就返回error.。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验三算符优先分析算法的设计与实现(8学时)一、实验目的根据算符优先分析法,对表达式进行语法分析,使其能够判断一个表达式是否正确。
通过算符优先分析方法的实现,加深对自下而上语法分析方法的理解。
二、实验要求1、输入文法。
可以是如下算术表达式的文法(你可以根据需要适当改变):E→E+T|E-T|TT→T*F|T/F|FF→(E)|i2、对给定表达式进行分析,输出表达式正确与否的判断。
程序输入/输出示例:输入:1+2;输出:正确输入:(1+2)/3+4-(5+6/7);输出:正确输入:((1-2)/3+4输出:错误输入:1+2-3+(*4/5)输出:错误三、实验步骤1、参考数据结构char *VN=0,*VT=0;//非终结符和终结符数组char firstvt[N][N],lastvt[N][N],table[N][N];typedef struct //符号对(P,a){char Vn;char Vt;} VN_VT;typedef struct //栈{VN_VT *top;VN_VT *bollow;int size;}stack;2、根据文法求FIRSTVT集和LASTVT集给定一个上下文无关文法,根据算法设计一个程序,求文法中每个非终结符的FirstVT 集和LastVT 集。
算符描述如下:/*求 FirstVT 集的算法*/PROCEDURE insert(P,a);IF not F[P,a] thenbeginF[P,a] = true; //(P,a)进栈end;Procedure FirstVT;Beginfor 对每个非终结符 P和终结符 a doF[P,a] = falsefor 对每个形如 P a…或 P→Qa…的产生式 doInsert(P,a)while stack 非空begin栈顶项出栈,记为(Q,a)for 对每条形如 P→Q…的产生式 doinsert(P,a)end;end.同理,可构造计算LASTVT的算法。
3、构造算符优先分析表依据文法和求出的相应FirstVT和 LastVT 集生成算符优先分析表。
算法描述如下:for 每个形如 P->X1X2…X n的产生式 dofor i =1 to n-1 dobeginif X i和X i+1都是终结符 thenX i = X i+1if i<= n-2, X i和X i+2 是终结符, 但X i+1 为非终结符 then X i = X i+2if X i为终结符, X i+1为非终结符 thenfor FirstVT 中的每个元素 a doX i < a ;if X i为非终结符, X i+1为终结符 thenfor LastVT 中的每个元素 a doa > X i+1 ;end4、构造总控程序算法描述如下:stack S;k = 1; //符号栈S的使用深度S[k] = ‘#’REPEAT把下一个输入符号读进a中;If S[k] ∈ VT then j = k else j = k-1;While S[j] > a doBeginRepeatQ = S[j];if S[j-1] ∈ VT then j = j-1 else j = j-2 until S[j] < Q;把S[j+1]…S[k]归约为某个N,并输出归约为哪个符号;K = j+1;S[k] = N;end of whileif S[j] < a or S[j]= a thenbegin k = k+1; S[k] = a endelse error //调用出错诊察程序until a = ‘#’5、对给定的表达式,给出准确与否的分析过程6、给出表达式的计算结果。
(本步骤可选作)四、实验报告要求1.写出编程思路、源代码(或流程图);2.写出上机调试时发现的问题,以及解决的过程;3.写出你所使用的测试数据及结果;4.谈谈你的体会。
5.上机8小时,完成实验报告2小时。
程序代码:#include<stdio.h>#include <stdlib.h>#include <iostream.h>char data[20][20]; //算符优先关系char s[100]; //模拟符号栈schar lable[20]; //文法终结符集char input[100]; //文法输入符号串char string[20][10]; //用于输入串的分析int k;char a;int j;char q;int r; //文法规则个数int r1; //转化后文法规则个数char st[10][30]; //用来存储文法规则char first[10][10]; //文法非终结符FIRSTVT集char last[10][10]; //文法非终结符LASTVT集int fflag[10]={0}; //标志第i个非终结符的FIRSTVT集是否已求出int lflag[10]={0}; //标志第i个非终结符的LASTVT集是否已求出int deal(); //对输入串的分析int zhongjie(char c); //判断字符c是否是终结符int xiabiao(char c); //求字符c在算符优先关系表中的下标void out(int j,int k,char *s); //打印s栈void firstvt(char c); //求非终结符c的FIRSTVT集void lastvt(char c); //求非终结符c的LASTVT集void table(); //创建文法优先关系表int 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);getchar(); deal();system("pause");}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{return 0;}}printf("\nflase");system("pause");return 0;}void out(int j,int k,char *s) //从栈中输出j到k的元素{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;}运行结果演示:。