编译原理词法分析器实验报告最终版

时间:2024.4.20

         

学院(系)名称:计算机工程系

实验步骤:

1.基本思想:从源程序中依次读入字符并解析,与关键字、运算符、结束符进行比较,得出其中的关键字,并将它存入到数组中去。

2.程序源代码:

#include<stdio.h>

#include<cstring>

#include<stdlib.h>

#define MaxSize1  17//关键字的个数

#define MaxSize2  20//运算符的个数

#define MaxSize3  4//结束符的个数

//数据结构

struct TNode

{

   char value[20];       //存放标识符的值

   int number;   //存放标识符的种别码

   char description[20];//描述

}KeyWords[MaxSize1],Operation[MaxSize2],EndOperation[MaxSize3];

//存放关键字的数组

char *WordsBuff[MaxSize1]={"const","long","float","double","void","main","if","else","then","break","int","char","include","for","while","printf","scanf"};

//存放运算符的数组

char *OperationBuff[MaxSize2]={"+","-","*","/","+=","-=","*=","++","--","<","<=",">",">=","<>","=","(",")","#","{","}"};

char EndOperationBuff[MaxSize3]={' ',';','\n','\t'};

//存放词法分析程序输出的结果

TNode Table1[500];

TNode Variable[100];//标识符表

TNode Const[100];

//关键字数组初始化

void inputKeyWords(char * buff[],int size)

{

   //关键字编码从1-size

   for(int i=0;i<size;i++)

   {

          strcpy(KeyWords[i].value,buff[i]);

          KeyWords[i].number=i+1;

          strcpy(KeyWords[i].description,"关键字");

   }

}

//运算符数组初始化

void inputOperation(char * buff[],int size)

{

   //运算符编码从50-(50+size)

   for(int i=0;i<size;i++)

   {

          strcpy(Operation[i].value,buff[i]);

          Operation[i].number=i+50;

          strcpy(Operation[i].description,"运算符");

   }

}

//结束符数组初始化

void inputEndOperation(char buff[],int size)

{

   //结束符编码从100-(100+size);

   for(int i=0;i<size;i++)

   {

          EndOperation[i].value[0]=buff[i];

          EndOperation[i].value[1]='\0';

          EndOperation[i].number=i+100;


          strcpy(EndOperation[i].description,"结束符");

   }

}


//输出数据结构数组中的信息

void outputInfo(TNode a[],int size)

{

   for(int i=0;i<size;i++)

   {

          printf("(%d",a[i].number);

          printf("\t");

          printf("%s)",a[i].value);

          printf("\t");

          printf(a[i].description);

          printf("\n");

   }

}

void outInfoToFile(TNode a[],int size,FILE *out)

{

   //将词法分析程序的结果输出到文件中去

   for(int i=0;i<size;i++)

   {

          fprintf(out,"(%d",a[i].number);

          fprintf(out,"\t");

          fprintf(out,"%s)",a[i].value);

          fprintf(out,"\t");

          fprintf(out,a[i].description);

          fprintf(out,"\n");

         

   }

}

//从文件中读取一个字符

//返回文件中读取的字符

char getChar(FILE *fp)

{

   char ch=fgetc(fp);

   return ch;

}

//判读是否是运算符

int isOperation(char a[])

{

   //返回i表示是运算符在运算符数组中的位置

   //返回-1表示不是运算符

   int result;

   for(int i=0;i<MaxSize2;i++)

   {

          result=strcmp(a,Operation[i].value);

          if(result==0)

          {

                 return i;

                 break;    

          }

   }

   return -1;       

}

//判读是否是关键字

int isKeyWords(char a[])

{

   //返回i表示在关键字表中的位置

   //返回-1表示不是关键字

   int result;

   for(int i=0;i<MaxSize1;i++)

   {

          result=strcmp(a,KeyWords[i].value);

          if(result==0)

          {

                 return i;

                 break;           

          }

   }

   return -1;

}

