基本要求:
①掌握程序语言的词法结构。
②掌握状态转换图的使用。
③掌握设计词法分析程序的一般方法。
④学会熟练调式程序。
重点及难点:掌握用状态转换图描述程序词法结构的一般方法,并在此基础上完成简版C语言子集词法分析程序的设计和调试运行。

一、 C语言子集的单词符号表示

一个非常重要的事实是:大多数程序语言的单词符号都可以用状态转换图予以识别。作为本次实验,我们来构造一个C语言子集的简单词法分析器。下表列出了这个C语言子集的所有单词符号以及它们的种别编码和内码值。由于直接使用整数编码不利于记忆,故该程序中用一些特殊符号来表示种别编码。
C语言子集的单词符号及内码值
在这里插入图片描述

二、 C语言子集对应的状态转换图

在设计的状态转换图中,首先对输入串做预处理,即剔除多余的空白符(在实际的词法分析中,预处理还包括剔除注释和制表换行符等编辑性字符的工作),使词法分析工作既简单又清晰。其次,将保留字作为一类特殊的标识符来处理,也即对保留字不专设对应的状态转换图,当转换图识别出一个标识符时就去查对上表的前五项,确定它是否为一个保留字。当然,也可以专设一个保留字表来进行处理。
在这里插入图片描述
状态2时,所识别出的标识符应先与表的前五项逐一比较,若匹配,则该标识符是一个保留字,否则就是标识符。如果是标识符,应先查符号表,看表中是否有此标识符。若表中无此标识符,则将它登录到符号表中,然后返回其在符号表中的入口指针(地址)作为该标识符的内码值;若表中有此标识符,则给出重名错误信息。在状态4时,应将识别的常数转换成二进制常数并将其登录到常数表,然后返回其在常数表中的入口指针作为该常数的内码值。

三、状态转换图的实现

状态转换图非常容易用程序实现,最简单的办法是让每个状态对应一小段程序。对于上述状转换图,我们首先引进一组变量和过程如下:
(1)character:字符变量,存放最新读入的源程序字符。
(2)token:字符数组,存放构成单词符号的字符串。
(3)getbe( ):若character中的字符为空白,则调用getchar( ),直至character为非空白符为止。
(4)concatenation( ):将token中的字符串与character中的字符连接并作为token中新的字符串。
(5) letter( )和digit( ):判断character中的字符是否为字母和数字的布尔函数,是则返回true,否则返回false。
(6) reserve( ):按token数组中的字符串查表中的前五项(即判别其是否为保留字),若是保留字则返回它的编码,否则返回0值。
(7) retract( ):扫描指针回退一个字符,同时将character置为空白。
(8) buildlist( ):将标识符登录到符号表或将常数登录到常数表。
(9)error( ):出现非法字符,显示出错信息。

四.源代码

#include <stdio.h>
#include <string.h>
int i,j,k;
char s;
char a[20],token[20];
int letter()
{
	if ((s>=97)&&(s<=122))
		return 1;
	else 
		return 0;
}
int Digit()
{
	if ((s>=48)&&(s<=57))
		return 1;
	else 
		return 0;
}
void get()
{
	s=a[i];
	i=i+1;
}
void retract()
{
	i=i-1;
}
int lookup()
{
	if (strcmp(token,"while")==0)
		return 1;
	else if (strcmp(token,"if")==0)
		return 2;
	else if (strcmp(token,"else")==0)
		return 3;
	else if (strcmp(token,"switch")==0)
		return 4;
	else if (strcmp(token,"case")==0)
		return 5;
	else
		return 0;
}
void main()
{
	printf("Please input you source program,end('#'):\n");
	i=0;
	do
		{
			i=i+1;
			scanf("%c",&a[i]);
		}
		while(a[i]!='#');
			i=1;
			memset(token,0,sizeof(char)*10);
			j=0;
			get();
		while(s!='#')
			{
			if(s==' '||s==10||s==13)
				get();
			else
			{
				switch(s)
					{
						case'a':
						case'b':
						case'c':
						case'd':
						case'e':
						case'f':
						case'g':
						case'h':
						case'i':
						case'j':
						case'k':
						case'l':
						case'm':
						case'o':
						case'p':
						case'q':
						case'r':
						case's':
						case't':
						case'u':
						case'v':
						case'w':
						case'x':
						case'y':
						case'z':
						while(Digit()||letter())
							{
							token[j]=s;
							j=j+1;
							get();
							}
							retract();
							if(k==0)
								printf("(6,%s)\n",token);
							else
								printf("(%d,null)\n",k);
								break;
								case'0':
								case'1':
								case'2':
								case'3':
								case'4':
								case'5':
								case'6':
								case'7':
								case'8':
								case'9':
								while(Digit())
								{
									token[j]=s;
									j=j+1;
									get();
								}
								retract();
								printf("(%d,%s)\n",7,token);
									break;
								case'+':printf("(+,null)\n");
									break;
								case'-':printf("(-,null)\n");
									break;
								case'*':printf("(*,null)\n");
									break;
								case'<':
									get();
									if (s=='=')
										printf("(relop,LE)\n");
									else
									{
											retract();
											printf("(relop,LT)\n");
									}
									break;
								case'=':
									get();
									if(s=='=')
									printf("(relop,EQ)\n");
									else
										{
										retract();
										printf("(=,null)\n");
										}
									break;
								case';':printf("(;,null)\n");
									break;
								default:printf("(%c,error)\n,s");	
									break;
							}
								memset(token,0,sizeof(char)*10);
								j=0;
								get();
						}
			}
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