编译原理实验报告材料(预测分析报告表方法)

合集下载

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。

二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。

三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。

在本次实验中,我们使用有限自动机的理论来设计词法分析器。

首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。

然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。

在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。

(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。

在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。

首先,我们根据给定的语法规则,编写了相应的递归函数。

每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。

在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。

(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。

在本次实验中,我们使用了四元式作为中间代码的表示形式。

在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。

同时,根据语法树的结构,生成相应的四元式中间代码。

(四)代码优化代码优化的目的是提高生成代码的质量和效率。

在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。

通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。

编译原理语法分析实验报告

编译原理语法分析实验报告

编译原理语法分析实验报告第一篇:编译原理语法分析实验报告实验2:语法分析1.实验题目和要求题目:语法分析程序的设计与实现。

实验内容:编写语法分析程序,实现对算术表达式的语法分析。

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

E→E+T|E-T|TT→T*F|T/F|F F→id|(E)|num实验要求:在对输入表达式进行分析的过程中,输出所采用的产生式。

方法1:编写递归调用程序实现自顶向下的分析。

方法2:编写LL(1)语法分析程序,要求如下。

(1)编程实现算法4.2,为给定文法自动构造预测分析表。

(2)编程实现算法4.1,构造LL(1)预测分析程序。

方法3:编写语法分析程序实现自底向上的分析,要求如下。

(1)构造识别所有活前缀的DFA。

(2)构造LR分析表。

(3)编程实现算法4.3,构造LR分析程序。

方法4:利用YACC自动生成语法分析程序,调用LEX自动生成的词法分析程序。

实现(采用方法1)1.1.步骤:1)对文法消除左递归E→TE'E'→+TE'|-TE'|εT→FT'T'→*FT'|/FT'|εF→id|(E)|num2)画出状态转换图化简得:3)源程序在程序中I表示id N表示num1.2.例子:a)例子1 输入:I+(N*N)输出:b)例子2 输入:I-NN 输出:第二篇:编译原理实验报告编译原理实验报告报告完成日期 2018.5.30一.组内分工与贡献介绍二.系统功能概述;我们使用了自动生成系统来完成我们的实验内容。

我们设计的系统在完成了实验基本要求的前提下,进行了一部分的扩展。

增加了声明变量类型、类型赋值判定和声明的变量被引用时作用域的判断。

从而使得我们的实验结果呈现的更加清晰和易懂。

三.分系统报告;一、词法分析子系统词法的正规式:标识符(|)* 十进制整数0 |(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)* 八进制整数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)* 十六进制整数0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)* 运算符和分隔符 +| * | / | > | < | = |(|)| <=|>=|==;对于标识符和关键字: A5—〉 B5C5 B5—〉a | b |⋯⋯| y | z C5—〉(a | b |⋯⋯| y | z |0|1|2|3|4|5|6|7|8|9)C5|ε综上正规文法为: S—〉I1|I2|I3|A4|A5 I1—〉0|A1 A1—〉B1C1|ε C1—〉E1D1|ε D1—〉E1C1|εE1—〉0|1|2|3|4|5|6|7|8|9 B1—〉1|2|3|4|5|6|7|8|9 I2—〉0A2 A2—〉0|B2 B2—〉C2D2 D2—〉F2E2|ε E2—〉F2D2|εC2—〉1|2|3|4|5|6|7 F2—〉0|1|2|3|4|5|6|7 I3—〉0xA3 A3—〉B3C3 B3—〉0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f C3—〉(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)|C3|εA4—〉+ |-| * | / | > | < | = |(|)| <=|>=|==; A5—〉 B5C5 B5—〉a | b |⋯⋯| y | z C5—〉(a | b |⋯⋯| y | z |0|1|2|3|4|5|6|7|8|9)C5|ε状态图流程图:词法分析程序的主要数据结构与算法考虑到报告的整洁性和整体观感,此处我们仅展示主要的程序代码和算法,具体的全部代码将在整体的压缩包中一并呈现另外我们考虑到后续实验中,如果在bison语法树生成的时候推不出目标的产生式时,我们设计了报错提示,在这个词的位置出现错误提示,将记录切割出来的词在code.txt中保存,并记录他们的位置。

编译原理实验报告材料LL(1)分析报告法84481

编译原理实验报告材料LL(1)分析报告法84481

课程编译原理实验名称实验二 LL(1)分析法实验目的1.掌握LL(1)分析法的基本原理;2.掌握LL(1)分析表的构造方法;3.掌握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#),如:i+i*i#。