//判读是否是结束符

int isEndOperation(char a)

{

   //返回i表示是结束符在结束符表中的位置

   //返回-1表示不是结束符

   for(int i=0;i<MaxSize3;i++)

   {

          if(a==EndOperation[i].value[0])

          {

                 return i;

                 break;

          }

   }

   return -1;

}

//判读是否是字符

int isChar(char a)

{

   //返回1表示是字符

   //返回0表示不是字符

   if(a>='a'&&a<='z')

          return 1;

   else if(a>'A'&&a<='Z')

          return 1;

   else

          return 0;

}

//判读是否是数字

int isDigit(char a)

{

   //返回1表示是数字

   //返回0表示不是数字

   if(a>='0'&&a<='9')

          return 1;

   else

          return 0;

}

int count=0;//记录结果表中的关键字及运算符等表项个数,用于返回

int count1=0;//记录标识符的表项个数

int count2=0;//记录常量的表项的个数

//从屏幕上面获得字符并解析,返回在结果表中的表项

int start1(FILE *in)

{

   char buff[20];//用于保存单词的缓冲区

   char nextchar[2];

   char temp[20];//用于保存变量或常量的类型数组

   int i=0;//缓冲区指针

   int a;//比较的结果指针

   char op[3];//用于保存第一个运算符

   op[2]='\0';

   nextchar[0]=fgetc(in);

   nextchar[1]='\0';

   while(nextchar[0]!=EOF)

   {

          if(isChar(nextchar[0]))

          {

                 buff[i]=nextchar[0];i++;

                 nextchar[0]=fgetc(in);

          }

          else if(isDigit(nextchar[0]))

          {

                 buff[i]=nextchar[0];i++;

                 nextchar[0]=fgetc(in);

          }

          else if(nextchar[0]=='\r'||nextchar[0]=='\n')

          {

                 buff[i]='\0';

                 a=isKeyWords(buff);

                 if(a!=-1&&i>0)

                 {

                        strcpy(Table1[count].value,KeyWords[a].value);

                        Table1[count].number=KeyWords[a].number;

                        strcpy(Table1[count].description,KeyWords[a].description);

                        count++;//计数器加一

                        i=0;//清空缓冲区

                 }

                 else if(i>0)

                 {

                        if(isChar(buff[0]))

                        {

                               //是标识符

                               strcpy(Variable[count1].value,buff);

                               Variable[count1].number=count1;

                               strcpy(Variable[count1].description,"标识符");

                               count1++;//计数器加一

                               i=0;//清空缓冲区

                        }

                        else if(isDigit(buff[0]))

                        {

                               //是常量

                               strcpy(Const[count2].value,buff);

                               Const[count2].number=count2;

                               strcpy(Const[count2].description,"常量");

                               count2++;//计数器加一

                               i=0;//清空缓冲区

                        }

                 }

                 else

                 {

                        //缓冲区为空!

                 }

                 //处理回车符与换行符

                 nextchar[0]=fgetc(in);

          }

          else if(isEndOperation(nextchar[0])!=-1)

          {

                 buff[i]='\0';

                 a=isKeyWords(buff);

                 if(a!=-1&&i>0)

                 {

                        strcpy(Table1[count].value,KeyWords[a].value);

                        Table1[count].number=KeyWords[a].number;

                        strcpy(Table1[count].description,KeyWords[a].description);

                        strcpy(temp,KeyWords[a].value);

                        count++;//计数器加一

                        i=0;//清空缓冲区

                 }

                 else if(i>0)

                 {

                        if(isChar(buff[0]))

                        {

                               //是标识符

                               strcpy(Variable[count1].value,buff);

                               Variable[count1].number=count1;

                               strcpy(Variable[count1].description,"标识符");

                               count1++;//计数器加一

                               i=0;//清空缓冲区

                        }

                        else if(isDigit(buff[0]))

                        {

                               //是常量

                               strcpy(Const[count2].value,buff);

                               Const[count2].number=count2;

                               strcpy(Const[count2].description,"常量");

                               count2++;//计数器加一

                               i=0;//清空缓冲区

                        }

                 }

                 else

                 {

                        //缓冲区为空!

                 }

                 nextchar[0]=fgetc(in);

          }

          else if((a=isOperation(nextchar))!=-1)

          {

                 //首先输出缓冲区中的数据

                 buff[i]='\0';

                 a=isKeyWords(buff);

                 if(a!=-1&&i>0)

                 {

                        strcpy(Table1[count].value,KeyWords[a].value);

                        Table1[count].number=KeyWords[a].number;

                        strcpy(Table1[count].description,KeyWords[a].description);

                        count++;//计数器加一

                        i=0;//清空缓冲区

                 }

                 else if(i>0)

                 {

                        if(isChar(buff[0]))

                        {

                               //是标识符

                               strcpy(Variable[count1].value,buff);

                               Variable[count1].number=count1;

                               strcpy(Variable[count1].description,"标识符");

                               count1++;//计数器加一

                               i=0;//清空缓冲区

                        }

                        else if(isDigit(buff[0]))

                        {

                               //是常量

                               strcpy(Const[count2].value,buff);

                               Const[count2].number=count2;

                               strcpy(Const[count2].description,"常量");

                               count2++;//计数器加一

                               i=0;//清空缓冲区

                        }

                 }

                 else

                 {

                        //缓冲区为空!

                 }

                 //处理运算符

                 op[0]=nextchar[0];

                 nextchar[0]=fgetc(in);

                 if(nextchar[0]!='@')

                 {

                        if(isOperation(nextchar)!=-1)

                        {

                               op[1]=nextchar[0];

                               if((a=isOperation(op))!=-1)

                               {

                                      //输出双目运算符

                                      strcpy(Table1[count].value,Operation[a].value);

                                      Table1[count].number=Operation[a].number;

                                      strcpy(Table1[count].description,Operation[a].description);

                                      count++;//计数器加一

                                      //读取下一个字符

                                      nextchar[0]=fgetc(in);

                               }

                               else

                               {

                                      //错误的双目运算符

                                      strcpy(Table1[count].value,op);

                                      Table1[count].number=-1;

                                      strcpy(Table1[count].description,"未定义的运算符");

                                      count++;//计数器加一

                                      //读取下一个字符

                                      nextchar[0]=fgetc(in);

                               }

                        }

                        else

                        {

                               //输出一元运算符

                               op[1]='\0';

                               a=isOperation(op);

                               strcpy(Table1[count].value,Operation[a].value);

                               Table1[count].number=Operation[a].number;

                               strcpy(Table1[count].description,Operation[a].description);

                               count++;//计数器加一

                        }

                 }

          }

   }

   return count;

}

