合肥工业大学编译原理实验报告(完整代码版)

  计算机与信息学院

  编译原理

  实验报告 专

 业

 班

 级

  信息安全 131 班

  学生姓名及学号

  马骏 2013211869

 课 程 教 学 班 号

 任

 课

 教

 师

 李宏芒

  实 验 指 导 教 师

 李宏芒

 实 验 地 点

 实验楼机房

  2015

  ~2016

  学年第 二 学期 验 实验 1

 词法分析设计 一、

 实验目得

  通过本实验得编程实践,使学生了解词法分析得任务,掌握词法分析程序设 计得原理与构造方法,使学生对编译得基本概念、原理与方法有完整得与清楚得 理解,并能正确地、熟练地运用 二、 实验要求

  1、编程时注意编程风格:空行得使用、注释得使用、缩进得使用等。

 2、将标识符填写得相应符号表须提供给编译程序得以后各阶段使用。

 3、根据测试数据进行测试。测试实例应包括以下三个部分:

  全部合法得输入。

  各种组合得非法输入。

  由记号组成得句子。

 4、词法分析程序设计要求输出形式:

 例:输入 VC++语言得实例程序:

 If i=0 then

  n++;

 a﹤= 3b %);

 输出形式为:

 单词

  二元序列

 类

 型

 位置(行,列)

  (单词种别,单词属性)

 for

 (1,for )

  关键字

 (1,1)

 i

 ( 6,i )

 标识符

  (1,2)

 =

  ( 4,= )

 关系运算符

 (1,3)

  12

 0

  ( 5,0 )

  常数

 (1,4)

 then

 ( 1,then)

  关键字

 (1,5)

 n

  (6,n )

  标识符

 (1,6)

 ++

 Error

  Error

  (1,7)

 ;

  ( 2, ; )

  分界符

  (1,8)

 a

  (6,a )

 标识符

 (2,1)

 ﹤=

  (4,<= )

  关系运算符

  (2,2)

 3b

 Error

  Error

  (2,4)

 %

 Error

  Error

  (2,4)

 )

  ( 2, ) )

 分界符

 (2,5)

 ;

  ( 2, ; )

 分界符

  (2,6)

 三、

 实验内容 用 VC++/VB/JAVA 语言实现对 C 语言子集得源程序进行词法分析。通过输 入源程序从左到右对字符串进行扫描与分解,依次输出各个单词得内部编码及单 词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示 ;同时 进行标识符登记符号表得管理。

 以下就是实现词法分析设计得主要工作:

 (1)从源程序文件中读入字符。

 (2)统计行数与列数用于错误单词得定位。

 (3)删除空格类字符,包括回车、制表符空格。

 (4)按拼写单词,并用(内码,属性)二元式表示。(属性值——token 得机内 表示)

 (5)如果发现错误则报告出错

  7

 (6)根据需要就是否填写标识符表供以后各阶段使用。

 四、实验步骤 1、根据流程图编写出各个模块得源程序代码上机调试。

 2、 编制好源程序后,设计若干用例对系统进行全面得上机测试,并通过所设计 得词法分析程序;直至能够得到完全满意得结果。

 3、书写实验报告 ;实验报告正文得内容:

 功能描述:该程序具有什么功能?

 程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;函数 之间得调用关系图。

 详细得算法描述(程序总体执行流程图) 。

 给出软件得测试方法与测试结果。

 实验总结 (设计得特点、不足、收获与体会)。

 五、实验 截图

 先创建 salary 文件 输入 If i=0 then

  n++;

 a<= 3b %);

 六、 核心代码

 #include<iostream> #include<string> #include<fstream> #include <sstream> using namespace std; const char* salaryfile="salary"; const int max=40; string id[max]={"do","end","for","if","printf","scanf","then","while"};// 关键字表 string s[max]={",",";","(",")","[","]","+","","*","/","<","<=","=",">",">=","<>"};// 分界符表 算数运算符表

 关系运算符表 string k[max];// 标识符 string ci[max];// 常数 int fjfpoint=5;// 分界符表尾 int mathpoint=9;// 算数运算符表尾 int cipointer=0;// 常数表尾 int idpointer=0;// 关键字表尾 int kpointer=0;// 标识符表尾 int fjf;//0 不就是分界符 1 就是

 int rowy=1;// 识别输入行位置 int rowx=1;// 识别输入列位置 int outkey=0;// 打印控制 0 为数字后有字母 其她可以 void searcht(int i,string m)// 根据已识别得首字母识别字符串 { // cout<<"enter searcht!!"<<endl;

 int x;

 if(i==0)// 首字符就是字母识别关键字

 { //

 cout<<" a word!!"<<endl;

  for(x=0;x<max;x++)

  {

 if(id[x]==m)

 {

  cout<<"(1,"<<id[x]<<")"<<" 字 关 键 字 ("<<rowy<<","<<rowx<<")"<<endl;

  break;

 }

  }

  if(x==max)// 不就是关键字再识别标识符

  {

 for(x=0;x<max;x++)

 {

  if(k[x]==m)

  {

 cout<<"(6,"<<m<<") "<<" 符 标 识 符 ("<<rowy<<","<<rowx<<")"<<endl;

  break;

  }

 }

 if(x==max)// 标识符表没有时插入标识符

 {

  cout<<"(6,"<<m<<") "<<" 符 标 识 符 ("<<rowy<<","<<rowx<<")"<<endl;

  k[kpointer]=m;

  kpointer++;

 }

  }

 }

 if(i==1)// 识别常数

 {

 // cout<<"

 a number!!"<<endl;

  for(x=0;x<max;x++)

  {

  if(ci[x]==m)

 {

  cout<<"(5,"<<x<<")"<<endl;

  break;

 }

  }

  if(x==max)

  {

  cout<<"(5,"<<m<<") 常数 ("<<rowy<<","<<rowx<<")"<<endl;

 ci[cipointer]=m;

 cipointer++;

  }

 }

 if(i==2)// 识别 分界符 算数运算符

 关系运算符

 {

 // cout<<"

 a signal!!"<<endl;

  for(x=0;x<max;x++)

  {

 if(s[x]==m)

  break;

  }

 // x;

  if(x<6)

  {

 fjf=1;

  }

  if(x>5&&x<10)

  {

 if(outkey==1)

 {

  cout<<"(3,"<<s[x]<<") 符 算 数 运 算 符 ("<<rowy<<","<<rowx<<")"<<endl;

 outkey=0;

 }

 fjf=0;

  }

  if(x>9&&x<max1)

  {

 if(outkey==1)

 {

 cout<<"(4,"<<s[x]<<") 符 关 系 运 算 符 ("<<rowy<<","<<rowx<<")"<<endl;

 outkey=0;

 }

  fjf=0;

  }

  if(x==max)

  {

 if(outkey==1)

 {

 cout<<"Error

  Error ("<<rowy<<","<<rowx<<")"<<endl;

 outkey=0;

 }

 fjf=0;

  }

 } }; void wordlook(char t,string sn)// 识别首字符, 分类识别字符串 {

 if(t>=48&&t<=57)

  searcht(1,sn);

 else

 {

  if((t>64&&t<91)||(t>96&&t<123))

  searcht(0,sn);

  else searcht(2,sn);

 } }; void split(string s)// 分割字符串 { // cout<<s<<endl;

 string now[max];

 string sn;

 int nowpointer=0;

 int i=0;

 int x;

 int sign=2;// 非法数字标志

 int diannumber=0;// 数中点得个数

 for(x=0;x<s 、length;x++)

 {

  if((s[x]>64&&s[x]<91)||(s[x]>96&&s[x]<123)||(s[x]>=48&&s[x]<=57)||(x>0&&s[x]==46&&sign==1))// 判断数字后跟字母还就是字母后有数字

  {

 if(i==0)

 {

 if(s[x]>=48&&s[x]<=57)

  sign=1;

 else sign=2;

 }

 else

 {

  if(sign==1)

  {

 if(s[x]>=48&&s[x]<=57||s[x]==46)

 {

  if(s[x]==46)

  {

 if(diannumber==0)

  diannumber++;

 else sign=0;

  }

 }

 else sign=0;

  }

 }

 i++;

 if(x==(s 、length1))

 {

 sn=s 、substr(xi+1,i);

 if(i>0)

 {

 //

 cout<<sn<<" i="<<i<<endl;

  cout<<sn<<" ";

  if(sign==0)// 数字后有字母得情况

  cout<<"

  Error

 Error

 ("<<rowy<<","<<rowx<<")"<<endl;

 else // 字母开头得字符串

  {

 //

 cout<<"

  true"<<endl;

 wordlook(sn[0],sn);

  rowx++;

  }

 }

 }

  }

  else

  {

 if(x>0&&(s[x1]>64&&s[x1]<91)||(s[x1]>96&&s[x1]<123)||(s[x1]>=48&&s[x1]<=57))// 遇到分界符运算符 如果前面就是数字或字母

 {

 sn=s 、substr(xi,i);

  if(i>0)

  {

 //

 cout<<sn<<" i="<<i<<endl;

 cout<<sn<<" ";

 if(sign==0)

 cout<<" Error Error ("<<rowy<<","<<rowx<<")"<<endl;

 else

 {

  //

  cout<<"

  true"<<endl;

  wordlook(sn[0],sn);

 rowx++;

 }

  }

  i=0;

 }

 string ll=s 、substr(x,1);// 判断就是运算符还就是分界符

 wordlook(s[x],ll);

 if(fjf==0)// 就是运算符

 {

  i++;

  if((s[x+1]>64&&s[x+1]<91)||(s[x+1]>96&&s[x+1]<123)||(s[x+1]>=48&&s[x+1]<=57))// 如果后面就 是数字或字母

  {

 sn=s 、substr(xi+1,i);

 // cout<<sn<<" 运算符 i="<<i<<endl;

 cout<<sn<<" ";

 outkey=1;

 wordlook(sn[0],sn);

 rowx++;

  i=0;

  }

 }

 if(fjf==1)

 {

  if((s[x1]>64&&s[x1]<91)||(s[x1]>96&&s[x1]<123)||(s[x1]>=48&&s[x1]<=57))// 如 如果前面就是数字或字母

 {

 }

 else if(i>0)

 {

 sn=s 、substr(xi,i);

  // cout<<sn<<" 运算符 i="<<i<<endl;

 cout<<sn<<" ";

 outkey=1;

 wordlook(sn[0],sn);

 rowx++;

  i=0;

 }

 cout<<s[x]<<" (2,"<<s[x]<<") 符 分 界 符 ("<<rowy<<","<<rowx<<")"<<endl;

 rowx++;

 /*

 if(ll==";")

 {

 rowy++;

 rowx=1;

 }

 */

 }

  }

 } }; int main {

 int x;

 string instring;// 读入一行

 string sn; /*

  getline(cin,sn);// string 带空格输入

 cout<<sn<<endl;

 char t=sn[0];

 if(t>=48&&t<=57)

  searcht(1,sn);

 else

 {

  if((t>64&&t<91)||(t>96&&t<123))

  searcht(0,sn);

  else searcht(2,sn);

 } */

 ifstream input

  input(salaryfile); // inputfile>>noskipws;

 if(!inputfile)

 {

  cout<<"no file"<<endl;

  }

 string pp;

 while(!input)

  {

  getline(input);

  istringstream istr(pp);

  string ppword;

  while(istr>>ppword)// 按照空格分割字符串

  {

 split(ppword);

  } /*

  int begin = 0;// 去掉字符串得所有空格

  begin = pp 、find(" ",begin);

 // 查找空格在 str 中第一次出现得位置

  while(begin != 1)

 // 表示字符串中存在空格

  {

  pp 、replace(begin, 1, "");

 // 用空串替换 str 中从 begin 开始得 1 个字符 符

  begin = pp 、find(" ",begin);

 // 查找空格在替换后得 str 中第一次出现得位置

  }

  */ // cout<<"good

 "<<pp<<endl; // rowx++;

  rowy++;// 换行

  rowx=1;

 }

 return 0; } 七、 实验总结

 通过本次试验使我不仅对词法分析器有了更深得了解,而且提高了编程能力,希望在以后得学习中可以解决词法分析更多得问题。

 验 实验 2

 LL(1) 分析法

 一、 实验目得 通过完成预测分析法得语法分析程序,了解预测分析法与递归子程序法得区 别与联系。使学生了解语法分析得功能,掌握语法分析程序设计得原理与构造方 法,训练学生掌握开发应用程序得基本方法。有利于提高学生得专业素质,为培 养适应社会多方面需要得能力。

 二、 实验要求 1、编程时注意编程风格:空行得使用、注释得使用、缩进得使用等。

 2、如果遇到错误得表达式,应输出错误提示信息。

 3、对下列文法,用 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

 三、 实验内容 根据某一文法编制调试

 LL (

 1 )分析程序,以便对任意输入得符号串 进行分析。

  构造预测分析表,并利用分析表与一个栈来实现对上述程序设计语言得分 析程序。

  分析法得功能就是利用 LL(1)控制程序根据显示栈栈顶内容、向前瞧符号 以及 LL(1)分析表,对输入符号串自上而下得分析过程。

 四、实验步骤

  1、根据流程图编写出各个模块得源程序代码上机调试。

 2、 编制好源程序后,设计若干用例对系统进行全面得上机测试,并通过所设计 得 LL(1)分析程序;直至能够得到完全满意得结果。

 3、书写实验报告 ;实验报告正文得内容:

  写出 LL(1)分析法得思想及写出符合 LL(1)分析法得文法。

  程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;函数 之间得调用关系图。

  详细得算法描述(程序执行流程图) 。

  给出软件得测试方法与测试结果。

  实验总结 (设计得特点、不足、收获与体会)。

 五、实验 截图

  六、 核心代码

  #include<iostream> #include<string> using namespace std; string pp;// 输出字符串 string hh="\r\n";// 换行 const int max=50; int endfu[max];// 终止符序号表 int endfupointer=8; char endfureal[max]={"+","","*","/","(","i",")","#"}; int unendfu[max]; int unendfupointer=5; char unendfureal[max]={"E","G","T","S","F"}; string makemath[max]={"E>TG","G>+TG","G>TG","G>$","T>FS","S>*FS","S>/FS","S>$","F>(E)","F>i"}; //0 E>TG,1 G>+TG,2 G>TG,3 G>$,4 T>FS,5 S>*FS,6 S>/FS,7 S>$,8 F>(E),9 F>i //$ 代表空串 string behavior[max]={" 初始化","POP"}; int smarttable[max][max];// 分析表 int checkendfu(char fu)// 查终结符序号 {

 int x;

 for(x=0;x<endfupointer;x++)

 {

  if(endfureal[x]==fu)

 {

 break;

  }

 }

 if(x<endfupointer)

 return x;

 else return 1; }; int checkunendfu(char fu)// 查非终结符序号 {

 int x;

 for(x=0;x<unendfupointer;x++)

 {

  if(unendfureal[x]==fu)

 break;

 }

 if(x<unendfupointer)

 return x;

 else return1; }; string checkmakemath(int x)// 查产生式表 {

 return makemath[x]; }; int checksmarttable(int x,int y)// 查分析表 {

 return smarttable[x][y]; }; class smartbox { public:

 smartbox

 {

  box[0]="#";

  box[1]="E";

  boxpointer=1;

 }

 void push(char fu)

 {

  boxpointer++;

  box[boxpointer]=fu;

 }

 char pop

 {

 char a=box[boxpointer];

  if(a!="#")

  { //

 cout<<"pop: "<<boxpointer<<"

 "<<a<<endl; //

 stringstream oss; /*

  pp=pp+"pop: ";

  char buffer[max];

  sprintf(buffer,"%d",boxpointer);

  string s=buffer;

  pp=pp+" ";

  pp=pp+s;

  pp=pp+hh; */

  boxpointer;

  return a;

  }

 }

 void check

 {

  if(checkendfu(box[boxpointer])!=1)

  {

  char a; //

 cout<<box[boxpointer]<<checkendfu(box[boxpointer])<<"

  ";

  //char buffer[max];

  //sprintf(buffer //

 pp=pp+box[boxpointer];

 // pp=pp+checkendfu(box[boxpointer]); //

 pp=pp+"

  ";

  a=pop;

 // cout<<"out "<<a<<endl;

  }

 }

 char box[max];

 int boxpointer; }; int main {

 // TODO: Add extra validation here // pp=pp+" 步骤

 分析栈

  剩余输入串

 所用产生式

  动作"+hh; /*

 string s1="sdsfs

 \r\nsdfsds";

 string s3="aaaaaaaaaaaaa";

 s3=s3+s1;

  CString s2(s3 、c_str); // CString s2=CString(s1);

 SetDlgItemText(IDC_EDIT2,s2);// 用 SetDlgItemText( 文本框 ID, 字符串), 将文本框得内容设置为字符串得内容、

 SetDlgItemText(IDC_EDIT2,s2); */ // MessageBox(str); string str; cin>>str;

 int x,y;

 for(x=0;x<max;x++)

 // 初始化分析表 99 为错误代号

  for(y=0;y<max;y++)

 smarttable[x][y]=99;

  smarttable[0][4]=0;

 smarttable[0][5]=0;

 smarttable[1][0]=1;

 smarttable[1][1]=2;

 smarttable[1][6]=3;

 smarttable[1][7]=3;

 smarttable[2][4]=4;

 smarttable[2][5]=4;

 smarttable[3][0]=7;

 smarttable[3][1]=7;

 smarttable[3][2]=5;

 smarttable[3][3]=5;

 smarttable[3][6]=7;

 smarttable[3][7]=7;

 smarttable[4][4]=8;

 smarttable[4][5]=9;

 smartbox mark;

 char fu;

 char enterfu;

 int endfunumber;

 int unendfunumber;

 string readyin;

 string enter; // cin>>enter;

 //enter="i+i*i#";

 enter=str; //enter="(i)#";

 int count=0; // 步骤

 char buffer1[max];

  sprintf(buffer1,"%d",count);

 string s1=buffer1;

 pp=pp+s1+"

  ";

  // 分析栈

 for(int qq1=0;qq1<=mark 、boxpointer;qq1++)

 {

  pp=pp+mark 、box[qq1];

 }

 for(qq1=0;qq1<10mark 、boxpointer;qq1++)

 {

  pp=pp+" ";

 }

 // 剩余输入栈

 string jiequ1=enter 、substr(0,enter 、length);

 pp=pp+jiequ1;

 for(int t1=0;t1<20;t1++)

 {

  pp=pp+" ";

 }

 pp=pp+"

  初始化"+hh;

 for(x=0;x<enter 、length;)

 {

 // 步骤

  count++;

 char buffer[max];

  sprintf(buffer,"%d",count);

  string s=buffer;

 pp=pp+s+"

  ";

  // 分析栈

 for(int qq=0;qq<=mark 、boxpointer;qq++)

 {

  pp=pp+mark 、box[qq];

 }

 for(qq=0;qq<10mark 、boxpointer;qq++)

 {

  pp=pp+" ";

 }

 // 剩余输入栈

 string jiequ=enter 、substr(x,enter 、lengthx);

 pp=pp+jiequ;

 for(int t=0;t<x+10;t++)

 {

  pp=pp+" ";

 }

  enterfu=enter[x];

  // cout<<"enterfu: "<<enterfu<<endl;

  mark 、check;

  fu=mark 、pop; //

 cout<<"fu: "<<fu<<endl;

  if(fu=="#")//&&enterfu=="#")

  {

 //

 cout<<"sucessed!!!!

  over!!!!"<<endl;

 pp=pp+"sucessed!!!!

  over!!!!"+hh;

 break;

  }

  unendfunumber=checkunendfu(fu);

  endfunumber=checkendfu(enterfu);

 // cout<<unendfunumber<<endl;

 // cout<<endfunumber<<endl;

  if(smarttable[unendfunumber][endfunumber]==99)

  {

 pp=pp+"error!!";

 break;

  }

  readyin=makemath[smarttable[unendfunumber][endfunumber]];

  pp=pp+readyin;

  for(int ddd=0;ddd<14readyin 、length;ddd++)

  {

 pp=pp+" ";

  }

 pp=pp+"POP,PUSH(";

  for(y=readyin 、length1;y>2;y)

  {

 pp=pp+readyin[y];

  }

  pp=pp+")"+hh;

 // cout<<"readyin:

 "<<readyin<<endl;

  int firsttime=0;

  for(y=readyin 、length1;y>2;y)

  {

  // cout<<readyin[y]<<" ";

 if(readyin[y]!="$")

 {

  mark 、push(readyin[y]);

  if(firsttime==0)

  {

 if(checkendfu(readyin[y])!=1)

  {

 //

 cout<<"now x: "<<x<<"

 ";

 // 步骤

  count++;

 char buffer[max];

  sprintf(buffer,"%d",count);

  string s=buffer;

 pp=pp+s+"

  ";

  // 分析栈

 for(int qq=0;qq<=mark 、boxpointer;qq++)

 {

  pp=pp+mark 、box[qq];

 }

 for(qq=0;qq<10mark 、boxpointer;qq++)

 {

  pp=pp+" ";

 }

 // 剩余输入栈

 string jiequ=enter 、substr(x,enter 、lengthx);

 pp=pp+jiequ;

 for(int t=0;t<x+10;t++)

 {

  pp=pp+" ";

 }

 pp=pp+"

 GETNEXT(I)"+hh;

 x++;

 //

  cout<<"next x: "<<x<<"

 "<<endl;

 firsttime=1;

  }

  }

 }

  }

  mark 、check;

 // cout<<endl; //

 pp=pp+hh;

 } cout<<pp; return 0;

 //CDialog::OnOK; } 七、 实验总结

  通过本次试验使我不仅对 ll(1)分析法有了更深得了解,而且提高了编程能力,希望在以后得学习中可以解决自动构造 follow 集得问题。

  实验 3

  LR(1) 分析法

 一、 实验目得 构造 LR(1)分析程序,利用它进行语法分析,判断给出得符号串就是否为该文 法识别得句子,了解 LR(K)分析方法就是严格得从左向右扫描,与自底向上得 语法分析方法。

 二、 实验要求 1、编程时注意编程风格:空行得使用、注释得使用、缩进得使用等。

 2、如果遇到错误得表达式,应输出错误提示信息。

 3、程序输入/输出实例:

 输入一以#结束得符号串(包括+*i#):在此位置输入符号串

 输出过程如下:

 步骤

 状态栈

 符号栈

 剩余输入串

 动 作

  1

 0

  #

 i+i*i#

 移进

  i+i*i 得 LR 分析过程

 步骤

 状态栈

 符号栈

 输入串

 动作说明

 1

 0

 #

 i+i*i#

 ACTION[0,i]=S5,状态 5 入栈

 2

 05

 #i

 +i*i#

 r6: F→i 归约,GOTO(0,F)=3 入栈

 3

 03

 #F

 +i*i#

 r4: T→F 归约,GOTO(0,T)=3 入栈

 4

 02

 #T

 +i*i#

 r2: E→T 归约,GOTO(0,E)=1 入栈

 5

 01

 #E

 +i*i#

 ACTION[1,+]=S6,状态 6 入栈

 6

 016

 #E+

 i*i#

 ACTION[6,i]=S5,状态 5 入栈

 7

 0165

 #E+i

 *i#

 r6: F→i 归约,GOTO(6,F)=3 入栈

 8

 0163

 #E+F

 *i#

 r4: T→F 归约,GOTO(6,T)=9 入栈

 9

 0169

 #E+T

 *i#

 ACTION[9,*]=S7,状态 7 入栈

 10

 01697

 #E+T*

 i#

 ACTION[7,i]=S5,状态 5 入栈

 11

 016975

 #E+T*i

 #

 r6:F→i 归约,GOTO(7,F)=10 入栈

 12

 0169710

 #E+T*F

 #

 r3: T→T*F 归约,GOTO(6,T)=9 入栈

 13

 0169

 #E+T

 #

 r1:E→E+T,GOTO(0,E)=1 入栈

 14

 01

 #E

 #

 Acc:分析成功

 三、 实验内容 对下列文法,用 LR(1)分析法对任意输入得符号串进行分析:

 (1)E> E+T

 (2)E>T

 (3)T> T*F

 (4)T>F

 (5)F> (E)

 (6)F> i

 四、实验步骤 1、根据流程图编写出各个模块得源程序代码上机调试。

 2、编制好源程序后,设计若干用例对系统进行全面得上机测试,并通过所设计 得 LR(1)语法分析程序;直至能够得到完全满意得结果。

 3、书写实验报告 ;实验报告正文得内容:

  描述 LR(1)语法分析程序得设计思想。

  程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;函数

 之间得调用关系图。

  详细得算法描述(程序执行流程图) 。

  给出软件得测试方法与测试结果。

 五、实验 截图

  六、 核心代码 #include<iostream> #include<string> using namespace std; int count=1; string pp;// 输出字符串 string hh="\r\n";// 换行 const int max=100; char endfureal[max]={"i","+","*","(",")","#","E","T","F"}; int endfupointer=8; string creatword[max]={"E>E+T","E>T","T>T*F","T>F","F>(E)","F>i"}; //(0)E> E+T(1)E>T (2)T> T*F (3)T>F (4)F> (E) (5)F> i

  // 注意 rj 时 时 j 应对应数组下标 int checkendfu(char fu)// 查终结符序号 {

 int x;

 for(x=0;x<=endfupointer;x++)

 {

  if(endfureal[x]==fu)

  {

 break;

  }

  }

 if(x<=endfupointer)

 return x;

 else return 1; }; class actiongo// 原子动作 { public:actiongo

  {

  // cout<<"eroor! wrong action or goto creat"<<endl;

 actype=4;

  }

  action(int i,int j)

  {

 actype=i;

 number=j;

 //

 cout<<i<<" "<<j<<endl;

  }

  int actype;//0=s 1=r 2=acc 3=goto 表 4=wrong

  int number; }; actiongo smarttable[max][max]; class stylebox// 状态栈 { public:

 stylebox

 {

  box[0]=0;

  boxpointer=0;

 }

 void push(int style)

 {

  boxpointer++;

  box[boxpointer]=style;

 }

 int pop

 {

  int a=box[boxpointer];

 boxpointer; //

 cout<<"pop now"<<endl;

  return a;

 }

 int box[max];

 int boxpointer;

 }; class readybox// 已归约栈 { public:

 readybox

 {

  box[0]="#";

  boxpointer=0;

 }

 void push(char fu)

 {

  boxpointer++;

  box[boxpointer]=fu;

 }

 char pop

 {

  char a=box[boxpointer];

  boxpointer;

  return a;

 }

 char box[max];

 int boxpointer; }; int program(stylebox&style,readybox&ready,char fu,int icount,string ptr,int control)// 返回就是否需要移进信号 { if(control==1) {

  //////////////////////////////

 char ber[max];

  sprintf(ber,"%d",count);

  string st=ber;

 pp=pp+st+"

 ";

  count++;

  ////////////////////////////////////

 //

  pp=pp+"

  ";

 for(int qq=0;qq<=style 、boxpointer;qq++)

 {

 char bss[max];

 sprintf(bss,"%d",style 、box[qq]);

 string st=bss;

  pp=pp+st;

 }

  for(qq=0;qq<10style 、boxpointer;qq++)

 {

  pp=pp+" ";

 }

 for( qq=0;qq<=ready 、boxpointer;qq++)

 {

  pp=pp+ready 、box[qq];

 }

 for(qq=0;qq<10ready 、boxpointer;qq++)

 {

  pp=pp+" ";

 }

 for(int dj=icount;dj<ptr 、length;dj++)

 {

  pp=pp+ptr[dj];

 }

 pp=pp+"

  "; //

  ////////////////////////////////////////

 }

 int i=style 、pop;// 如果就是 s 则状态还要入栈 // cout<<" 现在状态"<<i;

 int j=checkendfu(fu);

 if(j==1)

 {

  pp=pp+"error!!!";

  return 4;//wrong!!!

 } // cout<<"

 现在符号: "<<fu<<" "<<j<<endl;

 int checkstyle=smarttable[i][j] 、actype;// 查表

 if(checkstyle==4)

 {

  pp=pp+"error!!!";

  return 4;//wrong!!!

 }

 if(checkstyle==0||checkstyle==3)

 {

  style 、push(i);// 如果就是 s 则状态还要入栈

  if(checkstyle==0)

  {

 //cout<<"ACTION["<<i<<","<<fu<<"]=S"<<smarttable[i][j] 、number<<",状 状态 态"<<smarttable[i][j] 、number<<" 入栈"<<endl;

 pp=pp+"ACTION[";

  char buffer[max];

 sprintf(buffer,"%d",i);

  string s=buffer;

  pp=pp+s;

  pp=pp+",";

  pp=pp+fu;

  pp=pp+"]=S";

 char buf[max];

  sprintf(buf,"%d",smarttable[i][j] 、number);

  s=buf;

  pp=pp+s;

  pp=pp+", 状态";

  pp=pp+s+" 入栈"+hh;

  }

  if(checkstyle==3)

  {

  // cout<<i<<","<<endfureal[j]<<")="<<smarttable[i][j] 、 number<<"入栈"<<endl;

  char bf[max];

  sprintf(bf,"%d",i);

  string s=bf;

  pp=pp+s;

  pp=pp+","+endfureal[j]+")=";

 char bfff[max];

  sprintf(bfff,"%d",smarttable[i][j] 、number);

 s=bfff;

  pp=pp+s+" 入栈"+hh;

  }

  ready 、push(fu);

  style 、push(smarttable[i][j] 、number); //

 cout<<style 、box[style 、boxpointer]<<endl;

  return 1;// 移进

 }

 if(checkstyle==1)

 {

  string l=creatword[smarttable[i][j] 、number];

 // cout<<"r"<<smarttable[i][j] 、number+1<<": "<<l<<" 归约,GOTO(";

  pp=pp+"r";

  int dd=smarttable[i][j] 、number+1;

  char bfc[max];

  sprintf(bfc,"%d",dd);

  string ss=bfc;

 pp=pp+ss+": "+l+" 归约,GOTO(";

  char n;//pop 用得

  int x;

  // cout<<l 、length<<endl;

  char sq=ready 、pop;

  for(x=0;x<l 、length4;x++)// 前面 pop 一次了

  {

 n=style 、pop;

 n=ready 、pop; //

  cout<<n<<endl;

  }

 // cout<<l[0]<<endl;

  x=program(style,ready,l[0],icount,ptr,0);// 识别非终结符

  return 0;// 归约

 }

 if(checkstyle==2)

  {

  return 2;// 接受

 } } int main {

 // TODO: Add extra validation here

 string str;

 cin>>str; //0=i 1=+ 2=* 3=( 4=) 5=# 6=E 7=T 8=F

 smarttable[0][0] 、action(0,5);

 smarttable[0][3] 、action(0,4);

 smarttable[0][6] 、action(3,1);

 smarttable[0][7] 、action(3,2);

 smarttable[0][8] 、action(3,3);

 smarttable[1][1] 、action(0,6);

 smarttable[1][5] 、action(2,0);

 smarttable[2][1] 、action(1,1);

 smarttable[2][2] 、action(0,7);

 smarttable[2][4] 、action(1,1);

 smarttable[2][5] 、action(1,1);

 smarttable[3][1] 、action(1,3);

 smarttable[3][2] 、action(1,3);

 smarttable[3][4] 、action(1,3);

 smarttable[3][5] 、action(1,3);

 smarttable[4][0] 、action(0,5);

 smarttable[4][3] 、action(0,4);

 smarttable[4][6] 、action(3,8);

 smarttable[4][7] 、action(3,2);

 smarttable[4][8] 、action(3,3);

 smarttable[5][1] 、action(1,5);

  smarttable[5][2] 、action(1,5);

 smarttable[5][4] 、action(1,5);

 smarttable[5][5] 、action(1,5);

 smarttable[6][0] 、action(0,5);

 smarttable[6][3] 、action(0,4);

 smarttable[6][7] 、action(3,9);

 smarttable[6][8] 、action(3,3);

 smarttable[7][0] 、action(0,5);

 smarttable[7][3] 、action(0,4);

 smarttable[7][8] 、action(3,10);

 smarttable[8][1] 、action(0,6);

 smarttable[8][4] 、action(0,11);

 smarttable[9][1] 、action(1,0);

 smarttable[9][2] 、action(0,7);

 smarttable[9][4] 、action(1,0);

 smarttable[9][5] 、action(1,0);

 smarttable[10][1] 、action(1,2);

 smarttable[10][2] 、action(1,2);

 smarttable[10][4] 、action(1,2);

 smarttable[10][5] 、action(1,2);

 smarttable[11][1] 、action(1,4);

 smarttable[11][2] 、action(1,4);

 smarttable[11][4] 、action(1,4);

 smarttable[11][5] 、action(1,4); string enter=str;

 int i;

 int x;

 stylebox st;

 readybox ready;

 for(i=0;i<enter 、length;)

 {

 // cout<<"enter:

  "<<enter[i]<<"

 "<<endl;

  x=program(st,ready,enter[i],i,enter,1);

  if(x==1)i++;

  if(x==2)

  {

  // cout<<"Acc: 分析成功 功"<<endl;

 pp=pp+"Acc: 分析成功"+hh;

 break;

  }

  if(x==4)

 break;

 // cout<<endl;

 // cout<<endl;

  // pp=pp+hh;

 } cout<<pp; // CDialog::OnOK; } 七、 实验总结

  通过本次试验使我不仅对 LR(1)分析法有了更深得了解,而且提高了编程能力,希望在以后得学习中可以解决 LR(1)中确定化得问题。