输出过程如下:步骤分析栈剩余输入串所用产生式1 E i+i*i# E->TG... ... ... ...二.实验过程及结果代码如下:#include<iostream>#include "edge.h"using namespace std;edge::edge(){cin>>left>>right;rlen=right.length();if(NODE.find(left)>NODE.length())NODE+=left;}string edge::getlf(){return left;}string edge::getrg(){return right;}string edge::getfirst(){return first;}string edge::getfollow(){return follow;}string edge::getselect(){return select;}string edge::getro(){string str;str+=right[0];return str;}int edge::getrlen(){return right.length();}void edge::newfirst(string w){int i;for(i=0;i<w.length();i++)if(first.find(w[i])>first.length())first+=w[i];}void edge::newfollow(string w){int i;for(i=0;i<w.length();i++)if(follow.find(w[i])>follow.length()&&w[i]!='@')follow+=w[i];}void edge::newselect(string w){int i;for(i=0;i<w.length();i++)if(select.find(w[i])>select.length()&&w[i]!='@') select+=w[i];}void edge::delfirst(){int i=first.find('@');first.erase(i,1);}int SUM;string NODE,ENODE;//计算firstvoid first(edge ni,edge *n,int x){int i,j;for(j=0;j<SUM;j++){if(ni.getlf()==n[j].getlf()){if(NODE.find(n[j].getro())<NODE.length()){for(i=0;i<SUM;i++)if(n[i].getlf()==n[j].getro())first(n[i],n,x);}elsen[x].newfirst(n[j].getro());}}}//计算followvoid follow(edge ni,edge *n,int x){int i,j,k,s;string str;for(i=0;i<ni.getrlen();i++){s=NODE.find(ni.getrg()[i]);if(s<NODE.length()&&s>-1) //是非终结符if(i<ni.getrlen()-1) //不在最右for(j=0;j<SUM;j++)if(n[j].getlf().find(ni.getrg()[i])==0){if(NODE.find(ni.getrg()[i+1])<NODE.length()){for(k=0;k<SUM;k++)if(n[k].getlf().find(ni.getrg()[i+1])==0){n[j].newfollow(n[k].getfirst());if(n[k].getfirst().find("@")<n[k].getfirst().length())n[j].newfollow(ni.getfollow());}}else{str.erase();str+=ni.getrg()[i+1];n[j].newfollow(str);}}}}//计算selectvoid select(edge &ni,edge *n){int i,j;if(ENODE.find(ni.getro())<ENODE.length()){ni.newselect(ni.getro());if(ni.getro()=="@")ni.newselect(ni.getfollow());}elsefor(i=0;i<ni.getrlen();i++){for(j=0;j<SUM;j++)if(ni.getrg()[i]==n[j].getlf()[0]){ni.newselect(n[j].getfirst());if(n[j].getfirst().find('@')>n[j].getfirst().length())return;}}}//输出集合void out(string p){int i;if(p.length()==0)return;cout<<"{";for(i=0;i<p.length()-1;i++){cout<<p[i]<<",";}cout<<p[i]<<"}";}//连续输出符号void outfu(int a,string c){int i;for(i=0;i<a;i++)cout<<c;}//输出预测分析表void outgraph(edge *n,string (*yc)[50]){int i,j,k;bool flag;for(i=0;i<ENODE.length();i++){if(ENODE[i]!='@'){outfu(10," ");cout<<ENODE[i];}}outfu(10," ");cout<<"#"<<endl;int x;for(i=0;i<NODE.length();i++){outfu(4," ");cout<<NODE[i];outfu(5," ");for(k=0;k<ENODE.length();k++){flag=1;for(j=0;j<SUM;j++){if(NODE[i]==n[j].getlf()[0]){x=n[j].getselect().find(ENODE[k]);if(x<n[j].getselect().length()&&x>-1){cout<<"->"<<n[j].getrg();yc[i][k]=n[j].getrg();outfu(9-n[j].getrlen()," ");flag=0;}x=n[j].getselect().find('#');if(k==ENODE.length()-1&&x<n[j].getselect().length()&&x>-1){cout<<"->"<<n[j].getrg();yc[i][j]=n[j].getrg();}}}if(flag&&ENODE[k]!='@')outfu(11," ");}cout<<endl;}}//分析符号串int pipei(string &chuan,string &fenxi,string (*yc)[50],int &b) {char ch,a;int x,i,j,k;b++;cout<<endl<<" "<<b;if(b>9)outfu(8," ");elseoutfu(9," ");cout<<fenxi;outfu(26-chuan.length()-fenxi.length()," "); cout<<chuan;outfu(10," ");a=chuan[0];ch=fenxi[fenxi.length()-1];x=ENODE.find(ch);if(x<ENODE.length()&&x>-1){if(ch==a){fenxi.erase(fenxi.length()-1,1);chuan.erase(0,1);cout<<"'"<<a<<"'匹配";if(pipei(chuan,fenxi,yc,b))return 1;elsereturn 0;}elsereturn 0;}else{if(ch=='#'){if(ch==a){cout<<"分析成功"<<endl;return 1;}elsereturn 0;}elseif(ch=='@'){fenxi.erase(fenxi.length()-1,1);if(pipei(chuan,fenxi,yc,b))return 1;elsereturn 0;}else{i=NODE.find(ch);if(a=='#'){x=ENODE.find('@');if(x<ENODE.length()&&x>-1)j=ENODE.length()-1;elsej=ENODE.length();}elsej=ENODE.find(a);if(yc[i][j].length()){cout<<NODE[i]<<"->"<<yc[i][j];fenxi.erase(fenxi.length()-1,1);for(k=yc[i][j].length()-1;k>-1;k--)if(yc[i][j][k]!='@')fenxi+=yc[i][j][k];if(pipei(chuan,fenxi,yc,b))return 1;elsereturn 0;}elsereturn 0;}}}void main(){edge *n;string str,(*yc)[50];int i,j,k;bool flag=0;cout<<"请输入上下文无关文法的总规则数:"<<endl;cin>>SUM;cout<<"请输入具体规则(格式:左部右部,@为空):"<<endl;n=new edge[SUM];for(i=0;i<SUM;i++)for(j=0;j<n[i].getrlen();j++){str=n[i].getrg();if(NODE.find(str[j])>NODE.length()&&ENODE.find(str[j])>ENODE.length()) ENODE+=str[j];}//计算first集合for(i=0;i<SUM;i++){first(n[i],n,i);}//outfu(10,"~*~");cout<<endl;for(i=0;i<SUM;i++)if(n[i].getfirst().find("@")<n[i].getfirst().length()){if(NODE.find(n[i].getro())<NODE.length()){for(k=1;k<n[i].getrlen();k++){if(NODE.find(n[i].getrg()[k])<NODE.length()){for(j=0;j<SUM;j++){if(n[i].getrg()[k]==n[j].getlf()[0]){n[i].newfirst(n[j].getfirst());break;}}if(n[j].getfirst().find("@")>n[j].getfirst().length()){n[i].delfirst();break;}}}}}//计算follow集合for(k=0;k<SUM;k++){for(i=0;i<SUM;i++){if(n[i].getlf()==n[0].getlf())n[i].newfollow("#");follow(n[i],n,i);}for(i=0;i<SUM;i++){for(j=0;j<SUM;j++)if(n[j].getrg().find(n[i].getlf())==n[j].getrlen()-1)n[i].newfollow(n[j].getfollow());}}//计算select集合for(i=0;i<SUM;i++){select(n[i],n);}for(i=0;i<NODE.length();i++){str.erase();for(j=0;j<SUM;j++)if(n[j].getlf()[0]==NODE[i]){if(!str.length())str=n[j].getselect();else{for(k=0;k<n[j].getselect().length();k++)if(str.find(n[j].getselect()[k])<str.length()){flag=1;break;}}}}//输出cout<<endl<<"非终结符";outfu(SUM," ");cout<<"First";outfu(SUM," ");cout<<"Follow"<<endl;outfu(5+SUM,"-*-");cout<<endl;for(i=0;i<NODE.length();i++){for(j=0;j<SUM;j++)if(NODE[i]==n[j].getlf()[0]){outfu(3," ");cout<<NODE[i];outfu(SUM+4," ");out(n[j].getfirst());outfu(SUM+4-2*n[j].getfirst().length()," ");out(n[j].getfollow());cout<<endl;break;}}outfu(5+SUM,"-*-");cout<<endl<<"判定结论: ";if(flag){cout<<"该文法不是LL(1)文法!"<<endl;return;}else{cout<<"该文法是LL(1)文法!"<<endl;}//输出预测分析表cout<<endl<<"预测分析表如下:"<<endl;yc=new string[NODE.length()][50];outgraph(n,yc);string chuan,fenxi,fchuan;cout<<endl<<"请输入符号串:";cin>>chuan;fchuan=chuan;fenxi="#";fenxi+=NODE[0];i=0;cout<<endl<<"预测分析过程如下:"<<endl;cout<<"步骤";outfu(7," ");cout<<"分析栈";outfu(10," ");cout<<"剩余输入串";outfu(8," ");cout<<"推导所用产生式或匹配";if(pipei(chuan,fenxi,yc,i))cout<<endl<<"输入串"<<fchuan<<"是该文法的句子!"<<endl;elsecout<<endl<<"输入串"<<fchuan<<"不是该文法的句子!"<<endl;}截屏如下:三.实验中的问题及心得这次实验让我更加熟悉了LL(1)的工作流程以及LL(1)分析表的构造方法。

编译原理预测分析法实验报告

编译原理预测分析法实验报告

编译原理实验预测分析法姓名**学号**班级**完成日期**1.实验目的加深对语法分析器工作过程的理解;加强对预测分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。

2.实验要求1.对语法规则有明确的定义;2.编写的分析程序能够对实验一的结果进行正确的语法分析;3. 3.对于遇到的语法错误, 能够做出简单的错误处理, 给出简单的错误提示, 保证顺利完成语法分析过程;4. 4.实验报告要求用文法的形式对语法定义做出详细说明, 说明语法分析程序的工作过程, 说明错误处理的实现。

5.实验原理对文法G进行语法分析, 文法G如下所示:*0. S→a */*1. S→.*2. S→(T)*3. T→SW **4..W→,S.*5. W→ε;6.软件设计与编程#include <stdio.h>#include <stdlib.h>#include <string.h>char str[100]; //存储待分析的句子const char T[ ] = "a^(),#"; //终结符, 分析表的列符const char NT[ ] = "STW"; //非终结符, 分析表的行符/*指向产生式右部符号串*/const char *p[] = {/*0. S→a */ "a",/*1.. S→. *. "^",/*2. S→(T) */ "(T)",/*3. T→SW */ "SW",/*4.. W→,S. */ ",SW",/*5. W→ε; */ ""};//设M[i][j]=x, 通过p[M[i][j]]=p[x]获取右部符号串。

const int M[][6] = {/* a ^ ( ) , # *//*S*/ { 0, 1, 2, -1, -1, -1 },/*T*/ { 3, 3, 3, -1, -1, -1 },/*W*/ { -1, -1,-1, 5, 4, -1 }};void init()//输入待分析的句子{printf("请输入待分析的句子(以$结束): \n");scanf("%s",str);}int lin(char c);//非终结符转换为行号int col(char c);//终结转换为列号bool isNT(char c);//isNT判断是否是非终结符bool isT(char c);//isT判断是否是终结符。

编译原理预测分析实验报告

编译原理预测分析实验报告

