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语法分析程序,手动构造了识别所有活前缀的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)语法分析的实现)
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分析算法对一些数据集进行分类,并评估分类效果。
二、实验原理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语法分析实验报告
目录引言 (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(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");}。
语法分析-实验报告
《编译系统设计实践》实验项目二:语法分析指导老师:**组长:030902336组员:030902246030902335一、实验目的根据给出的文法编制LR(1)分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对LR(1)分析法的理解。
二、实验内容对已给语言文法,构造LR(1)分析表,编制语法分析程序,要求将错误信息输出到语法错误文件中,并输出分析句子的过程(显示栈的内容)。
三、程序设计与实现1.功能描述:根据给定的文法,由程序生成项集族和语法分析表,对输入的源程序进行词法分析,得到语法分析的输入串,经过语法分析后得到三个栈,它们分别是状态栈,字符栈,输入栈,从而分析出输入的源程序是否有语法错误。
2.重要过程描述:1)本实验有两个输入文件:一个为源代码输入文件“in_code.txt”,一个为文法的输入文件“in_gram.txt”,三个输出文件:一个为词法的输出和语法的输入文件“out_in.txt”,一个为项目集族和分析表的输出文件“out_items.txt”一个为语法分析结果的输出即栈的输出“result.txt”。
2) 重要数据结构:typedef struct production{//产生式char suf[25]; //搜索符char rear[30]; //产生式后部char front; //产生式头部unsigned point; //小圆点的位置short seq;}prod;typedef struct statement{//状态iprod p[50];//产生式int num; //产生式数量}state; typedef struct collection{/状态集state i[300];int num; //状态个数}coll;struct fstruct{ //first集char str[50];//first符号串int num;//first符号串字符个数bool blank;//是否包含空符号}firstx;short int anatab[300]34. 重要函数说明find(state &unclosure,int n)函数:功能:判断是否已包含某一产生式。
编译原理语法分析实验报告
编译原理语法分析实验报告一、实验目的本实验主要目的是学习和掌握编译原理中的语法分析方法,通过实验了解和实践LR(1)分析器的实现过程,并对比不同的文法对语法分析的影响。
二、实验内容1.实现一个LR(1)的语法分析器2.使用不同的文法进行语法分析3.对比不同文法对语法分析的影响三、实验原理1.背景知识LR(1)分析器是一种自底向上(bottom-up)的语法分析方法。
它使用一个分析栈(stack)和一个输入缓冲区(input buffer)来处理输入文本,并通过移进(shift)和规约(reduce)操作进行语法分析。
2.实验步骤1)构建文法的LR(1)分析表2)读取输入文本3)初始化分析栈和输入缓冲区4)根据分析表进行移进或规约操作,直至分析过程结束四、实验过程与结果1.实验环境本实验使用Python语言进行实现,使用了语法分析库ply来辅助实验。
2.实验步骤1)构建文法的LR(1)分析表通过给定的文法,根据LR(1)分析表的构造算法,构建出分析表。
2)实现LR(1)分析器使用Python语言实现LR(1)分析器,包括读取输入文本、初始化分析栈和输入缓冲区、根据分析表进行移进或规约操作等功能。
3)使用不同的文法进行语法分析选择不同的文法对编写的LR(1)分析器进行测试,观察语法分析的结果。
3.实验结果通过不同的测试案例,实验结果表明编写的LR(1)分析器能够正确地进行语法分析,能够识别出输入文本是否符合给定文法。
五、实验分析与总结1.实验分析本实验通过实现LR(1)分析器,对不同文法进行语法分析,通过实验结果可以观察到不同文法对语法分析的影响。
2.实验总结本实验主要学习和掌握了编译原理中的语法分析方法,了解了LR(1)分析器的实现过程,并通过实验提高了对语法分析的理解。
六、实验心得通过本次实验,我深入学习了编译原理中的语法分析方法,了解了LR(1)分析器的实现过程。
在实验过程中,我遇到了一些问题,但通过查阅资料和请教老师,最终解决了问题,并完成了实验。
实验5---语法分析器(自下而上):LR(1)分析法
实验5---语法分析器(自下而上):LR(1)分析法实验5---语法分析器(自下而上):LR(1)分析法一、实验目的构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。
二、实验内容程序输入/输出示例(以下仅供参考):对下列文法,用LR(1)分析法对任意输入的符号串进行分析:(1)E->E+T(2)E->E—T(3)T->T*F(4)T->T/F(5)F-> (E)(6)F->i输出的格式如下:(1)LR(1)分析程序,编制人:姓名,学号,班级(2)输入一个以#结束的符号串(包括+—*/()i#):在此位置输入符号串(3)输出过程如下:3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。
同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照。
三、实验方法1.实验采用C++程序语言进行设计,文法写入程序中,用户可以自定义输入语句;2.实验开发工具为DEV C++。
四、实验步骤1.定义LR(1)分析法实验设计思想及算法①若ACTION[sm , ai] = s则将s移进状态栈,并把输入符号加入符号栈,则三元式变成为:(s0s1…sm s , #X1X2…Xm ai , ai+1…an#);②若ACTION[sm , ai] = rj则将第j个产生式A->β进行归约。
此时三元式变为(s0s1…sm-r s , #X1X2…Xm-rA , aiai+1…an#);③若ACTION[sm , ai]为“接收”,则三元式不再变化,变化过程终止,宣布分析成功;④若ACTION[sm , ai]为“报错”,则三元式的变化过程终止,报告错误。
2.定义语法构造的代码,与主代码分离,写为头文件LR.h。
3.编写主程序利用上文描述算法实现本实验要求。
编译原理 实验报告实验三 语法分析(LR分析程序)
华北水利水电学院编译原理实验报告2012~2013学年第一学期2011 级计算机科学与技术专业班级:2011179 学号:2011179 姓名:一、实验题目:语法分析(LR分析程序)(1)选择最有代表性的语法分析方法LR分析法;(2)选择对各种常见程序语言都用的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析方法要比较贴切。
二、实验内容(1)根据给定文法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到文件);(2)根据算法和优先关系表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式文法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(4) 分析的句子为:(i+i)*i和i+i)*i三、根据以上文法构造出的LR(1)分析表为:四、程序源代using System;using System.Text;using System.IO;namespace Syntax_Analyzer{class Syntax{StreamReader myStreamReader;int t;int[] lengh;int l =0;string[] grammar;int s=0;string[] Word;int w=0;int[] wordNum ;int n =0;int[,] LR;public Syntax(){lengh = new int[7];grammar=new string[7];Word=new string[100];wordNum = new int[100];LR=new int[30,30];}public void analyzer(){//读入grammarSyntax myTextRead=new Syntax();Console.WriteLine("-----------------------------语法分析开始---------------------------------\n");//***************************//循环读取文法//***************************string strStart;strStart="grammar.txt";myTextRead.myStreamReader=new StreamReader(strStart);string strBufferStart;int uu=0;do{strBufferStart =myTextRead.myStreamReader.ReadLine();if(strBufferStart==null)break;foreach (String subString in strBufferStart.Split()){grammar[uu]=subString; //每行文法存入grammar[]uu++;}}while (strBufferStart!=null);myTextRead.myStreamReader.Close();//***************************//循环读取lengh//***************************strStart="lengh.txt";myTextRead.myStreamReader=new StreamReader(strStart);uu=0;do{strBufferStart =myTextRead.myStreamReader.ReadLine();if(strBufferStart==null)break;foreach (String subString in strBufferStart.Split()){lengh[uu]=Convert.ToInt32(subString); //每行文法存入grammar[]uu++;}}while (strBufferStart!=null);myTextRead.myStreamReader.Close();//****************************// 读入文件,进行语法分析////****************************string strReadFile;strReadFile="input.txt";myTextRead.myStreamReader=new StreamReader(strReadFile);string strBufferText;int wid =0;Console.WriteLine("分析读入程序(记号ID):\n");do{strBufferText =myTextRead.myStreamReader.ReadLine();if(strBufferText==null)break;foreach (String subString in strBufferText.Split()){if(subString!=""){int ll;if(subString!=null){ll= subString.Length; //每一个长度}else{break;}int a=ll+1;char[] b = new char[a];StringReader sr = new StringReader(subString);sr.Read(b, 0, ll); //把substring 读到char[]数组里int sort=(int)b[0];// word[i] 和wordNum[i]对应//先识别出一整个串,再根据开头识别是数字还是字母Word[wid]=subString;if(subString.Equals("+")){wordNum[wid]=0;}else{if(subString.Equals("*")){wordNum[wid]=1;}else{if(subString.Equals("(")){wordNum[wid]=2;}else{if(subString.Equals(")")){wordNum[wid]=3;}else{if(subString.Equals("i")){wordNum[wid]=4;}}}}}Console.Write(subString+"("+wordNum[wid]+")"+" ");wid++;}}Console.WriteLine("\n");}while (strBufferText!=null);wordNum[wid]=5;myTextRead.myStreamReader.Close();//*********************************//读入LR分析表////***********************************string strLR;strLR="LR-table.txt";myTextRead.myStreamReader=new StreamReader(strLR);string strBufferLR;int pp=0;do{strBufferLR =myTextRead.myStreamReader.ReadLine();if(strBufferLR==null)break;else{int j=0;foreach (String subString in strBufferLR.Split()){if(subString!=null){int lllr=Convert.ToInt16(subString);LR[pp,j]=lllr; //把行与列读入数组j++;}}}pp++;}while (strBufferLR!=null);myTextRead.myStreamReader.Close();int[] state = new int[100];string[] symbol =new string[100];state[0]=0;symbol[0]="#";int p1=0;int p2=0;Console.WriteLine("\n按文法规则归约顺序如下:\n");//***************//归约算法//***************while(true){int j,k;j=state[p2];k=wordNum[p1];t=LR[j,k]; //当出现t为的时候if(t==0){//错误类型string error = "" ;if (k == 0)error = "+";elseif (k == 1)error = "*";elseif (k == 2)error = "(";elseif (k == 3)error = ")";elseif (k == 4)error = "i";elseerror = " 其它错误!";Console.WriteLine("\n检测结果:");Console.WriteLine("代码中存在语法错误");Console.WriteLine("错误状况:错误状态编号为"+j+" 读头下符号为"+error);break;}else{if(t==-100) //-100为达到接受状态{Console.WriteLine("\n");Console.WriteLine("\n检测结果:");Console.WriteLine("代码通过语法检测");break;}if(t<0&&t!=-100) //归约{string m=grammar[-t];Console.Write(m+" "); //输出开始符int length=lengh[-t];p2=p2-(length-1);Search mySearch=new Search();int right=mySearch.search(m);if(right==0){Console.WriteLine("\n");Console.WriteLine("代码中有语法错误");break;}int a=state[p2-1];int LRresult= LR[a,right];state[p2]=LRresult;symbol[p2]=m;}if(t>0){p2=p2+1;state[p2]=t;symbol[p2]=Convert.ToString(wordNum[p1]);p1=p1+1;}}}myTextRead.myStreamReader.Close();Console.WriteLine("-----------------------------语法分析结束---------------------------------\n");Console.Read();}}class Search{public int search(string x){string[] mysymbol=new string[3];mysymbol[0]="E";mysymbol[1]="T";mysymbol[2]="F";int r = 0;for(int s=0;s<=2;s++){if(mysymbol[s].Equals(x))r=s+6 ;}return r;}}}五、测试结果输入”( i + i ) * i”字符串,分析如下图所示输入”i + i ”字符串,分析如下图所示六、小结(包括收获、心得体会、存在的问题及解决问题的方法、建议等)本次实验是LR分析法,LR分析法是一种有效的自上而下分析技术,在自左向右扫描输入串时就能发现其中的任何错误。
编译原理-LR语法分析器的控制程序实验报告
编译原理实验报告学号姓名时间专业班级实验题目:LR语法分析器的控制程序实验目的:手工模拟控制程序计算,对源程序进行LR 语法分析主要是分析表的构造实验内容与步骤:1.将要进行LR 语法分析的源程序和LR 语法分析器控制程序放在同一文件夹中。
2.用 C 语言编写 LR 语法分析器控制程序,程序代码如下:#include <fstream.h>#include <iostream.h>#include <stdlib.h>#include <string.h>struct code_val{char code;char val[20];};const char *p[]={//产生式"S→ E","E → E+T","E → T","T → T*F","T → F","F → (E)","F → i"};const char TNT[ ]="+*()i#ETF";//LR 分析表列的字符const int M[][9]={//LR 分析表数字化,列字符 +*()i#ETF用数字 012345678 标识。
{ 0, 0, 4, 0, 5,0, 1, 2, 3},//0 表示出错, s4 用 4 表示。
{ 6, 0, 0, 0, 0,99},//Acc 用 99 表示{-2, 7, 0,-2, 0,-2},//r2 用 -2 表示{-4,-4, 0,-4, 0,-4},{ 0, 0, 4, 0, 5, 0, 8, 2, 3},{-6,-6, 0,-6, 0,-6}, { 0, 0,4, 0, 5, 0, 0, 9, 3},{ 0, 0, 4, 0, 5, 0, 0, 0,10},{ 6, 0, 0,11},{-1, 7, 0,-1, 0,-1},{-3,-3, 0,-3, 0,-3},{-5,-5, 0,-5, 0,-5}};int col(char);void main(){//列定位函数原型int state[50]={0};//状态栈初值char symbol[50]={'#'};//符号栈初值int top=0;//栈顶指针初值ofstream cout("par_r.txt");//语法分析结果输出至文件par_r.txtifstream cin("lex_r.txt");// lex_r.txt 存放词法分析结果,语法分析器从该文件输入数据。
北邮编译原理实验 LR语法分析 实验报告
LR语法分析实验报告班级:2010211308 姓名:杨娜学号:10211369一.题目:LR语法分析程序的设计与实现二.设计目的:(1)了解语法分析器的生成工具和编译器的设计。
(2)了解自上而下语法分析器的构造过程。
(3). 理解和掌握LR语法分析方法的基本原理;根据给出的LR)文法,掌握LR分析表的构造及分析过程的实现。
(4)掌握预测分析程序如何使用分析表和栈联合控制实现LR分析。
三.实验内容:编写语法分析程序,实现对算术表达式的语法分析,要求所分析算数表达式由如下的文法产生:E->E+T|E-T|TT->T/F|T*F|FF->i|n|(E)四.实验要求:编写LR语法分析程序,要求如下:(1)构造识别所有活动的DFA(2)构造LR分析表(3)编程实现算法4.3,构造LR分析程序五.算法流程分析程序可分为如下几步:六.算法设计1.数据结构s :文法开始符号line :产生式的个数G[i][0] :产生式的标号Vt[] :终结符Vn[] :非终结符id :项目集编号Prjt *next :指示下一个项目集Prjt[]:存储项目的编号,prjt[0]项目编号的个数Pointafter[] :圆点后的字符,pointafter[0]为字符个数Prjset*actorgo[]:存储出度Pointbefore:圆点前面的字符Form:动态数组下标,同时作为符号的编号Vn[] :非终结符序列Vt[]:终结符序列2.LR分析器由三个部分组成(1)总控程序,也可以称为驱动程序。
对所有的LR分析器总控程序都是相同的。
(2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
(3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
分析器的动作就是由栈顶状态和当前输入符号所决定。
编译原理-LR语法分析器的控制程序实验报告
编译原理实验报告实验目的:手工模拟控制程序计算,对源程序进行LR 语法分析 主要是分析表的构造实验内容与步骤:1•将要进行LR 语法分析的源程序和LR 语法分析器控制程序放在同一文件夹 中。
2.用C 语言编写LR 语法分析器控制程序,程序代码如下:#in elude <fstream.h> #in clude <iostream.h> #i nclude <stdlib.h> #in clude <stri ng.h> struct code_val{char code;char val[20]; };con st char *p[]={// 产生式"S T E","E T E+T","E T T","T T T*F","T T F","F T (E)","F T i };const char TNT[ ]="+*()i#ETF"; con st int M[][9]={{ 0, 0, 4, 0, 5,0, 1,2, 3}, { 6, 0, 0, 0, 0,99}, {-2, 7, 0,-2, 0,-2}, {-4,-4, 0,-4, 0,-4}, { 0, 0, 4, 0, 5, 0, 8, 2, 3}, {-6,-6, 0,-6, 0,-6},{ 0, 0, 4, 0, 5, 0, 0, 9, 3}, { 0, 0, 4, 0, 5, 0, 0, 0,10}, { 6, 0, 0,11}, {-1,7, 0,-1,0,-1}, {-3,-3, 0,-3, 0,-3}, {-5,-5, 0,-5, 0,-5} };//LR 分析表列的字符//LR 分析表数字化,列字符 +*()i#ETF 用数字012345678标识。
LR(1)实验报告
编译原理LR(1)语法分析09计算机(2)班组员:张清风030902233刘冰静030902241郑珊珊030902245郭俊杰030902206实验二:语法分析实验I. 【实验目的】根据给出的文法编制LR(1)分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对LR(1)分析法的理解。
Ⅱ.【实验内容】对所给语言文法,构造LR(1)分析表,编制语法分析程序,要求将错误信息输出到语法错误文件中,并输出分析句子的过程(显示栈的内容);实验报告必须包括采用的文法,设计的思路,LR(1)分析表,以及测试报告(输入测试例子,输出结果),设计的体会。
III.【要求的文法内容】i. 设计简要描述LR(1)分析表的构建:1、调整后的文法计非终结符的first集:2、项目集的构建(部分展示总共有157个):3、语法分析输出Action表:(总共有157项):4、语法分析goto表:PS:部分展示ii :设计思路:1、先是进行文法的整理;采用数组的方式对文法进行存储,还有做好相关的标识;2、构建LR(1)语法分析器,首先需要求得各个非终结first集,以便后期采用到根据搜索符进行规约判断。
3、通过分析所存储文法的数组以及相关的first集的相关标识数组,进行构建项目集。
整合语法分析表。
包括action表和goto表。
4、结合词法分析器得到所语法分析的输入词素,根据所构建的分析表,进行自底向上的语法分析。
5、规约得到“Accept”!iii. 详细设计描述项目构架:iv. 结果分析(原始图示)测试的源代码:实验结果:(部分截图)V.具体分析:(部分代码展示)变量:/*first集,first[α][b]为真表示b在first(α)集中*/bool first[200][200];int GOTO[300][300];struct action_node{ int v;int op;/*1移入2规约3接受*/ } ACTION[300][300];/*终结符/非终结符与编号映射增广S'编号为0*/ map<string,int>str_map; string strs[1000];int str_cnt = 0;/*文法A->αβγ...*/int G[100][100];int G_len[100],G_rows;int G_type[1000];/*1 非终结符2 终结符0其他*/ int vt_list[1000],vt_cnt;int vn_list[1000],vn_cnt;/*项[A->α·Bβ,a]*/struct item_node{ int gram_id;/*第几行文法0开始*/int dot;/*原点在第几个符号前面0开始*/int ahead_id; /*向前看符号*/bool operator ==(const item_node &b)const{return gram_id == b.gram_id && dot == b.dot && ahead_id == b.ahead_id; } }; /*项集*/struct itemset_node{item_node list[100];int added[100][100];int length;}C[300];int C_cnt = 0;/*项集族*/struct items_node{itemset_node I[100]; };Main函数:int main(){ ifstream ifile,ifile1;ofstream ofile,ofile2,ofile3;ifile.open("语法输入_文法表示.txt");read_G(ifile);get_first();ofile.open("语法输出_项集族.txt");ofile2.open("语法输出_GOTO表.txt");ofile3.open("语法输出_ACTION 表.txt");get_items(ofile,ofile2,ofile3);ifile1.open("语法输入_词素列表.txt");go(ifile1);scanf(" ");}/*读入文法*/void read_G(ifstream &ifile){int str_id = 0;string str;str_map.clear();memset(G_type,0,sizeof(G_type));vt_list[0] = 2;vt_cnt = 1;/*增广文法*/strs[0] = "<S'>"; /* 增广S'*/strs[1] = "<$>"; /* 结束$ */strs[2] = "<ε>"; /* 空ε*/str_map["<$>"] = 1; str_map["<#>"] = 2;str_cnt = 2;G[0][0] = 0;/*S' -> S*/G[0][1] = str_cnt+1;G_len[0] = 2;G_rows = 1;while(ifile >> str){if((str_id = str_map[str]) == 0){str_id = str_map[str] = ++str_cnt;strs[str_cnt] = str;G_type[str_id] = 1; /*非终结符*/vn_list[ vn_cnt++ ] = str_id; } G[ G_rows ][0] = str_id;G_len[ G_rows ] = 1;ifile >> str;while(ifile >> str){if(str == "<$>")break;if((str_id = str_map[str]) == 0){str_id = str_map[str] = ++str_cnt;strs[str_cnt] = str;if(str != "<>" && str[0] == '<' && str[str.length()-1] == '>'){G_type[str_id] = 1; /*非终结符*/vn_list[ vn_cnt++ ] = str_id; } else{G_type[str_id] = 2; /*终结符*/vt_list[ vt_cnt++ ] = str_id; } }G[ G_rows ][ G_len[G_rows]++ ] = str_id;}G_rows++; }cout<<"输入语法:"<<endl;for(int i=0;i<G_rows;i++){cout<<strs[G[i][0]]<<" -> ";for(int j=1;j<G_len[i];j++){cout<<strs[G[i][j]]<<" ";}cout<<endl;}}/*获取first集*/void get_first(){bool flag1 = true, flag2;int i, j, k, x, y;memset(first, 0, sizeof(first));while(flag1){ flag1 = false;for(i = 0; i < G_rows; i++){ x = G[i][0];for(j = 1, flag2 = true; flag2 && j < G_len[i]; j++) {flag2 = false; y = G[i][j];if(G_type[y] == 1)/* 如果是非终结符*/{for(k = 0;k < vt_cnt;k++)if(vt_list[k]!=2&&first[y][vt_list[k]]== true && first[x][vt_list[k]] ==false){first[x][vt_list[k]] = true;flag1 = true; }if(first[y][2]){flag2 = true; }}else if(first[x][y] == false){/* 如果第一个是终结符,加入first[x]集*/first[x][y] = true; flag1 = true;} }/*如果first[Y]都含有ε,将ε加入first[x]集*/if(flag2 == true && j == G_len[i]&& first[x][2] == false){ first[x][2] = true; flag1 =true; } }/*在屏幕上打印输出first集*/cout<<endl<<"非终结符first集:"<<endl;。
编译实验语法分析
语法分析器实验报告院系:专业:小组成员:学号:日期:一、实验目的根据给出的文法编制LR(1)分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对LR(1)分析法的理解。
二、实验内容对已给语言文法,构造LR(1)分析表,编制语法分析程序,要求将错误信息输出到语法错误文件中,并输出分析句子的过程(显示栈的内容)LR(1)分析法的功能:LR(1)分析法的功能是利用LR(1)分析表,对输入符号串自下而上的分析过程。
LR(1)分析表的构造及分析过程。
三.实验文法<program> ::= <block> .<block> ::= <const-decl> <var-decl> <proc-decl> <statement><const-decl> ::= const <const-assignment-list> ; | ε<const-assignment-list> ::= <ident> = <number>| <const-assignment-list> , <ident> = <number><var-decl> ::= var <ident-list> ; |ε<ident-list> ::= <ident> | <ident-list> , <ident><proc-decl> ::= <proc-decl> procedure <ident> ; <block> ; |ε<statement> ::= <ident> := <expression>| call <ident>| begin <statement-list> end| if <condition> then <statement>| while <condition> do <statement>|ε<statement-list> ::= <statement> | <statement-list> ; <statement><condition> ::= odd <expression> | <expression> <relation> <expression><relation> ::= = | <> | < | > | <= | >=<expression> ::= <term> | <adding-operator> <term>| <expression> <adding-operator> <term><adding-operator> ::= + | -<term> ::= <factor> | <term> <multiplying-operator> <factor><multiplying-operator> ::= * | /<factor> ::= <ident> | <number> | ( <expression> )注意:(1) "ε" 表示空串。
LR0语法分析器
西安邮电大学(计算机学院)课内实验报告实验名称:LR(0)语法分析器专业名称:计算机科学与技术班级:计科1304学生姓名:裴世宇学号(8位):04131132(12)指导教师:陈燕实验日期:2016年05月15日一、实验目的. 1.巩固对语法分析的基本功能和原理的认识。
2.通过对语法分析表的自动生成加深语法分析表的认识。
3.理解并处理语法分析中的异常和错误。
二、实验环境VC++6.0Windows 7三、实验内容大多数用上下文无关文法描述的程序语言都可用LR分析器予以识别。
LR分析法比算符优先分析法或其他的“移进-规约”技术更加广泛,而且分析效率并不比他们差。
规范规约的关键问题是寻找句柄。
一个LR分析器实质上是一个带先进后出的存储器(栈)点确定有限状态自动机。
1.通过设计、编制、陶氏一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。
2.选择对各种常见程序语言都用的语法结构,如赋值语句(尤其是表达式)作为分析对象,并且与所选语法分析方法要比较贴切。
四、实验功能LR分析器实质上是一个带先进后出存储器(栈)的确定有限状态自动机。
我们将把“历史”和“展望”材料综合地抽象成某些“状态”。
我们把栈的结构看成是:LR分析器模型LR分析器的核心部分是一张分析表。
这张分析表包括两部分,意识“动作”(ACTION)表,另一个是“状态转换”(GOTO)表。
他们都是二维数组。
ACTION[ s , a ]规定了当状态s面临符号a时应采取什么动作。
GOTO[ s ,X ]规定了状态。
面对文法符号X(终结符或非终结符)时下一个状态是什么。
显然,GOTO[s,X]定义了一个以文法符号为字母表的DFA。
对于任一文法G[S],若S’αAωαβω,若γ是αβ的前缀,则称γ是G的一个活前缀。
活前缀与句柄的关系:①活前缀已含有句柄的全部符号,表明产生式A→β的右部β已出现在栈顶。
LR0语法分析报告
《编译原理》课程实验报告题目语法分析专业班级学号姓名指导教师南京理工大学计算机学院2010年6月实验2:语法分析一、实验目的1.巩固对语法分析的基本功能和原理的认识。
2.通过对语法分析表的自动生成加深语法分析表的认识。
3.理解并处理语法分析中的异常和错误。
二、实验内容(1)掌握语法分析程序的总体框架,并将其实现。
(2) 在手工构造的文法的基础上实现LR(1)分析,给出其语法分析表的生成程序及其数据结构和查找算法。
分析表生成程序:char* StackStateToString(int stackLen,int *stateStack){int i;char pstr[5];char *kunchar=new char[256];kunchar[0]=0;for(i=0;i<stackLen;i++){itoa(stateStack[i],pstr,10);if(strlen(pstr)>1){strcat(kunchar,"(");strcat(kunchar,pstr);strcat(kunchar,")");}else{strcat(kunchar,pstr);}}return kunchar;}void initial(){int i;actionTable[0][0].doWhat='S';actionTable[0][0].number=2;actionTable[1][5].doWhat='A';。
actionTable[10][5].doWhat='r';actionTable[10][5].number=2;actionTable[11][5].doWhat='r';actionTable[11][5].number=4;GoTo[0][0]=1;GoTo[2][1]=4;GoTo[3][1]=6;}数据结构相对简单,利用二维数组存放当前状态下的Action和Goto字符查找算法:char* ActionToString(Action nowAction){char *pstr=new char[20];pstr[0]=0;char temp[4];if(nowAction.doWhat=='A')strcat(pstr,"Acc");else if(nowAction.doWhat=='S'||nowAction.doWhat=='R'){pstr[0]=nowAction.doWhat;pstr[1]=0;itoa(nowAction.number,temp,10);strcat(pstr,temp);}return pstr;}char* GotoToString(int goTo){char *temp=new char[4];temp[0]=0;if(goTo>0)itoa(goTo,temp,10);return temp;}(3)给出错误处理方法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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)经过各种不同的输入表达式进行测试,测试结果准确无误。