编译原理实验4算符优先算法

合集下载

实验四算符优先分析法分析器的设计

实验四算符优先分析法分析器的设计

实验四算符优先分析法分析器的设计(6学时)
【目的】设计一个算符优先分析器,理解优先分析方法的原理。

【要求】使用算符优先分析算法分析下面的文法:
E’ →#E#
E →E+T | T
T →T*F | F
F →(E) | i
其中i可以看作是一个终结符,无需作词法分析。

具体要求如下:
1.如果输入符号串为正确句子,显示分析步骤,包括分析栈中的内容、优先关系、输入符号串的
变化情况;
2.如果输入符号串不是正确句子,则指示出错位置。

【方法】首先构造算符优先关系表,然后根据算符优先分析算法编写程序。

【实验环境和工具】本实验不限定现所使用的开发工具以及运行环境。

编译原算符优先分析实验报告 (2)

编译原算符优先分析实验报告 (2)

编译原理实验报告——算符优先文法分析指导教师:***学号:**********姓名:***【实验名称】算符优先文法分析【实验目的】掌握算符优先分析法的原理,利用算符优先分析法将赋值语句进行语法分析,翻译成等价的四元式表示。

【实验内容】1.算术表达式的文法可以是:(1)S->#E# (2)E->E+T (3)E->T (4)T->T*F (5)T->F (6)F->P^F (7)F->P (8)P->(E) (9)P->i2.根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确。

【设计思想】(1)定义部分:定义常量、变量、数据结构。

(2)初始化:设立算符优先关系表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用算符优先文法分析算法进行表达式处理:根据优先关系表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。

【流程图】【源码】#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <stack>using namespace std;struct Node1{char vn;char vt;char s[10];}MAP[20];//存储分析预测表每个位置对应的终结符,非终结符,产生式int k;//用R代表E',W代表T',e代表空char G[10][10]={"E->TR","R->+TR","R->e","T->FW","W->*FW","W->e","F->(E)","F->i"};//存储文法中的产生式char VN[6]={'E','R','T','W','F'};//存储非终结符char VT[6]={'i','+','*','(',')','#'};//存储终结符char SELECT[10][10]={"(,i","+","),#","(,i","*","+,),#","(","i"};//存储文法中每个产生式对应的SELECT集char Right[10][8]={"->TR","->+TR","->e","->FW","->*FW","->e","->(E)","->i"};stack <char> stak,stak1,stak2;bool compare(char *a,char *b){int i,la=strlen(a),j,lb=strlen(b);for(i=0;i<la;i++)for(j=0;j<lb;j++){if(a[i]==b[j])return 1;}return 0;}char *Find(char vn,char vt){int i;for(i=0;i<k;i++){if(MAP[i].vn==vn && MAP[i].vt==vt)return MAP[i].s;}return "error";}char * Analyse(char * word){char p,action[10],output[10];int i=1,j,l=strlen(word),k=0,l_act,m;while(!stak.empty())stak.pop();stak.push('#');stak.push('E');printf("_________________________________________________________________________ _______\n");printf("\n 对符号串%s的分析过程\n",word);printf(" 步骤栈顶元素剩余输入串推到所用产生式或匹配\n");p=stak.top();while(p!='#'){printf("%7d ",i++);p=stak.top();stak.pop();printf("%6c ",p);for(j=k,m=0;j<l;j++)output[m++]=word[j];output[m]='\0';printf("%10s",output);if(p==word[k]){if(p=='#'){printf(" 接受\n");return "SUCCESS";}printf(" “%c”匹配\n",p);k++;}else{strcpy(action,Find(p,word[k]));if(strcmp(action,"error")==0){printf(" 没有可用的产生式\n");return "ERROR";}printf(" %c%s\n",p,action);int l_act=strlen(action);if(action[l_act-1]=='e')continue;for(j=l_act-1;j>1;j--)stak.push(action[j]);}}if(strcmp(output,"#")!=0)return "ERROR";}int main (){freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);char source[100];int i,j,flag,l,m;printf("\n为了方便编写程序,用R代表E',W代表T',e代表空\n\n");printf("该文法的产生式如下:\n");for(i=0;i<8;i++)printf(" %s\n",G[i]);printf("\n该文法的SELECT集如下:\n");for(i=0;i<8;i++){printf(" SELECT(%s) = { %s }\n",G[i],SELECT[i]);}//判断是否是LL(1)文法flag=1;for(i=0;i<8;i++){for(j=i+1;j<8;j++){if(G[i][0]==G[j][0]){if(compare(SELECT[i],SELECT[j])){flag=0;break;}}}if(j!=8)break;}if(flag)printf("\n有相同左部产生式的SELECT集合的交集为空,所以文法是LL(1)文法。