编译原理实验报告实验题目:预测分析法学院:计算机与通信工程学院专业班级:计算机科学与技术08—2班姓名:学号:预测分析法一、实验目的二、实验要求1、通过该课程设计要学会用消除左递归的方法来使文法满足进行确定自顶向下分析的条件。

2、学会用C/C++高级程序设计语言来设计一个LL(1)分析法的语法分析器;3、通过该课程设计,加深对语法分析理论的理解,培养动手实践的能力。

三、实验代码:#include <stdio.h>#include <tchar.h>#include <string.h>int main(int argc, char* argv[]){char syn[15]; //语法栈int top; //栈顶指针char lookahead; //当前单词char exp[50]; //表达式区int m =0; //表达式指针char s[4][5]={"d","+","*","("}; //表中有空白的符号char string[3]={'E','T','F'}; //表中有同步记号的的非终结符int ll1[7][6]={{1,0,0,1,9,9}, //LL(1)分析表,9表示同步记号,第6行是#,第7行是){0,2,0,0,3,3},{4,9,0,4,9,9},{0,6,5,0,6,6},{8,9,9,7,9,9},{12,12,12,12,12,10},{13,13,13,13,11,13}};int i,j; //表行和列int code; //表项printf("************************语法分析器**********************\n");printf("请输入合法字符串:\n");scanf("%s",exp);top=1;lookahead=exp[m++];syn[0]='#';syn[1]='E';printf("***********************预测分析表*********************\n"); printf("\ti\t *\t +\t (\t )\t #\n");printf(" E\tE—>TE'\t\t\tE—>TE'\n");printf(" E'\t\t\tE'—>+TE'\t E'—>ε\n");printf(" T\tT—>FT'\t\t\tT—>FT'\t\n");printf(" T'\t\tT'—>*FT'\t\t T'—>ε\t\n");printf(" F\tF—>d\t\t\tF—>(E)\n\n");printf("调用规则顺序:\n");while(1){switch(syn[top]) //行{case 'E':i=0;break;case 'e':i=1;break;case 'T':i=2;break;case 't':i=3;break;case 'F':i=4;break;case '#':i=5;break;case ')':i=6;break;}switch(lookahead) //列{case 'd':j=0;break;case '+':j=1;break;case '*':j=2;break;case '(':j=3;break;case ')':j=4;break;case '#':j=5;break;}code=ll1[i][j];if(code==10){ printf("语法分析结束\n");// break;}else{switch(code){case 0:{// printf("出错,用户多输入了%s,跳过%s\n",s[j],s[j]);if(j==0){//lookahead=exp[m++];lookahead=exp[m++];}elselookahead=exp[m++];break;}case 1:{printf("E →TE′\n");syn[top]='e';syn[top+1]='T';top++;break;}case 2:{printf("E′→+TE`\n");syn[top+1]='T';top++;lookahead=exp[m++];break;}case 3:{printf("E′→ε\n");syn[top]='\0';top--;break;}case 4:{printf("T →FT′\n");syn[top]='t';syn[top+1]='F';top++;break;}case 5:{printf("T′→* FT′\n");syn[top+1]='F';top++;lookahead=exp[m++];break;}case 6:{printf("T′→ε\n");syn[top]='\0';top--;break;}case 7:{printf("F →(E)\n");syn[top]=')';syn[top+1]='E';top++;lookahead=exp[m++];break;}case 8:{printf("F →d\n");syn[top]='\0';top--;lookahead=exp[m++];lookahead=exp[m++];break;}case 9:{printf("弹栈,弹出非终结符%c,用户少输入了一个d\n",string[i/2]);syn[top]='\0';top--;break;}case 11:{syn[top]='\0';top--;lookahead=exp[m++];break;}case 13:{printf("弹栈,弹出终结符) ,用户少输入了一个右括号\n");syn[top]='\0';top--;break;}}}}return 0;}实验运行结果:三、总结预测分析法主要是对预测分析表的输出,关键是要理解语法内容和结构。

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。

本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。

二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。

此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。

三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。

在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。

首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。

然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。

在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。

对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。

