LR语法分析实验报告

合集下载

lr语法分析实验报告

lr语法分析实验报告

lr语法分析实验报告LR语法分析实验报告引言在计算机科学领域,语法分析是编译器设计中非常重要的一个环节。

它负责将输入的源代码按照给定的文法规则进行解析,并生成语法树或分析表。

本实验报告将介绍LR语法分析器的设计与实现,并通过实验结果进行分析和评估。

一、背景知识1.1 语法分析语法分析是编译器的一个重要组成部分,它负责将输入的源代码转化为抽象语法树或分析表。

语法分析器根据给定的文法规则,逐个读取输入的字符并进行规约或移进操作,最终确定输入串是否符合给定的文法。

1.2 LR语法分析LR语法分析是一种自底向上的语法分析方法,它利用有限状态自动机进行分析。

LR分析器根据输入的文法规则和状态转移表,逐步推导输入串,直到达到最终的语法树或分析表。

二、实验设计2.1 实验目标本实验旨在设计和实现一个LR语法分析器,包括以下主要内容:- 设计和实现文法规则- 构建LR分析表- 实现LR分析器的状态转移和语法规约操作2.2 实验环境本实验使用Python语言进行实现,使用了Python的语法分析库PLY(Python Lex-Yacc)。

三、实验过程3.1 文法规则设计在本实验中,选择了一个简单的算术表达式文法作为示例:```E -> E + T| E - T| TT -> T * F| T / F| FF -> ( E )| number```该文法规则描述了四则运算表达式的语法结构,其中E表示表达式,T表示项,F表示因子。

3.2 构建LR分析表根据给定的文法规则,我们可以构建LR分析表。

该表记录了分析器在不同状态下的状态转移和规约操作。

3.3 实现LR分析器基于PLY库,我们可以很方便地实现LR分析器的状态转移和规约操作。

首先,我们需要定义文法规则的各个产生式对应的处理函数。

然后,通过PLY库提供的API,我们可以构建分析器对象,并进行状态转移和规约操作。

四、实验结果与分析4.1 实验结果经过实验,我们成功地实现了LR语法分析器,并对多个测试用例进行了分析。

LR语法分析程序实验报告

LR语法分析程序实验报告

语法分析程序实验报告一、实验题目:编写语法分析程序,实现对算术表达式的语法分析。

要求所分析算数表达式由如下的文法产生。

>>*> ()要求在对输入表达式进行分析的过程中,输出所采用的产生式。

二、设计思路:手工构造识别所有活前缀的,做出相应的分析表,本程序中和结构数组即为所需要的分析表部分,并用结构数组存储生成式。

经过计算的预测分析表如下:三、流程图:四、功能实现:()用于存储生成式、表、表的元素定义如下:生成式{生成式左部符号生成式右部符号个数[]生成式右部符号};表项元素{动作代表移进代表归约代表接受代表错误表示移进后的状态或者归约过程使用的生成式};表项元素()算法实现代码如下:()检查分析式{([[]][[]])看对应表项动作{''移进动作,将字符和状态压栈([]);([[]][[]]);;;;;''归约动作([[[]][[]]])输出相应产生式{;[[[]][[]]]出栈次数为产生式右部符号的个数[[[]][[]]]进栈的左部符号为产生式的左部符号(<){()弹出状态指针下移()弹出字符指针下移}()左部符号进栈指针上移}([]>)栈顶为非终结符{([[]][[]]){([[]][[]])查询表,并将相应状态压栈栈顶指针上移}{<<"匹配失败"<<;("");;}};''错误状态<<"匹配失败"<<;("");;''接受状态<<"匹配成功"<<;("");;}五、使用截图:输入(),结果如下:输入),结果如下:六、总结:通过编写语法分析程序,对自底向上语法分析方法加强了理解,熟悉自底向上分析表的构造过程,提高了将伪码算法转换成实际可执行代码的能力和抽象能力,收获很大。

北邮编译原理LR语法分析程序实验报告

北邮编译原理LR语法分析程序实验报告

