词法分析程序.docx
《词法分析程序.docx》由会员分享,可在线阅读,更多相关《词法分析程序.docx(23页珍藏版)》请在冰点文库上搜索。
词法分析程序
专业课程设计II
题目:
专业
学生姓名
班级学号
指导教师
指导单位
日期
词法分析程序的构造
一、课题内容和要求
基本功能:
通过状态转换图构造C或者PASCAL语言子集的词法分析程序。
例如选取了C语言,选取其中一个子集,例如包含了部分关键字main、float、if、for等等,特殊符号(、<、=、+等等,特殊定义的标识符变量以及部分常量等,采用《编译原理》词法分析中有穷自动机的思想构建出该语言子集的状态转换图,并编码实现。
要求将选取的语言子集编写一个简单程序,放在一个文本文件中;要将一个个单词区分清楚并归类(例如for属于关键字>,词法分析程序作一遍扫描,采用双缓冲区结构。
并且如vc将关键字着色以加以识别。
b5E2RGbCAP
二、概要设计
(1)状态装换图
(2)功能模块
核心代码:
1)、数据类型定义:
externstructtable//保留字<关键字)和各自的编码
{
intid。
charcode[10]。
}。
structtablekey[100]={{100,"main"},{101,"int"},{102,"char"},{103,"if"},p1EanqFDPw
{104,"else"},{105,"for"},{106,"while"},{107,"ERROR"},}。
DXDiTa9E3d
inta=200。
//自定义变量编码
intb=300。
//数字编码
intd=400。
//运算符编码
inte=500。
//分隔符编码
intf=600。
//关系运算符编码
2)、函数调用
voidscanner(FILE*fp>//读取文件内容,并加以识别判断
intreserve(char*p>//识别判断是否为关键字函数
voidoutput(intt,char*s>//输出函数
3)、状态判断
voidscanner(FILE*fp>
{
if(isalpha(ch>>//如果是字母
{
token[0]=ch。
i=1。
ch=fgetc(fp>。
while(isalpha(ch>||isalnum(ch>>//循环接受字母
{
token[i]=ch。
//放入数组中
i++。
ch=fgetc(fp>。
}
fseek(fp,-1,1>。
token[i]='\0'。
c=reserve(token>。
//判断是否为关键字
if(c!
=-1>{
output(c,token>。
}
else
output(a++,token>。
}
else
if(isdigit(ch>>//如果是数字
{
token[0]=ch。
ch=fgetc(fp>。
i=1。
while(isdigit(ch>>//循环接受
{
token[i]=ch。
i++。
ch=fgetc(fp>。
}
token[i]='\0'。
fseek(fp,-1,1>。
output(b++,token>。
}
else
switch(ch>//判断是否为符号
{
case'(':
output(e++,"(">。
break。
//是否为(,是则输出RTCrpUDGiT
case'>':
output(e++,">">。
break。
//是否为>,是则输出5PCzVD7HxA
case'[':
output(e++,"[">。
break。
//是否为[,是则输出jLBHrnAILg
case']':
output(e++,"]">。
break。
//是否为],是则输出xHAQX74J0X
case'{':
output(e++,"{">。
break。
//是否为{,是则输出LDAYtRyKfE
case'}':
output(e++,"}">。
break。
//是否为},是则输出Zzz6ZB2Ltk
case',':
output(e++,",">。
break。
//是否为,,是则输出dvzfvkwMI1
case':
':
output(e++,":
">。
break。
//是否为:
,是则输出rqyn14ZNXI
case'。
':
output(e++,"。
">。
break。
//是否为。
,是则输出EmxvxOtOco
case'"':
output(e++,"\"">。
break。
//是否为\,是则输出SixE2yXPq5
case'+':
ch=fgetc(fp>。
//是否为+,是则往前搜索一个字符
if(!
feof(fp>>//判断是否到文件末尾
{
if(ch=='+'>//如果下一个字符是+,则输出++
output(f++,"++">。
else//不是则文件指针回退一个,输出+
{
fseek(fp,0,1>。
output(f++,"+">。
}
}
elseoutput(f++,"+">。
break。
case'-':
ch=fgetc(fp>。
//是否为-,是则往前搜索一个字符
if(!
feof(fp>>
{
if(ch=='-'>
output(f++,"--">。
else
{
fseek(fp,0,1>。
output(f++,"-">。
}
}
elseoutput(f++,"-">。
break。
case'*':
output(d++,"*">。
break。
case'/':
output(d++,"/">。
break。
case'>':
ch=fgetc(fp>。
//是否为>,是则往前搜索一个字符
if(!
feof(fp>>
{
if(ch=='='>
output(f++,">=">。
else
{
fseek(fp,0,1>。
output(f++,">">。
}
}
elseoutput(f++,">">。
break。
case'<':
ch=fgetc(fp>。
//是否为<,是则往前搜索一个字符
if(!
feof(fp>>
{
if(ch=='='>
output(f++,"<=">。
else
{
fseek(fp,-1,1>。
output(f++,"<">。
}
}
else{
fseek(fp,0,1>。
output(f++,"<">。
}
break。
case'=':
ch=fgetc(fp>。
//是否为=,是则往前搜索一个字符
if(feof(fp>>{
fseek(fp,0,1>。
output(f++,"=">。
}
else
{
if(ch=='='>
output(f++,"==">。
else
{
fseek(fp,-1,1>。
output(f++,"=">。
}
}
break。
case'!
':
ch=fgetc(fp>。
//是否为!
,是则往前搜索一个字符6ewMyirQFL
if(!
feof(fp>>
{
if(ch=='='>
output(f++,"!
=">。
else
{
fseek(fp,0,1>。
output(f++,"!
">。
}
}
elseoutput(f++,"!
">。
break。
}
}
三、详细设计<格式:
宋体,4号,加粗,两端对齐)
源代码:
********************************extre.h*********************************kavU42VRUs
externstructtable
{
intid。
charcode[10]。
}。
structtablekey[31]={{100,"main"},{101,"int"},{102,"char"},{103,"if"},y6v3ALoS89
{104,"else"},{105,"for"},{106,"while"},{107,"ERROR"}}。
M2ub6vSTnP
intreserve(char*p>
{
inti=0。
for(i=0。
i<8。
i++>
{
if(strcmp(p,key[i].code>==0>
return(key[i].id>。
}
return(-1>。
}
voidoutput(intt,char*s>
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE>,15>。
0YujCfmUCw
if(100<=t&&t<=107>{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE>,FOREGROUND_GREEN>。
eUts8ZQVRd
printf("%-2d%-6s",t,s>。
printf("关键字\n">。
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE>,15>。
sQsAEJkW5T
}
elseprintf("%-2d%-6s",t,s>。
switch(t/100>{
case2:
printf("变量\n">。
break。
case3:
printf("数字\n">。
break。
case4:
printf("运算符\n">。
break。
case5:
printf("分隔符\n">。
break。
case6:
printf("关系运算符\n">。
break。
}
}
*****************************************guwen.cpp***********************************GMsIasNXkA
#include
#include
#include
#include
#include"extre.h"
externintreserve(char*>。
externvoidoutput(int,char*>。
chartoken[20]。
charch。
inti,c。
inta=200。
//变量
intb=300。
//数字
intd=400。
//运算符
inte=500。
//分隔符
intf=600。
//关系运算符
voidscanner(FILE*fp>
{
if(isalpha(ch>>//如果是字母
{
token[0]=ch。
i=1。
ch=fgetc(fp>。
while(isalpha(ch>||isalnum(ch>>//循环接受字母
{
token[i]=ch。
//放入数组中
i++。
ch=fgetc(fp>。
}
fseek(fp,-1,1>。
token[i]='\0'。
c=reserve(token>。
//判断是否为关键字
if(c!
=-1>{
output(c,token>。
}
else
output(a++,token>。
}
else
if(isdigit(ch>>//如果是数字
{
token[0]=ch。
ch=fgetc(fp>。
i=1。
while(isdigit(ch>>//循环接受
{
token[i]=ch。
i++。
ch=fgetc(fp>。
}
token[i]='\0'。
fseek(fp,-1,1>。
output(b++,token>。
}
else
switch(ch>//判断是否为符号TIrRGchYzg
{
case'(':
output(e++,"(">。
break。
//是否为(,是则输出7EqZcWLZNX
case'>':
output(e++,">">。
break。
//是否为>,是则输出lzq7IGf02E
case'[':
output(e++,"[">。
break。
//是否为[,是则输出zvpgeqJ1hk
case']':
output(e++,"]">。
break。
//是否为],是则输出NrpoJac3v1
case'{':
output(e++,"{">。
break。
//是否为{,是则输出1nowfTG4KI
case'}':
output(e++,"}">。
break。
//是否为},是则输出fjnFLDa5Zo
case',':
output(e++,",">。
break。
//是否为,,是则输出tfnNhnE6e5
case':
':
output(e++,":
">。
break。
//是否为:
,是则输出HbmVN777sL
case'。
':
output(e++,"。
">。
break。
//是否为。
,是则输出V7l4jRB8Hs
case'"':
output(e++,"\"">。
break。
//是否为\,是则输出83lcPA59W9
case'+':
ch=fgetc(fp>。
//是否为+,是则往前搜索一个字符mZkklkzaaP
if(!
feof(fp>>//判断是否到文件末尾AVktR43bpw
{
if(ch=='+'>//如果下一个字符是+,则输出++ORjBnOwcEd
output(f++,"++">。
else//不是则文件指针回退一个,输出+2MiJTy0dTT
{
fseek(fp,0,1>。
output(f++,"+">。
}
}
elseoutput(f++,"+">。
break。
case'-':
ch=fgetc(fp>。
//是否为-,是则往前搜索一个字符gIiSpiue7A
if(!
feof(fp>>
{
if(ch=='-'>
output(f++,"--">。
else
{
fseek(fp,0,1>。
output(f++,"-">。
}
}
elseoutput(f++,"-">。
break。
case'*':
output(d++,"*">。
break。
case'/':
output(d++,"/">。
break。
case'>':
ch=fgetc(fp>。
//是否为>,是则往前搜索一个字符uEh0U1Yfmh
if(!
feof(fp>>
{
if(ch=='='>
output(f++,">=">。
else
{
fseek(fp,0,1>。
output(f++,">">。
}
}
elseoutput(f++,">">。
break。
case'<':
ch=fgetc(fp>。
//是否为<,是则往前搜索一个字符IAg9qLsgBX
if(!
feof(fp>>
{
if(ch=='='>
output(f++,"<=">。
else
{
fseek(fp,-1,1>。
output(f++,"<">。
}
}
else{
fseek(fp,0,1>。
output(f++,"<">。
}
break。
case'=':
ch=fgetc(fp>。
//是否为=,是则往前搜索一个字符WwghWvVhPE
if(feof(fp>>{
fseek(fp,0,1>。
output(f++,"=">。
}
else
{
if(ch=='='>
output(f++,"==">。
else
{
fseek(fp,-1,1>。
output(f++,"=">。
}
}
break。
case'!
':
ch=fgetc(fp>。
//是否为!
,是则往前搜索一个字符asfpsfpi4k
if(!
feof(fp>>
{
if(ch=='='>
output(f++,"!
=">。
else
{
fseek(fp,0,1>。
output(f++,"!
">。
}
}
elseoutput(f++,"!
">。
break。
}
}
voidmain(>
{
FILE*fp。
charwenjian[30]。
printf("|************************您要分析的文件结果如下**********************|\n">。
ooeyYZTjj1
fp=fopen("1.txt","r">。
while(feof(fp>==0>
{ch=fgetc(fp>。
scanner(fp>。
}
fclose(fp>。
}
四、测试数据及其结果分析
测试用例<1):
测试结果:
测试用例<2):
测试结果:
五、课程设计总结
<1)课程设计过程中的问题
问题:
在超前搜索时候,当达到文件最后一个字符时候,仍然会超前搜索,搜索eof,从而程序陷入无限循环。
原来部分代码为:
BkeGuInkxI
case'<':
ch=fgetc(fp>。
if(ch=='='>output(f++,"<=">。
else{fseek(fp,-1,1>。
output(f++,"<">。
}
break。
解决方案:
在需要超前搜索的部分,再次读取一个字符,之后判断是否为文件结尾符号,是则输出当前符号,否则继续判断是否为双目符号。
修正后:
PgdO0sRlMo
case'<':
ch=fgetc(fp>。
if(!
feof(fp>>
{
if(ch=='='>output(f++,"<=">。
else
{fseek(fp,-1,1>。
output(f++,"<">。
}
}
else{
fseek(fp,0,1>。
output(f++,"<">。
}
break。
(2>课程设计的总结
词法分析程序的编写,是我对c语言编程的认识又多了一些新的认识。
让我把这段时间荒废的c语言中的一些知识点重新巩固了。
了解了一些计算机编程的艺术。
同样也发现了自己的不足,对于界面设计的缺乏。
3cdXwckm15
从这个设计中我更加理解了《编译原理》中关于词法分析这块的知识,对于这本书的理解加深了一层,“书读百遍,其义自现”最为贴切。
也从vc++这个程序运行环境发现了自己对于词法分析器考虑的不足之处,对于以后自身的发展有着重要的意义。
h8c52WOngM
教师评语
同学出勤率(满勤、较高、一般,较低>,学习态度(端正、较端正、一般、较差>,程序设计基础<好、较好、一般、较差),演示程序(已经、基本、没有>达到了基本要求,算法设计<好、较好、一般),界面友好程度<好、较好、一般),答辩过程中回答问题<准确、较准确、错误率较高),撰写报告格式(规范、较为规范、一般>、内容<丰满、较为丰满、简单)、表述(清晰、一般、不清楚>,<圆满、较好、基本>完成了课题任务。
教师签名:
年月日
成绩评定
备注
申明:
所有资料为本人收集整理,仅限个人学习使用,勿做商业用途。