词法分析器

一、实验目的

编制一个词法识别程序

二、实验题目

假设某语言允许的标识符为字母开头的字母数字串,允许的数据为无符号的十进制或十六进制整数。其中规定十六进制数必须以数字打头、以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<stdio.h>
#include<string.h>

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: %s\n\n",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]='\0'; //当前单词结束
						printf("%s is an identifier. \n" , word) ;
						strcpy(word,"\0"); //单词清空
						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]='\0'; //当前单词结束
						printf("%s is an Integer. \n" , word) ;
						strcpy (word,"\0"); //单词清空
						i=0; //重新计数
						state = 0;
						break;
					default: //其它(非法字符)
						word[i++] =*q;
						state = 5; //转移到出错状态
				}
				break ;
			case 3: //当前为3状态
				switch ( isDigitOrChar (*q)) {
					case space: //空格
						word[i]='\0'; //当前单词结束
						printf("%s is a Hex digit. \n" , word) ;
						strcpy (word,"\0"); //单词清空
						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]='\0';
					printf("%s is not an identifier. \n",word)strcpy (word,"\0")); //单词清空
					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语言编写一个基础的词法识别程序,还学会了先创建代码的主体框架,再对每部分细节进行填充的程序编写方法。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值