LR语法分析程序实验报告说明:该程序使用实现对算术表达式自底向上的语法分析,并且在对输入表达式进行分析的过程中,输出分析动作,移进或者用哪个产生式进行规约,该程序使用的是LR语法分析程序,手动构造了识别所有活前缀的DFA,为给定文法构造LR分析表,并通过预测分析表对输入的表达式进行分析,并将栈顶状态和预测分析过程详细输出,如果匹配成功则接受,如果匹配不成功则返回错误信息。

特别的是,该程序参照书上129页的有关LR分析的错误处理与恢复表对一些可能出现的错误进行报错和局部恢复,在action表中设置相应的错误处理过程入口,调用相应的过程进行错误处理和恢复,使语法分析能继续进行。

给定文法的产生式为:E->E+T | TT->T*F | FF-> id | (E)源代码:#include<iostream>#include<stack>using namespace std;stack<char> symbol;stack<int> state;char sen[50];char sym[12][6]={//符号表{'s','e','e','s','e','e'},{'e','s','e','e','e','a'},{'r','r','s','r','r','r'},{'r','r','r','r','r','r'},{'s','e','e','s','e','e'},{'r','r','r','r','r','r'},{'s','e','e','s','e','e'},{'s','e','e','s','e','e'},{'e','s','e','e','s','e'},{'r','r','s','r','r','r'},{'r','r','r','r','r','r'},{'r','r','r','r','r','r'}};char snum[12][6]={//数字表{5,1,1,4,2,1},{3,6,5,3,2,0},{2,2,7,2,2,2},{4,4,4,4,4,4},{5,1,1,4,2,1},{6,6,6,6,6,6},{5,1,1,4,2,1},{5,1,1,4,2,1},{3,6,5,3,11,4},{1,1,7,1,1,1},{3,3,3,3,3,3},{5,5,5,5,5,5}};int go2[12][3]={//goto表{1,2,3},{0,0,0},{0,0,0},{0,0,0},{8,2,3},{0,0,0},{0,9,3},{0,0,10},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};void action(int i,char *&a,char &how,int &num,char &A,int &b)//action函数[i,a] {int j;switch(*a){case 'i':j=0;break;case '+':j=1;break;case '*':j=2;break;case '(':j=3;break;case ')':j=4;break;case '#':j=5;break;default:j=-1;break;}printf("%c\t\t",*a);if(j!=-1){how=sym[i][j];num=snum[i][j];if(how=='r'){switch(num){case 1:A='E',b=3;cout<<"reduce by E->E+T"<<endl;break;case 2:A='E',b=1;cout<<"reduce by E->T"<<endl;break;case 3:A='T',b=3;cout<<"reduce by T->T*F"<<endl;break;case 4:A='T',b=1;cout<<"reduce by T->F"<<endl;break;case 5:A='F',b=3;cout<<"reduce by F->(E)"<<endl;break;case 6:A='F',b=1;cout<<"reduce by F->id"<<endl;break;default:break;}}}}int go(int t,char A)//goto[t,A]{switch(A){case 'E':return go2[t][0];break;case 'T':return go2[t][1];break;case 'F':return go2[t][2];break;}}void error(int i,int j,char *&a)//error处理函数{switch(j){case 1://期望输入id或左括号,但是碰到+,*,或$,就假设已经输入id了,转到状态5 cout<<"error:缺少运算对象id"<<endl;symbol.push('i');//必须有这个,如果假设输入id的话,符号栈里必须有....printf("i\t\t");state.push(5);printf("5\t\t");break;case 2://从输入中删除右括号a++;cout<<"error:不配对的右括号"<<endl;break;case 3://期望碰到+,但是输入id或左括号,假设已经输入算符+,转到状态6 cout<<"error:缺少运算符"<<endl;symbol.push('+');printf("+\t\t");state.push(6);printf("6\t\t");break;case 4://缺少右括号,假设已经输入右括号,转到状态11cout<<"error:缺少右括号"<<endl;symbol.push(')');printf(")\t\t");state.push(11);printf("11\t\t");break;case 5:a++;cout<<"error:*号无效,应该输入+号!"<<endl;case 6:a++;}}int main(){int s;char *a;char how;int num;int b;char A;cout<<"请输入表达式(以i表示标识符,以#结束):"<<endl;while(1){cin>>sen;a=sen;state.push(0);//先输入0状态printf("\t\t-------分析过程-------\n");printf("符号栈栈顶\t状态栈栈顶\t当前读入符号\t分析动作\n");printf(" \t\t0\t\t");while(*a!='\0'){b=0;num=0;how='\0';A='\0';s=state.top();action(s,a,how,num,A,b);if(how=='s')//移进{cout<<"Shift"<<endl;symbol.push(*a);printf("%c\t\t",*a);state.push(num);printf("%d\t\t",num);a++;}else if(how=='r')//规约{for(int i=0;i<b;i++){if(!state.empty())state.pop();if(!symbol.empty())symbol.pop();}int t=state.top();symbol.push(A);printf("%c\t\t",A);state.push(go(t,A));printf("%d\t\t",go(t,A));}else if(how=='a')//接受break;else{error(s,num,a);//错误处理}}cout<<"accept"<<endl;}return 0;}输入的表达式正确则不报错并接受:输入错误的表达式i*(i+i*i#报错并进行恢复:输入错误的表达式i+*i#报错并恢复:输入错误表达式i*ii+i)#进行报错并恢复:。