(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。

在本次实验中,我们使用了递归下降的语法分析方法。

首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。

在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。

为了处理语法错误,在分析过程中添加了错误检测和处理机制。

当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。

(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。

在本次实验中,我们使用了三地址码作为中间代码的表示形式。

在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。

对于符合语义规则的语法结构,生成相应的三地址码指令。

四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。

编译原理实验二 预测分析法

编译原理实验二  预测分析法

实验二预测分析法一、实验项目名称预测分析法二、实验目的根据某一LL(1)文法编制调试预测分析程序,以便对任意输入的符号串进行分析。

本次实验的目的主要是加深对预测分析法的理解。

三、实验环境Win8系统,VC++6.0软件,C语言开发工具四、实验内容本次实验的LL(1)文法为表达式文法:E→E+T | TT→T*F | FF→i | (E)编写识别表达式文法的合法句子的预测分析程序,对输入的任意符号串,给出分析过程及分析结果。

分析过程要求输出步骤、分析栈、剩余输入串和所用产生式。

如果该符号串不是表达式文法的合法句子,要给出尽量详细的错误提示。

五、实验步骤首先将终结符和非终结符以及预测分析表计算出来,并保存到数组中然后对输入的字符进行分析,将一个个终结符进行分配在分配的过程中输出每一步步骤对错误处,显示步骤数和错误字符六、源程序清单、测试数据、结果源程序:#include<iostream.h>#include<stdio.h>#include<string>using namespace std;char zhong[6]={'i','+','*','(',')','#'};char fzhong[5]={'E','R','T','Y','F'};char shu[20];1//R代表E' Y代表T'string biao[5][6]={{"TR","","","TR","",""},{"","+TR","","","@","@"}, //@代表空{"FY","","","FY","",""},{"","@","*FY","","@","@"},{"i","","","(E)","",""}};#define N 20;typedef char type;typedef struct{type *base;type *top;int stacksize;}sqstack;void initstack(sqstack &s){s.base=new type[2];if(!s.base)cout<<"错误";s.top=s.base;s.stacksize=N;}void push(sqstack &s,type e){if(s.top-s.base==s.stacksize)cout<<"栈满";*s.top++=e;}void pop(sqstack &s,type &e){if(s.top==s.base)cout<<"栈空";e=*--s.top;}type gettop(sqstack s){if(s.top==s.base)cout<<"栈空";return *(s.top-1);}int find1(char x){for(int i=0;i<5;i++){if(x==fzhong[i]){break;}}return i;}int find2(char x){for(int i=0;i<6;i++){if(x==zhong[i]){break;}}return i;}void showstack(sqstack fen){char a;sqstack x;initstack(x);while(fen.top!=fen.base){pop(fen,a);push(x,a);}3while(x.top!=x.base){pop(x,a);cout<<a;}}void fenxi(sqstack &fen){string str;int i=0,row=1,j;char ch1,ch2;// ch1=gettop(fen);while(1){if(gettop(fen)==shu[i]&&gettop(fen)!='#'){cout<<endl<<row++<<" ";showstack(fen);j=i;cout<<" ";while(shu[j]!='#'){cout<<shu[j];j++;}cout<<"# "<<shu[i]<<"被分配"<<endl;i++;pop(fen,ch2);}else if(gettop(fen)=='#'){cout<<row<<" # # 被接受";break;}else{str=biao[find1(gettop(fen))][find2(shu[i])];if(biao[find1(gettop(fen))][find2(shu[i])]==""){cout<<"第"<<row<<"行出现错误"<<gettop(fen)<<"与"<<shu[i]<<"无对应的关系"<<endl;break;}else if(biao[find1(gettop(fen))][find2(shu[i])]=="@"){cout<<row<<" ";showstack(fen);j=i;cout<<" ";while(shu[j]!='#'){cout<<shu[j];j++;}cout<<"# "<<gettop(fen)<<"->";for(j=0;j<str.length();j++){ cout<<str.at(j);}cout<<endl;row++;pop(fen,ch2);j=0;}else{cout<<row<<" ";showstack(fen);j=i;cout<<" ";while(shu[j]!='#'){cout<<shu[j];j++;}cout<<"# "<<gettop(fen)<<"->";5for(j=0;j<str.length();j++){ cout<<str.at(j);}row++;pop(fen,ch2);j=str.length()-1;while(j>=0){push(fen,str.at(j));j--;}cout<<endl;}}}}void main(){cout<<"这里是预测分析法程序测试!!!"<<endl;cout<<"请输入一串仅含i,+,*,(,)的字符串,并以#结束"<<endl;char a;sqstack fen;int i=0;while(a!='#'){cin>>a;shu[i]=a;i++;}cout<<"对输入串:"<<shu<<"的分析过程"<<endl;initstack(fen);push(fen,'#');push(fen,'E');fenxi(fen);}运行结果截图:测试一:测试二:7测试三:(错误测试)七、实验小结和思考预测分析法相对于RL法简单很多,而且预测分析表已经得到。

编译原理非递归预测分析实验报告

编译原理非递归预测分析实验报告

编译原理非递归预测分析实验报告一、实验目的本次实验旨在深入理解编译原理中的非递归预测分析方法,通过实际编程实现,掌握其基本原理和应用技巧,提高对编译过程中语法分析阶段的认识和实践能力。

二、实验原理非递归预测分析是一种基于预测分析表的自顶向下语法分析方法。

它通过预测下一个可能的输入符号,并根据语法规则进行相应的处理,从而逐步完成对输入字符串的语法分析。

预测分析表是该方法的核心,它是根据给定的语法规则生成的。

表中的行表示非终结符,列表示终结符或输入符号。

每个表项中存储着相应的分析动作,如匹配、移进、归约等。

在分析过程中,使用一个分析栈来存储当前的语法符号。

从起始符号开始,根据预测分析表和输入符号,不断进行栈操作和符号匹配,直到输入字符串完全被分析或发现语法错误。

三、实验环境本次实验使用的编程语言为_____,开发工具为_____。

四、实验内容1、定义语法规则确定所分析的语法的非终结符和终结符。

以 BNF(巴科斯瑙尔范式)或类似的形式描述语法规则。

2、构建预测分析表根据语法规则,通过计算 First 集和 Follow 集,生成预测分析表。

3、实现分析算法设计非递归的预测分析函数,实现对输入字符串的分析。

在函数中,根据分析栈、预测分析表和输入符号进行相应的操作。

4、处理语法错误设计错误处理机制,能够在发现语法错误时给出相应的提示信息。

五、实验步骤1、分析语法规则仔细研究给定的语法,明确各个语法成分之间的关系。

例如,对于一个简单的算术表达式语法:```E > E + T | TT > T F | FF >( E )| id```其中,E、T、F 是非终结符,+、、(、)、id 是终结符。

2、计算 First 集和 Follow 集First 集:First(X) 表示可以从非终结符 X 推导出来的开头终结符的集合。

例如,First(E) ={(, id },First(T) ={(, id },First(F)={(, id }。

编译原理课程实验报告示例

编译原理课程实验报告示例

编译原理实验报告04070010 张悦指导老师:蒋宗礼完成日期:2007-6-20一. 实验目的基本掌握计算机语言的词法分析程序的开发方法。

以及掌握计算机语言的语法分析程序设计与属性文法应用的实现方法。

锻炼自己的编程能力和逻辑思维能力,体会计算机编译器的奥妙之处二. 实验内容1.编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。

2.用二维预约分析表,编制一个能够进行语法分析并生成派生的产生式序列的编译程序。

3.用递归子程序法,编制一个能够进行语法分析并生成三地址代码的微型编译程序。

三. 实验要求1.编制正规式以及正规文法,画出状态图;2.根据状态图,设计词法分析函数int scan( ),完成以下功能:1)2)3)从键盘读入数据,分析出一个单词。

返回单词种别(用整数表示),返回单词属性(不同的属性可以放在不同的全局变量中)。

3.编写测试程序,反复调用函数scan( ),输出单词种别和属性。

4.改写文法,构造语法分析程序,要求按照最左派生的顺序输出派生的产生式序列;5.改写语法分析程序,构造三地址代码生成程序。

6.处理的源程序存放在文件中,它可以包含多个语句;四.系统设计完成整个系统,实现本个实验的要求,需要两个比较大的模块:词法分析器和语法分析器。

词法分析器的功能是将输入的程序串分解成一个一个独立的单词,并且记录下每个单词的类型以及数值。

这里词法分析器的实现有两种方法:调用一次词法分析器,返回一个词的类型以及数值,以此类推;还有一种方法是条用一次词法分析器将程序串的所有单词都分解出来并保存到一个地方(比如线形表)以便将来使用。

我采用的是前者,因为这样只需要对整个程序访问一遍语法分析器的功能是将已经分解好的单词按照一定的规范(产生式)组合起来,由此来确定输入程序的意思。

我的设计是“语法分析器调用词法分析器”,当语法分析其分析进行不下去的时候调用词法分析器获取一个单词,继续进行分析。

编译原理预测分析法C语言的实验报告

编译原理预测分析法C语言的实验报告

题目:编写识别由下列文法所定义的表达式的预测分析程序。

E→E+T | E-T | TT→T*F | T/F |FF→(E) | i输入:每行含一个表达式的文本文件。

输出:分析成功或不成功信息。

(题目来源:编译原理实验(三)--预测(LL(1))分析法的实现)解答:(1)分析a) ∵E=>E+T=>E+T*F=>E+T*(E)即有E=>E+T*(E)存在左递归。

用直接改写法消除左递归,得到如下:E →TE’ E’ →+TE’ | −TE’|εT →FT’ T’ →*FT’ | /FT’|εF → (E) | i对于以上改进的方法。

可得:对于E’:FIRST( E’ )=FIRST(+TE’)∪FIRST(-TE’)∪{ε}={+,−,ε}对于T’:FIRST( T’ )=FIRST(*FT’)∪FIRST(/FT’)∪{ε}={*,∕,ε} 而且:FIRST( E ) = FIRST( T ) = FIRST( F )=FIRST((E))∪FIRST(i)={(,i }由此我们容易得出各非终结符的FOLLOW集合如下:FOLLOW( E )= { ),#}FOLLOW(E’)= FOLLOW(E)={ ),#}FOLLOW( T )= FIRST(E’)\ε∪FOLLOW(E’)={+,−,),#}FOLLOW( T’ ) = FOLLOW( T ) ={+,−,),#}FOLLOW( F )=FIRST(T’)\ε∪FOLLOW(T’)={*,∕,+,−,),#}由以上FOLLOW集可以我们可以得出SELECT集如下:对E SELECT(E→TE’)=FIRST(TE’)=FIRST(T)={ (,i }对E’ SELECT(E’ →+TE’)={ + }SELECT(E’ →−TE’)={ − }SELECT(E’ →ε)={ε,),#}对T SELECT(T→FT’)={(,i}对T’ SELECT(T’ →*FT’)={ * }SELECT(T’ →∕FT’)={ ∕ }SELECT(T’ →ε)={ε,+,−,),#}对F SELECT(F→(E) )={ ( }SELECT(F→i)={ i }∴SELECT(E’ →+TE’)∩SELECT(E’ →−TE’)∩SELECT(E’ →ε)=ΦSELECT(T’ →*FT’)∩SELECT(T’ →∕FT’)∩SELECT(T’ →ε)=ΦSELECT(F→(E) )∩SELECT(F→i)= Φ由上可知,有相同左部产生式的SELECT集合的交集为空,所以文法是LL(1)文法。

编译原理实验报告

编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的重要课程,旨在让学生了解编译器的基本工作原理以及相关技术。

本次实验旨在通过设计和实现一个简单的编译器,来进一步加深对编译原理的理解,并掌握实际应用的能力。

二、实验环境本次实验使用了Java编程语言及相关工具。

在开始实验前,我们需要安装Java JDK并配置好运行环境。

三、实验内容及步骤1. 词法分析词法分析是编译器的第一步,它将源代码分割成一系列词法单元。

我们首先实现一个词法分析器,它能够将输入的源代码按照语法规则进行切割,并识别出关键字、标识符、数字、运算符等。

2. 语法分析语法分析是编译器的第二步,它将词法分析得到的词法单元序列转化为语法树。

我们使用自顶向下的LL(1)语法分析算法,根据文法规则递归地构建语法树。

3. 语义分析语义分析是编译器的第三步,它对语法树进行检查和转换。

我们主要进行类型检查、语法错误检查等。

如果源代码存在语义错误,编译器应该能够提供相应的错误提示。

4. 代码生成代码生成是编译器的最后一步,它将经过词法分析、语法分析和语义分析的源代码翻译为目标代码。

在本次实验中,我们将目标代码生成为Java字节码。

5. 测试与优化完成以上步骤后,我们需要对编译器进行测试,并进行优化。

通过多个测试用例的执行,我们可以验证编译器的正确性和性能。

四、实验心得通过完成这个编译器的实验,我收获了很多。

首先,我对编译原理的知识有了更深入的理解。

在实验过程中,我深入学习了词法分析、语法分析、语义分析和代码生成等关键技术,对编译器的工作原理有了更系统的了解。

其次,我提高了编程能力。

实现一个完整的编译器需要处理复杂的数据结构和算法,这对我的编程能力是一个很好的挑战。

通过实验,我学会了合理地组织代码,优化算法,并注意到细节对程序性能的影响。

最后,我锻炼了解决问题的能力。

在实验过程中,我遇到了很多困难和挑战,但我不断地调试和改进代码,最终成功地实现了编译器。

编译原理LL(1)分析实验报告

编译原理LL(1)分析实验报告

青岛科技大学LL(1)分析编译原理实验报告学生班级__________________________学生学号__________________________学生姓名________________________________年 ___月 ___日一、实验目的LL(1)分析法的基本思想是:自项向下分析时从左向右扫描输入串,分析过程中将采用最左推导,并且只需向右看一个符号就可决定如何推导。

通过对给定的文法构造预测分析表和实现某个符号串的分析,掌握LL(1)分析法的基本思想和实现过程。

二、实验要求设计一个给定的LL(1)分析表,输入一个句子,能根据LL(1)分析表输出与句子相应的语法数。

能对语法数生成过程进行模拟。

三、实验内容(1)给定表达式文法为:G(E’): E’→#E# E→E+T | T T→T*F |F F→(E)|i(2)分析的句子为:(i+i)*i四、模块流程五、程序代码#include<iostream>#include<stdio.h>#include <string>#include <stack>using namespace std;char Vt[]={'i','+','*','(',')','#'}; /*终结符*/char Vn[]={'E','e','T','t','F'}; /*非终结符*/ int LENVt=sizeof(Vt);void showstack(stack <char> st) //从栈底开始显示栈中的内容{int i,j;char ch[100];j=st.size();for(i=0;i<j;i++){ch[i]=st.top();st.pop();}for(i=j-1;i>=0;i--){cout<<ch[i];st.push(ch[i]);}}int find(char c,char array[],int n) //查找函数,返回布尔值{int i;int flag=0;for(i=0;i<n;i++){if(c==array[i])flag=1;}return flag;}int location(char c,char array[]) //定位函数,指出字符所在位置,即将字母转换为数组下标值{int i;for(i=0;c!=array[i];i++);return i;}void error(){cout<<" 出错!"<<endl;}void analyse(char Vn[],char Vt[],string M[5][6],string str){int i,j,p,q,h,flag=1;char a,X;stack <char> st; //定义堆栈st.push('#');st.push(Vn[0]); //#与识别符号入栈j=0; //j指向输入串的指针h=1;a=str[j];cout<<"步骤"<<"分析栈"<<"剩余输入串"<<" 所用产生式"<<endl;while(flag==1){cout<<h<<" "; //显示步骤h++;showstack(st); //显示分析栈中内容cout<<" ";for(i=j;i<str.size();i++) cout<<str[i]; //显示剩余字符串X=st.top(); //取栈顶符号放入X if(find(X,Vt,LENVt)==1) //X是终结符if(X==a) //分析栈的栈顶元素和剩余输入串的第一个元素相比较if (X!='#'){cout<<" "<<X<<"匹配"<<endl;st.pop();a=str[++j]; //读入输入串的下一字符}else{ cout<<" "<<"acc!"<<endl<<endl; flag=0;}else{error();break;}else{p=location(X,Vn); //实现下标的转换(非终结符转换为行下标)q=location(a,Vt); //实现下标的转换(终结符转换为列下标)string S1("NULL"),S2("null");if(M[p][q]==S1 || M[p][q]==S2) //查找二维数组中的产生式{error();break;} //对应项为空,则出错else{string str0=M[p][q];cout<<" "<<X<<"-->"<<str0<<endl; //显示对应的产生式st.pop();if(str0!="$") //$代表"空"字符for(i=str0.size()-1;i>=0;i--) st.push(str0[i]);//产生式右端逆序进栈}}}}main(){string M[5][6]={"Te" ,"NULL","NULL","Te", "NULL","NULL","NULL","+Te" ,"NULL","NULL","$", "$","Ft", "NULL","NULL","Ft", "NULL","NULL","NULL","$", "*Ft", "NULL","$", "$","i", "NULL","NULL","(E)", "NULL","NULL"}; //预测分析表j string str;int errflag,i;cout<<"文法:E->E+T|T T->T*F|F F->(E)|i"<<endl;cout<<"请输入分析串(以#结束):"<<endl;do{ errflag=0;cin>>str;for(i=0;i<str.size();i++)if(!find(str[i],Vt,LENVt)){ cout<<"输入串中包含有非终结符"<<str[i]<<"(输入错误)!"<<endl;errflag=1;}} while(errflag==1); //判断输入串的合法性analyse(Vn, Vt, M,str);return 0;}六、实验结果七、实验总结。

编译原理实验报告

编译原理实验报告

实验一词法分析一、实验目的通过设计、编写和调试词法分析程序,了解词法分析程序的作用,组成结构,不同种类单词的识别方法,掌握由单词的词法规则出发,画出识别单词的状态转换图,然后在用程序实现词法分析程序设计方法。

二、词法规则1、注释用{和}括起来。

注释体中不能有{。

注释可以出现在任何记号的后面。

2、记号间的空格可有可无,但关键字前后必须有空格、换行、程序的开头或者结尾的原点。

3、标识符的记号id 与以字母开头的字母数字串相匹配:Letter->[a-zA-Z]Digit->[0-9]Id->letter (letter | digit)*4、记号num与无符号整数相匹配:Digits->digit digit*Optional_fraction -> . Digits | ɛOptional_exponent->(E(+ | - | ɛ ) digits) | ɛNum ->digits optional_fraction optional_exponent5、关键字要被保留且在文法中以黑体出现6、关系运算符(relop)指:=、<、<>、<=、>=、>7、Addop: + 、 - 、or8、Mulop:*、/ 、div、mod、and9、Assignop: :=三、词法分析程序详细设计及判别状态图1、无符号数(可带小数和指数)的状态转换图:2、标识符/关键字的状态转换图:字母或数程序详细设计:四、开发环境本程序在Microsoft Visual C++ 6.0环境中编写,无特殊编译要求。

五、函数清单void LexcialAnalysis(FILE *fp);//词法分析主函数int JudgeFirstLetter(char ch);//判断单词的第一个字符int IsDigit(char ch);//判断是否为数字int IsLetter(char ch);//判断是否为字母int IsSpecialPunc(char ch);//判断是否为特殊标点void RecogDigit(char StrLine[]);//用状态图识别无符号数字void RecogIdentifier(char strLine[]);//用状态图识别标识符void RecogPunc(char strLine[]);//识别特殊标点int IsKeyWord(string str);//判断标识符是否为关键字void error();//出错处理六、测试程序program example(input, output);{comments goes here!}var x, y: integer;function gcd(a, b: integer): integer;beginif b =1.2e3 then gcd := aelse gcd := gcd(b, a mod b)end;beginread(x, y);write(gcd(x, y));end.七、运行效果八、实验总结通过这次编译器词法分析程序的编写,我更好地了解了词法分析的作用及工作原理,讲课本中的知识融入到程序编写过程中,理论结合了实际。

编译原理预测分析程序的实现

编译原理预测分析程序的实现

实验二预测分析表一、实验目的预测分析表的实现二、实验内容设有文法G:E→TE’E’→+TE’|εT→FT’T’→*FT’|εF→(E)|i;根据文法编写预测表分析总控程序,分析句子是否为该文法的句型。

当输入字符串: +i时,分析字符串是否为文法的句型三、实验步骤(详细的实验步骤)(1)文法E→TE’E’→+TE’|εT→FT’T’→*FT’|εF→(E)|i;(2)FIRST集FIRST(E)={(,i};FIRST(E’)={+, ε};FIRST(T)={(,i};FIRST(T’)={ *, ε};FIRST(F)={(,i};(3)FALLOW集FOLLOW(E)={),#};FOLLOW(E’)={),#};FOLLOW(T)={+,),#};FOLLOW(T’)={+,),#};FOLLOW(F)={*,+,),#};(4)预测分析表(5)分析过程步骤符号栈输入串应用句型0 #E i1*i2+i3#1 #E’T i1*i2+i3# E->TE’2 #E’T’F i1*i2+i3# E->TE’3 #E’T’i i1*i2+i3# F->i4 # E’T’i1*i2+i3#5 # E’T’F* *i2+i3# T’->*FT’6 # E’T’F *i2+i3#7 # E’T’i i2+i3# F->i8 # E’T’ i2+i3#9 #E’ +i3# T’->ε10 # E’T+ +i3# E’->+TE’11 #E’T +i3#12 # E’T’F i3# T->FT’13 # E’T’i i3# F->i14 # E’T’ i3#15 # E’ # T’->ε16 # # E’->ε(6)程序伪代码BEGIN首先把‘#’然后把文法开始符号推进STACK栈;把第一个输入符号读进a;FLAG:=TRUE;WHILE FLAG DOBEGIN把STACK栈顶符号托出去并放在X中;IF X属于VT THENIF X=a THEN 把下一输入符号读进a;ELSE ERROR;ELSE IF X=’#’ THENIF X=a THEN FLAG:=FALSE ELSE ERROR;ELSE IF M[A,a]={X->X1X2…Xk} THEN把Xk,X(k-1),…,X1一一推进栈ELSE ERROR;END OF WHILESTOPEND(7)运行结果截图注:为了将E和E’区分开,所以就有e来表示E’,因为在处理中E’会被当成两个字符来处理,所以就简化的表示了。

编译原理-实验报告3-LL1

编译原理-实验报告3-LL1

计算机硬件实验室实验报告根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。

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

二、实验要求:对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i输出的格式如下:(1)LL(1)分析程序,编制人:姓名,学号,班级(2)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串(3)输出过程如下:步骤分析栈剩余输入串所用产生式1 E i+i*i# E->TG(4)输入符号串为非法符号串(或者为合法符号串)备注:(1)在“所用产生式”一列中如果对应有推导则写出所用产生式;如果为匹配终结符则写明匹配的终结符;如分析异常出错则写为“分析出错”;若成功结束则写为“分析成功”。

(2) 在此位置输入符号串为用户自行输入的符号串。

(3)上述描述的输出过程只是其中一部分的。

注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符i,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);三、实验过程:1.模块设计:将程序分成合理的多个模块(函数),每个模块做具体的同一事情。

2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。

3.程序编写(1)定义部分:定义常量、变量、数据结构。

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

四、实验结果:(1)写出程序流程图(2)给出运行结果示例程序:注意:本示例只要修改分析的句子即可,不要改写文法/*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,g2,s,s2,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';strcpy(g1.array,"-TG");g1.length=3;g2.origin='G';g2.array[0]='^';g2.length=1;/////////////////////////////////////////////s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';strcpy(s1.array,"/FS");s1.length=3;s2.origin='S';s2.array[0]='^';s2.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';/*全部赋为空*//*填充分析表*///char v1[20]={'i','+','-','*','/','(',')','#'};/*终结符*///char v2[20]={'E','G','T','S','F'};/*非终结符*/C[0][0]=e;C[0][5]=e;C[1][1]=g;C[1][2]=g1;C[1][3]=C[1][4]=C[1][7]=g2;C[2][0]=t;C[2][3]=t;C[2][5]=t;C[3][1]=C[3][2]=s2;C[3][3]=s;C[3][4]=s1;C[3][6]=C[3][7]=s2;C[4][0]=f1; C[4][5]=f;printf("LL(1)分析程序,编制人:武普泉,20号,1020562班\n");printf("输入一以#结束的符号串(包括+ - * / () i #):");do/*读入分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+') &&(ch!='-')&&(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<=7;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<=7;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*。

编译原理实验报告

编译原理实验报告

编译原理实验报告编译原理实验报告一、引言编译原理是计算机科学中的重要课程之一,它研究的是如何将高级语言程序转化为机器语言程序的过程。

在本次实验中,我们将学习并实践编译原理中的一些基本概念和技术,包括词法分析、语法分析和语义分析等。

二、词法分析词法分析是编译过程中的第一步,它负责将源程序中的字符序列转化为有意义的词法单元。

在本次实验中,我们使用了Flex工具来生成词法分析器。

通过定义一系列正则表达式和对应的动作,我们可以将源程序中的字符序列识别为不同的词法单元,如标识符、关键字、运算符等。

三、语法分析语法分析是编译过程中的第二步,它负责将词法单元序列转化为抽象语法树。

在本次实验中,我们使用了Bison工具来生成语法分析器。

通过定义一系列文法规则和对应的动作,我们可以将词法单元序列转化为抽象语法树,并进行语法错误的检测和恢复。

四、语义分析语义分析是编译过程中的第三步,它负责对抽象语法树进行语义检查和语义动作的执行。

在本次实验中,我们通过自定义语义规则和对应的动作,对抽象语法树进行类型检查、符号表管理等操作。

同时,我们还实现了一些简单的语义动作,如计算表达式的值、生成中间代码等。

五、中间代码生成中间代码生成是编译过程中的一项重要任务,它负责将源程序转化为机器无关的中间表示形式。

在本次实验中,我们使用了三地址码作为中间表示形式。

通过对抽象语法树的遍历和一系列的转换规则,我们可以将源程序转化为等价的三地址码表示形式。

六、实验结果与分析通过对一些简单的测试程序的编译,我们验证了我们所实现的词法分析、语法分析、语义分析和中间代码生成的正确性。

同时,我们还进行了一些性能测试,对比了不同算法和数据结构在编译过程中的效率差异。

实验结果表明,我们所实现的编译器在处理大规模程序时具有较好的性能。

七、结论通过本次实验,我们深入了解了编译原理中的一些基本概念和技术,并通过实践加深了对编译过程的理解。

同时,我们也意识到编译器的设计和实现是一项复杂而有挑战性的任务,需要综合运用多种算法和数据结构。

编译原理中实验报告

编译原理中实验报告

实验名称:编译原理实验实验时间:2023年X月X日实验地点:实验室实验指导老师:XXX一、实验目的1. 理解编译原理的基本概念和流程。

2. 掌握词法分析和语法分析的基本方法。

3. 学习编译器生成中间代码和目标代码的过程。

4. 培养编程能力和问题解决能力。

二、实验内容本次实验主要包括以下内容:1. 词法分析:编写一个简单的词法分析器,将源代码输入转换为抽象语法树(AST)。

2. 语法分析:实现一个简单的递归下降解析器,对词法分析器输出的AST进行语法分析。

3. 中间代码生成:根据AST生成三地址代码(Three-Address Code)。

4. 代码优化:对生成的三地址代码进行优化。

5. 目标代码生成:将优化后的三地址代码转换为机器代码。

三、实验步骤1. 设计词法分析器首先,我们需要设计一个能够识别源代码中各种单词的词法分析器。

在本实验中,我们定义了以下几种单词:- 关键字:如if、else、while、int、float等。

- 标识符:由字母、数字和下划线组成,不能以数字开头。

- 常量:包括整型常量和浮点型常量。

- 运算符:如+、-、、/、==、<=等。

- 分隔符:如(、)、;、,等。

根据以上定义,我们可以编写一个词法分析器,它将输入的源代码字符串逐个字符地读取,并根据定义的规则识别出相应的单词。

2. 语法分析词法分析器生成的AST是一个树形结构,其中每个节点代表源代码中的一个单词或符号。

为了进一步分析AST的结构,我们需要实现一个递归下降解析器,它能够根据语法规则对AST进行解析。

在本实验中,我们以一个简单的算术表达式为例,实现了一个递归下降解析器。

解析器从AST的根节点开始,按照语法规则递归地解析每个子节点,直到整个表达式被解析完毕。

3. 中间代码生成在完成语法分析后,我们需要将AST转换为中间代码。

在本实验中,我们选择了三地址代码作为中间代码的形式。

三地址代码是一种表示赋值、条件判断和循环等操作的方式,它使用三个操作数和两个操作符来表示一个操作。

编译原理-预测分析程序的设计与实现-实验报告

编译原理-预测分析程序的设计与实现-实验报告

3.1目的和Array要求1、掌握LL(1)语法分析的基本原理和方法。

2、掌握相应数据结构的设计方法。

3.2实验环境Windows 7 + DEVC++6.03.3实验准备首先将下列算术表达式文法E-->E+T|TT-->T*F|FF-->(E)|i改写文法为LL(1)文法;构造LL(1)预测分析表。

解:1)该文法为左递归文法,设非终结符A,B;E=〉TAA=〉+TA|εT=>FBB=>*FB|εF=>(E)|i2)计算FIRST,FELLOW,SELECT集:因为A,B,F的的两个产生式的选择集都没有交集,所以,该文法为LL(1)文法。

、3)构造预测分析表4)给出i+i的预测分析过程。

3.4实验内容及步骤1、根据预测分析表编写预测分析程序yuce。

2、编译成功后,提示输入符号串,用回车键查看输出的结果。

3、比较自己分析的结果和屏幕上的输出结果。

3.5实验小结1、得到的经验。

2、遇到的主要问题。

3、改进方案。

自拟LL1文法G[A]:E=>aAEE=>bA=>bAA=>ε1)计算FIRST,FOLLOW,SELECT集。