编译原理课程设计算符优先分析法研究附源程序

编译原理课程设计算符优先分析法研究附源程序

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[S]:S->#E#E->E+T|TT->T*F|FF->P^F | PP->(E)|i二、主要数据结构char VT[]定义符号表;struct type{char origin; char array[5]; int length;}定义产生式类型;table[][]定义优先关系矩阵。

三、程序结构int locate(char s[],char c) 辅助函数,在一个字符串中查找某特定字符;int Find(type G[],char s[],int m,int n) 查找与已搜索出的短语对应的产生式,返回该产生式的序号;void doScan()对输入串进行分析的主控函数;void print(char s[],int k,int tag,char str[],int i,char action[])输出分析过程的函数。

在find()和doScan()中调用locate()函数,在doScan()中调用find()和print()函数,在main()中调用doScan()函数。

流程图:Y成功四、程序测试测试句子:i+i*i结果:测试句子:(i+i)*i结果:五、实验总结本实验重点解决算符优先矩阵的构造和算符优先算法的实现,我认为难点是构造优先矩阵,这个就需要掌握方法多练习,优先算法只需将PPT上的流程图一步一步地转化为代码就可以了。

总体来说,本实验比较简单。

THANKS !!!致力为企业和个人提供合同协议,策划案计划书,学习课件等等打造全网一站式需求欢迎您的下载,资料仅供参考。

编译原理算符优先分析程序设计

编译原理算符优先分析程序设计

编译原理算符优先分析程序设计算符优先分析(Operator Precedence Parsing)是一种基于文法的自下而上的语法分析方法,用于构造一个将输入串转化为语法分析树的分析器。

它通过根据每一个终结符号和非终结符号之间的优先级关系,来判断是否可以进行规约操作。

算符优先分析的基本思想是,为每一个终结符和非终结符分配一个优先级,然后根据这些优先级来决定如何进行规约操作。

一般来说,基本的终结符都有一个固定的优先级,而非终结符的优先级则由其所对应的产生式右部中的终结符优先级来决定。

算符优先分析的核心在于构造一个优先级关系表,用于指导规约过程。

这个表一般由产生式构造得到,每个终结符和非终结符对应一行和一列,表中的每个元素表示两个符号之间的优先级关系。

算符优先分析的步骤如下:1.根据给定的文法,确定每个终结符号和非终结符号的优先级。

2.构造优先关系表,填入每两个符号之间的优先关系。

3.初始化分析栈和输入栈,将栈底符号设为文法开始符号,并将输入串入栈。

4.重复以下步骤,直到分析完成:a.查找栈顶和当前输入符号之间的优先关系。

b.如果栈顶符号的优先级较低或相等,则进行规约操作,将栈顶的符号替换为相应的非终结符号。

c.如果栈顶符号的优先级较高,则进行移进操作,将当前输入符号移入栈中。

d.如果找不到优先关系,则出现错误,分析失败。

算符优先分析的优点是简单明了,且规约过程中不需要回溯,效率较高。

然而,由于它只适用于算符优先文法,而不是所有的上下文无关文法,因此适用范围有限。

在实际编程中,我们可以通过编写算符优先分析程序来对给定的文法进行分析。

程序可以根据文法自动生成优先关系表,然后根据输入串和优先关系表进行分析。

下面是一个简单的算符优先分析程序设计:```python#定义终结符和非终结符的优先级priority = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 0, ')': 0}#构造优先关系表def build_table(:table = {}for symbol1 in priority.keys(:row = {}for symbol2 in priority.keys(:if symbol1 == '(' and symbol2 == ')':row[symbol2] = 'r'elif symbol1 == ')' and symbol2 == '(':row[symbol2] = 'e'elif priority[symbol1] > priority[symbol2]:row[symbol2] = '>'elif priority[symbol1] < priority[symbol2]:row[symbol2] = '<'else:row[symbol2] = 'e'table[symbol1] = rowreturn table#算符优先分析程序def operator_precedence_parsing(table, input_str): input_stack = list(input_str)input_stack.append('#')analysis_stack = ['#']while len(analysis_stack) > 0:top = analysis_stack[-1]if top in priority.keys( and input_stack[0] in priority.keys(:relation = table[top][input_stack[0]]if relation == '>':analysis_stack.popprint('Reduce by', top)elif relation == '<':analysis_stack.append(input_stack.pop(0)) print('Shift', analysis_stack[-1])elif relation == 'e':analysis_stack.popinput_stack.pop(0)print('Error')returnelse:print('Error')returnelse:print('Error')return#测试代码table = build_tableinput_str = input('Please enter a valid expression: ')operator_precedence_parsing(table, input_str)```以上是一个简单的算符优先分析程序设计,实现了根据输入串和优先关系表进行分析的过程。

