词法分析实验报告Word格式文档下载.docx
- 文档编号:16259496
- 上传时间:2022-11-22
- 格式:DOCX
- 页数:19
- 大小:21.44KB
词法分析实验报告Word格式文档下载.docx
《词法分析实验报告Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《词法分析实验报告Word格式文档下载.docx(19页珍藏版)》请在冰豆网上搜索。
第三类:
保留字(32)
autobreakcasecharconstcontinue
defaultdodoubleelseenumextern
floatforgotoifintlong
registerreturnshortsignedsizeofstatic
structswitchtypedefunionunsignedvoid
volatilewhile
第四类:
界符‘/*’、‘//’、(){}[]"
"
'
等
第五类:
运算符<
、<
=、>
、>
=、=、+、-、*、/、^、等
对所有可数符号进行编码:
<
$,0>
auto,1>
...
while,32>
+,33>
-,34>
*,35>
/,36>
37>
=,38>
>
39>
=,40>
=,41>
==,42>
!
=,43>
;
44>
(,45>
),46>
^,47>
,48>
"
49>
'
50>
#,51>
&
52>
53>
|,54>
||,55>
%,56>
~,57>
58>
左移
59>
右移
[,60>
],61>
{,62>
},63>
\,64>
.,65>
?
66>
:
67>
68>
["
"
]"
{"
}"
常数99,数值>
标识符100,标识符指针>
上述二元组中左边是单词的符号,右边为其种别码,其中常数和标识符有点特别,因为是无穷集合,因此常数用自身来表示,种别码为99,标识符用标识符符号表的指针表示(当然也可用自身显示,比较容易观察),种别码100。
根据上述约定,一旦见到了种别码syn=63,就唯一确定了‘}’这个单词。
下面是一些变量的约定:
//全局变量,保留字表
staticcharreserveWord[32][20]={
auto"
"
break"
case"
char"
const"
continue"
default"
do"
double"
else"
enum"
extern"
float"
for"
goto"
if"
int"
long"
register"
return"
short"
signed"
sizeof"
static"
struct"
switch"
typedef"
union"
unsigned"
void"
volatile"
while"
};
//界符运算符表,根据需要可以自行增加
staticcharoperatorOrDelimiter[36][10]={
+"
-"
*"
/"
="
=="
("
)"
^"
\"
\'
#"
|"
||"
%"
~"
\\"
."
\?
staticcharIDentifierTbl[1000][50]={"
//标识符表
charresourceProject[10000];
//输入的源程序存放处,最大可以存放10000个字符。
chartoken[20]={0};
//每次扫描的时候存储已经扫描的结果。
intsyn=-1;
//syn即为种别码,约定‘$’的种别码为0,为整个源程序的结束符号一旦扫描到这个字符代表扫描结束
intpProject=0;
//源程序指针,始终指向当前源程序待扫描位置。
几个重要函数:
//查找保留字,若成功查找,则返回种别码
//否则返回-1,代表查找不成功,即为标识符
intsearchReserve(charreserveWord[][20],chars[])
/*********************判断是否为字母********************/
boolIsLetter(charletter)
/*****************判断是否为数字************************/
boolIsDigit(chardigit)
/********************编译预处理,取出无用的字符和注释**********************/
voidfilterResource(charr[],intpProject)
/****************************分析子程序,算法核心***********************/
voidScanner(int&
syn,charresourceProject[],chartoken[],int&
pProject)
下面说一下整个程序的流程:
1.词法分析程序打开源文件,读取文件内容,直至遇上’$’文件结束符,然后读取结束。
2.对读取的文件进行预处理,从头到尾进行扫描,去除//和/**/的内容,以及一些无用的、影响程序执行的符号如换行符、回车符、制表符等。
但是千万注意不要在这个时候去除空格,因为空格在词法分析中有用,比如说inti=3;
这个语句,如果去除空格就变成了“inti=3”,这样就失去了程序的本意,因此不能在这个时候去除空格。
3.选下面就要对源文件从头到尾进行扫描了,从头开始扫描,这个时候扫描程序首先要询问当前的字符是不是空格,若是空格,则继续扫描下一个字符,直至不是空格,然后询问这个字符是不是字母,若是则进行标识符和保留字的识别;
若这个字符为数字,则进行数字的判断。
否则,依次对这个字符可能的情况进行判断,若是将所有可能都走了一遍还是没有知道它是谁,则认定为错误符号,输出该错误符号,然后结束。
每次成功识别了一个单词后,单词都会存在token[]中。
然后确定这个单词的种别码,最后进行下一个单词的识别。
这就是扫描程序进行的工作,可以说这个程序彻底实现了确定有限自动机的某些功能,比如说识别标识符,识别数字等。
为了简单起见,这里的数字只是整数。
4.主控程序主要负责对每次识别的种别码syn进行判断,对于不同的单词种别做出不同的反应,如对于标识符则将其插入标识符表中。
对于保留字则输出该保留字的种别码和助记符,等等吧。
直至遇到syn=0;
程序结束。
二.流程图
下面是程序的流程图:
三.运行与测试
比如说,就拿这个源程序的一部分进行测试:
运行程序后结果为:
同样单词也写入了文件如下:
。
综上分析,达到了预期的结果。
四.实验体会
每做一次比较大的实验,都应该写一下实验体会,来加深自己对知识的认识。
其实这次的实验,算法部分并不难,只要知道了DFA,这个模块很好写,比较麻烦的就是五种类型的字符个数越多程序就越长。
但为了能识别大部分程序,我还是用了比较大的子集,结果花了一下午的功夫才写完,虽然很累吧,但看着这个词法分析器的处理能力,觉得还是值得的。
同时也加深了对字符的认识。
程序的可读性还算不错。
程序没有实现的是对所有复合运算的分离,但原理是相同的,比如“+=“,只需在”+“的逻辑之后向前扫描就行了,因此就没有再加上了。
感受最深的是学习编译原理必须要做实验,写程序,这样才会提高自己的动手能力,加深自己对难点的理解,对于以后的求first{},follow{},fisrtVT{},lastVT{}更是应该如此。
五.源程序
//Lexical_Analysis.cpp:
定义控制台应用程序的入口点。
//
#include"
stdio.h"
stdlib.h"
string.h"
iostream"
usingnamespacestd;
//词法分析程序
//首先定义种别码
/*
autobreakcasecharconstcontinue
defaultdodoubleelseenumextern
floatforgotoifintlong
registerreturnshortsignedsizeofstatic
structswitchtypedefunionunsignedvoid
=、=、+、-、*、/、^、
*/
/****************************************************************************************/
staticcharoperatorOrDelimiter[36][10]={
staticcharIDentifierTbl[1000][50]={"
};
/********查找保留字*****************/
intsearchReserve(charreserveWord[][20],chars[])
{
for(inti=0;
i<
32;
i++)
{
if(strcmp(reserveWord[i],s)==0)
{//若成功查找,则返回种别码
returni+1;
//返回种别码
}
return-1;
}
{//注意C语言允许下划线也为标识符的一部分可以放在首部或其他地方
if(letter>
='
a'
letter<
z'
||letter>
A'
Z'
||letter=='
_'
)
returntrue;
else
returnfalse;
if(digit>
0'
digit<
9'
voidfilterResource(charr[],intpProject)
chartempString[10000];
intcount=0;
=pProject;
if(r[i]=='
/'
r[i+1]=='
{//若为单行注释“//”,则去除注释后面的东西,直至遇到回车换行
while(r[i]!
\n'
i++;
//向后扫描
*'
{//若为多行注释“/*。
*/”则去除该内容
i+=2;
||r[i+1]!
//继续扫描
$'
printf("
注释出错,没有找到*/,程序结束!
!
\n"
);
exit(0);
//跨过“*/”
if(r[i]!
r[i]!
\t'
\v'
\r'
{//若出现无用字符,则过滤;
否则加载
tempString[count++]=r[i];
tempString[count]='
\0'
strcpy(r,tempString);
//产生净化之后的源程序
syn,charresourceProject[],chartoken[],int&
{//根据DFA的状态转换图设计
inti,count=0;
//count用来做token[]的指示器,收集有用字符
charch;
//作为判断使用
ch=resourceProject[pProject];
while(ch=='
{//过滤空格,防止程序因识别不了空格而结束
pProject++;
for(i=0;
i<
20;
{//每次收集前先清零
token[i]='
if(IsLetter(resourceProject[pProject]))
{//开头为字母
token[count++]=resourceProject[pProject];
//收集
//下移
while(IsLetter(resourceProject[pProject])||IsDigit(resourceProject[pProject]))
{//后跟字母或数字
}//多读了一个字符既是下次将要开始的指针位置
token[count]='
syn=searchReserve(reserveWord,token);
//查表找到种别码
if(syn==-1)
{//若不是保留字则是标识符
syn=100;
//标识符种别码
return;
elseif(IsDigit(resourceProject[pProject]))
{//首字符为数字
while(IsDigit(resourceProject[pProject]))
{//后跟数字
syn=99;
//常数种别码
elseif(ch=='
+'
||ch=='
-'
('
)'
^'
'
~'
#'
%'
['
]'
{'
}'
\\'
.'
{//若为运算符或者界符,查表得到结果
token[0]=resourceProject[pProject];
token[1]='
//形成单字符串
36;
{//查运算符界符表
if(strcmp(token,operatorOrDelimiter[i])==0)
syn=33+i;
//获得种别码,使用了一点技巧,使之呈线性映射
break;
//查到即推出
//指针下移,为下一扫描做准备
elseif(resourceProject[pProject]=='
{//<
<
=,<
//后移,超前搜索
if(resourceProject[pProject]=='
='
syn=38;
{//左移
pProject--;
syn=58;
syn=37;
//指针下移
{//>
>
=,>
syn=40;
syn=59;
syn=39;
{//=.==
syn=42;
syn=41;
{//!
!
=
pProject+
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 词法 分析 实验 报告