词法分析器.docx

上传人:b****3 文档编号:3853337 上传时间:2022-11-25 格式:DOCX 页数:15 大小:136.01KB
下载 相关 举报
词法分析器.docx_第1页
第1页 / 共15页
词法分析器.docx_第2页
第2页 / 共15页
词法分析器.docx_第3页
第3页 / 共15页
词法分析器.docx_第4页
第4页 / 共15页
词法分析器.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

词法分析器.docx

《词法分析器.docx》由会员分享,可在线阅读,更多相关《词法分析器.docx(15页珍藏版)》请在冰豆网上搜索。

词法分析器.docx

词法分析器

学号:

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;i

if(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;i

if(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进制的转换,所以,我以后的编程能力还是有待于提高的。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1