2)构造预测分析表。

E=>aAE=>abAcE=>abcb3) 给出abcb的预测分析过程。

3)改进代码,其中用e代替εusing namespace std;int main(){string sheet[2][5]={{"aAE","b","","",""}, //预测分析表{"","bAc","e","","e"}};vector<char> S;//分析栈vector<char> Stc;//用户输入栈vector<char> SOS;//空栈string STC;//用于获取用户输入的字符串int YourChoice;do{cout<<endl;S=SOS; //每次执行用空的SOS初始化分析栈S.push_back('#');//将#放到分析栈中S.push_back('E');//将E放到分析栈中STC=""; //将STC设置为空cout<<"请输入您要分析的字符串:";cin>>STC;STC.resize(STC.size()+1);STC[STC.size()-1]='#';//将输入串最后一位设置为#Stc=SOS; //Stc是将STC+#倒序压入的用户输入栈for(int x=STC.size()-1;x>=0;--x)Stc.push_back(STC[x]);string YY="EA";string XX="abce#";while(!(S[S.size()-1]=='#'&&Stc[Stc.size()-1]=='#')){int i=0,j=0;////////////////////查表找到相应规则//////////////////// for(i=0;i<2;++i)if(YY[i]==S[S.size()-1])break;for(j=0;j<5;++j)if(XX[j]==Stc[Stc.size()-1])break;if(i>=5||j>=6) //如果查找超出表{cout<<"出错啦!"<<endl;break;}else if(sheet[i][j]=="") {cout<<"出错啦!"<<endl;break;}else{///////////////分析栈里的压栈与弹栈//////////////////// S.pop_back();for(int k=sheet[i][j].size()-1;k>=0;--k)S.push_back(sheet[i][j][k]);if(S[S.size()-1]==Stc[Stc.size()-1]) //一般规则{S.pop_back();Stc.pop_back();}else if(S[S.size()-1]=='e') //含空串的规则{S.pop_back();if(S[S.size()-1]!='#'&&Stc[Stc.size()-1]!='#'&&S[S.size()-1]==Stc[Stc.size()-1]) {S.pop_back();Stc.pop_back();}}}}if(S[S.size()-1]=='#'&&Stc[Stc.size()-1]=='#')cout<<"分析成功!"<<endl;cout<<"继续分析";}while(cin>>YourChoice&&YourChoice==0);return 0; }。

编译原理预测分析程序的实现

编译原理预测分析程序的实现

实验二预测分析表一、实验目的预测分析表的实现二、实验内容设有文法G:E→TE’E’→+TE’|εT→FT’T’→*FT’|εF→(E)|i;根据文法编写预测表分析总控程序,分析句子是否为该文法的句型。

当输入字符串: +i时,分析字符串是否为文法的句型三、实验步骤(详细的实验步骤)(1)文法E→TE’E’→+TE’|εT→FT’T’→*FT’|εF→(E)|i;(2)FIRST集FIRST(E)={(,i};FIRST(E’)={+, ε};FIRST(T)={(,i};FIRST(T’)={ *, ε};FIRST(F)={(,i};(3)FALLOW集FOLLOW(E)={),#};FOLLOW(E’)={),#};FOLLOW(T)={+,),#};FOLLOW(T’)={+,),#};FOLLOW(F)={*,+,),#};(4)预测分析表(5)分析过程步骤符号栈输入串应用句型0 #E i1*i2+i3#1 #E’T i1*i2+i3# E->TE’2 #E’T’F i1*i2+i3# E->TE’3 #E’T’i i1*i2+i3# F->i4 # E’T’i1*i2+i3#5 # E’T’F* *i2+i3# T’->*FT’6 # E’T’F *i2+i3#7 # E’T’i i2+i3# F->i8 # E’T’ i2+i3#9 #E’ +i3# T’->ε10 # E’T+ +i3# E’->+TE’11 #E’T +i3#12 # E’T’F i3# T->FT’13 # E’T’i i3# F->i14 # E’T’ i3#15 # E’ # T’->ε16 # # E’->ε(6)程序伪代码BEGIN首先把‘#’然后把文法开始符号推进STACK栈;把第一个输入符号读进a;FLAG:=TRUE;WHILE FLAG DOBEGIN把STACK栈顶符号托出去并放在X中;IF X属于VT THENIF X=a THEN 把下一输入符号读进a;ELSE ERROR;ELSE IF X=’#’ THENIF X=a THEN FLAG:=FALSE ELSE ERROR;ELSE IF M[A,a]={X->X1X2…Xk} THEN把Xk,X(k-1),…,X1一一推进栈ELSE ERROR;END OF WHILESTOPEND(7)运行结果截图注:为了将E和E’区分开,所以就有e来表示E’,因为在处理中E’会被当成两个字符来处理,所以就简化的表示了。

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

预测分析表方法一、实验目的理解预测分析表方法的实现原理。

二、实验内容:编写一通用的预测法分析程序,要求有一定的错误处理能力,出错后能够使程序继续运行下去,直到分析过程结束。

可通过不同的文法(通过数据表现)进行测试。

三、实验步骤1.算法数据构造:构造终结符数组:char Vt[10][5]={“id”,”+”……};构造非终结符数组:char Vn[10]={ };构造follow集数组:char *follow[10][10]={ } (可将follow集与预测分析表合并存放)数据构造示例(使用的预测分析表构造方法1):/*data1.h简单算术表达式数据*/char VN[10][5]={"E","E'","T","T'","F"}; //非终结符表int length_vn=5; //非终结符的个数char VT[15][5]={"id","+","*","(",")","#"}; //终结符表int length_vt=6; //终结符的个数char Fa[15][10]={"TE'","+TE'","","FT'","*FT'","","(E)","id"};//产生式表:0:E->TE' 1:E'->+TE' 2:E'->空// 3:T->FT' 4:T'->*FT' 5:T'->空 6:F->(E) 7:F->idint analysis_table[10][11]={0,-1,-1,0,-2,-2,0,0,0,0,0,-1,1,-1,-1,2,2,0,0,0,0,0,3,-2,-1,3,-2,-2,0,0,0,0,0,-1,5, 4,-1,5, 5,0,0,0,0,0,7,-2,-2,6,-2,-2,0,0,0,0,0};//预测分析表,-1表示出错,-2表示该行终结符的follow集合,用于错误处理,正数表示产生式在数组Fa中的编号,0表示多余的列。

(1)预测分析表的构造方法1给文法的正规式编号:存放在字符数组中,从0开始编号,正规式的编号即为该正规式在数组中对应的下标。

如上述Fa数组表示存储产生式。

构造正规式数组:char P[10][10]={“E->TE’”,”E’->+TE’”,……..}; (正规式可只存储右半部分,如E->TE’可存储为TE’,正规式中的符号可替换,如可将E’改为M ) 构造预测分析表:int analyze_table[10][10]={ } //数组元素值存放正规式的编号,-1表示出错(2)预测分析表的构造方法2可使用三维数组Char analyze_table[10][10][10]={ }或Char *analyze_table[10][10]={ }2.针对预测分析表构造方法1的查预测分析表的方法提示:(1)查非终结符表得到非终结符的序号no1(2)查终结符表得到终结符的序号no2(3)根据no1和no2查预测分析表得到对应正规式的序号no3=analyze_table[no1][no2] ,如果no3=-1 表示出错。

(4)根据no3查找对应的正规式Fa[no3](5)对正规式进行处理3.错误处理机制紧急方式的错误恢复方法(抛弃某些符号,继续向下分析)(1)栈顶为非终结符A,串中当前单词属于FOLLOW(A),则从栈中弹出A(此时可认为输入串中缺少A表示的结构),继续分析。

---------错误编号为1(2)栈顶为非终结符A,串中当前单词不属于FOLLOW(A),则可使串指针下移一个位置(认为输入串中当前单词多余),继续分析。

----------错误编号为2(3)栈顶为终结符,且不等于串中当前单词,则从栈中弹出此终结符(认为输入串中缺少当前单词)或者将串指针下移一个位置(认为串中当前单词多余)。

在程序中可选择上述两种观点中的一种进行处理。

-------------错误编号3因此error()函数的编写方式可按如下方式处理Error(int errornum){If(errornum==1)………………Else if(errornum==2)……………Else ………………..//或者可用choose case语句处理}4.增加了错误处理的预测分析程序预测分析程序的算法:将“#”和文法开始符依次压入栈中;把第一个输入符号读入a;do{把栈顶符号弹出并放入x中;if(x∈VT){if(x==a) 将下一输入符号读入a;else error(3);}elseif(M[x,a]=“x→y1y2…yk”){按逆序依次把yk、yk−1、…、y1压入栈中;输出“x→y1y2…yk”;}else if a∈follow(x)error(1); else error(2);//在前述的数据定义中查表为-2表示a∈follow(x)}while(x!=“#”)给定算术表达式文法,编写程序。

测试数据:1.算术表达式文法E→TE’E’→ +TE’|- TE’|εT→FT’T’→*FT’ |/ FT’ |%FT’|εF→(E) |id|num给定一符合该文法的句子,如id+id*id$,运行预测分析程序,给出分析过程和每一步的分析结果。

输出形式参考下图($为结束符):#include<stdio.h>#include<string.h>#include<stdlib.h>#define TT 0char aa[20]=" ";int pp=0;# if TTchar VN[5]={'E','e','T','t','F'}; //非终结符表int length_vn=5; //非终结符的个数char VT[10]={'*','l','m','+','-','(',')','i','n','#'}; //终结符表l->/ m->% i->id n->numint length_vt=10; //终结符的个数charFa[12][6]={"Te","+Te","-Te","NULL","Ft","*Ft","nFt","mFt","NULL","(E)","i", "n"};//产生式表:0:E->Te 1:e->+Te 2:e->-Te 3:e->空charF[12][6]={"E->","e->","e->","e->","T->","t->","t->","t->","t->","F->","F->" ,"F->"};int analysis_table[5][10]={-2,-2,-2,-2,-2,0,-1,0,0,-1,-2,-2,-2,1,2,-2,3,-2,-2,3,-2,-2,-2,-1,-1,4,-1,4,4,-1,5,6,7,8,8,-2,8,-2,-2,8,-1,-1,-1,-1,-1,9,-1,10,11,-1};# elsechar VN[4]={'A','Z','B','Y'}; //非终结符表int length_vn=4; //非终结符的个数char VT[5]={'a','l','d','b','#'}; //终结符表int length_vt=5; //终结符的个数char Fa[6][6]={"aZ","ABl","NULL","dY","bY","NULL"};char F[6][6]={"A->","Z->","B->","Y->"};int analysis_table[4][5]={0,-2,-1,-2,-1,1,-2,2,-2,2,-2,-1,3,-2,-2,-2,5,-2,4,-2};# endifchar stack[50];int top=-1;void initscanner() //程序初始化:输入并打开源程序文件{int i=0;FILE *fp;if((fp=fopen("a.txt","r"))==NULL){printf("Open error!");exit(0);}char ch=fgetc(fp);while(ch!=EOF){aa[i]=ch;i++;ch=fgetc(fp);}fclose(fp);}void push(char a){top++;stack[top]=a;}char pop(){return stack[top--];}int includevt(char x){for(int i=0;i<length_vt;i++){if(VT[i]==x) return 1;}return 0;}int includean(char x,char a){int i,j;for(i=0;i<length_vn;i++)if(VN[i]==x) break;for(j=0;j<length_vt;j++)if(VT[j]==a) break;return analysis_table[i][j];}void destory(){int flag=0;int flagg=0;push('#'); //将"#"和文法开始符依次压入栈中push(VN[0]);char a=aa[pp]; //把第一个输入符号读入achar x;do{if(flag==0)x=pop(); //把栈顶符号弹出并放入x中flag=0;printf("%c\t\t\t%c\t",x,a);if(includevt(a)==1){if(includevt(x)==1){if(x==a){if(a=='#'){flagg=1;printf("结束\n");}else printf("匹配终结符%c\n",x);pp++;a=aa[pp]; //将下一输入符号读入a;}else{flag=1;printf("出错,跳过%c\n",a);pp++;a=aa[pp];}}else if(includean(x,a)>=0){int h=includean(x,a);printf("展开非终结符%s%s\n",F[h],Fa[h]);int k;for(k=0;k<10;k++)if(Fa[h][k]=='\0') break;if(k==4){//printf("+++++++++++pop %c \n",x);}else{while(k!=0) //按逆序依次把yk、yk?1、…、y1压入栈中{k--;push(Fa[h][k]);}}}else if(includean(x,a)==-1){flag=1;printf("出错,从栈顶弹出%c\n",x);x=pop();}else{flag=1;printf("出错,跳过%c\n",a);pp++;a=aa[pp];}}else{flag=1;printf("出错,跳过%c\n",a);pp++;a=aa[pp];}}while(x!='#');if(flagg==0){printf("%c\t\t\t%c\t",x,a);printf("结束\n");}}int main(){printf("请输入1 or 0:\n");//scanf("%d",TT);printf("语法分析工程如下:\n");initscanner();printf("要分析的语句是:%s\n",aa);printf("语法分析工程如下:\n");printf("栈顶元素\t\t当前单词记号\t\t\t动作\n");printf("--------------------------------------------------------------------\n");destory();return 0;}四、实验小结我成功的完成了实验基本要求和选做内容。

相关文档
最新文档