编译原理实验查填符号表含源代码和运行结果.docx
《编译原理实验查填符号表含源代码和运行结果.docx》由会员分享,可在线阅读,更多相关《编译原理实验查填符号表含源代码和运行结果.docx(14页珍藏版)》请在冰豆网上搜索。
编译原理实验查填符号表含源代码和运行结果
〈〈编译原理》实验报告
实验1查填符号表
姓名学号班级计科1001班
时间:
2012/3/22地点:
文波
同组人:
无
指导教师:
朱少林
实验目的
1、运用所学知识,选择语言、选择算法(数据结构),编程实现符号表管理程序。
2、熟悉编译过程,训练编写程序的能力,为后续实验积累经验。
实验内容
1、运用所学知识,编程实现符号表管理程序。
读出源程序中与C语言词法规定相一致的标
识符,并在符号表中进行查找,若存在则输出该标识符及其编号和位置;否则将其填入符号
表,并分配编号,确定位置,输出该标识符。
2、输出标识符表。
实验环境
软件:
VC++6.0
实验前准备
1、方案设计:
1准备模拟数据:
由于是识别符合c语言规定的标识符,故本实验中使用“测试文件.c”
2写出c语言标识符的正规式定义:
letter_rA|B|C|••-Z|a|b|•••z|_
digitr0|1|••-9idletter_(letter_|digit)*
3画出不确定的有限自动机
不确定的有限自动机如下:
C={3,4,5,6,8,9}
D={3,4,5,7,8,9}
状态转换表如下
状态
letter_
digit
A
B
B
C
D
C
C
D
D
C
D
4程序思想:
该实验重点是构造识别标识符的函数。
程序中,使用的数据结构如下:
structrecord
{
charname[20];
};
typedefstructrecordRECORD;
20
record是用来记录标识符的名字,并且规定标识符的长度最大为
structinfor//记录符号表的相关信息
(
structrecord*head;
intlength;//记录符号表的长度
};
typedefstructinforINFOR;
infor是用来指向record结构体的指针和符号表的长度,这个结构体主要是用于比较标
识符并将识别到的标识符写入分析结果文件中即本实验中的"search_table”函数,该函
数并没有直接把标识符写到文件,而是在该函数之外,新建一个文件用来放符号表,然在后来打印符号表的同时把打印的结果写该文件中去。
该程序中的"search_table”函数判断是否为新的标识符的方法就是把识别的一个标识符
与已经识别的一一比较看是否相同,如不相同则表长度加1,并将该标识符填入表中
while(j
(
j++;
}//与已有的标识符一一比较
if(j==i)//说明是新的标识符
(
strcpy(point[j].name,teststring);
//point[j].line=j;
p->length++;
}
2、程序设计
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
structrecord
(
charname[20];
};
typedefstructrecordRECORD;
structinfor//记录符号表的相关信息
structrecord*head;
intlength;//记录符号表的长度
};
typedefstructinforINFOR;
voidsearch_table(char*teststring,INFOR*p,FILE*f)//查填符号表函数,p为指向结构体的指针
(
inti=p->length;
intj=0;
RECORD*point;
point=p->head;
while(j
}//与已有的标识符一一比较
if(j==i)//说明是新的标识符
(
strcpy(point[j].name,teststring);
//point[j].line=j;
p->length++;
}
printf("标识符%s在符号表的第%d行\n",teststring,j+1);
fprintf(f,"%s\t%5d\n”,teststring,j+1);//将新的标识符写入文件分析结果文件f中
return;
}
voidmain()
(
charreadchar;//从文件中读到的字符
charteststr[20];//存放标识符
charlinkstr[2]={0};//用于把字符readchar连接到teststrFILE*fp;
fp=fopen("测试文件.c","r");
if(fp==NULL)
{
printf("打开文件失败!
");
exit(0);
}//打开测试文件fp
FILE*result;
result=fopen("结果.txt”,"w+");//新建打开一个存放分析结果的文件result
//fclose(result);这个命令使下面调用的search_table函数不能将分析结果写入"结果.txt"
//,因为search_table函数函数中没有打开"结果.txt"命令
INFORinformation;//用于指向符号表
RECORDmark[300];//定义符号表最多可以有300个符号
information.head=mark;
information.length=0;
readchar=fgetc(fp);
//charhistory=readchar;利用这个记录读取的上一个字符,判断是否是数字
while(readchar!
=EOF)
{
teststr[0]=0;
if(readchar<='z'&&readchar>='a'||readchar>='A'&&readchar<='Z'||readchar=='_')
//字母数字下划线开头,如果这个满足则下面的也一定满足
{
while(readchar<='z'&&readchar>='a'||readchar>='A'&&
readchar<='Z'||readchar=='_'||readchar>='0'&&readchar<='9')
{
linkstr[0]=readchar;
strcat(teststr,linkstr);//会自动添加'\0'
//if(history>'9'&&history<'0')
readchar=fgetc(fp);
}
if(strlen(teststr)!
=0)
{
search_table(teststr,&information,result);//将结果写入”结果.txt"
}
}//这个循环结束后就读入一个标识符
readchar=fgetc(fp);
fclose(fp);
fclose(result);
FILE*table=fopen("符号表.txt”,"w+");//新建”符号表.txt”文件if(table==NULL)
(
printf(-文件打开失败!
");
exit(0);
}
inti=0;
//printf("行数\t");
//printf("标识符\n");
printf("************************************\n");
printf(-以下是符号表的内容\n”);
printf("行数\t\t\t标识符\n”);
while(i(
printf("%3d\t\t\t%s\n”,i+1,mark[i].name);
fwrite(&information.head[i],strlen(mark[i].name),1,table);
fprintf(table,"%4d\n”,i+1);//向符号表中写入数据
i++;
}fclose(table);
}
实验步骤
1、建立简单的符号表,可以只包含标识符和编号;
2、编写单词解析子程序,从源程序中分离出单词;
3、编写查找标识符的子程序(应考虑查找算法),插入新的标识符;
4、程序调试,输出标识符表。
实验结果及其分析:
分析后输出的分析文件是“结果.txt”内容如下:
include
1
stdio
2
h
3
int
4
_qq
5
int
4
temp
6
char
7
temp_s
8
int
4
search
9
char
7
str
10
char
7
c
11
void
12
main
13
char
7
str
10
c
11
int
4
m
14
i
15
printf
16
please
17
input
18
a
19
string
20
gets
21
str
10
puts
22
please
17
input
18
the
23
char
7
you
24
search
9
c
11
getchar
25
m
14
search
9
str
10
c
11
if
26
m
14
printf
16
can
27
not
28
find
29
else
30
printf
16
the
23
c
11
you
24
search
9
is
31
d
32
n
33
m
14
int
4
search
9
char
7
str
10
char
7
c
11
int
4
i
15
for
34
i
15
str
10
i
15
i
15
if
26
str
10
i
15
c
11
return
35
i
15
return
35
存放符号表的文件“符号表.txt”内容如下:
include1
stdio2
h3
int4
_qq5
temp6
char7
temp_s8
search9
str10
c11
void12
main13
m14
i15
printf16
please17
input18
a19
string20
gets21
puts22
the23
you24
getchar25
if26
can27
not28
find29
else30
is31
d32
n33
for34
return35
使用的模拟数据“测试文件.c”如下:
#include
int_qq;
int3temp;
chartemp_s;
intsearch(charstr[80],charc);
voidmain()
{
charstr[80],c;
intm,i;
printf("pleaseinputastring:
");
gets(str);
puts("pleaseinputthecharyousearch");
c=getchar();
m=search(str,c);
if(m==-1)
printf("cannotfind");else
printf("thecyousearchis%d\n”,m);
}
intsearch(charstr[80],charc)
{
inti;
for(i=0;str[i]!
='\0';i++)
{
if(str[i]==c)
{
return(i);
}
}
return-1;
}
分析:
实验过程中最大的难题是文件的操作,因为之前关于文件的操作课程没有讲,再加上很久没
写代码的原因,就先学了下文件操作,实验过程中最开始“结果.txt”总是空,后来知道原来是我在创建了该文件后就关闭了,在没有打开的情况下不能进行写入结果的操作;还有就
是刚开始的“符号表.txt”每个符号后面都有不同数目的“烫”,经分析知道这种情况下每个标识符都是强制的长度一致,都是20(定义的标识符最大长度是20),这是因为向文件中写
入数据时:
fwrite(&information.head[i],strlen(mark[i].name),1,table);我把每次写入的数据块长
度设为了sizeof(record),而该结果是20,所以导致每个标识符长度是20.
不过该实验还有一个地方需要改进,因为对于“23aa”这样的字符串“aa”按照规定应该不
是一个标识符,而在这个试验中却也把“aa”识别为了一个标识符,本来想用一个char型
history来记录上个读入字符来判断识别的字符串是不是以数字开头的某字符串的后部分,但
是没成功,时间关系,我再思考下如何实现该功能。