C语言词法分析器实验报告汇总.docx
《C语言词法分析器实验报告汇总.docx》由会员分享,可在线阅读,更多相关《C语言词法分析器实验报告汇总.docx(24页珍藏版)》请在冰点文库上搜索。
C语言词法分析器实验报告汇总
计算机科学与工程系
编译原理课程设计实验报告
姓名:
__******__学号_*******__年级专业及班级___08计算机科学与技术成绩
实验名称
词法分析程序设计与实现
完成日期
2011/4/12
指导教师
*******
实验目的:
能够采用C编程语言实现简单的词法分析程序;设计、编制并调试一个词法分析程序,加深对词法分析原理的理解
实验要求:
1.对单词的构词规则有明确的定义;
2.编写的分析程序能够正确识别源程序中的单词符号;
3.识别出的单词以<单词符号,种别码>的形式保存在符号表中(链表);
4.词法分析中源程序的输入以.c格式,分析后的符号表,将二元组保存在.txt文件中。
实验内容:
选择高级语言(C语言),编制它的词法分析程序。
词法分析程序的实现可以采用任何一种编程工具
实验原理:
1、算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号;
2、其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
实验分析:
(1)关键字:
ifelsewhiledocaseintbreak等所有的关键字都是小写。
(2)运算符和界符:
=+-*/<<=<>>>==;()等
(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:
ID=_|letter(letter|digit)*
NUM=digitdigit*
(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
(5)注释被忽略
(6)各种单词符号对应的种别码(如下):
单词符号
种别码
单词符号
种别码
auto
1
double
2
int
3
struct
4
break
5
else
6
long
7
switch
8
case
9
enum
10
register
11
typedef
12
char
13
extern
14
return
15
union
16
const
17
float
18
short
19
unsigned
20
continue
21
for
22
signed
23
void
24
default
25
goto
26
sizeof
27
volatile
28
do
29
while
30
static
31
if
32
\a
33
\b
34
\f
35
\n
36
\t
37
\v
38
\\
39
\?
40
\’
41
\”
42
\0
43
\ddd
44
\xhh
45
数字
46
标识符
47
#
48
(
49
)
50
[
51
]
52
{
53
}
54
‘
55
*
56
:
57
~
58
%
59
^
60
+
61
?
62
=
63
|
64
&
65
!
66
<
67
>
68
>=
69
==
70
>>
71
!
=
72
<<
73
&&
74
<=
75
||
76
++
77
?
=
78
-
79
--
80
->
81
“
82
%A(A可为d’s’c)
83
;
84
_
85
/
86
87
88
89
90
91
其他类别
99
实验流程图(由于流程图过大因此各部分分开写):
整体:
扫描注释:
扫描数字:
扫描引号:
扫描单词:
扫描其他字符:
实验环境:
需要TC、VC++6.0等开发工具作为本次试验的环境。
实验步骤:
1、准备:
用TC、VC++等开发工具;
2、对本实验的任务进行分析,确定实现功能的函数;
3、写好程序,仔细修改函数;
4、上机操作:
输入源程序,修改、调试,运行。
5、写好试验报告。
实验调试过程及测试结果
/*******************************源代码******************************/
#include
#include
#include
#include
voidmain()
{
FILE*fp,*fp1;
inthanjsq=1;//行计数器,保存行号
intguanjz(charch1[]);//关键字和标识符判断
charch,infile[15],outfile[15];//定义输入和输出文件名
printf("*****************Entertheinfilename*******************\n");
scanf("%s",infile);//输入需要扫描的文件名
printf("*****************Entertheoutfilename******************\n");
scanf("%s",outfile);//输入需要另存为的文件名
if((fp=fopen(infile,"r"))==NULL)//打开需要扫描的文件
{
printf("cannotopenfile\n");
exit(0);
}
if((fp1=fopen(outfile,"w"))==NULL)//打开需要存入的文件
{
printf("cannotopenfile\n");
exit(0);
}
printf("\n*********************************************************\n");
printf("*》开始进行词法分析《*\n");
printf("*********************************************************\n");
printf("\n*********************************************************\n");
printf("行号字符串种别码\n");
printf("*********************************************************\n");
fprintf(fp1,"*********************************************************\n");
fprintf(fp1,"行号字符串种别码\n");
fprintf(fp1,"*********************************************************\n");
while(!
feof(fp))
{
ch=fgetc(fp);
if(ch==10)hanjsq++;
/**********************扫描头文件单词及保留字***********************/
if(isalpha(ch)||ch=='_')//如果第一个字符为字母或下划线则判断为标识符
{
inti=0;
charch1[30];//假定每个标识符最长为
ch1[i++]=ch;//将ch保存到ch1[0]中并使i自加1
while(!
feof(fp))
{
ch=fgetc(fp);
if(ch==10)hanjsq++;//如果ch为换行符,则行计数器自加1
if(isalpha(ch)||isdigit(ch)||ch=='_')
{//如果ch为字母、数字或下划线就把ch放到ch1[i]中并使i自加1
ch1[i++]=ch;
}
if(ch=='.')//如果ch为小数点则判断是否为头文件
{
if((ch=fgetc(fp))=='h')//如果小数点后一位为h则判定其为头文件
{
if(ch==10)hanjsq++;
ch1[i++]='.';
ch1[i++]='h';
ch1[i]='\0';//把结束标志放到ch1[i]中作为单词结束标志
printf("line%d:
%s83\n",hanjsq,ch1);//以字符串形式输出ch1
fprintf(fp1,"line%d:
%s83\n",hanjsq,ch1);
break;
}
else//如果小数点后一位不是h则判定其为标识符
{
fseek(fp,-1,1);//fp回退1
ch1[i]='\0';//把结束标志放到ch1[i]中作为单词结束标志
printf("line%d:
%s%d\n",hanjsq,ch1,guanjz(ch1));//以字符串形式输出ch1
fprintf(fp1,"line%d:
%s%d\n",hanjsq,ch1,guanjz(ch1));
break;
}
}
if(!
isalpha(ch)&&!
isdigit(ch)&&ch!
='_'&&ch!
='.')
{//如果ch不为字母、数字、下划线和点时判断其为标识符
ch1[i]='\0';
printf("line%d:
%s%d\n",hanjsq,ch1,guanjz(ch1));
fprintf(fp1,"line%d:
%s%d\n",hanjsq,ch1,guanjz(ch1));
break;
}
}
}
/************************扫描数字*************************/
if(isdigit(ch)||ch=='-')//如果ch为数字或'-'
{
if(isdigit(ch))//如果ch为数字
{
printf("line%d:
%c",hanjsq,ch);
fprintf(fp1,"line%d:
%c",hanjsq,ch);
while(!
feof(fp))
{
ch=fgetc(fp);//预读一位如果ch为数字和点则循环输出
if(isdigit(ch)||ch=='.')
{
printf("%c",ch);
fprintf(fp1,"%c",ch);
}
else//否则视为数字结束
{
printf("46\n");
fprintf(fp1,"46\n");
fseek(fp,-1,1);//回退一位
ch='0';//置ch为0,以免影响下面误判并顺利退出扫描数字
break;
}
}
}
if(ch=='-')//如果ch为'-'
{
ch=fgetc(fp);//预读一位
if(ch=='-')//如果ch还是为'-'则判断为自减符'--'
{
printf("line%d:
--80\n",hanjsq);
fprintf(fp1,"line%d:
--80\n",hanjsq);
}
if(ch=='>')//如果ch为'>',则判断为结构体运算符'->'
{
printf("line%d:
->81\n",hanjsq);
fprintf(fp1,"line%d:
->81\n",hanjsq);
}
if(isdigit(ch))//如果ch为数字则可能为减号或负号
{
fseek(fp,-3,1);//回退3为判断
ch=fgetc(fp);
if(isdigit(ch))//如果ch为数字则判断'-'为减号
{
ch=fgetc(fp);
printf("line%d:
%c79\n",hanjsq,ch);
fprintf(fp1,"line%d:
%c79\n",hanjsq,ch);
}
else//否则判断'-'为负号
{
ch=fgetc(fp);
printf("line%d:
%c",hanjsq,ch);
fprintf(fp1,"line%d:
%c",hanjsq,ch);
while(!
feof(fp))
{
ch=fgetc(fp);//预读一位如果ch为数字和点则循环输出
if(isdigit(ch)||ch=='.')
{
printf("%c",ch);
fprintf(fp1,"%c",ch);
}
else//否则视为数字结束
{
printf("46\n");
fprintf(fp1,"46\n");
fseek(fp,-1,1);//回退1
break;
}
}
}
}
}
}
/***********************扫描注释************************/
if(ch=='/')//如果ch为'/'则可能为注释
{
ch=fgetc(fp);//读下一个字符
if(ch==10)hanjsq++;
if(ch=='/')//如果该字符也为'/'则判断为注释一行
{
while(fgetc(fp)!
=10);
if(ch==10)hanjsq++;//直到遇到换行符出现才认为注释结束
}
if(ch=='*')//如果该字符为'*'则判断为注释多行
{//直到出现'*/'才认为注释结束
while(!
feof(fp))
{
ch=fgetc(fp);
if(ch==10)hanjsq++;
if(ch=='*')//出现'*'
{//且接着出现'/'
if((ch=fgetc(fp))=='/')
{
break;
}
}
}
}
else//否则原样输出'/'
{
printf("line%d:
/83\n",hanjsq);
fprintf(fp1,"line%d:
/83\n",hanjsq);
fseek(fp,-1,1);//回退1
break;
}
}
/***********************扫描引号************************/
if(ch=='"')//出现引号
{
inti=0;
printf("line%d:
%c82\n",hanjsq,ch);
fprintf(fp1,"line%d:
%c82\n",hanjsq,ch);
printf("line%d:
",hanjsq);
fprintf(fp1,"line%d:
",hanjsq);
while(!
feof(fp))
{//先整体输出引号内所有字符并定为第99类
ch=fgetc(fp);
i++;//用于积累回退长度
if(ch==10)hanjsq++;
if(ch!
='"')
{
if(ch!
=32)
{
printf("%c",ch);
fprintf(fp1,"%c",ch);
}
}
elsebreak;
}
printf("99\n");
fprintf(fp1,"99\n");
fseek(fp,-i,1);//回退到引号开始
for(;i>0;i--)
{
ch=fgetc(fp);
if(ch==92)//如果ch为'\'则可能为转义字符
{
charch5[13]={"abfntv\\?
'\"0"};//转义字符集
ch=fgetc(fp);//预读一位
for(intk=0;k<12;k++)
{//如果为转义字符则输出
if(ch==ch5[k])
{
printf("line%d:
\\%c%d\n",hanjsq,ch,k+33);
fprintf(fp1,"line%d:
\\%c%d\n",hanjsq,ch,k+33);
}
}
if(ch=='d'&&isdigit(fgetc(fp))&&isdigit(fgetc(fp)))//任意字符转换为三位八进制
{
fseek(fp,-2,1);
printf("line%d:
%c%c44\n",hanjsq,fgetc(fp),fgetc(fp));
fprintf(fp1,"line%d:
%c%c44\n",hanjsq,fgetc(fp),fgetc(fp));
}
if(ch=='x'&&isdigit(fgetc(fp))&&isdigit(fgetc(fp)))//任意字符转换为二位十六进制
{
fseek(fp,-2,1);
printf("line%d:
%c%c45\n",hanjsq,fgetc(fp),fgetc(fp));
fprintf(fp1,"line%d:
%c%c45\n",hanjsq,fgetc(fp),fgetc(fp));
}
}
if(ch=='%')//如果为'%'则可能为%s%c%d
{
ch=fgetc(fp);
charbfh[4]={"dcs"};
for(i=0;i<3;i++)
{
if(bfh[i]==ch)
{
printf("line%d:
%%%c83\n",hanjsq,ch);
fprintf(fp1,"line%d:
%%%c83\n",hanjsq,ch);
}
}
}
}
}
/*********************扫描其他符号********************/
if(!
isdigit(ch)&&!
isalpha(ch)&&ch!
='_'&&ch!
='"'&&ch!
='/')
{
charch2[14]={"#()[]{}'*:
~%^"};//定义部分单符号集
charch3[9]={"+?
=|&!
<>"};//定义部分单符号或双符号(前半部分)集
charch4[9]={"+==|&==="};//定义部分双符号(后半部分)
for(inti=0;i<13;i++)
{//判断单个符号
if(ch==ch2[i])
{
printf("line%d:
%c%d\n",hanjsq,ch,i+48);
fprintf(fp1,"line%d:
%c%d\n",hanjsq,ch,i+48);
}
}
for(intj=0;j<8;j++)
{//判断双符号
if(ch==ch3[j])
{//如果ch与ch3中第j个字符匹配
ch=fgetc(fp);//预读一位
//if(ch==10)hanjsq++;
if(ch==ch4[j])
{//且ch与ch4第j个匹配,则表示ch3[j]与ch4[j]连起来为一个双符号
printf("line%d:
%c%c%d\n",hanjsq,ch3[j],ch4[j],i+69);
fprintf(fp1,"line%d:
%c%c%d\n",hanjsq,ch3[j],ch4[j],i+69);
}
if(ch=='<'&&ch3[j]=='<')//判断'<<'符
{
printf("line%d:
<<77\n",hanjsq);
fprintf(fp1,"line%d:
<<77\n",hanjsq);
}
if(ch=='>'&&ch3[j]=='>')//判断'>>'符
{
printf("line%d:
>>78\n",hanjsq);
fprintf(fp1,"line%d:
>>78\n",hanjsq);
}
else//否则表示ch3[j]为单符号,不是双符号的一部分
{
printf("line%d:
%c%d\n",hanjsq,ch3[j],j+61);
fprintf(fp1,"line%d:
%c%d\n",hanjsq,ch