实验三 自下而上语法分析及语义分析
编译原理语法分析——自下而上分析
![编译原理语法分析——自下而上分析](https://img.taocdn.com/s3/m/15a8ab3f7fd5360cba1adb52.png)
E
1)LR分析法 2)算符优先分析法
E+ T
T
F
T * F i3
F
i2
i1
归约的含义: G(E): E i| E+E | E-E | E*E |
例:设文法G(S): (1) S aAcBe (2) A b (3) A Ab (4) B d
试对abbcde进行“移进-归约”分析。
e
BBd
abbbbcccdddeee
bcc
Ab
Saa
步骤: 1 2 3 4 5 6 7 8 9 10 动作: 进a 进b 归(2) 进b 归(3) 进c 进d 归(4) 进e 归(1)
规范归约是关于是一个最右推导的逆过程
最左归约
规范推导
由规范推导推出的句型称为规范句型。
把上例倒过来写,则得到:
S aAcBe aAcde aAbcde
abbcde
显然这是一个最右推导。
规范归约是关于是一个最右推导的逆过程
最左归约
规范推导
由规范推导推出的句型称为规范句型。
S
句柄“最左”特征的含 义
aAcde (4) B d
aAcBe (1) S aAcBe
S
S
a A c Be
A
bd
b S
S
a A c Be
Ab
d
S
a A c Bea A c Be d
定义:假定是文法G的一个句子,我们称序列 n, n-1, ,0
是的一个规范归约,如果此序列满足:
自下而上语法分析
![自下而上语法分析](https://img.taocdn.com/s3/m/67ab18966bec0975f465e2e8.png)
自下而上语法分析对于产生语言来讲,自上而下分析的方法是自然的。
对于分析语言来讲,自下而上分析的方法更自然,因为语法分析处理的对象一开始都是终结符组成的输入序列,而不是文法的开始符号。
同时,自下而上分析中最一般的方法,LR方法的能力比自上而下分析的LL方法要强,从而使得LR分析成为最为实用的语法分析方法。
3.5.1 自下而上分析的基本方法思路:从句子ω开始,从左到右扫描ω,反复用产生式的左部替换产生式的右部、谋求对ω的匹配,最终得到文法的开始符号,或者发现一个错误。
3.5.1.1 规范归约与“剪句柄”定义3.13设αβδ是文法G的一个句型,若存在S =*>αAδ,A =+>β,则称β是句型αβδ相对于A的短语,特别的,若有A→β,则称β是句型αβδ相对于产生式A→β的直接短语。
一个句型的最左直接短语被称为句柄。
##①直观上,句型是一个完整结构,短语是句型中的某部分。
S是一个句型,而不是一个短语。
②短语形成的两个要素:1.从S可以推导出A,即S=*>αAδ;2.从A至少一次推导出β,即A=+>β。
特征:①短语:以非终结符为根的子树中所有从左到右排列的叶子;②直接短语:只有父子关系的树中所有从左到右排列的叶子(树高为2);③句柄:最左边父子关系树中所有从左到右排列的叶子(句柄是唯一的)。
问题:id1+id2是句型id1+id2*id3的一个短语吗?答案:不是。
因为:①没有一个E的子树,它的全部叶子是id1+id2;或者②找不到某个E,使得E=>* E*id3,E=>+ id1+id2定义3.14 若α是文法G的句子且满足下述条件,则称序列αn,αn-1,...,α0是α的一个最左归约。
1. αn=α2. α0=S(S是G 的开始符号)3. 对任何i(0<i<=n),αi-1是从αi把句柄替换为相应产生式左部非终结符得到的。
##注意:最左归约的逆过程是一个最右推导,分别称最右推导和最左归约为规范推导和规范归约。
语法分析实验报告
![语法分析实验报告](https://img.taocdn.com/s3/m/f2e64c0e2f3f5727a5e9856a561252d381eb2043.png)
语法分析实验报告语法分析实验报告引言语法分析是自然语言处理中的一项重要任务,它旨在根据给定的语法规则和输入句子,确定句子的结构和语法成分,并进行语义解析。
本实验旨在探索语法分析的基本原理和方法,并通过实际操作来加深对其理解。
实验目标本实验的主要目标是实现一个简单的自底向上的语法分析器,即基于短语结构文法的分析器。
具体而言,我们将使用Python编程语言来实现一个基于CYK 算法的语法分析器,并对其进行评估和分析。
实验过程1. 语法规则的定义在开始实验之前,我们首先需要定义一个适当的语法规则集。
为了简化实验过程,我们选择了一个简单的文法,用于分析包含名词短语和动词短语的句子。
例如,我们定义了以下语法规则:S -> NP VPNP -> Det NVP -> V NP2. 实现CYK算法CYK算法是一种自底向上的语法分析算法,它基于动态规划的思想。
我们将使用Python编程语言来实现CYK算法,并根据定义的语法规则进行分析。
具体而言,我们将根据输入的句子和语法规则,构建一个二维的表格,用于存储句子中各个子串的语法成分。
通过填充表格并进行推导,我们可以确定句子的结构和语法成分。
3. 实验结果与分析我们使用几个示例句子来测试我们实现的语法分析器,并对其结果进行分析。
例如,对于句子"the cat eats fish",我们的语法分析器可以正确地识别出该句子的结构,并给出相应的语法成分。
具体而言,我们的分析器可以识别出句子的主语是"the cat",谓语是"eats",宾语是"fish"。
通过对多个句子的测试,我们可以发现我们实现的语法分析器在大多数情况下都能正确地分析句子的结构和语法成分。
然而,在一些复杂的句子中,我们的分析器可能会出现一些错误。
这可能是由于语法规则的不完备性或者算法的限制所致。
结论与展望通过本实验,我们深入了解了语法分析的基本原理和方法,并实现了一个简单的自底向上的语法分析器。
实验三 自下而上语法分析及语义分析
![实验三 自下而上语法分析及语义分析](https://img.taocdn.com/s3/m/49aeec65a45177232f60a297.png)
实验三自下而上语法分析及语义分析一、实验目的:通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:4学时。
三、实验内容根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。
对于错误的表达式,给出出错位置。
四、实验方法采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。
接下来给出LR分析表。
然后程序的具体实现:●LR分析表可用二维数组(或其他)实现。
●添加一个val栈作为语义分析实现的工具。
●编写总控程序,实现语法分析和语义分析的过程。
注:对于整数的识别可以借助实验1。
五、文法定义简单的表达式文法如下:E->E+T|E-T|TT->T*F|T/F|FF->(E)|i上式中,i 为整数。
六、处理程序例例1: 正确源程序例:23+(45+4)* 40分析结果应为:正确的表达式。
其值为:1983例2: 错误源程序例:5+(56+)-24分析结果应为:错误的表达式:出错位置为)附录:源程序#include <stdio.h>#include"string.h"#include <iostream>using namespace std;#define R 30#define C 20typedef struct elem{char e[4];}Elem; //ACTION表与GoTo表中的元素类型Elem LR[R][C]; //存放ACTION表与GoTo表中的内容typedef struct out{int order; //序号int state[10]; //状态栈char sign[30]; //符号栈char grasen[20]; //产生式char input[30]; //输入串char explen[50]; //解释说明}OutNode; //输出结果中每一行的类型OutNode out[20]; //存放输出结果char Sentence[20]; //存放文法的一个句子char GramSent[10][20]; //存放文法的一组产生式int row,colno; //row为状态个数数,colno为ACTION表与GoTo表列总数int stateTop=0,signTop=0; //状态栈与符号栈的栈顶位置(值与栈中元素的个数相等)void input_GramSent(){int i,num;printf("请输入文法中产生式的个数\n");scanf("%d",&num);for(i=0;i<num;i++){printf("请输入文法的第%d个产生式\n",i);scanf("%s",GramSent+i-1);}printf("请输入文法的一个句子\n");scanf("%s",Sentence);printf("**********************************************************\n");printf("* 文法的产生式如下: *\n");printf("**********************************************************\n");for(i=0;i<num;i++)printf("%s\n",GramSent+i);printf("**********************************************************\n");printf("* 文法的句子如下: *\n");printf("**********************************************************\n");printf("%s\n",Sentence);}void input_LR(int row,int colno) //row为行总数,colno为列总数{int i,j;char mid[4];printf("**********************************************************\n");printf("* 提示:每输入一个元素后就回车 *\n");printf("**********************************************************\n");printf("请输入LR分析表的终结符(包括#)与非终结符\n");for(j=0;j<colno;j++)scanf("%s",LR[0][j].e);for(i=0;i<row;i++){printf("请输入%d号状态所对应的各列的元素,空白的地方用s代替\n",i);for(j=0;j<colno;j++){scanf("%s",mid);if(strcmp(mid,"s")==0||strcmp(mid,"S")==0)strcpy(LR[i+1][j].e," ");elsestrcpy(LR[i+1][j].e,mid);}}}void output_LR(int row,int colno){int i,j;printf("**********************************************************\n"); printf("* LR分析表如下: *\n");printf("**********************************************************\n"); printf("\n");printf(" ");for(j=0;j<colno;j++)printf("%s ",LR[0][j].e);printf("\n");for(i=1;i<=row;i++){printf("%d ",i-1);for(j=0;j<colno;j++)printf("%s ",LR[i][j].e);printf("\n");}printf("\n");}int SignNum(char ch)//给定一个终结符或非终结符,返回其在ACTION表与GoTo表中的列位置int i;char c[2]="0";c[0]=ch;for(i=0;i<colno;i++)if(strcmp(c,LR[0][i].e)==0)return i;return -1;}int CharChangeNum(char* ch)//给定一数字字符串,返回其所对应的数字{int result=0;while(*ch!='\0'){result=result*10+(*ch-'0');ch++;}return result;}int OutResult(int s,int c,int i)//输出结果的第i+1行处理函数,(s 为状态,c为列){char mid[4],gra[20];int s_num,r_num;int n,len,j;strcpy(mid,LR[s+1][c].e);if(strcmp(mid," ")==0){ printf("不能规约\n"); return -2; }if(strcmp(mid,"acc")==0||strcmp(mid,"ACC")==0){ printf("规约成功\n"); return -1; }out[i+1].order=i+2;if(mid[0]=='s'||mid[0]=='S'){s_num=CharChangeNum(mid+1);//s_num为S后的数字for(j=0;j<stateTop;j++)out[i+1].state[j]=out[i].state[j];out[i+1].state[stateTop]=s_num;out[i+1].state[++stateTop]=-1; //完成第i+1行的状态栈赋值strcpy(out[i+1].sign,out[i].sign);out[i+1].sign[signTop]=out[i].input[0];out[i+1].sign[++signTop]='\0'; //完成第i+1行的符号栈的赋值strcpy(out[i+1].grasen," "); //完成第i+1行的产生式的赋值strcpy(out[i+1].input,out[i].input+1); //完成第i+1行的输入符号串的赋值}else if(mid[0]=='r'||mid[0]=='R'){r_num=CharChangeNum(mid+1);//r_num为r后的数字strcpy(gra,*(GramSent+r_num-1));len=strlen(gra);for(j=0;j<len;j++)if(gra[j]=='-' && gra[j+1]=='>')break;n=strlen(gra+j+2);stateTop-=n; signTop-=n;for(j=0;j<stateTop;j++)out[i+1].state[j]=out[i].state[j];j=SignNum(gra[0]);out[i+1].state[stateTop]=CharChangeNum(LR[out[i+1].state[stateTop-1]+1][ j].e);out[i+1].state[++stateTop]=-1; //完成第i+1行的状态栈赋值strcpy(out[i+1].sign,out[i].sign);out[i+1].sign[signTop]=gra[0];out[i+1].sign[++signTop]='\0'; //完成第i+1行的符号栈的赋值strcpy(out[i+1].grasen,gra); //完成第i+1行的产生式的赋值strcpy(out[i+1].input,out[i].input); //完成第i+1行的输入符号串的赋值}return 1;}void OutputResult(int r){int i,j;printf("**********************************************************\n"); printf("* 句子:%s 用LR分析表规约过程如下:*\n",Sentence);printf("**********************************************************\n"); for(i=0;i<=r;i++){j=0;printf("%2d ",out[i].order);while(out[i].state[j]!=-1)printf("%d",out[i].state[j++]);printf(" %s %s %s\n",out[i].sign,out[i].grasen,out[i].input);}}int OutControl()//输出结果的总控函数{int s_num,i=0;out[0].order=1; //序号赋值out[0].state[0]=0; stateTop=1; out[0].state[stateTop]=-1; //状态栈赋值,置栈顶位strcpy(out[0].sign,"#"); signTop=1; //符号栈赋值,置栈顶位strcpy(out[0].grasen," "); //产生式为空strcpy(out[0].input,Sentence); //以下两行为输入串赋值strcat(out[0].input,"#");strcpy(out[0].explen,"0和#进栈"); //解释说明//初使化输出结果的第一行while(1){s_num=SignNum(out[i].input[0]);//if(s_num!=-1)if(OutResult(out[i].state[stateTop-1],s_num,i)!=1)break;i++;}return i;}main(){int r;printf("**********************************************************\n"); printf("* 函数的输入: 文法的产生式,文法句型的一个句子,LR分析表 *\n");printf("* 函数的输出: LR分析器的工作过程与说明 *\n");printf("**********************************************************\n"); printf("请输入LR分析表中终结符与非终结符的总个数\n");scanf("%d",&colno);printf("请输入LR分析表中状态的总个数\n");scanf("%d",&row);input_LR(row,colno);output_LR(row,colno);input_GramSent();r=OutControl(); //r为输出结果的行数OutputResult(r);}七、实验小结这个程序是从网上下载下来的,根据这个实验要求做了些更改,但是总是出现溢出错误,只能运行到LR分析表的部分(如截图),没有找到解决问题的办法。
语法分析(自上而下分析)实验报告
![语法分析(自上而下分析)实验报告](https://img.taocdn.com/s3/m/57115350fc4ffe473368abcf.png)
实习二语法分析-自上而下分析一、实验目的使用预测分析方法对输入的表达式进行分析,掌握其具体的使用并且学会去分析一个文法。
二、实验内容1.设计表达式的语法分析器算法(使用预测分析)2.编写一段代码并上机调试查看其运行结果三、实验要求使用LL(1)分析算法设计表达式的语法分析器LL(1)文法是一个自上而下的语法分析方法,它是从文法的开始符号出发,生成句子的最左推导,从左到右扫描源程序,每次向前查看一个字符,确定当前应该选择的产生式。
实现LL(1)分析的另一种有效方法是使用一张分析表和一个栈进行联合控制。
预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前a的输入符号行事的。
对于任何(X,a),总控程序每次都执行三种可能的动作之一。
1.若X=a=“#”,则宣布分析成功,停止分析过程2.若X=a≠“#”,则把X从STACK栈顶逐出,让a指向下一个输入符号。
3.若X是一个非终结符,则查看分析表。
四、运行结果(本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析)五、源程序实现/*LL(1)分析法源程序,只能在VC++中运行*/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dos.h>char A[20];char B[20];char v1[20]={'i','+','*','(',')','#'};/*终结符*/char v2[20]={'E','G','T','S','F'};/*非终结符*/int j=0,b=0,top=0,l;/*L为输入串长度*/typedef struct type{char origin;/*大写字符*/char array[5];/*产生式右边字符*/int length;/*字符个数*/}type;type e,t,g,g1,s,s1,f,f1;/*结构体变量*/ type C[10][10];/*预测分析表*/void print()/*输出分析栈*/{int a;/*指针*/for(a=0;a<=top+1;a++)printf("%c",A[a]);printf("\t\t");}/*print*/void print1()/*输出剩余串*/{int j;for(j=0;j<b;j++)/*输出对齐符*/printf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}/*print1*/void main(){int m,n,k=0,flag=0,finish=0;char ch,x;type cha;/*用来接受C[m][n]*//*把文法产生式赋值结构体*/e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';g1.array[0]='^';g1.length=1;s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';s1.array[0]='^';s1.length=1;f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)/*初始化分析表*/for(n=0;n<=5;n++)C[m][n].origin='N';/*全部赋为空*/ /*填充分析表*/C[0][0]=e;C[0][3]=e;C[1][1]=g;C[1][4]=g1;C[1][5]=g1;C[2][0]=t;C[2][3]=t;C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=s1;C[4][0]=f1;C[4][3]=f;printf("请输入要分析的字符串:");do/*读入分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+') &&(ch!='*')&&(ch!='(')&&(ch!=')')&&(ch!='#')){printf("输入串中有非法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#'; A[++top]='E';/*'#','E'进栈*/printf("步骤\t\t分析栈\t\t剩余字符\t\t所用产生式\n");do{x=A[top--];/*x为当前栈顶字符*/ printf("%d",k++);printf("\t\t");for(j=0;j<=5;j++)/*判断是否为终结符*/ if(x==v1[j]){flag=1;break;}if(flag==1)/*如果是终结符*/{if(x=='#'){finish=1;/*结束标记*/printf("acc!\n");/*接受*/getchar();getchar();exit(1);}/*if*/if(x==ch){print();print1();printf("%c匹配\n",ch);ch=B[++b];/*下一个输入字符*/flag=0;/*恢复标记*/}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",ch);/*输出出错终结符*/exit(1);}/*else*/}/*if*/else/*非终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j]){m=j;/*行号*/break;}for(j=0;j<=5;j++)if(ch==v1[j]){n=j;/*列号*/break;}cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/{print();print1();printf("%c->",cha.origin);/*输出产生式*/for(j=0;j<cha.length;j++)printf("%c",cha.array[j]);printf("\n");for(j=(cha.length-1);j>=0;j--)/*产生式逆序入栈*/ A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",x);/*输出出错非终结符*/exit(1);}/*else*/}/*else*/}while(finish==0);}/*main*/。
语法分析实验报告
![语法分析实验报告](https://img.taocdn.com/s3/m/c4501c4c6fdb6f1aff00bed5b9f3f90f76c64d91.png)
语法分析实验报告一: 实验内容:编写语法分析程序, 实现对算术表达式的语法分析, 要求所分析的算术表达式由如下的文法产生。
E->E+T|E-T|TT->T*F|T/F|FF->id|(E)|num二: 实验要求:在对表达式进行分析的同时, 输出所采用的产生式。
1.编写LL(1)语法分析程序, 要求:编程实现算法4.2, 为给定的文法自动构造预测分析表编程实现算法4.1, 构造LL(1)预测分析程序,2.编写语法分析程序, 实现自底向上的分析, 要求:构造识别所有活前缀的DFA构造LR分析表编程实现算法4.3, 构造LR分析程序1.三: 实验分析:2.方法二(编写LL(1)语法分析程序)1.步骤:(1)根据题目所给出的文法构造相应的无左递归文法, 并求出该文法各非终结符的FIRST、FOLLOW集合;(2)构造文法的LL(1)分析表;(3)由此构造LL分析程序。
2.实现方法:1.输入缓冲区为一个字符型数组, 读入输入的算术表达式并保存在此, 以’$’结束;2.为构造文法的LL(1)分析表, 构建一个相对应的字符串数组;3.在实际程序中P代表E', Q代表T', e代表ε,i代表id, n代表num;4.处理输入表达式中代表id和num的子串, 分别将它们转化为'i'和'n'进行分析;5.LL(1)预测分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a做哪种过程的。
对于任何(X,a),总控程序每次都执行下述三种可能的动作之一:(1)若X = a =‘$’, 则宣布分析成功, 停止分析过程。
(2)若X = a!=‘$’, 则把X从STACK栈顶弹出, 让a指向下一个输入符号。
①如果是终结符合, 则栈不加入新符号②如果是非终结符合, 则把表达式右边入栈(3)若M[A, a]中存放着“出错标志”, 则调用出错诊断程序ERROR。
自下而上语法分析
![自下而上语法分析](https://img.taocdn.com/s3/m/70887f5800f69e3143323968011ca300a6c3f6e8.png)
自下而上语法分析1、规约:自下而上的语法分析过程:分为简单优先分析法,算符优先分析法,LR分析法。
2、自下而上的语法分析过程思想:自下而上的语法分析过程是一个最左规约的过程,从输入串开始,朝着文法的开始符号进行规约,直到文法的开始符号为止的过程。
输入串在这里是指词法分析器送来的单词符号组成的二元式的有限序列。
3、自下而上的PDA(下推自动机)工作方式:“移近-规约”方式注:初态时栈内仅有栈顶符“#”,读头指在最左边的单词符号上。
语法分析程序执行的动作:◆移进:读入一个单词并压入栈内,读头后移◆规约:检查栈顶若干符号能否进行规约,若能,就以产生式左部代替该符号串,同时输出产生式编号。
◆识别成功:移近-规约的结局是栈内只剩下栈底符号和文法的开始符号,读头也指向语句的结束符。
◆识别失败。
4、判读一语句是否是该文法的合法语句(可以用语法树)5、优先分析器:简单优先分析法(理论简单,实际比较麻烦)算符优先分析法6、LR分析器7、相邻文法符号之间的优先关系◆在句型中,句柄内各相邻符号之间具有相同的优先级。
◆由于句柄要先规约,所以规定句柄两端符号的优先级要比位于句柄之外的相邻符号的优先级高。
(#的优先级是最低的。
)9、简单优先文法:定义:一个文法G,如果它不含ε的产生式,也不含任何右部相同的不同产生式,并且它的任何符号(X,Y)-X,Y是非终结符或终结符—或者没有关系,或者存在优先级相同或低于、高于等关系之一,则这是一个简单优先文法。
10、简短优先分析的思想1)简单优先矩阵:根据优先关系的定义:将简单优先文法中各文法符号之间的这种关系用一个矩阵表示,称作简单优先矩阵。
2)PDA读入一个单词后,比较栈顶符号和该单词的优先级,若栈顶符号优先级低于该单词,继续读入;若栈顶符号优先级高于或者等于读入符号,则找句柄进行规约,找不到句柄继续读入11、简单优先法的优缺点:1、优点:算法比较好理解。
2、缺点:适用范围小,分析表尺寸太大。
语法之自下而上分析
![语法之自下而上分析](https://img.taocdn.com/s3/m/066836a20242a8956bece4a4.png)
5
#aAb
cde#
即输入符号串已经归约为:#aAbcde#,根据上述算法, 下一步Ab和b都可以归约(它们都在符号栈的栈顶且有 产生式AAb和Ab)。假若判b为句柄,则可把b归约 为A,即符号串归约为:#aAAcde#。那么,后面的工 作无论怎样做,都无法归约成功。
例2,设有文法G[E]:
F
+ * ( ) i STACK EFT , ii
EE+T |T TT*F | F
F(E) | i
E 10 01 10 0 01 T 0 01 10 0 10 F 0 0 10 0 10
TE ,, ** E,+ TFE,,((
①数组元素初始化为FALSE(用0表示FF)II;RRSSTTVVTT((ET))=={{+*,,*(,,(i,} i} ② F[U从,b文]=法T中RU找E出(用形1表如示U);b…E或EU+TVFbI的R产TST生VT式*TF,(F并)=使F{对(,应(iE}的) 数F组元i 素
自下而上分析 采用最左归约即规范归约。
5.1 自底向上分析的一般过程
一、一般过程:
一般的自底向上分析法,也称为“ 移进—归约”法,其一 般过程为: (1)设置一个存放符号的栈称为符号栈,用于记录分析的过程和确 定下一步的动作。
(2)把输入符号按扫描顺序逐个移进栈里(符号栈),当栈顶的符号 组成的符号串形成一个句柄时(正好是某条产生式的右部),就进 行归约。即把该符号串用与它对应的产生式左部的非终结符号代 替,仍然置于栈顶。
a的优先级高于b 记为: a .> b a的优先级等于b 记为: a . b a的优先级低于b 记为: a<. b
编译原理实验三-自下而上语法分析报告及语义分析报告.docx
![编译原理实验三-自下而上语法分析报告及语义分析报告.docx](https://img.taocdn.com/s3/m/84b3fde0561252d380eb6ee1.png)
上海电力学院编译原理课程实验报告实验名称:实验三自下而上语法分析及语义分析院系:计算机科学与技术学院专业年级:学生姓名:学号:指导老师:实验日期:实验三自上而下的语法分析一、实验目的:通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:4学时。
三、实验内容根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。
对于错误的表达式,给出出错位置。
四、实验方法采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。
接下来给出LR分析表。
然后程序的具体实现:●LR分析表可用二维数组(或其他)实现。
●添加一个val栈作为语义分析实现的工具。
●编写总控程序,实现语法分析和语义分析的过程。
注:对于整数的识别可以借助实验1。
五、文法定义简单的表达式文法如下:(1)E->E+T(2)E->E-T(3)E->T(4)T->T*F(5)T->T/F(6)T->F(7)F->(E)(8)F->i五、处理程序例和处理结果例示例1:20133191*(20133191+3191)+ 3191#六、源代码【cifa.h】//cifa.h#include<string> using namespace std;//单词结构定义struct WordType{int code;string pro;};//函数声明WordType get_w();void getch();void getBC();bool isLetter();bool isDigit();void retract();int Reserve(string str); string concat(string str); 【Table.action.h】//table_action.hclass Table_action{int row_num,line_num;int lineName[8];string tableData[16][8]; public:Table_action(){row_num=16;line_num=8;lineName[0]=30;lineName[1]=7;lineName[2]=13;lineName[3]=8;lineName[4]=14;lineName[5]=1;lineName[6]=2;lineName[7]=15;lineName[8]=0;for(int m=0;m<row_num;m++) for(int n=0;n<line_num;n++) tableData[m][n]="";tableData[0][0]="S5";tableData[0][5]="S4";tableData[1][1]="S6";tableData[1][2]="S12";tableData[1][7]="acc";tableData[2][1]="R3";tableData[2][2]="R3";tableData[2][3]="S7";tableData[2][6]="R3"; tableData[2][7]="R3"; tableData[3][1]="R6"; tableData[3][2]="R6"; tableData[3][3]="R6"; tableData[3][4]="R6"; tableData[3][6]="R6"; tableData[3][7]="R6"; tableData[4][0]="S5"; tableData[4][5]="S4"; tableData[5][1]="R8"; tableData[5][2]="R8"; tableData[5][3]="R8"; tableData[5][4]="R8"; tableData[5][6]="R8"; tableData[5][7]="R8"; tableData[6][0]="S5"; tableData[6][5]="S4"; tableData[7][0]="S5"; tableData[7][5]="S4"; tableData[8][1]="S6";tableData[8][6]="S11"; tableData[9][1]="R1"; tableData[9][2]="R1"; tableData[9][3]="S7"; tableData[9][4]="S13"; tableData[9][6]="R1"; tableData[9][7]="R1"; tableData[10][1]="R4"; tableData[10][2]="R4"; tableData[10][3]="R4"; tableData[10][4]="R4"; tableData[10][6]="R4"; tableData[10][7]="R4"; tableData[11][1]="R7"; tableData[11][2]="R7"; tableData[11][3]="R7"; tableData[11][4]="R7"; tableData[11][6]="R7"; tableData[11][7]="R7"; tableData[12][0]="S5"; tableData[12][5]="S4";tableData[13][5]="S4";tableData[14][1]="R2";tableData[14][2]="R2";tableData[14][3]="S7";tableData[14][4]="S13";tableData[14][6]="R2";tableData[14][7]="R2";tableData[15][1]="R5";tableData[15][2]="R5";tableData[15][3]="R5";tableData[15][4]="R5";tableData[15][5]="R5";tableData[15][6]="R5";tableData[15][7]="R5";}string getCell(int rowN,int lineN){int row=rowN;int line=getLineNumber(lineN);if(row>=0&&row<row_num&&line>=0&&line<=line_num) return tableData[row][line];elsereturn"";}int getLineNumber(int lineN){for(int i=0;i<line_num;i++)if(lineName[i]==lineN)return i;return -1;}};【Table_go.h】//table_go.hclass Table_go{int row_num,line_num;//行数、列数string lineName[3];int tableData[16][3];public:Table_go(){row_num=16;line_num=3;lineName[0]="E";lineName[1]="T";lineName[2]="F";for(int m=0;m<row_num;m++) for(int n=0;n<line_num;n++)tableData[m][n]=0;tableData[0][0]=1;tableData[0][1]=2;tableData[0][2]=3;tableData[4][0]=8;tableData[4][1]=2;tableData[4][2]=3;tableData[6][1]=9;tableData[6][2]=3;tableData[7][2]=10;tableData[12][1]=14;tableData[12][2]=3;tableData[13][2]=15;}int getCell(int rowN,string lineNa){int row=rowN;int line=getLineNumber(lineNa);if(row>=0&&row<row_num&&line<=line_num) return tableData[row][line];elsereturn -1;}int getLineNumber(string lineNa){for(int i=0;i<line_num;i++)if(lineName[i]==lineNa)return i;return -1;}};【Stack_num.h】class Stack_num{int i; //栈顶标记int *data; //栈结构public:Stack_num() //构造函数{data=new int[100];i=-1;}int push(int m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{i--;return data[i+1];}int getTop() //返回栈顶{return data[i];}~Stack_num() //析构函数{delete []data;}int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【Stack_str.h】class Stack_str{int i; //栈顶标记string *data; //栈结构public:Stack_str() //构造函数{data=new string[50];i=-1;}int push(string m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{data[i]="";i--;return i;}string getTop() //返回栈顶{return data[i];}~Stack_str() //析构函数{delete []data;int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【cifa.cpp】//cifa.cpp#include<iostream>#include<string>#include"cifa.h"using namespace std;//关键字表和对应的编码stringcodestring[10]={"main","int","if","then","else","return","void","cout","endlint codebook[10]={26,21,22,23,24,25,27,28,29};//全局变量char ch;int flag=0;/*//主函数int main(){WordType word;cout<<"请输入源程序序列:";word=get_w();while(word.pro!="#")//#为自己设置的结束标志{cout<<"("<<word.code<<","<<"“"<<word.pro<<"”"<<")"<<endl;word=get_w();};return 0;}*/WordType get_w(){string str="";int code;WordType wordtmp;getch();//读一个字符getBC();//去掉空白符if(isLetter()){ //以字母开头while(isLetter()||isDigit()){str=concat(str);getch();}retract();code=Reserve(str);if(code==-1){wordtmp.code=0;wordtmp.pro=str;}//不是关键字else{wordtmp.code=code;wordtmp.pro=str;}//是关键字}else if(isDigit()){ //以数字开头while(isDigit()){str=concat(str);getch();}retract();wordtmp.code=30;wordtmp.pro=str;}else if(ch=='(') {wordtmp.code=1;wordtmp.pro="(";} else if(ch==')') {wordtmp.code=2;wordtmp.pro=")";} else if(ch=='{') {wordtmp.code=3;wordtmp.pro="{";} else if(ch=='}') {wordtmp.code=4;wordtmp.pro="}";} else if(ch==';') {wordtmp.code=5;wordtmp.pro=";";} else if(ch=='=') {wordtmp.code=6;wordtmp.pro="=";} else if(ch=='+') {wordtmp.code=7;wordtmp.pro="+";} else if(ch=='*') {wordtmp.code=8;wordtmp.pro="*";} else if(ch=='>') {wordtmp.code=9;wordtmp.pro=">";} else if(ch=='<') {wordtmp.code=10;wordtmp.pro="<";} else if(ch==',') {wordtmp.code=11;wordtmp.pro=",";} else if(ch=='\'') {wordtmp.code=12;wordtmp.pro="\'";} else if(ch=='-') {wordtmp.code=13;wordtmp.pro="-";} else if(ch=='/') {wordtmp.code=14;wordtmp.pro="/";} else if(ch=='#') {wordtmp.code=15;wordtmp.pro="#";} else if(ch=='|') {wordtmp.code=16;wordtmp.pro="|";}else {wordtmp.code=100;wordtmp.pro=ch;}return wordtmp;}void getch(){if(flag==0) //没有回退的字符ch=getchar();else //有回退字符,用回退字符,并设置标志flag=0;}void getBC(){while(ch==' '||ch=='\t'||ch=='\n')ch=getchar();}bool isLetter(){if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return true;elsereturn false;}bool isDigit(){if(ch>='0'&&ch<='9')return true;elsereturn false;}string concat(string str){return str+ch;}void retract(){flag=1;}int Reserve(string str){int i;for(i=0;i<=8;i++){if(codestring[i]==str) //是某个关键字,返回对应的编码return codebook[i];}if(i==9) //不是关键字return -1;}【LR.cpp】#include<iostream>#include<string>#include<cstdlib>#include"cifa.h"#include"stack_num.h"#include"stack_str.h"#include"table_action.h"#include"table_go.h"using namespace std;void process(){int stepNum=1;int topStat;Stack_num statusSTK; //状态栈Stack_str symbolSTK; //符号栈Stack_num valueSTK; //值栈WordType word;Table_action actionTAB; //行为表Table_go goTAB; //转向表cout<<"请输入源程序,以#结束:";word=get_w();//总控程序初始化操作symbolSTK.push("#");statusSTK.push(0);valueSTK.push(0);cout<<"步骤\t状态栈\t符号栈\t值栈\t当前词\t动作\t转向"<<endl;//分析while(1){topStat=statusSTK.getTop(); //当前状态栈顶string act=actionTAB.getCell(topStat,word.code);//根据状态栈顶和当前单词查到的动作//输出cout<<stepNum++<<"\t";statusSTK.outStack(); cout<<"\t";symbolSTK.outStack(); cout<<"\t";valueSTK.outStack(); cout<<"\t";cout<<word.pro<<"\t";//行为为“acc”,且当前处理的单词为#,且状态栈里就两个状态//说明正常分析结束if(act=="acc"&&word.pro=="#"&&statusSTK.topNumber()==1){cout<<act<<endl;cout<<"分析成功!"<<endl;cout<<"结果为:"<<valueSTK.getTop()<<endl;return;}//读到act表里标记为错误的单元格else if(act==""){cout<<endl<<"不是文法的句子!"<<endl;cout<<"错误的位置为单词"<<word.pro<<"附近。
实验三 自下而上语法分析及语义分析复习进程
![实验三 自下而上语法分析及语义分析复习进程](https://img.taocdn.com/s3/m/3e3f7892aa00b52acec7ca43.png)
实验三自下而上语法分析及语义分析实验三自下而上语法分析及语义分析一、实验目的:通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:4学时。
三、实验内容根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。
对于错误的表达式,给出出错位置。
四、实验方法采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。
接下来给出LR分析表。
然后程序的具体实现:●LR分析表可用二维数组(或其他)实现。
●添加一个val栈作为语义分析实现的工具。
●编写总控程序,实现语法分析和语义分析的过程。
注:对于整数的识别可以借助实验1。
五、文法定义简单的表达式文法如下:E->E+T|E-T|TT->T*F|T/F|FF->(E)|i上式中, i 为整数。
六、处理程序例例1: 正确源程序例:23+(45+4)* 40分析结果应为:正确的表达式。
其值为:1983例2: 错误源程序例:5+(56+)-24分析结果应为:错误的表达式:出错位置为)附录:源程序#include <stdio.h>#include"string.h"#include <iostream>using namespace std;#define R 30#define C 20typedef struct elem{char e[4];}Elem; //ACTION表与GoTo表中的元素类型Elem LR[R][C]; //存放ACTION表与GoTo表中的内容typedef struct out{int order; //序号int state[10]; //状态栈char sign[30]; //符号栈char grasen[20]; //产生式char input[30]; //输入串char explen[50]; //解释说明}OutNode; //输出结果中每一行的类型OutNode out[20]; //存放输出结果char Sentence[20]; //存放文法的一个句子char GramSent[10][20]; //存放文法的一组产生式int row,colno; //row为状态个数数,colno 为ACTION表与GoTo表列总数int stateTop=0,signTop=0; //状态栈与符号栈的栈顶位置(值与栈中元素的个数相等)void input_GramSent(){int i,num;printf("请输入文法中产生式的个数\n");scanf("%d",&num);for(i=0;i<num;i++){printf("请输入文法的第%d个产生式\n",i);scanf("%s",GramSent+i-1);}printf("请输入文法的一个句子\n");scanf("%s",Sentence);printf("**********************************************************\n"); printf("* 文法的产生式如下: *\n");printf("**********************************************************\n"); for(i=0;i<num;i++)printf("%s\n",GramSent+i);printf("**********************************************************\n"); printf("* 文法的句子如下: *\n");printf("**********************************************************\n"); printf("%s\n",Sentence);}void input_LR(int row,int colno) //row为行总数,colno为列总数{int i,j;char mid[4];printf("**********************************************************\n"); printf("* 提示:每输入一个元素后就回车 *\n");printf("**********************************************************\n");printf("请输入LR分析表的终结符(包括#)与非终结符\n");for(j=0;j<colno;j++)scanf("%s",LR[0][j].e);for(i=0;i<row;i++){printf("请输入%d号状态所对应的各列的元素,空白的地方用s代替\n",i);for(j=0;j<colno;j++){scanf("%s",mid);if(strcmp(mid,"s")==0||strcmp(mid,"S")==0)strcpy(LR[i+1][j].e," ");elsestrcpy(LR[i+1][j].e,mid);}}}void output_LR(int row,int colno){int i,j;printf("**********************************************************\n"); printf("* LR分析表如下: *\n");printf("**********************************************************\n"); printf("\n");printf(" ");for(j=0;j<colno;j++)printf("%s ",LR[0][j].e);printf("\n");for(i=1;i<=row;i++){printf("%d ",i-1);for(j=0;j<colno;j++)printf("%s ",LR[i][j].e);printf("\n");}printf("\n");}int SignNum(char ch)//给定一个终结符或非终结符,返回其在ACTION表与GoTo表中的列位置{int i;char c[2]="0";c[0]=ch;for(i=0;i<colno;i++)if(strcmp(c,LR[0][i].e)==0)return i;return -1;}int CharChangeNum(char* ch)//给定一数字字符串,返回其所对应的数字{int result=0;while(*ch!='\0'){result=result*10+(*ch-'0');ch++;}return result;}int OutResult(int s,int c,int i)//输出结果的第i+1行处理函数,(s 为状态,c为列){char mid[4],gra[20];int s_num,r_num;int n,len,j;strcpy(mid,LR[s+1][c].e);if(strcmp(mid," ")==0){ printf("不能规约\n"); return -2; }if(strcmp(mid,"acc")==0||strcmp(mid,"ACC")==0){ printf("规约成功\n"); return -1; }out[i+1].order=i+2;if(mid[0]=='s'||mid[0]=='S'){s_num=CharChangeNum(mid+1);//s_num为S后的数字for(j=0;j<stateTop;j++)out[i+1].state[j]=out[i].state[j];out[i+1].state[stateTop]=s_num;out[i+1].state[++stateTop]=-1; //完成第i+1行的状态栈赋值strcpy(out[i+1].sign,out[i].sign);out[i+1].sign[signTop]=out[i].input[0];out[i+1].sign[++signTop]='\0'; //完成第i+1行的符号栈的赋值strcpy(out[i+1].grasen," "); //完成第i+1行的产生式的赋值strcpy(out[i+1].input,out[i].input+1); //完成第i+1行的输入符号串的赋值}else if(mid[0]=='r'||mid[0]=='R'){r_num=CharChangeNum(mid+1);//r_num为r后的数字strcpy(gra,*(GramSent+r_num-1));len=strlen(gra);for(j=0;j<len;j++)if(gra[j]=='-' && gra[j+1]=='>')break;n=strlen(gra+j+2);stateTop-=n; signTop-=n;for(j=0;j<stateTop;j++)out[i+1].state[j]=out[i].state[j];j=SignNum(gra[0]);out[i+1].state[stateTop]=CharChangeNum(LR[out[i+1].state[stateTop-1]+1][j].e);out[i+1].state[++stateTop]=-1; //完成第i+1行的状态栈赋值strcpy(out[i+1].sign,out[i].sign);out[i+1].sign[signTop]=gra[0];out[i+1].sign[++signTop]='\0'; //完成第i+1行的符号栈的赋值strcpy(out[i+1].grasen,gra); //完成第i+1行的产生式的赋值strcpy(out[i+1].input,out[i].input); //完成第i+1行的输入符号串的赋值}return 1;}void OutputResult(int r){int i,j;printf("**********************************************************\n"); printf("* 句子:%s 用LR分析表规约过程如下:*\n",Sentence);printf("**********************************************************\n"); for(i=0;i<=r;i++){j=0;printf("%2d ",out[i].order);while(out[i].state[j]!=-1)printf("%d",out[i].state[j++]);printf(" %s %s %s\n",out[i].sign,out[i].grasen,out[i].input); }}int OutControl()//输出结果的总控函数{int s_num,i=0;out[0].order=1; //序号赋值out[0].state[0]=0; stateTop=1;out[0].state[stateTop]=-1; //状态栈赋值,置栈顶位strcpy(out[0].sign,"#"); signTop=1; //符号栈赋值,置栈顶位strcpy(out[0].grasen," "); //产生式为空strcpy(out[0].input,Sentence); //以下两行为输入串赋值strcat(out[0].input,"#");strcpy(out[0].explen,"0和#进栈"); //解释说明//初使化输出结果的第一行while(1){s_num=SignNum(out[i].input[0]);//if(s_num!=-1)if(OutResult(out[i].state[stateTop-1],s_num,i)!=1)break;i++;}return i;}main(){int r;printf("**********************************************************\n"); printf("* 函数的输入: 文法的产生式,文法句型的一个句子,LR分析表 *\n");printf("* 函数的输出: LR分析器的工作过程与说明 *\n"); printf("**********************************************************\n");printf("请输入LR分析表中终结符与非终结符的总个数\n"); scanf("%d",&colno);printf("请输入LR分析表中状态的总个数\n");scanf("%d",&row);input_LR(row,colno);output_LR(row,colno);input_GramSent();r=OutControl(); //r为输出结果的行数OutputResult(r);}七、实验小结这个程序是从网上下载下来的,根据这个实验要求做了些更改,但是总是出现溢出错误,只能运行到LR分析表的部分(如截图),没有找到解决问题的办法。
【精品】自下而上语法分析共38页文档
![【精品】自下而上语法分析共38页文档](https://img.taocdn.com/s3/m/020e8d247c1cfad6185fa7bd.png)
谢谢!
38
13、遵守纪律的风气的培养,只有领 导者本 身在这 方面以 身作则 才能收 到成效 。—— 马卡连 柯 14、劳动者的组织性、纪律性、坚毅 精神以 及同全 世界劳 动者的 团结一 致,是 取得最 后胜利 的保证 。—— 列宁 摘自名言网
15、机会是不守纪律的。——雨果
▪
26、要使整个人生都过得舒适、愉快,这是不可能的,因为人类必须具备一种能应付逆境的态度。—上进的力量,才是成功的保证。——罗曼·罗兰
▪
28、知之者不如好之者,好之者不如乐之者。——孔子
▪
29、勇猛、大胆和坚定的决心能够抵得上武器的精良。——达·芬奇
▪
30、意志是一个强壮的盲人,倚靠在明眼的跛子肩上。——叔本华
【精品】自下而上语法分析
11、战争满足了,或曾经满足过人的 好斗的 本能, 但它同 时还满 足了人 对掠夺 ,破坏 以及残 酷的纪 律和专 制力的 欲望。 ——查·埃利奥 特 12、不应把纪律仅仅看成教育的手段 。纪律 是教育 过程的 结果, 首先是 学生集 体表现 在一切 生活领 域—— 生产、 日常生 活、学 校、文 化等领 域中努 力的结 果。— —马卡 连柯(名 言网)
语法分析实验报告
![语法分析实验报告](https://img.taocdn.com/s3/m/f503daa3900ef12d2af90242a8956bec0975a58e.png)
一、实验目的1. 了解语法分析的基本概念和原理。
2. 掌握语法分析的方法和步骤。
3. 提高对自然语言处理领域中语法分析技术的理解和应用能力。
二、实验内容1. 语法分析的基本概念语法分析是指对自然语言进行结构分析,将句子分解成词、短语和句子成分的过程。
通过语法分析,可以了解句子的结构、语义和语用信息。
2. 语法分析方法语法分析方法主要有两种:句法分析和语义分析。
(1)句法分析:句法分析是指根据语法规则,对句子进行分解和组合的过程。
常见的句法分析方法有:词法分析、短语结构分析、句法分析。
(2)语义分析:语义分析是指对句子进行分析,以揭示句子所表达的意义。
常见的语义分析方法有:词汇语义分析、句法语义分析、语用语义分析。
3. 语法分析步骤(1)词法分析:将句子中的单词进行分类,提取词性、词义和词形变化等特征。
(2)短语结构分析:将词法分析得到的词组进行分类,提取短语结构、短语成分和短语关系等特征。
(3)句法分析:根据短语结构分析的结果,将句子分解成句子成分,分析句子成分之间的关系。
(4)语义分析:根据句法分析的结果,分析句子所表达的意义。
三、实验过程1. 实验环境:Python 3.8,NLTK(自然语言处理工具包)。
2. 实验步骤:(1)导入NLTK库。
(2)加载句子数据。
(3)进行词法分析,提取词性、词义和词形变化等特征。
(4)进行短语结构分析,提取短语结构、短语成分和短语关系等特征。
(5)进行句法分析,分解句子成分,分析句子成分之间的关系。
(6)进行语义分析,揭示句子所表达的意义。
四、实验结果与分析1. 词法分析结果实验句子:“我喜欢吃苹果。
”词性标注:我/代词,喜欢/动词,吃/动词,苹果/名词。
2. 短语结构分析结果实验句子:“我喜欢吃苹果。
”短语结构:主语短语(我),谓语短语(喜欢吃苹果)。
3. 句法分析结果实验句子:“我喜欢吃苹果。
”句子成分:主语(我),谓语(喜欢),宾语(吃苹果)。
4. 语义分析结果实验句子:“我喜欢吃苹果。
实验三自上而下语法分析--预测分析
![实验三自上而下语法分析--预测分析](https://img.taocdn.com/s3/m/c6254d0ebb68a98271fefadb.png)
实验三预测分析法判断算术表达式的正确性学时数:6一、实验目的1、理解语法分析器的构造方法和工作原理;2、理解自上而下语法分析方法;3、熟练掌握预测分析程序的构造方法。
二、实验内容算术表达式的文法是G[E]:E→E+T| TT→T*F| FF→(E)| id用预测分析法按文法G[E]对算术表达式(包括+、*、()的算术表达式)进行语法分析,判断该表达式是否正确。
三、实验步骤1、准备:阅读课本有关章节,将上述算术表达式的文法改造成LL(1)文法;设计出预测分析表;按算法3.1(P56)编写程序。
2、上机调试,发现错误,分析错误,再修改完善。
四、测试要求1、为降低难度,表达式中不含变量(只含单个无符号整数或i);2、如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);3、测试用的表达式建议事先放在文本文件中,一行存放一个表达式,同时以分号结束。
同时将语法分析程序的输出结果写在另一个文本文件中;4、对学有余力的同学,可增加功能:当判断一个表达式正确时,输出计算结果。
5、程序输入/输出示例:如参考C语言的运算符。
输入如下表达式(以分号为结束)和输出结果:(a)1;输出:正确(b)1+2;输出:正确(c)(1+2)/3+4-(5+6/7);输出:正确(d)((1-2)/3+4输出:错误,缺少右括号(e)1+2-3+(*4/5)输出:错误五、实验报告要求1、写出修改后LL(1)文法,所构造的预测分析表。
2、通过对核心代码做注释或通过程序流程图的方式说明预测分析程序的实现思想。
3、写出调试程序出现的问题及解决的方法。
4、给出测试的结果。
六、思考(选作)文法G[E]所构造算术表达式只包含+和*。
请修改文法和程序,使得该语法程序可判断包含减号和除号的算术表达式的正确性。
[实验指导]将文法G[E]改造为LL(1)文法如下:G’[E]:E → TE’E’→ +TE’| εT → FT’T’→ *FT’|εF → (E)| i[补充说明]预测分析法分析程序可以从网上下载,但要求:(1)理解该程序,在实验报告中说明该程序所使用的文法和预测分析表;(2)实验报告要求同上。
编译原理-自下而上的语法分析
![编译原理-自下而上的语法分析](https://img.taocdn.com/s3/m/cf21627030126edb6f1aff00bed5b9f3f90f723a.png)
自上而下的语法分析
特点
从高层次的文法规则开始,通过不断展开和推导,直到生成目标字符串。
优点
易于理解和实现,可以生成详细的错误报告。
自下而上的语法分析
1
自底向上的语法分析方法概述
通过以输入的标记为起点,逐步推导文法规则,直到生成目标字符串。
2
LR语法分析
一种常用的自底向上的语法分析方法,通过构建一个LR分析表进行推导。
3
LALR语法分析
是LR语法分析的一种变体,通过合并相同状态来降低分析表的复杂度。
自下而上的语法分析的优点和局限性
优点
适用于大型文法,能够处理更广泛的语言结构。
局限性
分析过程复杂,容易产生冲突,需要较大的存储空 间。
自下而上的语法分析的实现
词法分分析器的生成
根据文法规则,构建分析表或语法分析器的数据结构。
语法制导翻译的实现
在语法分析过程中,将源代码转换为目标代码。
自下而上的语法分析的应用
1
编译器中的语法分析
语法分析是编译器中的重要组成部分,用于将源代码转换为中间代码或目标代码。
2
解析器生成器
自下而上的语法分析技术被广泛应用于解析器生成器中,用于自动生成语法分析 器。
结论
自下而上的语法分析是编译原理中重要的一环,虽然实现复杂,但却具有广 泛的应用价值。
编译原理-自下而上的语 法分析
编译原理是研究程序在计算机上的自动翻译过程,语法分析是其中的重要步 骤。自下而上的语法分析是一种常用的语法分析方法。
语法分析的定义和目的
1 定义
语法分析是编译器中的一个阶段,用于验证 和分析程序语法的正确性。
2 目的
语法分析的目的是将源代码转换为语法树, 为后续的编译过程提供基础。
《编译原理课程教案》第4章:自下而上语法分析
![《编译原理课程教案》第4章:自下而上语法分析](https://img.taocdn.com/s3/m/d514a8a5846a561252d380eb6294dd88d0d23d2e.png)
构造识别活前缀的DFA, 并根据DFA构造分析表
构造过程中需要消除直接 左递归和提取左因子等操 作
SLR(1)文法及其分析表的构造
SLR(1)文法是LR(0)文法 的简化版本,通过引入 FOLLOW集解决冲突问题
FOLLOW集表示在当前非 终结符之后可能出现的终 结符集合
ABCD
构造SLR(1)分析表时,需 要计算每个非终结符的 FOLLOW集
算符优先分析算法
01
02
03
算符优先分析算法是一 种自下而上的语法分析 方法,通过不断归约和
移进来构造语法树。
在分析过程中,需要维 护一个分析栈和一个输 入缓冲区,分别用于存 储已经分析过的部分和
待分析的部分。
根据优先关系表和分析 栈顶的元素,可以确定 下一步的操作是移进还
是归约。
算符优先分析法的局限性
《编译原理课程教案》第4章:自 下而上语法分析
contents
目录
• 引言 • 自下而上语法分析基本概念 • 算符优先分析法 • LR分析法 • 自下而上语法分析的优化技术 • 实验环节:自下而上语法分析器设计 • 章节小结与拓展思考
01 引言
编译原理课程概述
编译原理是计算机科学的一个重 要分支,研究将高级语言程序转 换为机器语言程序的原理和技术。
总结经验教训
总结实验过程中的经验教训,包括设计思路 的合理性、实现过程的难点和易错点等,为 今后的学习和工作提供参考。
07 章节小结与拓展思考
章节小结:关键知识点回顾
自下而上语法分析基本概念
从输入串开始,逐步进行归约,直到文法的 开始符号。
LR分析法
利用移进-归约思想,结合栈和状态转移表 进行语法分析。
自下而上语法分析
![自下而上语法分析](https://img.taocdn.com/s3/m/27dcfb03bb1aa8114431b90d6c85ec3a87c28b48.png)
⾃下⽽上语法分析⼀实验题⽬⾃下⽽上语法分析⼆实验⽬的1.给出PL/0⽂法规范,要求编写PL/0语⾔的语法分析程序。
2.通过设计、编制、调试⼀个典型的⾃下⽽上语法分析程序,实现对词法分析程序所提供的单词序列进⾏语法检查和结构分析,进⼀步掌握常⽤的语法分析⽅法。
3.选择最有代表性的语法分析⽅法,如算符优先分析法、LR分析法;或者调研语法分析器的⾃动⽣成⼯具YACC的功能与⼯作原理,使⽤YACC⽣成⼀个⾃底向上的语法分析器。
三实验环境Ubuntu16.04、C++语⾔、gcc⼯具链四实验内容已给PL/0语⾔⽂法,构造表达式部分的语法分析器。
分析对象(算术表达式)的BNF定义如下:<表达式>::=[-|+]<项>{<加法运算符><项>}<项>::=<因⼦>{<乘法运算符><因⼦>}<因⼦>::=<标识符>|<⽆符号整数>|‘(’<表达式>‘)’<加法运算符>::=+|-<乘法运算符>::=*|/<关系运算符>::==|#|<|<=|>|>=五实验要求1. 将实验⼀的“词法分析”的输出结果,作为表达式语法分析器的输⼊,进⾏语法解析,对于语法正确的表达式,报告“语法正确”;对于语法错误的表达式,报告“语法错误”,指出错误原因。
2. 把语法分析器设计成⼀个独⽴的⼀遍的过程。
3. 采⽤算符优先分析法或者LR分析法实现语法分析;或者调研语法分析器的⾃动⽣成⼯具YACC的功能与⼯作原理,使⽤YACC⽣成⼀个⾃底向上的语法分析器。
六设计思想我采⽤LR(0)分析法,⾸先写出表达式的⽂法,再写出⽂法的项⽬,画出识别前缀的DFA,构造LR(0)分析表,根据分析表写出程序。
四实验步骤1写出表达式的⽂法:2⽂法的项⽬:3画出识别前缀的DFA:4构造LR(0)分析表:五算法流程六源程序#include<stdio.h>#include<string.h>#include<stdlib.h>char sym[20][8]={//符号表 {'s','s','e','s','s','s','e','e'},//1 {'e','e','e','e','e','e','a','e'},//2 {'e','e','e','s','s','s','e','e'},//3 {'r','r','r','r','r','r','r','r'},//4{'r','r','r','r','r','r','r','r'},//5{'s','e','e','e','e','e','e','e'},//6 {'s','e','s','e','e','e','e','s'},//7{'r','r','r','r','r','r','r','r'},//8{'r','r','r','r','r','r','r','r'},//9{'s','s','e','s','s','s','e','e'},//10{'r','r','r','r','r','r','r','r'},//11{'e','e','e','s','s','s','e','e'},//12{'r','r','r','r','r','r','r','r'},//13{'e','e','e','s','s','s','e','e'},//14{'e','e','e','e','e','e','e','s'},//15{'s','e','e','e','e','e','e','e'},//16{'e','e','s','e','e','e','a','e'},//17{'r','r','r','r','r','r','r','r'},//18{'r','r','r','r','r','r','r','r'},//19{'r','r','r','r','r','r','r','r'}};//20char snum[20][8]={//数字表{3,4,0,7,8,9,0,0},//1{0,0,0,0,0,0,0,0},//2{0,0,0,7,8,9,0,0},//3{8,8,8,8,8,8,8,8},//4{11,11,11,11,11,11,11,11},//5{11,0,0,0,0,0,0,0},//6{11,0,13,0,0,0,0,17},//7{26,26,26,26,26,26,26,26},//8{28,28,28,28,28,28,28,28},//9{3,4,0,7,8,9,0,0},//10{6,6,6,6,6,6,6,6},//11{0,0,0,7,8,9,0,0},//12{19,19,19,19,19,19,19,19},//13{0,0,0,7,8,9,0,0},//14{0,0,0,0,0,0,0,17},//15{11,0,0,0,0,0,0,0},//16{0,0,13,0,0,0,0,0},//17{32,32,32,32,32,32,32,32},//18{15,15,15,15,15,15,15,15},//19{23,23,23,23,23,23,23,23}};//20int go[20][6]={//goto表{2,1,0,0,0,6},//1{0,0,0,0,0,0},//2{0,0,5,0,0,6},//3{0,0,0,0,0,0},//4{0,0,0,0,0,0},//5{0,0,0,10,0,0},//6{0,0,0,0,12,0},//7{0,0,0,0,0,0},//8{0,0,0,0,0,0},//9{2,14,0,0,0,6},//10{0,0,0,0,0,0},//11{0,0,15,0,0,6},//12{0,0,0,0,0,0},//13{0,0,0,0,0,16},//14{0,0,0,0,0,0},//15{0,0,0,18,0,0},//16{0,0,0,0,19,0},//17{0,0,0,0,0,0},//18{0,0,0,0,0,0},//19{0,0,0,0,0,0}};//20void main(){int step=1;/*number of analysis step*/int length=0;/*length of string*/int i,j,m,n;int l=0;/*length of state & ch*/int k=0;int num,x=1;int state[20]={0};/*initial state stack*/char ch[20]={'#'};/*initial character stack*/char str[20];/*define array of string*/char cha;char how;/*how include's','r','a'and null*/char A;//clrscr();printf("please input a string:");do{scanf("%c",&cha);str[length]=cha;length++;}while(cha!='#');/*input a string calculate it's length*/printf("\n--------------------------------------------------------------------------\n"); printf("step\tstate\t\tcharacter\tstring\t\taction\n");printf("--------------------------------------------------------------------------\n"); do{//if(step==10) {printf("\nhhh:%c %c\n",ch[1],ch[2]);}switch(str[k])/*judge str[k]*/{case '+':j=0;break;case '-':j=1;break;case '*':j=2;break;case 'i':j=3;break;case 'n':j=4;break;case '(':j=5;break;case '#':j=6;break;case ')':j=7;break;default:j=-1;break;}if(j!=-1){how=sym[state[l]][j];/*judge how*/num=snum[state[l]][j];/*state's number*/if(how=='s'){printf("%d\t",step);/*output step*/for(i=0;i<=l;i++){printf("%d ",state[i]);/*ouput state stack*/}if(l>=3) printf("\t");else printf("\t\t");for(i=0;i<=l;i++){if(ch[i]==' ' && x==1){ch[i]='*';x++;}printf("%c",ch[i]);/*ouput character stack*/}printf("\t\t");for(i=0;i<k;i++){str[i]=' ';printf("%c",str[i]);}for(i=k;i<length;i++){printf("%c",str[i]);/*output string stack*/}printf("\t");printf("push state %d!\n",num);/*output action*/ l=l+1;state[l]=num;ch[l]=str[l-1];//printf("ch:%c\n",ch[l]);step=step+1;k=k+1;/*next rotate value*/}else if(how=='r'){printf("%d\t",step);/*output step*/for(i=0;i<=l;i++){printf("%d ",state[i]);/*ouput state stack*/}if(l>=3) printf("\t");else printf("\t\t");for(i=0;i<=l;i++){if(ch[i]==' ' && x==2){ch[i]='i';x++;}printf("%c",ch[i]);/*ouput character stack*/}printf("\t\t");for(i=0;i<k;i++){str[i]=' ';printf("%c",str[i]);}for(i=k;i<length;i++){printf("%c",str[i]);/*output string stack*/ }printf("\t");switch(num)/*judge num*/{case 8:A='S',m=1;l=l-m;printf("s->+");break;case 11:A='S',m=1;l=l-m;printf("S->-");break;case 26:A='F',m=1;l=l-m;printf("F->i");break;case 28:A='F',m=1;l=l-m;printf("F->n");break;case 6:A='E',m=3;l=l-m;printf("E->STA");break;case 19:A='T',m=2;l=l-m;printf("T->FB");break;case 32:A='F',m=5;//printf("l=%d",l);//3l=l-m;printf("F->(E)");//F->(F+F)break;case 15:A='A',m=3;l=l-m;printf("A->+TA");break;case 23:A='B',m=3;l=l-m;printf("B->*FB");break;}switch(A)/*judge A*/{case 'S':n=0;break;case 'E':n=1;break;case 'T':n=2;break;case 'A':n=3;break;case 'B':n=4;break;case 'F':n=5;break;}num=go[state[l]][n];printf(",push%d!\n",num);l=l+1;state[l]=num;ch[l]=A;//if(l==1) l++;step=step+1;k=k;}else if(how=='a'){printf("%d\t",step);/*output step*/for(i=0;i<=l;i++){printf("%d ",state[i]);/*ouput state stack*/}if(l>=3) printf("\t");else printf("\t\t");for(i=0;i<=l;i++){printf("%c",ch[i]);/*ouput character stack*/}printf("\t\t");for(i=0;i<k;i++){str[i]=' ';printf("%c",str[i]);}for(i=k;i<length;i++){printf("%c",str[i]);/*output string stack*/}printf("\t");//\tprintf("acc!\n");printf("语法正确!\n");exit(1);}else{printf("ERROR!\n");exit(1);}}else{printf("wrong character!\n");exit(1);}}while(str[k]!='\0');printf("--------------------------------------------------------------------------\n");return ;}七调试数据及结果调试数据:(i+n)*i最终结果:⼋实验体会这次实验为了更⽅便观察⾃下⽽上的分析过程,我将标识符的符号简写为i,将数字的符号简写为n,将加号简写为+,将减号简写为-,将括号简写为(),其实可以从词法分析输出的⽂件中使⽤ident、plus等符号来进⾏分析,但上述符号的表⽰⽅法更符合书中的分析过程,并且更易观察程序分析的对错。
自上而下语法实验报告剖析
![自上而下语法实验报告剖析](https://img.taocdn.com/s3/m/cd37751610661ed9ad51f33f.png)
自上而下语法分析一、实验目的:1.根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
(选做)2.根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。
(必做)二、本次实验的目的主要是加深对自上而下分析法的理解。
实验内容:(一)程序的功能描述LL(1)分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。
具体描述如下:对下列文法,对任意输入的符号串进行分析:(1)E->TG(2)G->+TG(3)G->ε(4)T->FS(5)S->*FS(6)S->ε(7)F->(E)(8)F->i输入一以#结束的符号串(包括+—*/()i#):输出结果:包括分析栈、数组中的剩余字符串以及所用的产生式,形如:分析栈剩余输入串所用产生式E i+i*i# E->TG其中有如下两点要求:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符I,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);(二)LL(1)分析法实验设计思想及算法三、程序设计的过程以及关键函数的功能(一)模块结构:1、定义部分:定义常量、变量、数据结构。
2、初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体等);3、运行程序:让程序分析一个text 文件,判断输入的字符串是否符合文法定义的规则;4、利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示简单的错误提示。
(二)程序的整体流程及关键函数解析: 1、定义一个栈,用于存放非终结符2、将终结符和非终结符各存放在一个数组中,用于判断栈顶元素是否是终结符或非终结符,然后根据情况判断接下来是查表,还是进行匹配移进。
X ∈V‘#’‘S’进栈,当前输入符送sym上托栈顶符号放入X若产生式为 X X 1X 2…X n按逆序即X n …X 2X 1入栈 出错X=’#’X ∈VX=M[X,sym]是产生式吗出错X=读入下一个符号结束是是是 是否否否 否 否是3、定义一个全局变量f,用于指示从文件中读出的匹配后的剩余字符串中的首个字符在数组中的位置。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验三自下而上语法分析及语义分析一、实验目的:通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:4学时。
三、实验内容根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。
对于错误的表达式,给出出错位置。
四、实验方法采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。
接下来给出LR分析表。
然后程序的具体实现:●LR分析表可用二维数组(或其他)实现。
●添加一个val栈作为语义分析实现的工具。
●编写总控程序,实现语法分析和语义分析的过程。
注:对于整数的识别可以借助实验1。
五、文法定义简单的表达式文法如下:E->E+T|E-T|TT->T*F|T/F|FF->(E)|i上式中,i 为整数。
六、处理程序例例1: 正确源程序例:23+(45+4)* 40分析结果应为:正确的表达式。
其值为:1983例2: 错误源程序例:5+(56+)-24分析结果应为:错误的表达式:出错位置为)附录:源程序#include <stdio.h>#include"string.h"#include <iostream>using namespace std;#define R 30#define C 20typedef struct elem{char e[4];}Elem; //ACTION表与GoTo表中的元素类型Elem LR[R][C]; //存放ACTION表与GoTo表中的内容typedef struct out{int order; //序号int state[10]; //状态栈char sign[30]; //符号栈char grasen[20]; //产生式char input[30]; //输入串char explen[50]; //解释说明}OutNode; //输出结果中每一行的类型OutNode out[20]; //存放输出结果char Sentence[20]; //存放文法的一个句子char GramSent[10][20]; //存放文法的一组产生式int row,colno; //row为状态个数数,colno为ACTION表与GoTo表列总数int stateTop=0,signTop=0; //状态栈与符号栈的栈顶位置(值与栈中元素的个数相等)void input_GramSent(){int i,num;printf("请输入文法中产生式的个数\n");scanf("%d",&num);for(i=0;i<num;i++){printf("请输入文法的第%d个产生式\n",i);scanf("%s",GramSent+i-1);}printf("请输入文法的一个句子\n");scanf("%s",Sentence);printf("**********************************************************\n");printf("* 文法的产生式如下: *\n");printf("**********************************************************\n");for(i=0;i<num;i++)printf("%s\n",GramSent+i);printf("**********************************************************\n");printf("* 文法的句子如下: *\n");printf("**********************************************************\n");printf("%s\n",Sentence);}void input_LR(int row,int colno) //row为行总数,colno为列总数{int i,j;char mid[4];printf("**********************************************************\n");printf("* 提示:每输入一个元素后就回车 *\n");printf("**********************************************************\n");printf("请输入LR分析表的终结符(包括#)与非终结符\n");for(j=0;j<colno;j++)scanf("%s",LR[0][j].e);for(i=0;i<row;i++){printf("请输入%d号状态所对应的各列的元素,空白的地方用s代替\n",i);for(j=0;j<colno;j++){scanf("%s",mid);if(strcmp(mid,"s")==0||strcmp(mid,"S")==0)strcpy(LR[i+1][j].e," ");elsestrcpy(LR[i+1][j].e,mid);}}}void output_LR(int row,int colno){int i,j;printf("**********************************************************\n"); printf("* LR分析表如下: *\n");printf("**********************************************************\n"); printf("\n");printf(" ");for(j=0;j<colno;j++)printf("%s ",LR[0][j].e);printf("\n");for(i=1;i<=row;i++){printf("%d ",i-1);for(j=0;j<colno;j++)printf("%s ",LR[i][j].e);printf("\n");}printf("\n");}int SignNum(char ch)//给定一个终结符或非终结符,返回其在ACTION表与GoTo表中的列位置int i;char c[2]="0";c[0]=ch;for(i=0;i<colno;i++)if(strcmp(c,LR[0][i].e)==0)return i;return -1;}int CharChangeNum(char* ch)//给定一数字字符串,返回其所对应的数字{int result=0;while(*ch!='\0'){result=result*10+(*ch-'0');ch++;}return result;}int OutResult(int s,int c,int i)//输出结果的第i+1行处理函数,(s 为状态,c为列){char mid[4],gra[20];int s_num,r_num;int n,len,j;strcpy(mid,LR[s+1][c].e);if(strcmp(mid," ")==0){ printf("不能规约\n"); return -2; }if(strcmp(mid,"acc")==0||strcmp(mid,"ACC")==0){ printf("规约成功\n"); return -1; }out[i+1].order=i+2;if(mid[0]=='s'||mid[0]=='S'){s_num=CharChangeNum(mid+1);//s_num为S后的数字for(j=0;j<stateTop;j++)out[i+1].state[j]=out[i].state[j];out[i+1].state[stateTop]=s_num;out[i+1].state[++stateTop]=-1; //完成第i+1行的状态栈赋值strcpy(out[i+1].sign,out[i].sign);out[i+1].sign[signTop]=out[i].input[0];out[i+1].sign[++signTop]='\0'; //完成第i+1行的符号栈的赋值strcpy(out[i+1].grasen," "); //完成第i+1行的产生式的赋值strcpy(out[i+1].input,out[i].input+1); //完成第i+1行的输入符号串的赋值}else if(mid[0]=='r'||mid[0]=='R'){r_num=CharChangeNum(mid+1);//r_num为r后的数字strcpy(gra,*(GramSent+r_num-1));len=strlen(gra);for(j=0;j<len;j++)if(gra[j]=='-' && gra[j+1]=='>')break;n=strlen(gra+j+2);stateTop-=n; signTop-=n;for(j=0;j<stateTop;j++)out[i+1].state[j]=out[i].state[j];j=SignNum(gra[0]);out[i+1].state[stateTop]=CharChangeNum(LR[out[i+1].state[stateTop-1]+1][ j].e);out[i+1].state[++stateTop]=-1; //完成第i+1行的状态栈赋值strcpy(out[i+1].sign,out[i].sign);out[i+1].sign[signTop]=gra[0];out[i+1].sign[++signTop]='\0'; //完成第i+1行的符号栈的赋值strcpy(out[i+1].grasen,gra); //完成第i+1行的产生式的赋值strcpy(out[i+1].input,out[i].input); //完成第i+1行的输入符号串的赋值}return 1;}void OutputResult(int r){int i,j;printf("**********************************************************\n"); printf("* 句子:%s 用LR分析表规约过程如下:*\n",Sentence);printf("**********************************************************\n"); for(i=0;i<=r;i++){j=0;printf("%2d ",out[i].order);while(out[i].state[j]!=-1)printf("%d",out[i].state[j++]);printf(" %s %s %s\n",out[i].sign,out[i].grasen,out[i].input);}}int OutControl()//输出结果的总控函数{int s_num,i=0;out[0].order=1; //序号赋值out[0].state[0]=0; stateTop=1; out[0].state[stateTop]=-1; //状态栈赋值,置栈顶位strcpy(out[0].sign,"#"); signTop=1; //符号栈赋值,置栈顶位strcpy(out[0].grasen," "); //产生式为空strcpy(out[0].input,Sentence); //以下两行为输入串赋值strcat(out[0].input,"#");strcpy(out[0].explen,"0和#进栈"); //解释说明//初使化输出结果的第一行while(1){s_num=SignNum(out[i].input[0]);//if(s_num!=-1)if(OutResult(out[i].state[stateTop-1],s_num,i)!=1)break;i++;}return i;}main(){int r;printf("**********************************************************\n"); printf("* 函数的输入: 文法的产生式,文法句型的一个句子,LR分析表 *\n");printf("* 函数的输出: LR分析器的工作过程与说明 *\n");printf("**********************************************************\n"); printf("请输入LR分析表中终结符与非终结符的总个数\n");scanf("%d",&colno);printf("请输入LR分析表中状态的总个数\n");scanf("%d",&row);input_LR(row,colno);output_LR(row,colno);input_GramSent();r=OutControl(); //r为输出结果的行数OutputResult(r);}七、实验小结这个程序是从网上下载下来的,根据这个实验要求做了些更改,但是总是出现溢出错误,只能运行到LR分析表的部分(如截图),没有找到解决问题的办法。