编译原理-实验三
- 格式:doc
- 大小:48.00 KB
- 文档页数:3
《编译原理(实验部分)》实验3_PL0语法分析《编译原理》(实验部分)实验3_PL0语法分析一、实验目的加深和巩固对于语法分析的了解和掌握;给出PL/0文法规范,要求编写PL/0语言的语法分析程序。
二、实验设备1、PC 兼容机一台;操作系统为WindowsWindowsXP。
2、Visual C++ 6.0 或以上版本, Windows 2000 或以上版本,汇编工具(在Software 子目录下)。
三、实验原理PL/O语言的编译程序,是用高级语言PASCAL语言书写的。
整个编译过程是由一些嵌套及并列的过程或函数完成。
语法分析是由过程BLOCK完成。
采用自顶向下的递归子程序法。
所产生的目标程序为假象栈式计算机的汇编语言。
对目标程序的执行是由PASCAL语言书写的解释程序进行的。
四、实验步骤实验代码int lp=0;int rp=0;#define getsymdo if(-1==getsym()) return -1#define expressiondo() if(-1==expression()) return -1#define termdo() if(-1==term()) return -1#define factordo() if(-1==factor()) return -1int expression();//语法分析int factor(){if(sym!=ident &&sym!=number&&sym!=lparen){err++;if(err==1) printf("语法错误: \n");printf("error----Factor Needs Ident or Number or Lparen\n");}if ((sym == ident) || (sym == number) || (sym == lparen)){if (sym == ident){WordAnalyse();if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("变量后没有跟上+-*\\ \n");}if(lp==0 && sym==rparen){err++;if(err==1) printf("语法错误: \n");printf("没有左括号匹配\n");}}else if (sym == number){WordAnalyse();if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=rparen) {err++;if(err==1) printf("语法错误: \n");printf("数字后没有跟上+-*\\ \n");}if(lp==0 && sym==rparen){err++;if(err==1) printf("语法错误: \n");printf("没有左括号匹配\n");}}else if (sym == lparen){WordAnalyse();lp++;if(getsym()==-1){lp--;err++;if(err==1) printf("语法错误: \n");printf("error----Needs Rparen \n");return -1;}expressiondo();if (sym == rparen){WordAnalyse();lp--;if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus) {err++;if(err==1) printf("语法错误: \n");printf("括号后没有跟上+-*\\ \n");}}else{err++;if(err==1) printf("语法错误: \n");printf("error----Needs Rparen \n");}}}return 0;}int term(){factordo();if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus&&sym!=ident&&sym!=number&&sym!=lparen&&sym!=rparen) {err++;if(err==1) printf("语法错误: \n");printf("不能识别字符\n");}while ((sym == times) || (sym == slash)){WordAnalyse();if(getsym()==-1){err++;if(err==1) printf("语法错误: \n");printf("* \\ 后缺项\n");return -1;}factordo();}return 0;}int expression(){if ((sym == plus) || (sym == minus)){//cout<<strlen(id)<<endl;< p="">if (sym==minus&&2==strlen(ID)+1)flg=1;else{flg=0;WordAnalyse();}getsymdo;termdo();}else{//WordAnalyse();termdo();}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=ident&&sym!=number&&sym!=lparen&&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("不能识别字符\n");}while ((sym == plus) || (sym == minus)){WordAnalyse();if(getsym()==-1){err++;if(err==1) printf("语法错误: \n");printf("+ - 后缺项\n");return -1;}termdo();}return 0;}int main(int argc, char* argv[]){init();err=0;ifstream fin("in.txt");ofstream fout("out.txt");ch=' ';lp=0;getsymdo;expression();if(err==0) cout<<"语法正确"<<endl;< p="">elsecout<<"语法错误,错误个数: "<<err<<=""></err< </endl;<></strlen(id)<<endl;<>。
编译原理实验报告——表达式语法分析 ——表达式语法分析表达式语法分析实验报告一、实验题目设计一个简单的表达式语法分析器 (采用递归下降方法设计实现)二、实验目的1、 了解形式语言基础及其文法运算; 2、 熟悉语法分析原理及 4 种常用的语法分析方法; 其中: 四种算法为 (1)设计算术表达式的递归下降子程序分析算法 (2)设计算术表达式的 LL(1) 分析算法 (3)设计算术表达式的简单优先分析算法 (4)设计算术表达式的 SLR(1) 分析算法 3、选择上述一种方法并设计一个表达式的语法分析器。
(本实验设计的是递归下降的表达式语法分析器)三、实验内容1.设计递归下降语法分析器算法; 2.编写代码并上机调试运行通过; 3、写出试验体会及心得。
四、实验要求1、 给出算术表达式文法 2、 进行适当的文法变换 3、 选择一种语法分析的方法,并说明其原理 4、 根据原理给出相应的算法设计,说明主要的数据结构并画出算法流 程图 5、 编写代码并上机调试运行通过 6、 写出程序运行结果 7、 写出相应的文档以及代码注释 8、输入——表达式; 输出——表达式语法是否正确。
五、递归下降的表达式语法分析器设计概要1.算术表达式文法 . G(E): E T F 2.文法变换: 文法变换: G’(E): E->TE' E'->+TE'|ε T->FT' T'->*FT'|ε F->(E)|I E +T | T T* F | F i | (E)3. 递归下降子程序框图: 递归下降子程序框图:六、实验设计源程序#include <iostream.h>char inputstream[50]; int temp=0; int right; void e(); void e1(); void t(); void t1(); void f(); void main() { right=1;//存储输入句子//数组下标 //判断输出信息cout<<"请输入您要分析的字符串以#结束(^为空字符):"<<endl; cin>>inputstream; e(); if((inputstream[temp]=='#')&&right) cout<<"分析成功"<<endl; else cout<<"分析失败"<<endl; } void e() { cout<<"E->TE'"<<endl; t(); e1(); } void e1() { if(inputstream[temp]=='+') { cout<<"E'->+TE'"<<endl; temp++; t();e1(); } else if (inputstream[temp]!='#'||inputstream[temp]!=')') { cout<<"T'->^"<<endl; return ; } else right=0; } void t() { cout<<"T->FT'"<<endl; f(); t1(); } void t1() { if(inputstream[temp]=='*') { cout<<"T'->*FT'"<<endl; temp++; f(); t1(); } else if (inputstream[temp]!='#'&&inputstream[temp]!=')'&&inputstream[temp ]!='+') { cout<<"T'->^"<<endl; right=0;} } void f() { if(inputstream[temp]=='i') { cout<<"F->i"<<endl; temp++; } elseif(inputstream[temp]=='(') { cout<<"F->(E)"<<endl; temp++; e(); if(inputstream[temp]==')') { cout<<"F->(E)"<<endl; temp++; } else right=0; } else right =0; }七、运行结果八、实验思考题语法分析的任务是什么? 语法分析的任务是什么? 答:语法分析器的任务是识别和处理比单词更大的语法单位,如:程序设 计语言中的表达式、各种说明和语句乃至全部源程序,指出其中的语法错误; 必要时,可生成内部形式,便于下一阶段处理。
编译原理实验报告实验三语法分析(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 = "+";if (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分析法是⼀种有效的⾃上⽽下分析技术,在⾃左向右扫描输⼊串时就能发现其中的任何错误。
班级:学号:姓名:实验7-8 预测分析表方法一、实验目的理解预测分析表方法的实现原理。
二、实验内容提示测试数据:1.算术表达式文法E→TAA → +TA|- TA|εT→FBB →*FB |/ FB |%FB|εF→(E) |id|num给定一符合该文法的句子,如id+id*id#,运行预测分析程序,给出分析过程和每一步的分析结果。
三.实验要求程序源代码及参考图:部分代码:void analysis ( nonterminator nont, terminator term , stack stac ){string wenjian;string rece;string ch;string top_stack;cout<<"请输入要测试的文件:";cin>>wenjian;ifstream infile ( wenjian.c_str (), ios::in );if ( !infile )cout<<"不存在"<<wenjian<<endl;else{print ();stac.push ( "E" );infile>>ch;while ( ch != "\0"){top_stack = stac.inn [stac.top];if ( term.is_term ( ch ) ){if ( top_stack == "#" && ch == "#" ){//结束stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t本次匹配结束!"<<endl;infile>>ch;if ( ch != "\0" ){cout<<"下一条语句开始执行匹配:"<<endl;stac.push ( "E" );continue;}else{cout<<"\t\t文件语法分析完毕!\n"<<endl;break;}}else if ( term.is_term ( top_stack ) ) //终结符{if ( top_stack == ch ) {stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t匹配终结符:"<<ch<<endl;stac.pop ( );}else{stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t出错跳过该符号"<<ch<<endl;}}else if ( ( rece = find ( top_stack, ch ) ) != "\0" )//非终结符{if ( rece == empty ){//指向空stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t展开非终结符:"<<top_stack<<"->ε"<<endl;stac.pop ();continue;}else if ( rece == "ERROR" )//出错{if ( nont.is_follow ( stac.inn [stac.top-1], ch ) )//属于follow集error ( 1 ){stac.display ();cout<<"\t\t"<<stac.inn [--stac.top] <<"\t\t"<<ch<<"\t\t出错,弹出该栈顶元素"<<endl;}else{//不属于follow集error ( 2 )stac.display ();cout<<"\t\t"<<stac.inn [stac.top] <<"\t\t"<<ch<<"\t\t 出错,不属于follow集故须跳过符号"<<ch <<endl;infile>>ch;}continue;}else//指向正常的非终结符{if ( rece == "id" || rece == "num" ){stac.pop ( );stac.push ( rece );}else{string str2;int i = 0;while ( rece[i] != '\0' )i ++;stac.pop ();for ( int j = i - 1; j >= 0; j -- ){str2 += rece[j];stac.push ( str2 );str2 = "\0";}}stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t展开非终结符:"<<top_stack<<"->"<<rece<<endl;continue;}}}else {stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t出错,跳过,无法识别该标识符"<<ch<<endl;}infile>>ch;}}infile.close ();}输出形式参考下图:四、实验总结通过实验,我对LL1()的算法有了初步的了解,基本能够编出代码,虽然有的地方处理的不是很好,我想通过后期的改正能够把程序改的完美。
实验3 语义分析实验报告一、实验目的二、通过上机实习, 加深对语法制导翻译原理的理解, 掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
三、实验要求四、采用递归下降语法制导翻译法, 对算术表达式、赋值语句进行语义分析并生成四元式序列。
五、算法思想1.设置语义过程。
(1)emit(char *result,char *ag1,char *op,char *ag2)该函数的功能是生成一个三地址语句送到四元式表中。
四元式表的结构如下:struct{ char result[8];char ag1[8];char op[8];char ag2[8];}quad[20];(2) char *newtemp()该函数回送一个新的临时变量名, 临时变量名产生的顺序为T1, T2, …char *newtemp(void){ char *p;char m[8];p=(char *)malloc(8);k++;itoa(k,m,10);strcpy(p+1,m);p[0]=’t’;return(p);}六、 2.函数lrparser 在原来语法分析的基础上插入相应的语义动作: 将输入串翻译成四元式序列。
在实验中我们只对表达式、赋值语句进行翻译。
源程序代码:#include<stdio.h>#include<string.h>#include<iostream.h>#include<stdlib.h>struct{char result[12];char ag1[12];char op[12];char ag2[12];}quad;char prog[80],token[12];char ch;int syn,p,m=0,n,sum=0,kk; //p是缓冲区prog的指针, m是token的指针char *rwtab[6]={"begin","if","then","while","do","end"};void scaner();char *factor(void);char *term(void);char *expression(void);int yucu();void emit(char *result,char *ag1,char *op,char *ag2);char *newtemp();int statement();int k=0;void emit(char *result,char *ag1,char *op,char *ag2){strcpy(quad.result,result);strcpy(quad.ag1,ag1);strcpy(quad.op,op);strcpy(quad.ag2,ag2);cout<<quad.result<<"="<<quad.ag1<<quad.op<<quad.ag2<<endl;}char *newtemp(){char *p;char m[12];p=(char *)malloc(12);k++;itoa(k,m,10);strcpy(p+1,m);p[0]='t';return (p);}void scaner(){for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];while(ch==' '){ch=prog[p];p++;}if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){m=0;while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}else if((ch>='0'&&ch<='9')){{sum=0;while((ch>='0'&&ch<='9')){sum=sum*10+ch-'0';ch=prog[p++];}}p--;syn=11;if(sum>32767)syn=-1;}else switch(ch){case'<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=23;p--;}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'*':syn=13;token[0]=ch;break; case'/':syn=14;token[0]=ch;break; case'+':syn=15;token[0]=ch;break; case'-':syn=16;token[0]=ch;break; case'=':syn=25;token[0]=ch;break; case';':syn=26;token[0]=ch;break; case'(':syn=27;token[0]=ch;break; case')':syn=28;token[0]=ch;break; case'#':syn=0;token[0]=ch;break; default: syn=-1;break;}}int lrparser(){//cout<<"调用lrparser"<<endl;int schain=0;kk=0;if(syn==1){scaner();schain=yucu();if(syn==6){scaner();if(syn==0 && (kk==0))cout<<"success!"<<endl;}else{if(kk!=1)cout<<"缺end!"<<endl;kk=1;}}else{cout<<"缺begin!"<<endl;kk=1;}return(schain);}int yucu(){// cout<<"调用yucu"<<endl;int schain=0;schain=statement();while(syn==26){scaner();schain=statement();}return(schain);}int statement(){//cout<<"调用statement"<<endl;char *eplace,*tt;eplace=(char *)malloc(12);tt=(char *)malloc(12);int schain=0;switch(syn){case 10:strcpy(tt,token);scaner();if(syn==18){scaner();strcpy(eplace,expression());emit(tt,eplace,"","");schain=0;}else{cout<<"缺少赋值符!"<<endl;kk=1;}return(schain);break;}return(schain);}char *expression(void){char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt =(char *)malloc(12);strcpy(eplace,term ()); //调用term分析产生表达式计算的第一项eplacewhile((syn==15)||(syn==16)){if(syn==15)strcpy(tt,"+");else strcpy(tt,"-");scaner();strcpy(ep2,term()); //调用term分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果emit(tp,eplace,tt,ep2); //生成四元式送入四元式表strcpy(eplace,tp);}return(eplace);}char *term(void){// cout<<"调用term"<<endl;char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt=(char *)malloc(12);strcpy(eplace,factor());while((syn==13)||(syn==14)){if(syn==13)strcpy(tt,"*");else strcpy(tt,"/");scaner();strcpy(ep2,factor()); //调用factor分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果emit(tp,eplace,tt,ep2); //生成四元式送入四元式表strcpy(eplace,tp);}return(eplace);}char *factor(void){char *fplace;fplace=(char *)malloc(12);strcpy(fplace,"");if(syn==10){strcpy(fplace,token); //将标识符token的值赋给fplacescaner();}else if(syn==11){itoa(sum,fplace,10);scaner();}else if(syn==27){scaner();fplace=expression(); //调用expression分析返回表达式的值if(syn==28)scaner();else{cout<<"缺)错误!"<<endl;kk=1;}}else{cout<<"缺(错误!"<<endl;kk=1;}return(fplace);}void main(){p=0;cout<<"**********语义分析程序**********"<<endl;cout<<"Please input string:"<<endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();}七、结果验证1、给定源程序begin a:=2+3*4; x:=(a+b)/c end#输出结果2、源程序begin a:=9; x:=2*3-1; b:=(a+x)/2 end#输出结果八、收获(体会)与建议通过此次实验, 让我了解到如何设计、编制并调试语义分析程序, 加深了对语法制导翻译原理的理解, 掌握了将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
《编译原理》实验报告班级:计C104姓名:李云霄学号:108490实验一词法分析程序实现一、实验目的与要求通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符形式的源程序流转化为一个由各类单词符号组成的流的词法分析方法。
二、实验内容选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。
输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。
输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。
三、实现方法与环境1、首先设计识别各类单词的状态转换图。
描述无符号常数的确定、最小化状态转换图如图1所示。
其中编号0,1,2,…,6代表非终结符号<无符号数>、<余留无符号数>、<十进小数>、<小数部分>、<指数部分>、<整指数>及<余留整指数>, 1,2和6为终态,分别代表整数、小数和科学计数的识别结束状态。
图1 文法G[<无符号数>]的状态转换图其中编号0,1,2,…,6代表非终结符号<无符号数>、<余留无符号数>、<十进小数>、<小数部分>、<指数部分>、<整指数>及<余留整指数>, 1,2和6为终态,分别代表整数、小数和科学计数的识别结束状态。
在一个程序设计语言中,一般都含有若干类单词符号,为此可首先为每类单词建立一张状态转换图,然后将这些状态转换图合并成一张统一的状态图,即得到了一个有限自动机,再进行必要的确定化和状态数最小化处理,最后据此构造词法分析程序。
四则运算算术符号的识别很简单,直接在状态图的0状态分别引出相应标记的矢根据描述语言中各类单词的文法状态转换图或状态矩阵,利用某种语言(C语言或JAVA语言)直接编写词法分析程序。
实验报告第 1 页专业____软件工程________ 班级____2_____ 姓名_71李飞强77欧艺欣81吴文浩89张泰鑫__ 组别:第四组实验日期:2014年 3 月26 日报告退发(订正、重做)课程编译原理实验名称递归下降的预测分析一、实验目的1. 学会用语法图来形式化地描述一门简单的语言;2. 掌握递归下降的预测分析;3. 掌握词法分析。
二、实验环境Visual Studio 或 GCC 或Eclipse三、实验内容、步骤和结果分析实验内容:请基于递归下降的分析方法(教材P55页),编写一个“语法图.doc”所对应语言的语法分析器。
该语法分析器能读入一个源代码文件(如“test.c”文件所示),并判断其中的源代码是否符合“语法图.doc”的规定。
如果符合,打印出Yes;如果不符合,打印出No。
(所用编程语言不限)C语言版:#include<stdio.h>#include<string.h>#include<stdlib.h>#define MaxIdLen 20 //标志符的最大长度#define KeyWordsCount 5 //该语言拥有的关键字个数#define BoolValueCount 2 //bool类型可能取值的个数#define SymTypeCount 17 //symType个数enum SymType//枚举{OR , //或AND, //与LP, //左括号RP, //右括号ID, //标志符ASSIGN, //赋值LB, //左大括号RB, //右大括号COMMA, //逗号SEMICOLON, //分号UNDEFINED, //未定义BOOLVALUE, //bool类型的值IF, //ifELSE, //elseWHILE, //whilePRINTF, //printfBOOL, //bool};enum boolValue{TRUE,FALSE,};//关键字static char * keywords[KeyWordsCount] = { "if","else","while","printf","bool",};//关键字对应类别static int keyType[KeyWordsCount] = { IF,ELSE,WHILE,PRINTF,BOOL,};static char * boolvalue[BoolValueCount]={"true","false",};static int boolValueType[BoolValueCount]={TRUE,FALSE,};char ch=' '; //当前字符char id[MaxIdLen+1]; //当前符号串int token; //当前记号(的类型)int value; //当前记号的值FILE * fp; //用来打开要识别的源代码文件int lineNum=1; //要识别的代码行数bool isPass = false ; //判断识别的代码是否全部合法void getToken();void program();void program();void statement();void definition();void term();void factor();void expression();void match(int t);void main(){fopen_s(&fp,"D:\\test.c","r");getToken();program();if(isPass)printf("Y\n");else printf("N\n");fclose(fp);}/****************************************lexical*****************************************/int getKeyWord(char * str){for(int i=0;i<KeyWordsCount;i++)if(strcmp(str,keywords[i])==0)return keyType[i];return UNDEFINED;}int getBoolValue(char* str){for(int i=0;i<BoolValueCount;i++)if(strcmp(str,boolvalue[i])==0){value = boolValueType[i];return BOOLVALUE;}return UNDEFINED;}bool isLetter(char ch){return (ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'); }bool isDigit(char ch){return ch>='0'&&ch<='9';}void nextChar(){ch = fgetc(fp);}void getToken(){while(ch==' '||ch=='\t'||ch=='\r'||ch=='\n'){if(ch == '\n')lineNum++;nextChar();}if(isLetter(ch)){int index=0;id[index++] = ch;nextChar();while(isLetter(ch) || isDigit(ch)){if(index<MaxIdLen){id[index++] = ch;nextChar();}else{//cout<<"identifier is too long."<<endl;//exit(1);}}id[index]='\0';token = getKeyWord(id);if(token == UNDEFINED)token = getBoolValue(id);if(token == UNDEFINED){token = ID;}}else if(ch == '='){token = ASSIGN;nextChar();}else if(ch=='|'){nextChar();if(ch=='|'){token=OR;nextChar();}elseexit(1);}else if(ch=='&'){nextChar();if(ch=='&'){token=AND;nextChar();}elseexit(1);}else if(ch == ';'){token = SEMICOLON;nextChar();}else if(ch == '('){token = LP;nextChar();}else if(ch == ')'){token = RP;nextChar();}else if(ch == ','){token = COMMA;nextChar();}else if(ch == '{'){token = LB;nextChar();}else if(ch == '}'){token = RB;nextChar();}else if(ch == EOF){printf(" EOF!\n");isPass = true;}else{printf("第%d行不能识别的符号!\n",lineNum );exit(1);}}/****************************************grammar*****************************************/void match(int t){if(t == token){getToken();}else{printf("大概在第%d行错误\n",lineNum);exit(1);}}void expression(){term();while(token == OR){match(OR);term();}}void factor(){if(token == BOOLVALUE && value == TRUE)match(BOOLVALUE);else if(token == BOOLVALUE && value == FALSE) match(BOOLVALUE);else if(token == LP){match(LP);expression();match(RP);}else if(token == ID)match(ID);}void term(){factor();while(token == AND){match(AND);factor();}}void definition(){do{match(BOOL);match(ID);match(ASSIGN);expression();match(SEMICOLON);}while(token == BOOL);}void statement(){if(token == IF){match(IF);match(LP);expression();match(RP);statement();if(token == ELSE){match(ELSE);statement();}}else if(token == PRINTF){match(PRINTF);match(LP);expression();while(token == COMMA){match(COMMA);expression();}match(RP);match(SEMICOLON);}else if(token == WHILE){match(WHILE);match(LP);expression();match(RP);statement();}else if(token == LB){match(LB);do{statement();}while(token != RB);match(RB);}else if(token == ID){match(ID);match(ASSIGN);expression();match(SEMICOLON);}else if(token == SEMICOLON){match(SEMICOLON);}}void program(){definition();statement();}Java版:(吴文浩)Java版的关键代码:// 由语法分析带动翻译public void parse(String src) {this.lexer = new GrammarLexer(src);lookahead = lexer.getToken();program();}private void match(TokenType type) {// 如果记号lookahead的类型是type,则取下一个记号System.out.println("------------>" + type);if (lookahead.tokenType.equals(type)) {lookahead = lexer.getToken();} else {error("NO");// 否则报错}}private void error(String str) {// out.println(str);System.out.println(str);System.exit(-1);}/*** program:程序 definition----->statement-------->*/public void program() {definition();//定义statement();// 声明}// definition:定义/*** bool-->id-->=-->expression-->;*/public void definition() {do {match(TokenType.BOOLEAN);match(TokenType.ID);match(TokenType.EQUAL);expression();match(TokenType.SEMICOLON);// 匹配分号} while (lookahead.isBoolean());}// statement:声明public void statement() {if(lookahead.isIf()) {// -->if-->(-->expression-->)-->statement--->match(TokenType.IF);match(TokenType.LeftP);expression();match(TokenType.RightP);statement();if(lookahead.isElse()) {//缺陷:如果用全部代码测试时,程序走到这里停止了,while循环后的语句将不能执行!match(TokenType.ELSE);statement();} else {}} else if (lookahead.isWhile()) {match(TokenType.WHILE);match(TokenType.LeftP);expression();match(TokenType.RightP);statement();} else if (lookahead.isPrint()) {match(TokenType.PRINT);match(TokenType.LeftP);expression();while (lookahead.isComma()) {match(MA);expression();}match(TokenType.RightP);match(TokenType.SEMICOLON);} else if (lookahead.isSemicolon()) {// ;match(TokenType.SEMICOLON);} else if (lookahead.isLeftBrace()) {match(TokenType.LeftBrace);statement();while(!lookahead.isRightBrace() || lookahead.isId() ){//必须加入lookahead.isId()否则a = false;运行不出来(语法图缺陷吧!)statement();}match(TokenType.RightBrace);} else if (lookahead.isId()) {// id = expression;// System.out.println("++++++++++++++++++++");match(TokenType.ID);match(TokenType.EQUAL);expression();match(TokenType.SEMICOLON);} else {}}/***expression:式子-------->term()----(---->||------->term()---->);*/private void expression() {term();while (lookahead.isOr()) {// 如果是||就继续循环处理match(TokenType.OR);term();}}/***term:项 Factor(); While(match(‘&&’)){ Factor(); }*/private void term() {factor();while (lookahead.isAnd()) {// 判断是&&就继续进行match(TokenType.AND);factor();}}/*** --->(------>expression--------->)--------->* ---->true---->* ---->false---->* ---->id------>*/private void factor() {if (lookahead.isTrue()) {match(TokenType.TRUE);} else if (lookahead.isLeftP()) {match(TokenType.LeftP);expression();match(TokenType.RightP);} else if (lookahead.isFalse()) {match(TokenType.FALSE);} else if (lookahead.isId()) {match(TokenType.ID);} else{}}/*** 获取下一个Token*/public Token getToken() {int value = 0;char cur;while (true) {if (index >= src.length())return Token.EOF;else {// 取下一字符cur = next();// 如果下一个字符是空白,继续读取字符if (this.isBlank(cur))continue;else if (this.isAlpha(cur)) {// 字符缓冲区StringBuilder buffer = new StringBuilder();buffer.append(cur);while (isAlpha((char) peek())) {buffer.append(next());}if(buffer.toString().equals(KeyWord.BOOLEAN)) {return new Token(TokenType.BOOLEAN, buffer.toString());} else if (buffer.toString().equals(KeyWord.FALSE)) {return new Token(TokenType.FALSE, buffer.toString());} else if (buffer.toString().equals(KeyWord.TRUE)) {return new Token(TokenType.TRUE, buffer.toString());} else if(buffer.toString().equals(KeyWord.IF)) {return new Token(TokenType.IF, buffer.toString());} else if (buffer.toString().equals(KeyWord.WHILE)) {return new Token(TokenType.WHILE, buffer.toString());} else if (buffer.toString().equals(KeyWord.PRINT)) {return new Token(TokenType.PRINT, buffer.toString());} else {return new Token(TokenType.ID, buffer.toString());}} else if (cur == ',') {return MA;} else if (cur == '(') {return Token.LeftP;} else if (cur == ')') {return Token.RightP;} else if (cur == '|' && next() == '|') {return Token.OR;// 或者} else if (cur == '&' && next() == '&') {return Token.AND;// 且} else if (cur == '=') {return Token.EQUAL;} else if (cur == ';') {return Token.SEMICOLON;// 分号} else if (cur == '{') {// 左大括号return Token.LeftBrace;} else if (cur == '}') {return Token.RightBrace;} else if (cur == '\n') {line++;} else {this.error();}}}}运行这个测试代码的截图:String src = "boolean a = true;boolean b = false;boolean c = (a && b);if( a || b) print(a,b);else print(c);";运行这个测试代码的截图:String src = "boolean a = true; while(a && (b||c)){print(a,b,c);a = false;}";四、讨论(说明实验过程中遇到的问题及解决办法;未解决/需进一步研讨的问题或建议新实验方法等)在text.c中先是声明bool类型,然后是if语句,最后是while语句。
编译原理实验教程课程设计背景编译原理是计算机科学专业的一门重要课程,它研究如何将高级语言翻译成低级语言,以便计算机执行。
编译器是实现这一过程的关键工具。
然而,对于很多学生来说,编译原理的理论知识学习起来比较抽象,难以掌握。
因此,本文旨在为编译原理的学习提供一些实验教程的设计思路。
实验一:词法分析器词法分析器是编译器的第一个模块,它的作用是将输入的字符流转化为一个个单词符号。
本实验的目的是设计并实现一个简单的词法分析器,实现以下功能:1.识别输入的程序中所包含的各个单词符号。
2.输出所有单词符号及其对应的单词类型。
3.当遇到不合法单词符号时,给出相应的错误提示。
具体实现可以采用有限自动机的思想,使用正则表达式或者手写代码,实现对于不同的单词类型的识别,并对于不合法单词进行识别和报错处理。
实验二:语法分析器语法分析器是编译器的第二个模块,它的作用是将词法分析器输出的单词序列转换成语法树或者语法分析表,以便后续进行语义分析和目标代码生成。
本实验的目的是设计并实现一个简单的语法分析器,实现以下功能:1.识别输入的程序是否符合所设计的文法规则。
2.输出语法树或语法分析表。
具体实现可以采用自上而下的递归下降分析法或自下而上的移进-规约分析法,实现对于不同的句型的识别,并生成语法树或语法分析表。
实验三:语义分析器语义分析器是编译器的第三个模块,它的作用是对语法分析器输出的语法树或语法分析表进行语义分析,并生成中间代码。
本实验的目的是设计并实现一个简单的语义分析器,实现以下功能:1.对语法树或语法分析表进行遍历,识别语法错误和语义错误,给出相应的错误提示。
2.生成中间代码。
具体实现可以采用语义规则和符号表的检查方式,识别语法错误和语义错误,并在生成中间代码时,根据中间代码语言的规则进行实现。
实验四:目标代码生成器目标代码生成器是编译器的第四个模块,它的作用是将中间代码转换成机器语言,以便计算机执行。
本实验的目的是设计并实现一个简单的目标代码生成器,实现以下功能:1.将中间代码转换成机器语言。
电力学院编译原理课程实验报告实验名称:实验三自下而上语法分析及语义分析院系:计算机科学与技术学院专业年级:学生:学号:指导老师:实验日期:实验三自上而下的语法分析一、实验目的:通过本实验掌握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][4]="S13";tableData[2][6]="R3";tableData[2][7]="R3";tableData[3][1]="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][2]="S12"; 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][0]="S5"; tableData[13][5]="S4"; tableData[14][1]="R2"; tableData[14][2]="R2";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;//关键字表和对应的编码string codestring[10]={"main","int","if","then","else","return","void","cout","endl"}; int 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<<"附近。