编译原理-语法分析程序报告

编译原理-语法分析程序报告

编译原理实验实验二语法分析器实验二:语法分析实验一、实验目的根据给出的文法编制LR(1)分析程序,以便对任意输入的符号串进行分析。

本次实验的目的主要是加深对LR(1)分析法的理解。

二、实验预习提示1、LR(1)分析法的功能LR(1)分析法的功能是利用LR(1)分析表,对输入符号串自下而上的分析过程。

2、LR(1)分析表的构造及分析过程。

三、实验内容对已给语言文法,构造LR(1)分析表,编制语法分析程序,要求将错误信息输出到语法错误文件中,并输出分析句子的过程(显示栈的内容);实验报告必须包括设计的思路,以及测试报告(输入测试例子,输出结果)。

语法分析器一、功能描述:语法分析器,顾名思义是用来分析语法的。

程序对给定源代码先进行词法分析,再根据给定文法,判断正确性。

此次所写程序是以词法分析器为基础编写的,由于代码量的关系,我们只考虑以下输入为合法:数字自定义变量+ * ()$作为句尾结束符。

其它符号都判定为非法。

二、程序结构描述:词法分析器:class wordtree;类,内容为字典树的创建,插入和搜索。

char gettype(char ch):类型处理代入字串首字母ch,分析字串类型后完整读入字串,输出分析结果。

因读取过程会多读入一个字母,所以函数返回该字母进行下一次分析。

bool isnumber(char str[]):判断是否数字代入完整“数字串”str,判断是否合法数字,若为真返回1,否则返回0。

bool isoperator(char str[]):判断是否关键字代入完整“关键字串”str,搜索字典树判断是否存在,若为存在返回1,否则返回0。

语法分析器:int action(int a,char b):代入当前状态和待插入字符,查找转移状态或归约。

node2 go(int a):代入当前状态,返回归约结果和长度。

void printstack():打印栈。

int push(char b):将符号b插入栈中,并进行归约。

实验三编译原理综合实验报告——(LR(0)语法分析的实现)

