[编译原理词法分析器语法分析器实验报告] 语义分析实验报告

 精品文档

 编译技术 班 级 网络 0802

  学 号 3080610052

 姓 名 叶晨舟

 指导老师 朱 玉 全

 2011年 7 月 4 日

 一、目的编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。

 二、任务及要求

 基本要求:

 词法分析器 产生下述小语言的单词序列

 这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表:

 

 单词符号

 种别编码

 助记符

 内码值

 DIM

 IF

 DO

 STOP

 END

 标识符

 常数(整)

 =

 +

 *

 **

 ,

 (

 )

 1

 2

 3

 4

 5

 6

 7

 8

 9

 10

 11

 12

 13

 14

 $DIM

 $IF

 $DO

 $STOP

 $END

 $ID

 $INT

 $ASSIGN

 $PLUS

 $STAR

 $POWER

 $COMMA

 $LPAR

 $RPAR

 -

 -

 -

 -

 -

 -

 内部字符串

 标准二进形式

 -

 -

 -

 -

 -

 -

 对于这个小语言,有几点重要的限制:

 首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。例如,下面的写法是绝对禁止的:

  IF(5)=x

 其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。也就是说,对于关键字不专设对应的转换图。但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。

 再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。例如,一个条件语句应写为

  IF i>0 i= 1;

 而绝对不要写成

   IFi>0 i=1;

 因为对于后者,我们的分析器将无条件地将IFI看成一个标识符。

 这个小语言的单词符号的状态转换图,如下图:

 语法分析器 能识别由加+ 减- 乘* 除/ 乘方^ 括号()操作数所组成的算术表达式,其文法如下:

 E→E+T|E-T|T

 T→T*F|T/F|F

 F→P^F|P

 p→(E)|i

  使用的算法可以是:预测分析法;递归下降分析法;算符优先分析法;LR分析法等。

 中间代码生成器 产生上述算术表达式的中间代码(四元式序列)

 三、实现过程

 给出各题目的详细算法描述,数据结构和函数说明,流程图。

 1、词法分析器的流程图

 2、语法分析器主程序图

 3、中间代码生成器流程图:

 四、源程序

 词法分析器:

 #include<string.h>

 #include<malloc.h>

 #include<iostream>

 using namespace std;

 typedef struct table //分析表存储结构

 {

  char m[100];

 }table;

 table M[100][100]; //定义分析表

 typedef struct stacknode //定义栈内元素节点 (带头结点(为空)的)

 {

  char data;

  struct stacknode *next;

 }stackk;

 void initlink(stackk *&s) //初始化新栈

 {

  s=(stackk *)malloc(sizeof(stackk));

  s->next=NULL;

 }

 void poplink(stackk *&s) //顶元素出栈

 {

 stackk *p;char v;

  if(s->next!=NULL)

  {

  p=s->next;

  v=p->data;

  s->next=p->next;

  }

 free(p);

 }

 void pushlink(stackk *&s,char x) //新 元 素 入 栈

 {

  stackk *p;

  p=(stackk *)malloc(sizeof(stackk));

  p->data=x;

  p->next=s->next;

  s->next=p;

 }

 void display(stackk *s) //打印 现实显示 栈内元素

 {

  stackk *p;

  int i=0,j;

  char st[100];

  p=s->next;

  while(p!=NULL)

  {

  st[i++]=p->data;

  p=p->next;

  }

  for(j=i-1;j>=0;j--)

  printf("%c",st[j]);

  for(j=0;j<16-i;j++) //打印 对齐格式

  printf("%c",' ');

 

 }

 char gettop(stackk *s) //返 回 栈 顶 元 素 值

 {

  if(s->next==NULL)

  return 0;

  else

  return s->next->data;

 

 }

 int find(char c,char array[]) //查找函数,

 {

 int i;

 int flag=0;

 for(i=0;i<100;i++)

 {

 if(c==array[i])

  flag=1;

 }

 return flag;

 }

 int location(char c,char array[]) //定位函数,指出字符所在位置

 {

 int i;

 for(i=0;i<100;i++)

 {

 if(c==array[i])

  return i;

 }

 }

 void error() //出错函数定义

 {

  printf("%15c出错!\n",' ');

 }

 void analyse(char Vn[],char Vt[])

 {

  int i,j,m,p,q,length,t,h;

  char w,X;

  char str[100];

 opt0:

  scanf("%s",str);

  for(i=0;i<strlen(str);i++)

  {

  if(!find(str[i],Vt))

  {

  printf("输入字符串有误!请重新输入!");

  goto opt0;

  break;

  }

  }

  stackk *st;

  initlink(st);

  pushlink(st,'#');

  pushlink(st,Vn[0]); //#与识别符号入栈

  j=0;

  h=1;

  w=str[0];

  printf("步骤%-12c分析栈%-24c剩余输入串%-12c所用产生式\n",' ',' ',' ');

 opt1:

  printf("%-16d",h); //显示步骤

  h++;

  display(st); //显示分析栈中内容

  X=gettop(st); //上托栈顶符号放入X

  poplink(st);

 

  for(int k=0;k<14+j;k++) //打印对齐格式

  printf("%c",' ');

 

  for(t=j;t<strlen(str);t++)

  {

  printf("%c",str[t]); //显示剩余字符串

  }

  if(find(X,Vt)&& X!='#') //分析栈的栈顶元素和剩余输入串的第一个元素相比较

  {

 

  if(X==w)

  {

  printf("%15c匹配\n",X);

  j++;

  w=str[j];

  goto opt1;

  }

  else

  error();

  }

  else

  {

  if(X=='#')

  {

  if(X==w)

  {

  printf("%8c是该文法的句子!\n",' ');

  }

  else

  error();

  }

  else

  {

  p=location(X,Vn);

  q=location(w,Vt);

  char *S1="null",*S2="NULL";

  if(strcmp(M[p][q].m,S1)==0||strcmp(M[p][q].m,S2)==0) //查找产生式

  error();

  else

  {

  char str0[100];

  strcpy(str0,M[p][q].m);

  printf("%15c-->%s\n",X,str0); //显示对应的产生式

  if(strcmp(str0,"$")==0)

  goto opt1;

  else

  {

  length=strlen(str0); //逆序进栈

  for(m=length-1;m>=0;m--)

  {

  pushlink(st,str0[m]);

  }

  goto opt1;

  }

  }

  }

  }

 }

 int main()

 {

  int i,k,n,r;

  char Vn[100],Vt[100],select;

  printf("******************************************************************\n");

  printf("对任意输入LL(1)文法的分析表,判断验证字符串是否为该文法的句子 \n");

  printf("并能给出分析和演示过程。

  \n");

  printf("******************************************************************\n");

 opt2:

  printf("请输入各终结符(#号表示结束 )Vt[i]:\n");

  for(i=0;i<100;i++)

  {

  scanf("%c",&Vt[i]);

  if(Vt[i]=='#')

  {

  r=i;

  break;

  }

  }

  printf("请输入非终结符个数:\n");

  scanf("%d",&n);

  getchar();

  for (i=0;i<n;i++)

  {

  printf("请输入非终结符Vn[%d]:\n",i);

  scanf("%c",&Vn[i]);

  getchar();

  printf("请输入此非终结符对应各终结符的产生式右部(null或NULL表示出错;$表示空串):\n");

  for(k=0;k<=r;k++)

  {

  scanf("%s",M[i][k].m);

  getchar();

  }

  }

 opt3:

  printf("请输入要分析的字符串,且以#结束:\n");

  analyse(Vn, Vt);

  printf("********************请选择***********************\n");

  printf(" 1: 输入字符串 \n");

  printf(" 2: 输入新分析表 \n");

  printf(" 0: 退 出 \n");

  printf("*************************************************\n");

 opt4:

  cin>>select;

  switch(select)

 {

  case '1': {goto opt3;break;}

  case '2': {goto opt2;}

  case '0': {break;}

  default: {printf("输入错误!请重新选择:");

  goto opt4;

  break;}

 }

  return 0;

 }

 运行结果:

 语法分析器 源程序:

 #include<string.h>

 #include<iostream>

 using namespace std;

 char prog[100],token[10];

 char ch;

 int syn,p,m=0,n,row,sum=0;

 char *rwtab[20]={"dim","if","do","stop","end" ,"and","begin","bool","case","char",

  "false","for","int","not","or","set","then","true","until","while"

 };

 void scaner()

 {

  for(n=0;n<9;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=21;

  for(n=0;n<20;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=7+15;

  if(sum>32767)

  syn=-1;

  }

  else switch(ch)

  {

  case'=':syn=8+15;token[0]=ch;break;

  case'+':syn=9+15;token[0]=ch;break;

  case'*':

  m=0;

  token[m++]=ch;

  ch=prog[p++];

  if(ch=='*')

  {

  syn=11+15;

  token[m++]=ch;

  }

  else

  {

  syn=10+15;

  p--;

  }

  break;

 case',':syn=12+15;token[0]=ch;break;

 case'(':syn=13+15;token[0]=ch;break;

 case')':syn=14+15;token[0]=ch;break;

 case'#':syn=0;token[0]=ch;break;

 case'<':m=0;token[m++]=ch;

  ch=prog[p++];

  if(ch=='>')

  {

  syn=17+15;

  token[m++]=ch;

  }

  else if(ch=='=')

  {

  syn=16+15;

  token[m++]=ch;

  }

  else

  {

  syn=15+15;

  p--;

  }

  break;

 case'>':m=0;token[m++]=ch;

  ch=prog[p++];

  if(ch=='=')

  {

  syn=19+15;

  token[m++]=ch;

  }

  else

  {

  syn=18+15;

  p--;

  }

  break;

 case':':m=0;token[m++]=ch;

  ch=prog[p++];

  if(ch=='=')

  {

  syn=21+15;

  token[m++]=ch;

  }

  else

  {

  syn=20+15;

  p--;

  }

  break;

 case'/':syn=22+15;token[0]=ch;break;

 case'-':syn=23+15;token[0]=ch;break;

 case';':syn=24+15;token[0]=ch;break;

 default: syn=-1;break;

  }

 }

 void main()

 {

  p=0;

  row=1;

  cout<<endl<<endl<<endl;

  cout<<"***************************小型词法分析器**********************************"<<endl<<endl;

  cout<<"请输入一段程序(以#结束):";

  do

  {

  cin.get(ch);

  prog[p++]=ch;

  }

  while(ch!='#');

  p=0;

  cout<<endl<<"**************************词法分析结果如下*********************************"<<endl;

  cout<<" 种别编码 自身值"<<endl;

  do

  {

  scaner();

  switch(syn)

  {

  case 22 : cout<<" ("<<syn<<" , "<<sum<<")"<<endl; break;

  case -1: cout<< " Error in row"<<row<<"!"<<endl; break;

  default: cout<<" ("<<syn<<" , "<<token<<")"<<endl;break;

  }

  }

  while (syn!=0);

 }

 运行结果:

 }

 中间代码生成器源程序:

 表达式生成四元式

 递归子程序法

 #include<string>

 #include <iostream>

 using namespace std;

 #define DEFAULT_SIZE 100

 char EMachine(char w); //表达式E的自动机

 char TMachine(char w); //表达式T的自动机

 char FMachine(char w); //表达式F的自动机

 bool ZMachine(); //表达式Z的自动机

 string intToString(int a); //整形变成字符串形函数

 class stack //栈类定义

 {

 private:

  int top;

  string *stacka;

  int maxsize;

 public:

  stack(int size=DEFAULT_SIZE);

  ~stack(){ delete [] stacka; }

  void push(const string &item);

  string pop(void);

  string gettop(void) const ;

  bool empty(void) const { return (top==-1); }

  bool full(void) const { return (top==maxsize-1); }

  void clear(void) { top=-1; }

 };

 stack::stack(int size) //栈类的构造函数

 {

  top=-1;

  maxsize=size;

  stacka=new string[maxsize];

  if(!stacka)

  {

  cerr<<"allocate memory failed."<<endl;

  exit(1);

  }

 }

 void stack::push(const string &item) //压栈操作

 {

  if(full())

  {

  cerr<<"stack full, cannot push."<<endl;

  return;

  }

  top++;

  stacka[top]=item;

 }

 string stack::pop(void) //出栈操作

 {

  if(empty())

  {

  cerr<<"stack empty, cannot pop."<<endl;

  exit(1) ;

  }

  string item=stacka[top];

  top--;

  return item;

 }

 string stack::gettop(void) const //取栈顶操作

 {

  if(empty())

  {

  cerr<<"stack empty, cannot gettop."<<endl;

  exit(1) ;

  }

  return stacka[top];

 }

 static stack wordStack; //符号栈

 static int noOfQuet=0; //静态四元式个数记录

 static int noOfT = 1; //静态状态个数记录

 

 void main(){ //主函数

  char yesOrNo; //进行一个循环操作控制

  do{

  cout<<"请输入算术表达式:"<<endl;

  noOfT = 1; //每次结束询问

  ZMachine();

  cout<<endl<<"Continue?Yes or Not:";

  cin>>yesOrNo; //输入“Y”则继续

  }while(yesOrNo=='y'); //否则程序结束

 }

 bool ZMachine(){ //Z自动机

  char w;

  cin>>w;

  w = EMachine(w); //调用E自动机

  if(w=='#'){ //遇到“#”则结束

  return true;

  }

  else{

  return false;

  }

 }

 char EMachine(char w){ //E自动机

  string operate,a,b,c;

  string state[5];

  w = TMachine(w); //调用T自动机

  while(w=='+'||w=='-'){ //是加或减符号

  operate = w;

  cin>>w; //读入下一字符

  w = TMachine(w); //调用T自动机

  b = wordStack.pop(); //字符栈弹出

  a = wordStack.pop(); //两个操作字符

  cout<<"(\""<<operate<<"\","<<a<<","<<b<<",t"<<noOfT<<")"<<endl;

  c = "t"+intToString(noOfT); //输出四元式

  wordStack.push(c); //新状态压栈

  noOfT++; //状态计数加一

  }

  return w;

 }

 char TMachine(char w){

  string operate,a,b,c;

  string state[5];

  w = FMachine(w); //调用F自动机

  while(w=='*'||w=='/'){ //是乘除号

  operate = w;

  cin>>w; //读取下一字符

  w = FMachine(w); //调用F自动机

  b = wordStack.pop(); //符号栈弹出

  a = wordStack.pop(); //两个操作字符

  cout<<"(\""<<operate<<"\","<<a<<","<<b<<",t"<<noOfT<<")"<<endl;

  c = "t"+intToString(noOfT); //输出四元式

  wordStack.push(c); //新状态压栈

  noOfT++; //状态计数加1

  }

  return w;

 }

 char FMachine(char w){ //F自动机

  string theWord;

  if(w>='a'&&w<='z'||w>='A'&&w<='Z'){

  theWord = w; //当前字符是字母

  wordStack.push(theWord); //则压栈

  }

  else if(w == '('){ //是左括号

  cin>>w; //则读取下一字符

  w = EMachine(w); //调用E自动机

  if(w!=')'){ //不是右括号则输入有误,报错

  cerr<<"the input is wrong!"<<endl;

  exit(0);

  }

  }

  else{ //否则有误,报错

  cerr<<"the input is wrong!"<<endl;

  exit(0);

  }

  cin>>w; //读取下一字符

  return w;

 }

 string intToString(int a){ //整形变字符串形函数

  string d;

  char b='0',c;

  int i;

  while(a!=0){

  i = a%10;

  a = a/10;

  c = (int)b + i;

  d = c + d;

  }

  return d;

 }

 //Y=a+b*(c+(-d)*(e+f))

 //Y=(a+b*(c-d*e/f+g*(h-i*x*(j+k*(-l)*(j+k)))+w))

 //H=(d+a-(c+b-q)*a)+c-(a+b*(c+d))

 六、总结

 

 通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把理论知识应用于实验中,也让我重新熟悉了C++语言的相关内容,加深了对C++语言知识的深化和用途的理解。相信在以后的毕业设计以及读研自己做项目时可以有更大的提升。

 售后服务方案(赠送)

 1.售后服务概述

  公司长期以来一直致力于提供高质量、完善的支持服务,确保用户的系统稳定运行。

  公司拥有一批资深的施工人员,具有丰富的经验,能够很好的解决设备各类故障,强大的用户支持队伍和良好的用户满意度是我们的一大优势。

  维护计划及承诺  

 ?一、 项目售后服务内容承诺  

  我公司贯彻执行:“诚信正直、成就客户、完善自我、追求卓越”的宗旨,对于已经竣工、验收合格的项目进行质量跟踪服务,本着技术精益求精的精神,向用户奉献一流的技术和一流的维护服务。

 我公司如果承接了端拾器项目,将严格遵循标书及合同的规定,在保证期内向业主提供该项目的责任和义务。在保修期之后,考虑到设备维护的连续性,建议业主与我公司签订维护合同,以确保此系统项目的正常运行所必需的技术支持和管理支持。

 二、 服务与保证期  

 ?在项目验收合格之日起,开始进行售后服务工作,包括以下几个方面:

  1、售后服务期; ?2、维护人员; 3、售后服务项目; 4、服务响应时间。

 ? 三、 售后服务期  

 ? 在项目验收合格之日起,即进入了售后服务期。

 售后服务期=质量保证期+质量维护期

 ? 质量保证期:在质量保证期内,如因质量问题造成的故障,实行免费更换设备、元器件及材料。如因非质量因素造成的故障,收取更换设备、元器件及材料成本费。

 质量维护期:在质量保证期之后,即自行进入质量维护期。

 我方对所承担端拾器项目提供终身质量维护服务,以不高于本合同设备单价的优惠价格提供所需更换的元器件及材料,另收维护人员工本费。

   四、 具体措施承诺  

 ? 1、首先在签订项目合同的同时与客户签订售后服务保证协议书,排除客户的后顾之忧,对客户做出实事求是的、客观的承诺。

 2、对已经验收合格交付用户的端拾器项目,在合同期内与用户进行联系,记录用户使用情况,系统运行状况等进行质量跟踪调查,变被动服务为主动服务。

 3、对已交工的端拾器项目建立系统运行档案,并进行质量跟踪。

 4、系统运行档案记录其端拾器项目运行情况、各类设备使用情况、操作人员操作水平情况及人员流动情况。

 5、针对各用户单位操作人员出现的代表性问题,定期对操作人员进行技术培训或到现场培训及指导。

 6、正在使用中的系统、设备出现故障时,公司维修服务人员接到报告后及时赴现场处理、维修。

 7、对于运行时间较长的端拾器项目,公司维修服务人员定期与客户进行联系询问情况,定期到客户方进行巡视、检查,并做出记录,记录归档保存。

 8、施工保证

 将选派具有丰富经验的技术人员负责端拾器项目具体施工,保证安装质量及系统使用功能,并保证整个系统运行平稳、高效、可靠。

 9、系统保修

 作为项目承包单位,我公司将严格遵循招标文件及合同的规定,向业主提供端拾器项目最终验收合格之日起,在保质期范围内免费维修。

 10、保修期内设备损坏,经鉴定为设备本身原因造成的故障,我方负责免费维修或者更换;同时负责在保修期内定期对设备提供保养维护服务。

 总之,为使业主使用放心、使用方便、保证端拾器项目正常运行,公司全体技术、维护人员本着客户第一的原则,全心全意地为客户着想,全力以赴的进行工作,让我们共同携手,为创造美好的明天而努力工作。

  五、保修服务内容及范围

  我公司将为所承担的各个端拾器项目提供保修服务,有效期从项目验收后,业主在竣工报告上签字之日起。

 1、 响应时间:具体的响应时间将按故障级别划分;

 2、 维修地点:用户现场。

 我公司负责实施的所有系统项目,在正常环境下做适当使用时所发生的故障,我公司将提供约定保修服务。非当前故障,我公司安排提供服务,但需按收费标准另收费用。

 我公司的保修服务仅限于经我公司认定的合格产品。所谓不合格的产品包括:非经我公司供应的产品、非经我公司认定合格的产品及顾客不允许我公司做功能改进的产品。

  下列情况所发生的系统损害不包括在保修服务范围内:

 1、 使用不适当的工具进行系统维护时造成的系统设备损坏;

 2、 现场环境不符合我公司建议的规范;

 3、 意外、自然灾害、疏忽及不当使用、战争、暴动、罢工、雷击或电力故障、顾客搬运不当的损坏,经由非我公司人员或其授权的子承包商对系统进行修改和变动;

 4.设备的维护和信息处理方式。

  六、 系统维护

  1、系统运行管理工作

 为了保证系统能够长时间的正常运行,我们将进行完善的系统培训,同时制定各个系统项目操作规程,并配合业主制定操作人员责任界面及合理的交接班制度。

 2、系统维护保养

 我公司的售后服务人员在维护期内将对贵方的系统项目提供服务,使它们保持良好的运行状态。

 ? 3、月度保养

 ?  坚持月度维护保养,保证每个系统项目机械装置保持最佳工作状态。

  七、维护及服务支持措施

 1、电话支持服务

 电话服务热线号码以我方提供给业主的号码为准(包括电话和传真号码)。如有更改,我方至少在自更改之日起3天内以电子邮件、传真、电话的方式通知业主。

 2、现场排除故障或技术指导

 我方在接到业主的电话支持服务请求后,如果不能通过电话支持服务解决设备或产品发生的技术故障,且经双方商议确认需要进行现场支持的情况下,我方将派专业项目技术人员及时前往现场协助业主排除故障。

  3、电话咨询服务

 对业主在使用设备或产品过程中产生的非故障类问题,我方提供电话咨询服务。

 4、投诉受理服务

  我方在公司设有用户投诉电话

推荐访问:分析器 词法 编译 语法 原理