词法分析之实验报告
词法分析实验
一、实验目的
编制一个词法分析程序
二、实验内容和要求
1.输入:源程序字符串
2.输出:二元组(种别,单词本身)
单词与种别码
三、实验方法、步骤及结果测试
(一).原理分析及流程图
1.原理分析
存储结构:此词法分析程序,我采用的主要存储结构有链队列和指针数组。链队列用于存 储输入的原程序,之所以考虑用链队列,是因为链队列是需要时才申请空间的,更重要的原因 是链队列是先进先出的,这符合我要编写的词法分析程序,而数组是在定义时就要设置好它的 容量,系统会为其分配一个固定容量的存储空间,数组一旦创建后,它的容量就不能更改,所 以它很容易造成数组越界而导致程序终止,数组容量过大就会浪费存储空间,会影响程序的运 行速度。此程序指针数组是用于存储关键字、符、算符、界符等已知其需要多大存储空间的字 符,而且程序上涉及的种别码可以通过获取数组下标得到。
主要算法:先将源程序用链队列存储起来,然后逐一从链队列中取出单个字符分析,具体 实 现,看下面的流程图
关键函数的实现:
void InitQueue() //初始化一个带节点的空队列
void Printf() //输出原程序
int search(char searchstr[],int wordtype)//符号匹配 返回种别码
void Analyze() //词法程序分析
2.流程图
2.主要程序段及其解释:
1 void Analyze() 2 { 3 char str; 4 char letter[20]; //存放字母的数组 5 char num[20]; //存放数字的字符数组 6 char other[20]; //存放其他字符的数组 7 int i; 8 do //循环获取字符分析 9 { 10 Q.front=Q.front->next; //获取单个字符 11 str=Q.front->ch; //出队列 12 if (isalpha(str)!=0) //如果是字符 13 { 14 i=-1; 15 while (isalnum(str)!=0) //判断下一个字符是否是字母 16 { 17 letter[++i]=str; //将字母存放到字符数组 18 Q.front=Q.front->next; //出队列 19 str=Q.front->ch; //获取下一个字符 20 } 21 letter[i+1]='\0'; //字符串的结束 22 if (search(letter,1)!=-1) // 调用int search(char searchstr[],int wordtype)函数,判断该字符串是否能和指针数组中的字符串匹配 23 { 24 printf("( %d,%s )\n",search(letter,1),letter);//输出种别码和单词本身 25 26 } 27 else 28 { 29 printf("( %d,%s )\n",71,letter); //输出种别码和单词本身 30 } 31 } 32 else 33 { 34 if (isdigit(str)!=0) //判断是否为数字 35 { 36 i=-1; 37 while (isdigit(str)!=0) //判断下一个字符是否为数字 38 { 39 num[++i]=str; //将数字存放到数字字符数组里去 40 Q.front=Q.front->next; //出队列 41 str=Q.front->ch; //获取下一个字符 42 } 43 if(isalpha(str)!=0) //数字后面是字符 44 { 45 while(isspace(str)==0) 46 { 47 num[++i]=str; 48 Q.front=Q.front->next; //出队列 49 str=Q.front->ch; //获取下一个字符 50 51 } 52 num[i+1]='\0'; //字符串的结束 53 printf("错误!非法标识符:%s\n",num); 54 55 } 56 num[i+1]='\0'; 57 printf("( %d,%s )\n",72,num); 58 } 59 else 60 { 61 i=-1; 62 if (isspace(str)!=0) //判断是否为空格 63 { 64 Q.front=Q.front->next; //出队列,即跳过空格 65 str=Q.front->ch; //获取下一个字符 66 67 } 68 while ((isspace(str)==0)&&(isalnum(str)==0)) 69 { 70 other[++i]=str; 71 Q.front=Q.front->next; 72 str=Q.front->ch; 73 74 75 } 76 other[i+1]='\0'; 77 if (search(other,2)!=-1) 78 printf("( %d,%s )\n",search(other,2),other); //输出种别码和单词本身 79 else if (search(other,3)!=-1) 80 printf("( %d,%s )\n",search(other,3),other); //输出种别码和单词本身 81 else if (search(other,4)!=-1) 82 printf("( %d,%s )\n",search(other,4),other); //输出种别码和单词本身 83 else if (search(other,5)!=-1) 84 printf("( %d,%s )\n",search(other,5),other); //输出种别码和单词本身 85 else if (search(other,6)!=-1) 86 printf("( %s,注释符号 )\n",other); //输出种别码和单词本身 87 else if (search(other,7)!=-1) 88 printf("( %d,%s )\n",search(other,7),other); //输出种别码和单词本身 89 else 90 printf("错误!非法字符:%s\n",other); 91 } 92 } 93 }while(Q.front!=Q.rear); 94 printf("词法分析结束,谢谢使用!\n"); 95 }
3. 运行结果及分析
四、 实验总结
难点一:. 想将字符串存进数组中去,觉得这样获取种别码比较简单,但是用没有加指针的数组会报错
解决方法:用一个指针数组存储就可以解决这一问题。
难点二:如果将所有的字符和数字都存储在同一指针数组,那样指针数组看起来太长,且分析时也比较浪费时间,每次都要从头开始匹配
解决方法:按类型将字符串和字符分别放在不同的指针数组中,获取种别码时要加上前一个数组的长度。
难点三:.输入原程序后,对原程序的分析时,要判断各种字符和数字,判断条件太多,代码长且难看懂,很容易把自己绕晕。
解决方法:调用#include<ctype.h>库函数里的字符类型判断的函数,这样可以使代码简洁易懂。