void main()

{

   inputKeyWords(WordsBuff,MaxSize1);

   inputOperation(OperationBuff,MaxSize2);

   inputEndOperation(EndOperationBuff,MaxSize3);

   FILE *in,*out;

   bool Flag=true;

   while(Flag)

   {

          printf("源文件的位置:C:\\input.txt\n");

          if((in=fopen("C:\\input.txt","r"))==NULL)

          {

                 printf("读取源文件失败!\n");

                 exit(0);

          }

          if((out=fopen("C:\\out.txt","w"))==NULL)

          {

                 printf("打开文件失败!\n");

                 exit(0);

          }

          int MaxSize=start1(in);

          printf("关键字及运算符\n");

          fprintf(out,"关键字及运算符\n");

          outputInfo(Table1,MaxSize);

          outInfoToFile(Table1,MaxSize,out);

          printf("标识符表:\n");

          fprintf(out,"标识符表:\n");

          outputInfo(Variable,count1);

          outInfoToFile(Variable,count1,out);

          printf("常量表:\n");

          fprintf(out,"常量表:\n");

          outputInfo(Const,count2);

          outInfoToFile(Const,count2,out);

          Flag=false;

          fclose(in);

          fclose(out);

   }

  

}

3.测试用例:

int a=3;

double b=4;

