当前位置:文档之家› 编译原理词法分析器

编译原理词法分析器

编译原理大作业词法分析器班级:电计0902学号:200981174姓名:修德斌一、实验目的通过设计、调试词法分析程序,实现从源程序中分出各种单词的方法;熟悉词法分析程序所用的工具自动机,进一步理解自动机理论。

掌握文法转换成自动机的技术及有穷自动机实现的方法。

确定词法分析器的输出形式及标识符与关键字的区分方法。

加深对课堂教学的理解;提高词法分析方法的实践能力。

通过本实验,应达到以下目标:1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。

2、掌握词法分析的实现方法。

3、上机调试编出的词法分析程序。

二、实验过程1、需求分析:词法分析是编译程序的第一个阶段,主要任务是对于字符串流的输入,根据词表,将关键字、变量等转化成自定义逻辑结构,就是输入源程序,输出单词符号,用于下一步的语法分析。

比如:{int a; int b;{a=10;if (a>0) then b=aa and b;}}词法分析的功能就是输入源程序,输出单词符号,去除空白符等无意义字符,然后对于像main、a、b这样的函数名、变量名字符串参考前后关键字,按照各自的分类,转换成一个变量表,对于像char = +这种关键字,按照关键词词表转化成对应的序号。

2、概要设计:(1)、输入输出方式:以文件的形式进行输入,然后对识别出的单词以Linenum: 行数 string= 具体的单词或者符号类型(如分解符等)最后在识别完成后列出了标示符的个数以及标示符的表示名称关键字表:sting key[6]key[0]=”if”key[1]=”else”key[2]=”while”key[3]=”do”key[4]=”int”key[5]=”then”分界符表:border[7]={ "," , ";" , "{" , "}" , "(" , ")" ,"="}算数运算符arithmetic[6]={"+" , "-" , "*" , "/" , "++" , "--"}关系运算符relation[6]={"<" , "<=" , ">" , ">=" , "==" ,"!="}逻辑运算符logicaloperator[2]={"and","or"}标识符表char *lableconst[80];(2)、状态转换图:根据对实验分析,对词法分析过程的剖析,画出其基本状态转换图如下;3、详细设计:1、字符串的输入采用文件方式,然后将文件中的数据读入数组lableconst中。

2、对标识符、逻辑运算符和关键字的判断3、对数字,分界符等的识别4、输出按照linenum 行数具体输入词类型的形式输出三、实验结果输入源:{int a; int b;{a=10;if (a>0) then b=aa and b;}}程序运行以及输出结果:四、讨论与分析该词法分析器能够进行简单的词法分析,包括对关键字、分界符、算术运算符、关系运算符、标示符、逻辑运算符以及常数的识别,对不同类型的词归类,为下一步的语法分析做好铺垫,在处理常数时,先把常数转换为二进制,再存储在数组中。

但是仍有不足之处,各类型表囊括的项目部完全,还需进一步完善。