算符优先词法分析器_编译原理完整课程设计

算符优先词法分析器_编译原理完整课程设计

目录一、设计目的 (1)二、设计原理 (1)三、设计思想 (2)四、设计要求 (3)五、设计流程图及程序 (4)六、运行结果及分析 (14)七、设计总结 (16)八、参考文献 (16)算符优先词法分析器一、设计目的算符优先算法是自底而上分析方法的一种。

所谓自底向上分析,也称移进—规约分析,粗略地说他的实现思想是对输入符号串自左向右进行扫描,并将输入符逐个移入一个后进先出的栈中,边移进边分析,一旦栈顶符号串形成某个句型的句柄或可规约串是,就用该产生式的左部非终结符代替相应右部的文法符号串,这称为一部规约。

重复这一过程直到规约到栈中只剩文法的开始符号是则为分析成功,也就确认输入串是文法的句子。

而算符优先分析的基本思想是只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系。

本课程设计的主要目的:1、通过本次课程设计,全面系统的了解编译原理程序构造的一般原理和基本实现方法,尤其是对自底向上的优先分析方法的认识和理解;2、提高对编译程序工作基本过程及其各阶段基本任务的分析技能;3、加强对编译程序的生成过程、构造工具及编译程序总流程框图的理解,巩固所学的课本知识。

二、设计原理算符优先分析法是一种有效的自底向上的分析方法。

自底向上分析方法面临的主要问题是如何确定可归约串,而算符优先分析法根据两个终结符号之间的优先关系比较,成功的解决了可归约串的问题。

算符优先分析法是采用最左素短语进行归约的,严格来讲不属于规范规约的范畴。

因此,在设计以前我们必须要知道什么是素短语和最左素短语。

所谓素短语就是指句型中具有这样性质的短语:至少含有一个终结符,且除了自身之外,不再含有任何更小的素短语的短语。

最左素短语,是指在句型的所有素短语中,处于句型最左边的素短语。

了解了素短语和最左素短语,那么如何构造这种算法呢?首先,根据非终结符的FIRSTVT集和LASTVT集找出它们之间的优先关系,构造算符优先矩阵。

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

算符优先实验报告

算符优先实验报告

算符优先实验报告算符优先实验报告引言算符优先是一种用于描述和分析算术表达式的语法分析方法。

在本次实验中,我们将通过编写一个算符优先分析器来深入理解算符优先算法的原理和应用。

实验目的1. 了解算符优先算法的基本原理和概念;2. 掌握算符优先算法的具体实现方法;3. 实现一个简单的算符优先分析器,用于分析和判断输入的算术表达式是否符合文法规则。

实验过程1. 算符优先的基本原理算符优先算法是一种自底向上的语法分析方法,用于判断算术表达式中运算符的优先级关系。

它通过构建一个算符优先关系表来实现对表达式的分析和判断。

2. 算符优先的概念和定义算符优先表是一个二维表格,行和列分别表示算术表达式中的运算符。

表格中的每个元素表示两个运算符之间的优先关系,可以是大于、小于或等于。

根据这个表格,我们可以判断两个相邻的运算符之间的优先级关系。

3. 算符优先分析器的实现为了实现一个算符优先分析器,我们首先需要构建算符优先表。

算符优先表的构建需要根据文法规则和运算符的优先级来确定。

在本次实验中,我们假设算术表达式中只包含加法和乘法运算符,并且加法运算符的优先级高于乘法运算符。

4. 算符优先分析的过程算符优先分析的过程可以分为两个步骤:扫描和规约。

在扫描过程中,我们从左到右扫描输入的算术表达式,并将扫描到的运算符和操作数依次入栈。

在规约过程中,我们根据算符优先表中的优先关系,将栈中的符号进行规约,直到最终得到一个唯一的非终结符号。

