词法分析器.docx
《词法分析器.docx》由会员分享,可在线阅读,更多相关《词法分析器.docx(15页珍藏版)》请在冰豆网上搜索。
![词法分析器.docx](https://file1.bdocx.com/fileroot1/2022-11/25/8cab3c18-fde1-4b38-a524-d2afed03b565/8cab3c18-fde1-4b38-a524-d2afed03b5651.gif)
词法分析器
学号:
0740303104
姓名:
雷凤
实验一词法分析设计
一、实验目的
通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。
二、实验内容
用VC++/VB/JAVA语言实现对C语言子集的源程序进行词法分析。
通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。
以下是实现词法分析设计的主要工作:
(1)从源程序文件中读入字符。
(2)统计行数和列数用于错误单词的定位。
(3)删除空格类字符,包括回车、制表符空格。
(4)按拼写单词,并用(内码,属性)二元式表示。
(属性值——token的机内表示)
(5)如果发现错误则报告出错
(6)根据需要是否填写标识符表供以后各阶段使用。
单词的基本分类:
◆关键字:
由程序语言定义的具有固定意义的标识符。
也称为保留字例如if、for、while、printf;单词种别码为1。
◆标识符:
用以表示各种名字,如变量名、数组名、函数名;
◆常数:
任何数值常数。
如125,1,0.5,3.1416;
◆运算符:
+、-、*、/;
◆关系运算符:
<、<=、=、>、>=、<>;
◆分界符:
;、,、(、)、[、];
三、词法分析实验设计思想及算法
1、主程序设计考虑:
◆程序的说明部分为各种表格和变量安排空间。
在具体实现时,将各类单词设计成结构和长度均相同的形式,较短的关键字后面补空。
k数组------关键字表,每个数组元素存放一个关键字(事先构造好关键字表)。
s数组------存放分界符表(可事先构造好分界符表)。
为了简单起见,分界符、算术运算符和关系运算符都放在s表中(编程时,应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。
id和ci数组分别存放标识符和常数。
instring数组为输入源程序的单词缓存。
outtoken记录为输出内部表示缓存。
还有一些为造表填表设置的变量。
◆主程序开始后,先以人工方式输入关键字,造k表;再输入分界符等造p表。
◆主程序的工作部分设计成便于调试的循环结构。
每个循环处理一个单词;接收键盘上送来的一个单词;调用词法分析过程;输出每个单词的内部码。
例如,把每一单词设计成如下形式:
(type,pointer)
其中type指明单词的种类,例如:
Pointer指向本单词存放处的开始位置。
还有一些为造表填表设置的变量。
◆主程序开始后,先以人工方式输入关键字,造k表;再输入分界符等造p表。
◆主程序的工作部分设计成便于调试的循环结构。
每个循环处理一个单词;接收键盘上送来的一个单词;调用词法分析过程;输出每个单词的内部码。
例如,把每一单词设计成如下形式:
(type,pointer)
其中type指明单词的种类,例如:
Pointer指向本单词存放处的开始位置。
词法分析设计流程图
2、词法分析过程考虑
◆根据输入单词的第一个字符(有时还需读第二个字符),
判断单词类,产生类号:
以字符k表示关键字;id表示标识符;
ci表示常数;s表示分界符。
◆对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id中,将常数变为二进制形式存入数组中ci中,并记录其在表中的位置。
lexical过程中嵌有两个小过程:
一个名为getchar,其功能为从instring中按顺序取出一个字符,并将其指针pint加1;另一个名为error,当出现错误时,调用这个过程,输出错误编号。
◆要求:
所有识别出的单词都用两个字节的等长表示,称为内部码。
第一个字节为t,第二个字节为i。
t为单词的种类。
关键字的t=1;分界符的t=2;算术运算符的t=3;关系运算符的t=4;无符号数的t=5;标识符的t=6。
i为该单词在各自表中的指针或内部码值。
表1为关键字表;表2为分界符表;表3为算术运算符的i值;表4为关系运算符的i值。
取字符和统计字符行列位置子程序
四、实验要求
1、编程时注意编程风格:
空行的使用、注释的使用、缩进的使用等。
2、将标识符填写的相应符号表须提供给编译程序的以后各阶段使用。
3、根据测试数据进行测试。
测试实例应包括以下三个部分:
◆全部合法的输入。
◆各种组合的非法输入。
◆由记号组成的句子。
4、词法分析程序设计要求输出形式:
例:
输入VC++语言的实例程序:
Ifi=0thenn++;
a﹤=3b%);
输出形式为:
单词二元序列类型位置(行,列)
(单词种别,单词属性)
for(1,for)关键字(1,1)
i(6,i)标识符(1,2)
=(4,=)关系运算符(1,3)
0(5,0)常数(1,4)
then(1,then)关键字(1,5)
n(6,n)标识符(1,6)
++ErrorError(1,7)
;(2,;)分界符(1,8)
a(6,a)标识符(2,1)
﹤=(4,<=)关系运算符(2,2)
3bErrorError(2,4)
%ErrorError(2,4)
)(2,))分界符(2,5)
;(2,;)分界符(2,6)
五、源代码
#include
#include//包含函数malloc
#include//isalpha和isdigit函数会用到
#include
#defineNULL0
FILE*fp;//fp为文件指针,用来打开一个文件
charcbuffer;//
char*key[11]={"if","else","for","while","int","return","break","continue","then","goto","char"};//关键字
char*border[6]={",",";","{","}","(",")"};//分界符
char*arithmetic[5]={"+","-","*","/","="};//运算符
char*relation[6]={"<","<=","==",">",">=","!
="};//关系运算符
char*consts[20];//常数
char*label[20];//标识符
intconstnum=0,labelnum=0;
intsearch(charsearchchar[],intwordtype)//searchchar是字符串数组,用于接收按值传递的参数和wordtype一样
{
inti=0;
switch(wordtype)//wordtype为单词种别码
{
case1:
for(i=0;i<=10;i++)//返回在关键字数组中的位置
if(strcmp(key[i],searchchar)==0)return(i+1);
return0;
case2:
for(i=0;i<=5;i++)//返回在分界符表中的位置
if(strcmp(border[i],searchchar)==0)return(i+1);
return(0);
case3:
for(i=0;i<=4;i++)//返回在运算符表中的位置
if(strcmp(arithmetic[i],searchchar)==0)return(i+1);
return(0);
case4:
for(i=0;i<=5;i++)//返回在关系运算符表中的位置
if(strcmp(relation[i],searchchar)==0)return(i+1);
return(0);
case5:
for(i=0;iif(strcmp(consts[i],searchchar)==0)return(i+1);//常数在表中,记录在表中的位置
consts[i]=(char*)malloc(sizeof(searchchar));//malloc
strcpy(consts[i],searchchar);//将输入的这个常数填入consts常数数组中
constnum++;//常数数组的长度加1
return(i+1);
case6:
for(i=0;iif(strcmp(label[i],searchchar)==0)return(i+1);
label[i]=(char*)malloc(sizeof(searchchar));
strcpy(label[i],searchchar);
labelnum++;
return(i+1);
}
return0;
}
charalphaprocess(charbuffer)//字母开头串的处理(可能是保留字或标识符)buffer为当前首字符
{
intatype;
inti=-1;
charalphatp[20];
while((isalpha(buffer))||(isdigit(buffer)))//isalpha和isdigit是库文件里包含的函数
{
alphatp[++i]=buffer;
buffer=fgetc(fp);//从fp所指的文件中读取字符
}
alphatp[i+1]='\0';//表示字符结束
if(atype=search(alphatp,1))
printf("(%s,1,%d)\n",alphatp,atype);//
//elseif(atype=search(alphatp,5))
//printf("(%s,5,%d)\n",alphatp,atype);
else
{
atype=search(alphatp,6);
printf("(%s,6,%d)\n",alphatp,atype);
}
return(buffer);//
}
chardigitprocess(charbuffer)//常量串
{
inti=-1;
chardigittp[20];
intdtype;
while((isdigit(buffer)))
{
digittp[++i]=buffer;
buffer=fgetc(fp);
}
digittp[i+1]='\0';
dtype=search(digittp,5);
printf("(%s,5,%d)\n",digittp,dtype);
return(buffer);
}
charotherprocess(charbuffer)//其它符号的处理
{
inti=-1;
charothertp[20];
intotype,otypetp;
othertp[0]=buffer;
othertp[1]='\0';
if(otype=search(othertp,3))//算术运算符
{
printf("(%s,3,%d)\n",othertp,otype);
buffer=fgetc(fp);
gotoout;
}
if(buffer=='>')//关系运算符
{
buffer=fgetc(fp);
if(buffer=='=')
printf("(>=4,5)\n");
buffer=fgetc(fp);
gotoout;
}
if(buffer=='<')
{
buffer=fgetc(fp);
if(buffer=='=')
printf("(<=4,2)\n");
buffer=fgetc(fp);
gotoout;
}
if(buffer=='=')
{
buffer=fgetc(fp);
if(buffer=='=')
printf("(==4,3)\n");
buffer=fgetc(fp);
gotoout;
}
if(otype=search(othertp,4))
{
printf("(%s,4,%d)\n",othertp,otype);
buffer=fgetc(fp);
gotoout;
}
if(otype=search(othertp,2))//分界符
{
printf("(%s,2,%d)\n",othertp,otype);
buffer=fgetc(fp);
gotoout;
}
if((buffer!
='\n')&&(buffer!
=''))//查找分界符表没找到
printf("%cerror,notaword\n",buffer);
buffer=fgetc(fp);
out:
return(buffer);
}
voidmain()
{
inti;
for(i=0;i<=20;i++)
{
label[i]=NULL;
consts[i]=NULL;
};
if((fp=fopen("example.txt","r"))==NULL)
printf("OpenFileError!
");
else
{
printf("输出格式为:
(单词,类别,位置)\n");
cbuffer=fgetc(fp);
while(cbuffer!
=EOF)//结束
{
if(isalpha(cbuffer))
cbuffer=alphaprocess(cbuffer);
else
if(isdigit(cbuffer))
cbuffer=digitprocess(cbuffer);
elsecbuffer=otherprocess(cbuffer);
}
printf("AnysisEnd\n");
}
}
六、运行结果
输出格式为:
(单词,类别,位置)
(if,1,1)
(a,6,1)
(=,3,5)
(b,6,2)
(;,2,2)
(int,1,5)
(312,5,1)
(;,2,2)
(char,1,11)
(c,6,3)
(;,2,2)
(if,1,1)
(a,6,1)
(>=4,5)
(b,6,2)
(;,2,2)
(then,1,9)
(goto,1,10)
(;,2,2)
AnysisEnd
Pressanykeytocontinue
七、心得体会
好长时间没用C++了,刚开始编程时很吃力,所以在写这个程序时遇到了些困难,看着报错的程序有时也找不到出错的地方,所以在完全把这个程序写正确前,同学也帮我改掉了不少错误。
我的这个程序实现的功能不是很强,也没有进行8进制和16进制的转换,所以,我以后的编程能力还是有待于提高的。