五、附录:(给出适当注释,可读性高)#include <iostream>#include <ctype.h>#include <fstream>#include <string.h>#include <malloc.h>using namespace std;ifstream fp("1.txt",ios::in);char cbuffer;char *key[6]={"if","else","while","do","int","then"}; //关键字char *border[7]={ "," , ";" , "{" , "}" , "(" , ")" ,"="}; //分界符char *arithmetic[6]={"+" , "-" , "*" , "/" , "++" , "--"}; //算数运算符char *relation[6]={"<" , "<=" , ">" , ">=" , "==" ,"!="};//关系运算符char *logicaloperator[2]={"and","or"}; //逻辑运算符char *lableconst[80]; //标识符int constnum=40;int lableconstnum=0;int linenum=1; //统计常数和标识符数量int search(char searchchar[],int wordtype){int i=0,t=0;switch (wordtype){case 1:{ for (i=0;i<=5;i++) //关键字{if (strcmp(key[i],searchchar)==0)return(i+1);}return(0);}case 2:{for (i=0;i<=6;i++) //分界符{if (strcmp(border[i],searchchar)==0)return(i+1);}return(0);}case 3:{for (i=0;i<=5;i++) //算数运算符{if (strcmp(arithmetic[i],searchchar)==0)return(i+1);}return(0);}case 4:{for (i=0;i<=5;i++) //关系运算符{if (strcmp(relation[i],searchchar)==0)return(i+1);}return(0);}case 5:{for (t=40;t<=constnum;t++) //常数{if (strcmp(searchchar,lableconst[t])==0)//判断该常数是否已出现过return(t+1);}lableconst[t-1]=(char *)malloc(sizeof(searchchar));//为新的元素分配内存空间strcpy(lableconst[t-1],searchchar);//为数组赋值lableconst指针数组名constnum++; //常数个数自加return(t);}case 6:{for (i=0;i<=lableconstnum;i++){if (strcmp(searchchar,lableconst[i])==0) //判断标识符是否已出现过return(i+1);}lableconst[i-1]=(char *)malloc(sizeof(searchchar));strcpy(lableconst[i-1],searchchar);lableconstnum++; //标识符个数自加return(i);}case 7:{ for (i=0;i<=1;i++) //逻辑运算符{if (strcmp(logicaloperator[i],searchchar)==0)return(i+1);}return(0);}default:cout<<"错误!";}}char alphaprocess(char buffer) //字符处理过程{int atype;int i=-1;char alphatp[20];while ((isalpha(buffer))||(isdigit(buffer)))//这两个函数分别是判字符和判数字函数位于ctype.h中{alphatp[++i]=buffer;fp.get(buffer);}alphatp[i+1]='\0';//在末尾添加字符串结束标志if (atype=search(alphatp,1))cout<<"linenum: "<<linenum<<" String= "<<alphatp<<"\t\t\t"<<"关键字"<<endl;else{if (atype=search(alphatp,7))cout<<"linenum: "<<linenum<<" String= "<<alphatp<<"\t\t\t"<<"逻辑运算符"<<endl;else {atype=search(alphatp,6); //标识符cout<<"linenum: "<<linenum<<" String= "<<alphatp<<"\t\t\t"<<"标识符"<<endl;}}return(buffer);}char digitprocess(char buffer) //数字处理过程{int i=-1;char digittp[20];int dtype;while ((isdigit(buffer))){digittp[++i]=buffer;fp.get(buffer);}digittp[i+1]='\0';dtype=search(digittp,5);cout<<"linenum: "<<linenum<<" String= "<<digittp<<"\t\t\t"<<"数据"<<endl;return(buffer);}char otherprocess(char buffer) //分界符、运算符、逻辑运算符、等{int i=-1;char othertp[20];int otype,otypetp;othertp[0]=buffer;othertp[1]='\0';if (otype=search(othertp,3)){fp.get(buffer);othertp[1]=buffer;othertp[2]='\0';if (otypetp=search(othertp,3)) //判断该运算符是否是//由连续的两个字符组成的{cout<<"linenum: "<<linenum<<" String= "<<othertp<<"\t\t\t"<<"运算符"<<endl;fp.get(buffer);goto out;}else //单字符逻辑运算符{othertp[1]='\0';cout<<"linenum: "<<linenum<<" String= "<<othertp<<"\t\t\t"<<"算术运算符"<<endl;goto out;}}if (otype=search(othertp,4)) //关系运算符{fp.get(buffer);othertp[1]=buffer;othertp[2]='\0';if (otypetp=search(othertp,4)) //判断该关系运算符是否是//由连续的两个字符组成的{cout<<"linenum: "<<linenum<<" String= "<<othertp<<"\t\t\t"<<"关系运算符"<<endl;fp.get(buffer);goto out;}else //单字符逻辑运算符{othertp[1]='\0';cout<<"linenum: "<<linenum<<" String= "<<othertp<<"\t\t\t"<<"算数运算符"<<endl;goto out;}}if (buffer=='!') //"=="的判断{fp.get(buffer);if (buffer=='=')//cout<<"!= (2,2)\n";fp.get(buffer);goto out;}else{if (otype=search(othertp,2)) //分界符{cout<<"linenum: "<<linenum<<" String= "<<othertp<<"\t\t\t"<<"分界符"<<endl;fp.get(buffer);goto out;}}if ((buffer!='\n')&&(buffer!=' '))cout<<"错误!,字符非法"<<"\t\t\t"<<buffer<<endl;fp.get(buffer);out: return(buffer);}void main(){int i;for (i=0;i<=50;i++){lableconst[i]=" ";//用于保存标识符}if (!fp)cout<<"文件打开错误!!"<<endl;else{fp.get (cbuffer);while (!fp.eof()){if(cbuffer=='\n'){linenum++;fp.get(cbuffer);}else if (isalpha(cbuffer)){cbuffer=alphaprocess(cbuffer);}else if (isdigit(cbuffer)){cbuffer=digitprocess(cbuffer);}elsecbuffer=otherprocess(cbuffer);}}cout<<"标识符个数是:"<<lableconstnum<<"分别是"<<endl;i=0;while(i<lableconstnum){cout<<lableconst[i++]<<" ";}cout<<endl;cout<<"完成\n"<<endl;getchar();}。

相关主题