实验结果与分析通过实验,我们成功实现了一个简单的算符优先分析器,并对不同的算术表达式进行了分析和判断。

实验结果表明,算符优先分析器能够准确地判断算术表达式的语法正确性,并且能够正确地处理运算符的优先级关系。

结论算符优先算法是一种常用的语法分析方法,能够有效地判断算术表达式的语法正确性。

通过本次实验,我们深入理解了算符优先算法的原理和应用,并成功实现了一个简单的算符优先分析器。

这对我们进一步学习和应用语法分析方法具有重要的意义。

算符优先算法的实现概要

算符优先算法的实现概要

算符优先算法的实现以下是程序的实现过程:DOC.h:#include<stdio.h>typedef struct{int base;int top;char array[100];}stack;//定义的后进先出栈,栈中最多存放100个字符stack s;typedef struct{char pLeft;//规则左部符号char pRight[20];//规则右部最多包括20个字符int pRightSize;//记录规则右部的字符数}Rule;//此结构体用来存放输入的规则左部存放一个字符,右部最多20个字符Rule rule[12];//定义文法最多可以包含12个产生式int rule_num=0;/*规则数*/char Vn[20];/*非终结符*/char Vt[20];/*终结符*/int VnNum=0;/*非终结符个数*/int VtNum=0;/*终结符个数*/bool F[100][100];//行是非终结符bool L[100][100];//列是终结符char table[50][50];//算符优先表char DisTable[200][200];char Input[100];//输入的字符串int InputSize=0;//输入字符串大小;char mstack[100];//符号栈DOC.cpp#include<stdio.h>#include<iostream.h>#include<string.h>#include"DOC.h"/*栈的操作*/void create(stack &s)//创建栈{s.base=0;s.top=0;}void push(stack &s,char &p,char &a)//压两个字符入栈{s.array[s.top++] = p;s.array[s.top++] = a;}void push(stack &s,char &p)//压一个字符入栈{s.array[s.top++] = p;}void pop(stack &s,char &q)//弹出一个字符{q = s.array[--s.top];}void pop(stack &s,char &q,char &a)//弹出两个字符{a= s.array[--s.top];q = s.array[--s.top];}bool Empty(stack &s)//判断栈是否为空{if(s.top<=s.base)return true;else return false;}void InitializeVn()//键盘输入非终结符初始化Vn {printf("请输入非终结符:");int i=0;char ch;char temp[20];while((ch=getchar())!='\n'){temp[i]=ch;++i;}for(int j=0;j<i;j++){Vn[j]=temp[j];}VnNum=i;}void InitializeVt()//键盘输入终结符初始化Vt{printf("请输入终结符:");int i=0;char ch;char temp[20];while((ch=getchar())!='\n'){temp[i]=ch;++i;}for(int j=0;j<i;j++){Vt[j]=temp[j];}VtNum=i;}void GetRule()//从输入的规则并给结构体赋值{printf("请输入文法个数:");cin>>rule_num;for(int i=0;i<rule_num;i++){printf("请输入文法%d ",i);int count=0;char ch;char temp[20];//允许输入”->”可以过滤while((ch=getchar())!='\n'){if(ch=='-')//过滤”-”{ch=getchar();if(ch=='>')//过滤”>”{ch=getchar();}}temp[count]=ch;count++;}rule[i].pLeft=temp[0];//左部存放规则左部rule[i].pRightSize=count-1;//右部存放规则右部//对于涉及到字符判空问题(形如T->F)右部只有一个字符,在每个规则右部尾部加入$符,读到规则右部的第二个字符为$是就可以跳过for(int j=1;j<count;j++){rule[i].pRight[j-1]=temp[j];}if(count==2){rule[i].pRight[j]='$';//将$添加到对应的规则右部尾部}}}int FindVnIndex(char a)//根据指定的字符a找到它在Vn中的索引如果为-1不存在{int index=0;bool flag=false;for(int j=0;j<VnNum;j++){if(Vn[j]==a)//存在此字符{flag=true;}}if(flag){for(int i=0;i<VnNum;i++){if(Vn[i]==a){index=i;}}}else{index=-1;}return index;}int FindVtIndex(char a)// 根据指定的字符a找到它在Vt中的索引如果为-1不在{int index=0;bool flag=false;for(int j=0;j<VtNum;j++){if(Vt[j]==a) //存在此字符{flag=true;}}if(flag){for(int i=0;i<VtNum;i++){if(Vt[i]==a){index=i;}}}else{index=-1;}return index;}void InsertF(stack &s,char &p,char &a)//初始化时F[][]数组为false,如果指定的非终结符和终结符在F[][]中为true,压栈(算法课件){int p1=FindVnIndex(p);int a1=FindVtIndex(a);if(!F[p1][a1]){F[p1][a1] = true;push(s,p,a);}}void InsertL(stack &s,char &q,char &a)// 初始化时L[][]数组为false,如果指定的非终结符和终结符在L[][]中为true,压栈(算法课件){int q1=FindVnIndex(q);int a1=FindVtIndex(a);if(!L[q1][a1]){L[q1][a1] = true;push(s,q,a);}}void FirstVT(stack &s)//(算法书上例6.3){char a0,a1;//ao,a1规则右部第一第二个字符for(int i=0; i<VnNum; i++)//初始化{for(int j=0; j<VtNum; j++){F[i][j] = false;}}for(int a=0; a<rule_num; a++)//遍历规则是否存在A->a…..和A->Ba….产生式{a0=rule[a].pRight[0];a1=rule[a].pRight[1];if(a1=='$'&&FindVnIndex(a0)!= -1)//满足"T->F,F$"形式{continue;//结束此次循环}else if(FindVtIndex(a0)!= -1)//满足(A->a….)形式存在此非终结符{InsertF(s,rule[a].pLeft, a0);continue;//结束这次循环}else if(FindVnIndex(a0) != -1 && FindVtIndex(a1) != -1)//满足(A->Ba.....)形式{InsertF(s,rule[a].pLeft,a1);}}while(!Empty(s))//存在A->B….产生式{char q, a;pop(s,q, a);for(i=0; i<rule_num; i++){if(rule[i].pRight[0] == q){InsertF(s,rule[i].pLeft, a);}}}}void LastVT(stack &s)// (算法书上例6.3,同FirstVT){char a0,a1;for(int i=0; i<VnNum; i++){for(int j=0; j<VtNum; j++){L[i][j] = false;}}for(int a=0; a<rule_num; a++){a0=rule[a].pRight[rule[a].pRightSize-1];a1=rule[a].pRight[rule[a].pRightSize-2];if(a0=='$'&&FindVnIndex(a1)!=-1)//满足(A$)形式{continue;}else if(FindVtIndex(a0) != -1){InsertL(s,rule[a].pLeft, a0);continue;//结束这次循环}else if(FindVnIndex(a0) != -1 &&FindVtIndex(a1) != -1)//满足(....aC形式){InsertL(s,rule[a].pLeft, a1);}}while(!Empty(s)){char q, a;pop(s,q,a);for(i=0; i<rule_num; i++){if(rule[i].pRight[rule[i].pRightSize-1] == q){InsertL(s,rule[i].pLeft, a);}}}}void DisplayFirstVT()//显示FirstVT表{char p, a;int row = VnNum;int col = VtNum;cout<<"FirstVT"<<"\n";for(int i=0; i<row; i++){p = Vn[i];cout<<p<<"{";for(int j=0;j<col;j++){if(F[i][j]){a=Vt[j];cout<<" "<<a<<" ";}}cout<<"}"<<'\n';}}void DisplayLastVT()//显示LastVT表{char p, a;int row = VnNum;int col = VtNum;cout<<"LastVT"<<"\n";for(int i=0; i<row; i++){p = Vn[i];cout<<p<<"{";for(int j=0;j<col;j++){if(L[i][j]){a=Vt[j];cout<<" "<<a<<" ";}}cout<<"}"<<"\n";}}void OPT()//构造算付优先表{for(int a=0;a<rule_num;a++){for(int b=0;b<rule[a].pRightSize-1;b++)//根据定义{char xa = rule[a].pRight[b];char xa1 =rule[a].pRight[b+1];int pxa = FindVtIndex(xa);int pxa1 =FindVtIndex(xa1);if(pxa != -1 && pxa1 != -1)//xa,xa1为终结符(相邻为终结符则"="){if(table[pxa][pxa1] == 0){table[pxa][pxa1] = '=';}else{printf("不是算符优先文法");return;}continue;}if(b+2 < rule[a].pRightSize)//xa,xa2为终结符(形如aBb则"="){char xa2 = rule[a].pRight[b+2];int pxa2 = FindVtIndex(xa2);if(pxa != -1 && pxa1 == -1 && pxa2 != -1){if(table[pxa][pxa2] == 0){table[pxa][pxa2] = '=';}else{printf("不是算符优先文法");return;}}}if(pxa != -1 && pxa1 == -1)//xa1为终结符,xa为非终结符{pxa1 = FindVnIndex(xa1);for(int k=0; k<VtNum; k++)if(F[pxa1][k])//xa1<FIRSTVT(xa){if(table[pxa][k] == 0)table[pxa][k] = '<';else{printf("不是算符优先文法");return;}}continue;}if(pxa== -1 && pxa1 != -1)//xa为终结符,xa1为非终结符{pxa = FindVnIndex(xa);for(int k=0; k<VtNum; k++){if(L[pxa][k]){if(table[k][pxa1] == 0)table[k][pxa1] = '>';else{printf("不是算符优先文法");return;}}}}}}}void Analyse()//分析规约过程(下推栈实现)算法课件-但课件有错{printf("以下是分析过程:");printf("\n");char sym;//当前读入的字符int k=1;mstack[k]='#';int position=0;//当前字符位置int j=0;char Q;do{sym=Input[position];if(FindVtIndex(mstack[k])!=-1)//存在终结符{j=k;}else{j=k-1;}while(table[FindVtIndex(mstack[j])][FindVtIndex(sym)]=='>'){do{Q=mstack[j];if(FindVtIndex(mstack[j-1])!=-1){j=j-1;}else{j=j-2;}}while(table[FindVtIndex(mstack[j])][FindVtIndex(Q)]=='='||table[FindVtIn dex(mstack[j])][FindVtIndex(Q)]=='>');for(int b=j+1;b<=k;b++)//把S[j+1]…S[k]归约为某个N{cout<<mstack[b]<<" ";mstack[b]='\0';}cout<<"规约为N"<<"\n";k=j+1;mstack[k]='N';}if(table[FindVtIndex(mstack[j])][FindVtIndex(sym)]=='<'||table[FindVtIndex(mst ack[j])][FindVtIndex(sym)]=='='){k=k+1;mstack[k]=sym;position++;cout<<sym<<"移进"<<"\n";if(table[FindVtIndex(mstack[j])][FindVtIndex('#')]=='='){cout<<"输出正常!"<<"\n";}}else{cout<<"出错,规约失败!";break;}}while(sym!='#');if(mstack[2]=='N'){cout<<"规约成功!";}}void Initialize(){InitializeVn();InitializeVt();GetRule();}void main(){Initialize();stack s;create(s);FirstVT(s);DisplayFirstVT();stack temp;create(temp);LastVT(temp);DisplayLastVT();OPT();memset(mstack,'\0',100);//将栈置为’\0’printf("请输入要分析的子句:");int a=0;char ch;while((ch=getchar())!='\n')//放入字符串数组中{Input[a]=ch;a++;}InputSize=a;//输入的字符串个数Analyse();cout<<"\n";//打印算付优先表for(int i=0;i<VnNum;i++){for(int j=0;j<VtNum;j++){cout<<"["<<Vn[i]<<","<<Vt[j]<<"]"<<"="<<table[i][j]<<" ";}cout<<"\n";}}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、实验目的与任务
算术表达式和赋值语句的文法可以是(你可以根据需要适当改变):
S→i=E
E→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;
else
return FALSE;
}
h)
{
k = TRUE; h == 'E')
{
n ++;
}
return n;
}
词结束(遇到“#”号),无法移进,需要规约,返回:1
词没有结束,需判断是否可以移进
栈单词<=单词:移进后返回:2
栈单词>单词:不能移进,需要规约,返回:1
单词没有优先关系:出错,返回:-1
int 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("表达式中含有非法字符。

");
}
break;
}
TokenNumber ++;
}
}
//从表达式缓冲区中取到下面第一个非空字符
//成功:返回字符;不成功:返回'\0'
char GetFirstChar()
{
while(GetChar() != '\0')
{
if(ch>32) return ch;
}
return '\0';
}
//从表达式缓冲区取一个字符,返回该字符的同时将它存于全局变量ch中//成功:返回字符;不成功:返回'\0'
char GetChar()
{
if((ch = Buffer[ipBuffer]) != '\0')
ipBuffer ++;
return ch;
}
//生成错误信息
//错误信息存于全局变量ErrMsg中
//返回:TRUE
bool MakeErr(char * ErrMassage)
{
ErrMsg = ErrMassage;
return TRUE;
}。

相关文档
最新文档