0/20武汉科技大学实验报告课程名称编译原理专业班级姓名学号1/20实验一词法分析器设计【实验目的】1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。3.通过完成词法分析程序,了解词法分析的过程。【实验内容】用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。【实验步骤和要求】1.要求绘出词法分析过程的流程图。2.根据词法分析的目的以及内容,确定完成分析过程所需模块。3.写出每个模块的源代码。4.整理程序清单及所得结果。【流程图】2/20【源代码】//resource.h#defineIDD_MAINDLG101#defineIDR_MENU102#defineIDI_ICON104#defineIDC_INPUT1001#defineIDC_OUTPUT1003#defineIDC_ERRPUT1004#defineIDC_BUTTON11005#defineID_START40001#defineID_ABOUT40003#defineID_OPEN40005#defineID_SAVE40006#defineID_LISTKEY40007//Nextdefaultvaluesfornewobjects//#ifdefAPSTUDIO_INVOKED#ifndefAPSTUDIO_READONLY_SYMBOLS#define_APS_NEXT_RESOURCE_VALUE105#define_APS_NEXT_COMMAND_VALUE40008#define_APS_NEXT_CONTROL_VALUE1007#define_APS_NEXT_SYMED_VALUE101#endif#endif//getsym.h#ifndef_GETSYM_H_#define_GETSYM_H_#includestdlib.h//Formemset()#includestring.h//Forstrcpy()#defineISLETTER(c)((c)='A'&&(c)='Z'||(c)='a'&&(c)='z')#defineISNUMBER(c)((c)='0'&&(c)='9')#defineISCHAR(c)((c)=33&&(c)=126)#defineMAX_SYM32768//最大符号量#defineMAX_SYMFORM1024//最大符号表长度#defineMAX_NUMFORM4096//最大常数表长度#defineMAX_SYMLEN31//最大符号长度#defineMAX_NUMLEN10//最大常数长度#defineMAX_BUFFERMAX_SYMLEN+1//最大缓冲长度3/20#defineMAX_KEYWORD27//关键字数量#defineMAX_OPWORDA8//单字运算符数量#defineMAX_OPWORDB4//双字运算符数量#defineMAX_ENDWORD8//单字界符数量#defineMAX_ERROR5//错误类型数量#defineTYPE_KEYWORD1//关键字类型号#defineTYPE_SYMBOL2//符号类型号#defineTYPE_NUMBER3//常量类型号#defineTYPE_OPWORD4//运算符类型号#defineTYPE_ENDWORD5//界符类型号#defineTYPE_ERROR-1//错误类型号#defineERR_OVERSYMLEN1//以下是一般错误号#defineERR_OVERNUMLEN2#defineERR_NUMBER3#defineERR_WRONGOP4#defineERR_OVERSYMFORM10001//以下是严重错误号#defineERR_OVERNUMFORM10002#defineERR_OVERSYMNUM10003#defineERR_OVERERRNUM10004#ifdef__cplusplusexternC{#endifstructSYM//符号描述结构体(含错误描述结构){inttype;//类型号(0:错误)intid;//ID号(错误值)intline;//所在行数//intno;//SYM编号/列号charname[MAX_SYMLEN+1];//所取的词};structFORM//表格结构体{intsymnum;intnumnum;structSYMF//符号表项结构体{intid;charname[MAX_SYMLEN+1];4/20}symf[MAX_SYMFORM];structNUMF//常量表项结构体{intid;charname[MAX_NUMLEN+1];}numf[MAX_NUMFORM];};structSYMINFO//词法分析信息结构体{intnum;structSYMsym[MAX_SYM];structFORMform;};//取词函数(返回读字符数量,如果是0则表示结束,lin表示当前行数)int__stdcallgetsym(constchar*in,structSYM*out,int*ln,structFORM*form);//取所有词函数(正常返回0,否则返回严重错误号)int__stdcallgetsyminfo(constchar*in,structSYMINFO*out);#ifdef__cplusplus}#endif#endif#includegetsym.h//关键字[BASIC:13,EXTEND:14]constchar*constkeytxt[MAX_KEYWORD]={procedure,call,begin,end,var,const,if,then,while,do,read,write,odd,program,type,function,array,integer,real,char,boobean,case,of,repeat,until,to,down};//单字运算符constcharopatxt[MAX_OPWORDA]={'+','-','*','/','=','#','',''};//双字运算符constchar*constopbtxt[MAX_OPWORDB]={=,=,:=,};5/20//单字界符constchareoptxt[MAX_ENDWORD]={'(',')',',',';','.','[',']',':'};//错误提示信息constchar*consterrtxt[MAX_ERROR]={OK,//Notused.Toolongsymbol,Toolongnumber,Mixednumberandletter,Unkownoperator,};intgetsym(constchar*in,structSYM*out,int*ln,structFORM*form){charb[MAX_BUFFER];//建符号缓冲区inti,m=0,n=0,e=0;//序号/非字符数/字符数/出错标记memset(out,0,sizeof(structSYM));while(!ISCHAR(*in))//滤出前面的非字符{if(*in==10)(*ln)++;//换行时,ln++if(*in++)m++;elsereturn0;//如果无字符则退出}out-line=*ln;if(ISLETTER(*in))//字母开头情况{while(ISLETTER(*in)||ISNUMBER(*in)){if(n=MAX_SYMLEN)b[n]=*in;n++;in++;}b[MAX_SYMLEN]=0;//符号结尾置0if(nMAX_SYMLEN)b[n]=0;strcpy(out-name,b);if(nMAX_SYMLEN)//超出符号最大长度{out-type=TYPE_ERROR;out-id=ERR_OVERSYMLEN;}else{for(i=0;iMAX_KEYWORD;i++)6/20if(strcmp(b,keytxt[i])==0)break;if(iMAX_KEYWORD)//属于关键字{out-type=TYPE_KEYWORD;out-id=i;}else//不属于关键字{for(i=0;iform-symnum;i++)if(strcmp(b,form-symf[i].name)==0)break;if(i==form-symnum)//不在符号表中则添加{if(form-symnum=MAX_SYMFORM){//超出符号表范围产生严重错误out-type=TYPE_ERROR;out-id=ERR_OVERSYMFORM;returnm+n;}form-symf[i].id=i;strcpy(form-symf[i].name,b);form-symnum++;}out-type=TYPE_SYMBOL;//符号类型out-id=i;}}returnm+n;}if(ISNUMBER(*in))//数字开头情况{e=0;while(ISNUMBER(*in)||ISLETTER(*in)){if(ISLETTER(*in))e=1;//含字母则置出错标记if(n=MAX_NUMLEN)b[n]=*in;n++;in++;}b[MAX_NUMLEN]=0;//数字尾置0if(nMAX_NUMLEN)b[n]=0;strcpy(out-name,b);if(e||nMAX_NUMLEN)//有出错标记或超出数字最大长度{out-type=TYPE_ERROR;if(e)//含字母情况7/20out-id=ERR_NUMBER;else//超出数字最大长度情况out-id=ERR_OVERNUMLEN;}else//无错情况{if(form-numnum=MAX_NUMFORM){//超出常量表范围产生严重错误out-type=TYPE_ERROR;out-id=ERR_OVERNUMFORM;returnm+n;}form-numf[form-numnum].id=form-numnum;strcpy(form-numf[form-numnum].name,b);out-type=TYPE_NUMBER;out-id=form-numnum;form-numnum++;}returnm+n;}for(i=0;iMAX_OPWORDB;i++)//双字运算符情况if(*(short*)in==*(short*)(opbtxt[i]))break;if(iMAX_OPWORDB){out-type=TYPE_OPWORD;out-id=MAX_OPWORDA+i;*(short*)out-name=*(short*)opbtxt[i];out-name[2]=0;returnm+2;}out-name[0]=*in;out-name[1]=0;for(i=0;iMAX_OPWORDA;i++)//单字运算符情况if(*in==opatxt[i])break;if(iMAX_OPWORDA){out-type=TYPE_OPWORD;out-id=i;returnm+1;}for(i=0;iMAX_ENDWORD;i++)//单字界符情况if(*in==eoptxt[i])break;if(iMAX_ENDWORD){8/20out-type=TYPE_ENDWORD;out-id=i;returnm+1;}out-type=TYPE_ERROR;out-id=ERR_WRONGOP;//其他符号则出错return