实验三编译原理综合实验报告——(LR(0)语法分析的实现)
m_pTree->Create(IDD_DIALOG3, this);
m_pTree->SetControlInfo(IDC_TREE1, RESIZE_BOTH);
m_pTree->SetControlInfo(IDOK, ANCHORE_BOTTOM | ANCHORE_RIGHT);
void CAnalyzeDlg::OnOK()
{
// TODO: Add extra validation here
//CDialog::OnOK();
}
void CAnalyzeDlg::OnCancel()
{
// TODO: Add extra cleanup here
六、实验原理、数据(程序)记录
(一)实验原理:
利用LR(k)类分析算法的四个步骤,分别实现"移进"、"归约"、"成功"、"报错"的分析能力。同时采用相应的数据结构实现分析表的描述。
(二)程序框架:
#include "stdafx.h"
#include "GoData.h"
GoData::GoData()
assert(j != -1);
out.WriteString(GetStepInfo(iStep, Status, Symbol, m_input.Right(m_input.GetLength() - iPos), ToDo, j));
for(i = 0; i < m_g.GetPrecept(ToDo.two).GetRight().length(); i++)

LR分析实验报告

LR分析实验报告

LR分析实验报告实验报告:LR分析一、实验目的LR分析是一种常用的机器学习算法,主要用于分类问题。

本实验的目的是使用LR分析算法对一些数据集进行分类,并评估分类效果。

二、实验原理1.LR模型逻辑回归(Logistic Regression)是一种常用的分类算法,它主要用于解决二分类问题。

它利用逻辑函数(Logistic函数)将输入的特征线性两两组合,并通过Sigmoid函数将结果映射到[0,1]的概率值。

具体来说,假设输入特征为x=(x1,x2,...,xn),输出为y,那么逻辑回归模型可以表示为:p(y=1,x) = sigmoid(w0 + w1*x1 + w2*x2 + ... + wn*xn)其中,p(y=1,x)表示在给定特征x的条件下y=1的概率,sigmoid 函数为:sigmoid(z) = 1/(1+exp(-z))模型的参数w0, w1, ..., wn可以通过最大似然估计等方法求解。

2.LR模型训练在LR模型训练过程中,需要使用一个损失函数来衡量预测结果与实际结果的差异,并通过梯度下降等优化算法来求解参数。

一般使用对数似然损失函数(Log Loss)来训练LR模型,其定义如下:Loss(y, p) = -[y*log(p) + (1-y)*log(1-p)]其中,y表示实际结果(0或1),p表示模型预测结果。

参数的更新可以使用梯度下降法来进行:w = w - α * gradient其中,α为学习率,gradient为损失函数对参数的梯度。

三、实验步骤1.数据预处理对原始数据进行特征选择、缺失值填充、离散特征编码等处理,生成可用于训练的数据集。

2.特征工程对数据进行特征工程,包括特征的归一化、离散特征的独热编码等。

3.模型训练使用训练集对LR模型进行训练,在训练中不断调整参数,直至达到收敛条件。

4.模型评估使用测试集对训练好的模型进行评估,并计算准确率、精确率、召回率、F1值等指标。

LR语法分析实验报告

LR语法分析实验报告

目录引言 (1)第一章概述 (2)1.1设计题目及内容 (2)1.2设计环境 (2)第二章设计的基本原理 (3)2.1 LR分析器的基本理 (3)2.2 LR分析器工作过程算法 (3)第三章程序设计 (5)3.1总体方案设计 (5)3.2各模块设计 (5)第四章程序测试和结论以及心得................................ ..7 参考文献. (7)附录程序清单 (8)一概述1.1设计题目及内容设计题目:根据LR分析表构造LR分析器内容:已知文法G:(1)E→E+T(2) E→T(3) T→T*F(4) T→F(5) F→(E)(6) F→Irj 表示按第j个产生式进行规约acc 表示接受空格表示出错标志,报错根据以上文法和LR分析表,构造LR分析器,并要求输出LR工作过程。

1.2设计环境:硬件设备:一台PC机软件设备:Windows 2000/XP OS ,VC++6.0实现语言:C语言二设计的基本原理2.1 基本原理:1.LR方法的基本思想:在规范规约的过程中,一方面记住已移进和规约出的整个符号串,即记住“历史”,另一方面根据所用的产生式推测未来可能碰到的输入符号,即对未来进行“展望”。

当一串貌似句柄的符号串呈现于分析栈的顶端时,我们希望能够根据记载的“历史”和“展望”以及“现实”的输入符号等三个方面的材料,来确定栈顶的符号串是否构成相对某一产生式的句柄。

2.LR分析器实质上是一个带先进后出存储器(栈)的确定有限状态自动机。

3.LR分析器的每一步工作是由栈顶状态和现行输入符号所唯一决定的。

4.为清晰说明LR分析器实现原理和模型:LR分析器的核心部分是一张分析表。

这张分析表包括两个部分,一是“动作”(ACTION)表,另一是“状态转换”(GOTO)表。

他们都是二维数组。

ACTION(s,a)规定了当状态s面临输入符号a时应采取什么动作。

GOTO(s,X)规定了状态s面对文法符号X(终结符或非终结符)时下一状态是什么。

LR分析——精选推荐

LR分析——精选推荐

LR分析LR(1)语法分析实验报告⼀、实验需求:构造LR(1)分析程序,利⽤它进⾏语法分析,判断给出的符号串是否为该⽂法识别的句⼦。

⼆、实验预习:1、设计思想:为了使⼀个⽂法是LR的,只要保证当句柄出现在栈顶时,⾃左向右扫描的移进-归约分析器能够及时识别它便⾜够了。

当句柄出现在栈顶时,LR分析器必须要扫描整个栈就可以知道这⼀点,栈顶的状态符号包含了所需要的⼀切信息。

如果仅知道栈内的⽂法符号就能确定栈顶是什么句柄。

LR分析表的转移函数本质上就是这样的有限⾃动机。

不过,这个有限⾃动机不需要根据每步动作读栈,因为,如果这个识别句柄的有限⾃动机⾃底向上读栈中的⽂法符号的话,它达到的状态正是这时栈顶的状态符号所表⽰的状态,所以,LR分析器可以从栈顶的状态确定它需要从栈中了解的⼀切。

2、LR分析器组成:(1)总控程序,也可以称为驱动程序。

对所有的LR分析器总控程序都是相同的。

(2)分析表或分析函数,不同的⽂法分析表将不同,同⼀个⽂法采⽤的LR分析器不同时,分析表将不同,分析表⼜可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可⽤⼆维数组表⽰。

(3)分析栈,包括⽂法符号栈和相应的状态栈,它们均是先进后出栈。

分析器的动作就是由栈顶状态和当前输⼊符号所决定。

程序输⼊/输出⽰例:对下列⽂法,⽤LR(1)分析法对任意输⼊的符号串进⾏分析:(1)E->E+T(2)E->E—T(3)T->T*F(4)T->T/F(5)F->(E)(6)F->i输出结果:主要源程序代码及注释#include#include#include#define NVT 8#define NVN 3#define NLR 9char *action[16][8]={"s4",NULL,NULL,NULL,NULL,"s5",NULL,NULL,//ACTION表NULL,"s6","s7",NULL,NULL,NULL,NULL,"acc",NULL,"r3","r3","s8","s9",NULL,"r3","r3",NULL,"r6","r6","r6","r6",NULL,"r6","r6",NULL,"r8","r8","r8","r8",NULL,"r8","r8","s4",NULL,NULL,NULL,NULL,NULL,NULL,NULL,"s4",NULL,NULL,NULL,NULL,"s5",NULL,NULL,"s4",NULL,NULL,NULL,NULL,"s5",NULL,NULL,"s4",NULL,NULL,"s10",NULL,"s5",NULL,NULL,"s4",NULL,NULL,NULL,"s13","s5",NULL,NULL,NULL,"r4","r4","r4","r4",NULL,"r4","r4",NULL,"r1","r1","s8","s9",NULL,"r1","r1",NULL,"r2","r2","s8","s9",NULL,"r2","r2",NULL,"r5","r5","r5","r5",NULL,"r5","r5",NULL,"s6","s7",NULL,NULL,NULL,"s15",NULL,NULL,"r7","r7","r7","r7",NULL,"r7","r7"};int goto1[16][3]={1,2,3, /*GOTO表*/0,0,0,0,0,0,0,0,0,0,0,0,14,2,3,0,11,3,0,12,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};char vt[NVT]={'i','+','-','*','/','(',')','#'}; /*存放终结符*/char vn[NVN]={'E','T','F'}; /*存放⾮终结符*/char *LR[NLR]={"S->E","E->E+T","E->E-T","E->T","T->T*F","T->T/F","T->F","F->(E)","F->i"};/*存放产⽣式*/ int a[16];//状态栈char b[16],c[16],c1;//符号栈,输⼊栈void main(){int top1,top2,top3,top;int i,j,k,y,z,count,m;char x,copy[4],copy1[7];top1=0;//状态栈栈顶top2=0;//符号栈栈顶top3=0;//输⼊栈栈顶top=0;//⽬前输⼊串的位置a[0]=0;y=a[0];b[0]='#';count=0;z=0;printf("请输⼊表达式\n");scanf("%c",&c1);c[top3]=c1;top3=top3+1;}while(c1!='#');printf("步骤\t状态栈\t\t符号栈\t\t输⼊串\t\tACTION\tGOTO\n"); do{ y=z;m=0; /*y,z指向状态栈栈顶*/j=0;k=0;x=c[top];count++;printf("%d\t",count);while(m<=top1){ /*输出状态栈*/printf("%d",a[m]);m=m+1;}printf("\t\t");m=0;while(m<=top2){ /*输出符号栈*/printf("%c",b[m]);m=m+1;}printf("\t\t");m=top;while(m<=top3){ /*输出输⼊串*/printf("%c",c[m]);m=m+1;}printf("\t\t");while(x!=vt[j]&&jj++;if(j==NVT&&x!=vt[j]){printf("\n输⼊字符串不是由终结符组成\n"); system("pause");return;}if(action[y][j]==NULL)printf("error\n");system("pause");return;}elsestrcpy(copy,action[y][j]);if(copy[0]=='s'){ /*处理移进*/if(copy[2]!='\0')z=(copy[1]-'0')*10+copy[2]-'0';elsez=copy[1]-'0';top1=top1+1;top2=top2+1;a[top1]=z;b[top2]=x;top=top+1;i=0;while(copy[i]!='\0'){printf("%c",copy[i]);i++;}printf("\n");}if(copy[0]=='r'){ /*处理归约*/i=0;while(copy[i]!='\0'){printf("%c",copy[i]);i++;}strcpy(copy1,LR[copy[1]-'0']); while(copy1[0]!=vn[k])k++;top1=top1-(strlen(LR[copy[1]-'0'])-4); top2=top2-(strlen(LR[copy[1]-'0'])-4); y=a[top1-1];a[top1]=goto1[y][k];b[top2]=copy1[0];z=goto1[y][k];printf("\t");printf("%d\n",goto1[y][k]);}}while(action[y][j]!="acc");printf("acc\n");system("pause");}。

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

目录引言 (1)第一章概述 (2)1.1设计题目及内容 (2)1.2设计环境 (2)第二章设计的基本原理 (3)2.1 LR分析器的基本理 (3)2.2 LR分析器工作过程算法 (3)第三章程序设计 (5)3.1总体方案设计 (5)3.2各模块设计 (5)第四章程序测试和结论以及心得................................ ..7 参考文献. (7)附录程序清单 (8)一概述1.1设计题目及内容设计题目:根据LR分析表构造LR分析器内容:已知文法G:(1)E→E+T(2) E→T(3) T→T*F(4) T→F(5) F→(E)(6) F→Irj 表示按第j个产生式进行规约acc 表示接受空格表示出错标志,报错根据以上文法和LR分析表,构造LR分析器,并要求输出LR工作过程。

1.2设计环境:硬件设备:一台PC机软件设备:Windows 2000/XP OS ,VC++6.0实现语言:C语言二设计的基本原理2.1 基本原理:1.LR方法的基本思想:在规范规约的过程中,一方面记住已移进和规约出的整个符号串,即记住“历史”,另一方面根据所用的产生式推测未来可能碰到的输入符号,即对未来进行“展望”。

当一串貌似句柄的符号串呈现于分析栈的顶端时,我们希望能够根据记载的“历史”和“展望”以及“现实”的输入符号等三个方面的材料,来确定栈顶的符号串是否构成相对某一产生式的句柄。

2.LR分析器实质上是一个带先进后出存储器(栈)的确定有限状态自动机。

3.LR分析器的每一步工作是由栈顶状态和现行输入符号所唯一决定的。

4.为清晰说明LR分析器实现原理和模型:LR分析器的核心部分是一张分析表。

这张分析表包括两个部分,一是“动作”(ACTION)表,另一是“状态转换”(GOTO)表。

他们都是二维数组。

ACTION(s,a)规定了当状态s面临输入符号a时应采取什么动作。

GOTO(s,X)规定了状态s面对文法符号X(终结符或非终结符)时下一状态是什么。

显然,GOTO(s,X)定义了一个以文法符号为字母表的DFA。

每一项ACTION(s,a)所规定的动作不外是下述四种可能之一:(1)移进把(s,a)的下一个转态s’ = GOTO(s,X)和输入符号a推进栈,下一输入符号变成现行输入符号。

(2)规约指用某一产生式A→β 进行规约。

假若β的长度为r,规约的动作是A,去除栈顶的r个项,使状态Sm-r 变成栈顶状态,然后把(Sm-r,A)的下一状态s’ = GOTO(Sm-r,A)和文法符号A推进栈。

规约动作不改变现行输入符号。

执行规约动作意味着β(= Xm-r+1…Xm)已呈现于栈顶而且是一个相对于A的句柄。

(3)接受宣布分析成功,停止分析器的工作。

(4)报错发现源程序含有错误,调用出错处理程序。

2.2 LR分析器工作过程算法描述:一个LR分析器的工作过程可看成是栈里的状态序列,已规约串和输入串所构成的三元式的变化过程。

分析开始时的初始三元式为(s0, #, a1a2……an#)其中,s0为分析器的初态;#为句子的左括号;a1a2……an为输入串;其后的#为结束符(句子右括号)。

分析过程每步的结果可表示为(s0s1……sm,#X1X2……Xm ai, ai+1……an#)分析器的下一步动作是由栈顶状态sm和现行输入符号ai所唯一决定的。

即,执行ACTION(sm,ai)所规定的动作。

经执行每种可能的动作之后,三元式的变化情形是:(1)若ACTION(sm,ai)为移进,且s = GOTO(sm,ai),则三元式变成:(s0s1……sm s,#X1X2……Xm ai, ai+1……an#)(2)若ACTION(sm,ai)= {A→β},则按照产生式A→β进行规约。

此时三元式变为(s0s1……sm s,#X1X2……Xm A, ai ai+1……an#)此处s = GOTO(Sm-r,A),r为β的长度,β = Xm-r+1……Xm。

(3)若ACTION(sm,ai)为“接受”,则三元式不再变化,变化过程终止,宣布分析成功。

(4)若ACTION(sm,ai)为“报错”,则三元式的变化过程终止,报告错误。

一个LR分析器的工作过程就是一步一步的变换三元式,直至执行“接受”或“报错”为止。

三程序设计3.1总体设计方案:1.建模:(1)分析表建模:构造一个int 型二维数组table[13][9],用于存放LR分析表。

并初始化。

作者这样规定:0~11 表示状态sj,其中0对应s0,1对应s1……21~26 表示规约rj,其中21对应r1,22对应r2……12 表示“接受”-1 表示规约出错,报错(2)栈建模:建立一个int 型状态栈,该栈为顺序栈。

建立一个char型符号栈和一个char型输入串栈,该栈为顺序栈。

(3)规约表达式建模:建立一个rule型结构,成员变量为char型非终结符和int型表示规约第几条表达式。

2.程序设计关键注意环节:(1)在输入串(句子)输入的过程中,涉及到一个压栈的问题。

但是输入串压入的字符顺序刚好与原理中的字符串模型刚好相反,这样需要先弹出的反而在栈底。

为了既要保证字符串输入,又要让输入的字符串存储顺序与输入的字符串相反。

采取以下措施:先将输入的字符串压入符号栈symbol中,然后符号栈弹出的字符再压入输入串栈instr中,这样实现了输入串的倒序存储。

(2)状态栈status_stack(status_p)和符号栈symbol_instr(symbol_p)输出(遍历)过程均采取自栈底到栈顶的顺序,而输入串栈symbol_instr(instr_p)则是采取自栈顶到栈底的顺序输出。

3.2各模块设计:1.栈设计:构造一个int型“状态栈”status和一个char型“符号-输入串栈”symbol_instr。

该栈包括初始化该栈init_status(),压栈push(),弹栈pop(),取栈顶元素get_top(),自栈底到栈顶遍历元素out_stack1()和自栈顶到栈底遍历元素out_stack2().2.LR分析器工作过程算法设计:构造一个状态转换函数实现状态转换int goto_char(status *status_p,symbol_instr *instr_p)构造一个移进--规约函数实现移进规约动作void action(status *status_p,symbol_instr *symbol_p,symbol_instr *instr_p)构造一个打印LR分析器的工作过程函数实现输出void print(status *status_p,symbol_instr *symbol_p,symbol_instr *instr_p)3.流程图:LR分析器设计流程图四程序测试和结果以及心得1.测试结果:见附录经过测试,输入各种各样的正确句子,均能正确规约。

而且,输入错误的句子,也能正确报错。

2.心得:附录程序源代码:四:主程序:#include"status_stack.h"#include"symbol_instr_stack.h"#include"lr.h"//打印LR分析器的工作过程void print(status *status_p,symbol_instr *symbol_p,symbol_instr *instr_p){int i;out_stack(status_p);for(i=0;i<20-status_p->top;i++)printf(" ");out_stack1(symbol_p);for(i=0;i<20;i++)printf(" ");out_stack2(instr_p);printf("\n");}//状态转换函数int goto_char(status *status_p,symbol_instr *instr_p){char x;int y,z;x = get_top(instr_p);y = get_top(status_p);z = get_index_char(x);return table[y][z];}//移进--规约函数void action(status *status_p,symbol_instr *symbol_p,symbol_instr *instr_p){int i,j,x;char a;i = goto_char(status_p,instr_p);//规约出错if(i == -1)printf("\n===============规约出错!================\n"); //规约成功if(i == 12)printf("\n===============规约成功!================\n"); //移进动作if(i>=0 && i<=11){push(status_p,i);a = pop(instr_p);push(symbol_p,a);print(status_p,symbol_p,instr_p);action(status_p,symbol_p,instr_p);}//规约动作if(i>=21 && i<=26){x = r[i-21].y;for(j=0;j<x;j++){pop(status_p);pop(symbol_p);}push(instr_p,r[i-21].x);action(status_p,symbol_p,instr_p);}}int main(){char x;//分配空间status *status_p;symbol_instr *symbol_p,*instr_p ;status_p = (status *)malloc(sizeof(status));symbol_p = (symbol_instr *)malloc(sizeof(symbol_instr));instr_p = (symbol_instr *)malloc(sizeof(symbol_instr));//初始化各栈init_stack(status_p);init_stack(symbol_p);init_stack(instr_p);//压进栈初始元素push(status_p,0);//push(symbol_p,'#');////输入表达式printf("\n请输入要规约的输入串,各字符之间不能有空格,以'#'字符结束!\n"); printf("===========Expression =");//先将输入串压进符号栈do{scanf("%c",&x);push(symbol_p,x);}while(x != '#');//然后由符号栈弹出,压进输入栈while( symbol_p->top != 0){x = pop(symbol_p);push(instr_p,x);}printf("\n\n");//打印框架printf("\n状态栈==============符号栈==============输入串\n");print(status_p,symbol_p,instr_p);//打印初始分析表//移进,规约,并打印每一步分析过程action(status_p,symbol_p,instr_p);return 0;}程序测试截图:图(1)图(2)文档来源为:从网络收集整理.word版本可编辑.欢迎下载支持.图(3)经过各种不同的输入表达式进行测试,测试结果准确无误。

相关文档
最新文档