int c;

if(a>b)

c=a;

else

c=b;

4.测试结果:

5.心得体会:

通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把 理论知识应用于实验中,实验过程中对于转义字符,结束符、欠缺了考虑,在多次的调试和改进中最终完善了程序,而在调试过程中学习的知识得到了完善和补充,对词法分析器的理解更进一步。 也让我重新熟悉了 C++语言的相关内容, 加深了对 C++ 语言知识的深化和用途的理解。

更多相关推荐:
编译原理实验报告词法分析

编译原理实验报告词法分析器学院计算机科学与技术时间20xx69一问题描述选择计算机高级程序语言之一C语言运用恰当的词法分析技术线路设计和实现其对应的词法分析器提示技术线路选择如下两种之一正则式NFADFAmin...

编译原理词法分析器实验报告

曲阜师范大学实验报告计算机系20xx年级软件工程一班组日期20xx年10月17日星期日姓名陈金金同组者姓名课程编译原理成绩实验名称教师签章词法分析器一实验目的1掌握词法分析的原理2熟悉保留字表等相关的数据结构与...

编译原理词法分析实验报告1

实验1词法分析实验报告一实验目的调试并完成一个词法分析程序加深对词法分析原理的理解二实验要求1待分析的简单语言的词法beginifthenwhiledoend所有关键字都是小写2运算符和界符ltltltgtgt...

编译原理_词法分析器_实验报告

词法分析器实验报告实验目的设计编制调试一个词法分析子程序识别单词加深对词法分析原理的理解功能描述该程序要实现的是一个读单词过程从输入的源程序中识别出各个具有独立意义的单词即基本保留字标识符常数运算符分隔符五大类...

编译原理实验-词法分析器的设计

集美大学计算机工程学院实验报告一、实验目的通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。二、实验内容编写一个词法分…

编译原理词法分析器实验报告

塔里木大学信息工程学院编译原理实验编译原理结课论文题目词法分析器学号作者班级电话Email教师递交日期年月日塔里木大学信息工程学院编译原理实验目录摘要3涉及知识点31输入预处理32单词符号的识别状态转换图33利...

编译原理词法分析器实验报告

编译原理实验报告词法分析器院系班级姓名学号词法分析器实验报告一实验目的设计一个词法分析程序理解词法分析器实现的原理掌握程序设计语言中的各类单词的词法分析方法加深对词法分析原理的理解二实验原理词法分析是从左向右扫...

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

词法分析器实验报告按<<>编译原理>课程的要求,根据词法分析器的基本原理,设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。一、实验要求2.1待分析的简单的词法(1)关键字:beginifthenwh…

编译原理实验报告--词法分析器

编译原理实验词法分析器姓名王吉军学号0920xx15班级软件92一实验目的通过动手实践使学生对构造编译系统的基本理论编译程序的基本结构有更为深入的理解和掌握使学生掌握编译程序设计的基本方法和步骤能够设计实现编译...

编译原理实验报告(词法分析器 语法分析器)

编译原理实验报告实验一一实验名称词法分析器的设计二实验目的1词法分析器能够识别简单语言的单词符号2识别出并输出简单语言的基本字标示符无符号整数运算符和界符三实验要求给出一个简单语言单词符号的种别编码词法分析器四...

词法分析器的设计与实现 编译原理实验报告

中北大学软件学院实验报告专业课程名称学号姓名辅导教师张静成绩

编译原理课程(词法分析器及语法分析器)

编译原理实验报告词法分析器与语法分析器I问题描述设计编制并调试一个词法分析子程序完成识别语言单词的任务设计编制调试一个语法分析程序并用它对词法分析程序所提供的单词序列进行语法检查和结构分析ii设计简要描述界面需...

编译原理词法分析器实验报告(32篇)