[业务]C语言词法分析实验
实验一
课题名称,词法分析实验 指导教师,尚冬娟 实验类型,验证性 专 业: 计算机科学与技术系
班 级,1001班(陈才组)
2013年4月22日
实验目的:
能够采用C编程语言实现简单的词法分析程序;设计、编制并调试一个词法分析程序,加深对词法分析原理的理解
实验要求:
1. 对单词的构词规则有明确的定义;
2. 编写的分析程序能够正确识别源程序中的单词符号;
3. 识别出的单词以<单词符号,种别码>的形式保存在符号
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
中(链表);
4. 词法分析中源程序的输入以.c格式,分析后的符号表,将二元组保存在.txt文件中。
实验内容:
选择高级语言(C语言),编制它的词法分析程序。词法分析程序的实现可以采用任何一种编程工具。
实验原理:
1、算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号;
2、其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
实验分析:
(1)关键字:if else while do case int break等所有的关键字都是小写。
(2)运算符和界符: = + - * / < <= <> > >= = ; ( ) 等
(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:
ID = _ | letter (letter | digit)*
NUM = digit digit*
(4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
(5)注释被忽略
实验流程图:
输入需要扫输入扫描结果另存为的文件名描的文件名
返回,结跳转到扫描判断文件是否p处束程序其他符号否为空
否
跳转到扫描预读一位Ch是Ch是否为引号引号
否行计数器跳转到扫描是是Ch是否为空格Ch是否为‘/’自加1注释
否否
跳转到扫描头Ch是否为字母跳转到扫描Ch是否为数是是文件单词及保或下划线数字字或‘-’留字
否
实验环境:需要TC、VC++ 6.0等开发工具作为本次试验的环境。
实验步骤:
1、准备: 用TC、VC++等开发工具;
2、对本实验的任务进行分析,确定实现功能的函数; 3、写好程序,仔细修改函数;
4、上机操作:输入源程序,修改、调试,运行; 5、写好试验报告;
实验调试过程及测试结果:
/*******************************源代码******************************/
#include
#include
#include
#include
void main()
{
FILE *fp,*fp1;
int hanjsq=1;//行计数器,保存行号
int guanjz(char ch1[]);//关键字和标识符判断
char ch,infile[15],outfile[15];//定义输入和输出文件名
printf("*****************Enter the infile name*******************\n");
scanf("%s",infile);//输入需要扫描的文件名
printf("*****************Enter the outfile name******************\n");
scanf("%s",outfile);//输入需要另存为的文件名
if((fp = fopen(infile,"r")) == NULL)//打开需要扫描的文件
{
printf("cannot open file\n");
exit(0);
}
if((fp1 = fopen(outfile,"w")) == NULL)//打开需要存入的文件
{
printf("cannot open file\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=='_')//如果第一个字符为字母或下划线则判断为标识符
{
int i=0;
char ch1[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: %s 83\n",hanjsq,ch1);//以字符串形式输出ch1
fprintf(fp1,"line %d: %s 83\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: %c 79\n",hanjsq,ch);
fprintf(fp1,"line %d: %c 79\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=='"')//出现引号
{
int i=0;
printf("line %d: %c 82\n",hanjsq,ch);
fprintf(fp1,"line %d: %c 82\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);
}
}
else break;
}
printf(" 99\n");
fprintf(fp1," 99\n");
fseek(fp,-i,1);//回退到引号开始
for(;i>0;i--)
{
ch=fgetc(fp);
if(ch==92)//如果ch为'\'则可能为转义字符
{
char ch5[13]={"abfntv\\?'\"0"}; //转义字符集
ch=fgetc(fp);//预读一位
for(int k=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%c 44\n",hanjsq,fgetc(fp),fgetc(fp));
fprintf(fp1," line %d: %c%c 44\n",hanjsq,fgetc(fp),fgetc(fp));
}
if(ch=='x' && isdigit(fgetc(fp)) && isdigit(fgetc(fp)))//任意字符转换为二位十六进制
{
fseek(fp,-2,1);
printf(" line %d: %c%c 45\n",hanjsq,fgetc(fp),fgetc(fp));
fprintf(fp1," line %d: %c%c 45\n",hanjsq,fgetc(fp),fgetc(fp));
}
}
if(ch=='%')//如果为'%'则可能为%s%c%d
{
ch=fgetc(fp);
char bfh[4]={"dcs"};
for(i=0;i<3;i++)
{
if(bfh[i]==ch)
{
printf(" line %d: %%%c 83\n",hanjsq,ch);
fprintf(fp1," line %d: %%%c 83\n",hanjsq,ch);
}
}
}
}
}
/*********************扫描其他符号********************/
if(!isdigit(ch) && !isalpha(ch) && ch!='_' && ch!='"' && ch!='/')
{
char ch2[14]={"#()[]{}'*:~%^"};//定义部分单符号集
char ch3[9]={"+?=|&!<>"};//定义部分单符号或双符号(前半部分)集
char ch4[9]={"+==|&==="};//定义部分双符号(后半部分)
for(int i=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(int j=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,ch3[j],j+61);
fseek(fp,-1,1);
}
}
}
}
/**********************************************************************************************/
}
printf("*********************************************************\n");
printf("*》 词法分析结束 《*\n");
printf("*》 分析结果保存在文件%s中 《*\n",outfile);
printf("*》 欢迎下次使用,谢谢~ 《*\n");
printf("*********************************************************\n");
fprintf(fp1,"*********************************************************\n");
fprintf(fp1,"*》 词法分析结束 《*\n");
fprintf(fp1,"*》 欢迎下次使用,谢谢~ 《*\n");
fprintf(fp1,"*********************************************************\n");
}
int guanjz(char ch1[])//关键字和标识符判断
{
char
ch2[32][9]={"auto","double","int","struct","break","else","long","switch","case","enum",
"register","typedef","char","extern","return","union","const","float","short",
"unsigned","continue","for","signed","void","default","goto","sizeof",
"volatile","do","while","static","if"};//定义关键字集
for(int i=0;i<32;i++)
{//逐个比对如果为关键字则返回类别i+1
if(!strcmp(ch1,ch2[i]))return i+1;
}
return 47;//否则返回一般标识符类
}
输入:
输出:
实验分组:
组长:陈 才(2010100121) ------负责扫描注释部分功能的实现 组员:田 健(2010100113) ------负责扫描数字部分功能的实现
闫晓云(2010100116) ------负责扫描其他字符部分功能的实现
刘胜虎(2010100120) ------负责扫描单词部分功能的实现
邓少松(2010100131) ------负责扫描其他字符部分功能的实现
姜 涵(2010100149) ------负责主函数的构建部分功能的实现
陈振北(2010100152) ------负责扫描引号部分功能的实现
刘 瑞(2010100154) ------负责扫描引号部分功能的实现
实验
总结
初级经济法重点总结下载党员个人总结TXt高中句型全总结.doc高中句型全总结.doc理论力学知识点总结pdf
: