词法分析程序设计一、程序功能描述1.文法扩充对实验所给的文法进行如下扩充:标识符→字母︱标识符字母︱标识符数字无符号整数→数字︱无符号整数数字无符号小数→数字无符号小数|数字小数小数→.无符号整数单字符分界符→+︱-︱*︱;︱,︱(︱)︱{︱}双字符分界符→大于=︱小于=︱小于︱感叹号=︱等于=︱斜竖*|加号+|减号-|大于|小于|加号=|减号=|乘号=|斜竖=|斜竖/|乘号/小于→等于→=大于→斜竖→/感叹号→!加号→+减号→-乘号→*该语言的保留字:voidintfloatdoubleifelsefordowhilethen输入文件:input.txt保留字及其编码文件:reserved.txt输出文件:此法分析结果以“(类型编码,单词符号)”的形式输出到指定文件output.txt中2.程序所能识别的单词符号及其类别编码程序能够识别的文法所规定的所有合法的单词符号,对大小写不敏感;能够识别“/******/”和“//”两种形式的注释;能够将词法分析的结果以二元式的形式输出到中间文件中。所能识别的单词符号及其类别编码见下表(红色部分为语言的保留字):单词符号类别编码单词符号类别编码单词符号类别编码非法字符0}21*/-1=22标识符1=23无符号整数224void3!=25int4==26float5/*27double6++28if7--29else830for931do10+=32while11-=33then12*=34+13/=35-1436*15=37;1638,17/39(18!40)19无符号小数41{20//42表格1语言的保留字表如下:3.程序所能识别的字符串中的错误类型程序还能发现输入串中的错误,能够发现的错误如下:错误类型错误举例所有该语言没有定义的单词符号~、&、%、$标识符不能以数字开头1abc、2a34数中包含多个小数点1.2.3小数中包括字母1.fg、2a.b表格2二、主要数据结构描述全局变量charToken[20];字符数组,用来依次存放一个单词词文中的各个字符FILE*fpout;输出文件指针关键的局部变量FILE*fpinput;输入文件指针intch;用来存放从文件中读入的字符FILE*fp;文件指针charword[20];用来存放从保留字表中读入的保留字boolhasDot;记录正在识别的单词符号中是否有小数点boolerror;记录正在识别的单词符号中是否有错误boolisAnnotation;标志当前读入的单词符号是否是注释中的内容intc;存储单词符号所对应的类别编码表格3三、程序结构描述1.设计方法0122STARTINITCATGETCHARRETRACTC=LOOKUPCATGETCHARAlpha,digitAlpha非Alpha或digitOUT(C,TOKEN)3CATGETCHAR其它RETRACTdigitdigit5dotCATGETCHAR4digitCATGETCHARdigitCATGETCHAR66digitCATGETCHAR77RETRACTAlpha,dot有小数点时:OUT(41,TOKEN)无小数点时:OUT(2,TOKEN)Error8=非=、、99101011111212RETRACTout(23,=)out(24,)out(31,)out(36,)13GETCHARGETCHAR=CATGETCHAR1414=1515非=RETRACTout(26,==)out(37,=)16GETCHAR1717=out(22,=)1818out(30,)1919out(38,)非=、RETRACT20212122222323+GETCHAR=+非=、+RETRACT24252526262727-GETCHAR=-非=、-RETRACTout(32,+=)out(28,++)out(13,+)out(33,-=)out(29,--)out(14,-)2829293030*=非=out(34,*=)out(15,*)RETRACT31isAnnotation=flase32isAnnotation=true3333/out(-1,*/)GETCHARGETCHAR非/34/3535=GETCHARout(35,/=)3636/3737非=、/、*RETRACTout(42,//)out(39,/)38*非*GETCHAR3939isAnnotation=trueout(27,/*)RETRACT40!GETCHAR4141=out(25,!=)4242非=out(40,!)RETRACT(GETCHAR4444out(18,())GETCHAR4545out(19,)){GETCHAR4646out(20,{)}GETCHAR4444out(21,});GETCHAR4545out(16,;),GETCHAR4646out(17,,)其他CATErrorGETCHAR4646out(0,Token)GOTOSTART图1程序所能识别的单词符号的DFA及相关的语义过程图1中所出现的语义变量及语义函数的含义及功能说明如下:函数GETCHAR每调用一次,就把扫描指示器当前所指示的源程序字符送入字符变量ch中,然后把扫描指示器前推一个字符位置。字符数组TOKEN用来依次存放一个单词词文中的各个字符。函数CAT每调用一次,就把当前ch中的字符拼接于TOKEN中所存字符串的右边。函数LOOKUP每调用一次,就以TOKEN中的字符串查保留字表,若查到,并返回相应关键字的类别码,否则返回1(标识符的类别编码)。函数RETRACT每调用一次,就把扫描指示器回退一个字符位置(即回退多读的那个字符)。函数OUT一般仅在进入终态时调用此函数,调用的形式为OUT(c,VAL).其中,实参c为相应单词的类别码;当所识别的单词为标识符、整数或小数时,实参VAL为TOKEN(即词文分别为字母和数字串)。2.函数定义/***********************************************函数名:isalpha*功能:判断字符是否是字母*参数:charch要验证的字符*返回值:bool是否是字母***********************************************/boolisalpha(charch)/***********************************************函数名:isUper*功能:判断字符是否是大写字母*参数:charch要验证的字符*返回值:bool是否是大写字母***********************************************/boolisUper(charch)/***********************************************函数名:isalnumm*功能:判断字符是否是字母或数字*参数:charch要验证的字符*返回值:bool是否是字母或数字***********************************************/boolisalnum(charch)/***********************************************函数名:isdigit*功能:判断字符是否是数字*参数:charch要验证的字符*返回值:bool是否是数字***********************************************/boolisdigit(charch)/***********************************************函数名:lookUp*功能:以所给的字符串查找保留字表,若查到,就*返回相应的关键字的类别码,否则返回'0'*参数:char*p要查找的字符串*返回值:int关键字的类别码***********************************************/intlookUp(char*p)/***********************************************函数名:out*功能:将词法分析结果以二元式的形式输出到文件中*参数:intc单词符号编码*char*q所读入的单词符号串*返回值:无***********************************************/voidout(intc,char*q)/***********************************************函数名:report_error*功能:将词法分析结果以二元式的形式输出到文件中*参数:intc单词符号编码*char*q所读入的单词符号串*返回值:无***********************************************/voidreport_error(char*ch)/***********************************************函数名:scanner*功能:识别输入文件中的单词符号,判断其是否是*文法所规定的合法的单词符号*参数:FILE*fp文件指针*返回值:无***********************************************/voidscanner(FILE*fp)/***********************************************函数名:main*功能:主函数,调用其他函数实现程序功能***********************************************/intmain(intargc,char*argv[])四、程序测试1.测试用例Doublecalculate(intnum){/**ddddsdfdsd*/inta1=num+3.0.8;floatb=2.456*c;if(f=1e23){do{h-=x/2;y+=1.2;//sdfgh}while(a==6);}else{y++;ax--;1.f12dqwe.gh~&%$}}上述为测试用例,其中黄色部分为错误输入,在程序中应该报错;红色部分为注释。其余为可识别单词符号。2.测试结果1)词法分析结果以二元式序列的方式输出到文件中从输出结果可以看出,注释符号“/**/”之间的内容和注释符号“//”后面的内容没有存入文件中,错误单词符号的类别编码为0。2)测试用例中的报错五、心得体会通过本次实验,我对词法分析的过程有了更好的理解,通过绘制状态转换图,能够使得我们编程时条理更加清晰,在本次实验时,我先前没有绘制状态转化图,使得编程时思路比较乱,代码可读性也比较差,特别是在程序错误识别时,由于没有清晰的思路,使得编程存在一些困难。后来通过看状态转换图各状态之间的转换关系,才能编写出更加合理的代码。在实验中,我是仿照书上所给的状态转化图进行编程,但是同时也发现书上的状态转换图中存在的一些问题,比如书上的图对于字符串“1a”的识别是将其看做是两个单词符号,整数“1”和标志符“a”,并将这两个单词符号都以二元式的形式存入文件中,这显然是不合理的,所以我对其进行了一些修改,使得程序能够识别一些较常见的错误。