编制一个词法识别程序
二、实验题目假设某语言允许的标识符为字母开头的字母数字串,允许的数据为无符号的十进制或十六进制整数。其中规定十六进制数必须以数字打头、以H结尾,数中允许使用的字母为A,B,C,D,E,F(分别表示10~15)。试设计一个DFA,使它能识别标识符、无符号的十进制和十六进制整数(假定各单词之间用界限符或空格分开),并编制相应的词法识别程序。
输入:可以自定义符号串的输入形式,如键盘输入、文本文件、字符数组等。
输出:标识出规范的符号串与不合规范的符号串。
三、分析与设计0状态是初始状态。1,2,3是终止状态。
在初始状态0时,输入数字会进入状态2,即将输出十进制或十六进制的整数,输入字母会进入状态1,即将输出字母开头的标识符
在状态2时,术后如数字仍然进入2,输入A-F的字母或H,即将输出十六进制的整数,作为终止状态之一,如果输入空格,就输出该字符串,并重新进入到状态0
在状态1时,允许输入字母或是数字,并仍然处于状态1,如果输入空格,就输出该字符串,并重新进入到状态0
在状态4时,输出的应为十六进制,但结尾要为H,故而输入数字或是A-F仍然进入状态4,但输入H会进入状态3
在状态3时,如果输入空格就输出,并重新加入状态0,其他非空格外的输入都是非法输入
#include五、实验结果(运行截屏) 六、实验总结#include enum type {digit,space,Hh,AF,letter} ; //判断.数字:1 ﹔空格:2;H(h):3;字母A,B,C,D,E,F:4;其它字母:5 int isDigitOrChar (char ch) { //数字 if(ch>=48 && ch<=57) return digit; //空格 else if( ch == 32 ) return space; //H or h else if( ch == 72 || ch == 104 ) return Hh; //字母A,B,C,D,E,F else if((ch>=65 && ch<=70)||(ch>=97 && ch<=102)) return AF; //除A~F外的其它字母 else if((ch>=65 && ch<=90)||(ch>=97 && ch<=122)) return letter; } int main() { //测试的输入符号串 char words[100]=" Ae35 6638 5392H A10 83A2Eh 65Ha 3G2H 80 "; printf("Input string is: %snn",words); //指向输入符号串中当前的字符 char *q; //存储当前识别的单词 char word[20]; //表示所处的状态 int state=0; //单词的下标 int i; q = words; while(*q) { switch(state) { case 0: //当前为0状态 switch( isDigitOrChar(*q)) { case digit: //数字 word[i++]=*q; state = 2; break; case Hh: //H or h case AF: //字母A,B,C,D,E, F or a, b, c, d,e,f case letter: //字母 word[i++] =*q; state = 1; break; case space: //空格 state = 0; break; default: //其它(非法字符) word[i++]=*q ; state = 5; //转移到出错状态 } break ; case 1: //当前为1状态 switch ( isDigitOrChar (*q)) { case digit : //数字 case Hh: //H or h case AF: //字母A,B,C, D,E,F or a, b, c, d,e, case letter: //字母 word[i++]= *q; state = 1; break ; case space://空格 word[i]=' '; //当前单词结束 printf("%s is an identifier. n" , word) ; strcpy(word," "); //单词清空 i=0; //重新计数 state = 0; break; default: //其它(非法字符) word[i++] =*q; state = 5; //转移到出错状态 } break; case 2: //当前为2状态 switch( isDigitOrChar(*q)) { case digit: //数字 word[i++] = *q ; state = 2; break; case Hh: //H or h word[i++]= *q ; state = 3; break; case AF: //字母A,B,C,D,E,F or a, b, c,d,e,f word[i++] =*q ; state = 4; break; case space: //空格 word[i]=' '; //当前单词结束 printf("%s is an Integer. n" , word) ; strcpy (word," "); //单词清空 i=0; //重新计数 state = 0; break; default: //其它(非法字符) word[i++] =*q; state = 5; //转移到出错状态 } break ; case 3: //当前为3状态 switch ( isDigitOrChar (*q)) { case space: //空格 word[i]=' '; //当前单词结束 printf("%s is a Hex digit. n" , word) ; strcpy (word," "); //单词清空 i=0; //重新计数 state = 0; break; default: //其它(非法字符) word[i++]=*q ; state = 5; //转移到出错状态 } break; case 4: //当前为4状态 switch ( isDigitOrChar (*q)) { case digit: //数字 word[i++] =*q; state = 4; break; case AF: //字母A,B,C,D,E, F or a, b, c,d, e,f word[i++]=*q ; state = 4; break; case Hh: //H or h word[i++]=*q; state = 3; break ; default: //其它(非法字符) word[i++]=*q; state = 5; //转移到出错状态 } break; case 5: //出错状态 if(*q == 32 ) { //空格(当前单词结束) word[i]=' '; printf("%s is not an identifier. n",word); strcpy (word," ")); //单词清空 i=0; //重新计数 state = 0 ; //重新开始提取单词 } else { //当前单词还未结束 word[i++] =*q; //添加到单词尾部 q++; continue; } } q++;//指针下移(指向输入符号串中的下一字符) } }
(1)重点与难点
画出DFA图,并进行分析
(2)存在的不足
没有将case中的switch封装,导致主函数语句太多
(3)未来改进方案
封装switch语句
封装case space的输出语句
(4)结论(开发体验、收获、感想等)
本次实验之前,对教材上DFA相关理论知识进行了复习,并在实验中通过实践,进一步巩固了所学知识。通过本次实验,我巩固复习了if-else switch-case语句的逻辑结构,初步学会了如何通过c语言编写一个基础的词法识别程序,还学会了先创建代码的主体框架,再对每部分细节进行填充的程序编写方法。



