编译原理课程设计词法分析器文档附详细代码分析.docx
- 文档编号:3808339
- 上传时间:2022-11-25
- 格式:DOCX
- 页数:15
- 大小:153.01KB
编译原理课程设计词法分析器文档附详细代码分析.docx
《编译原理课程设计词法分析器文档附详细代码分析.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计词法分析器文档附详细代码分析.docx(15页珍藏版)》请在冰豆网上搜索。
编译原理课程设计词法分析器文档附详细代码分析
《编译原理》课程设计报告
专业:
计算机科学与技术
学生姓名:
张金荣
指导教师:
孔繁茹
完成时间:
2021年4月24日
2011—2012学年第一学期
感谢孔繁茹老师在课程设计中的大力支持及给予的无私帮助
1.设计目的
理解词法分析器的基本功能。
词法分析的任务是:
从左至右逐个字符地对源程序进行扫描,产生一个个的单词符号(token),把作为字符串的源程序改造成单词符号串的中间程序。
因此,词法分析是编译的基础。
理解词法规则的描述方法。
程序设计语言一般可以用标识符、关键字、运算符、分隔符、常量、字符串和注释符来描述
理解状态转换图及其实现。
一个状态转换图可用于识别(或接受)一定的字符。
大多数程序语言的单词符号都可以用转换图予以识别。
转换图非常易于用程序实现,最简单的办法是让每个状态结对应一小段程序。
能够编写简单的词法分析器。
2.课程设计的要求
手工构造一个简单的词法分析程序,能够识别标识符、整数、关键字、算符、界符。
画出识别单词的状态转换图。
(若状态转换图过于复杂,可以只画出主要部分;若依旧复杂,可只识别标识符和整数)
根据状态转换图手工构造词法分析程序。
从以下方法中选一:
✧词法分析器作为独立的一遍。
±词法分析结果输出到屏幕上或存入文件。
✧词法分析器作为一个子程序被语法分析器调用。
±每次调用返回一个单词
±同时将单词及属性存入符号表
实现状态转换图。
从以下方法中选一:
✧直接转向法
✧表驱动法
四、选做实验
☻使用缓冲技术
3.课程设计内容
程序语言的单词符号一般可分为下列五种。
(1)关键字
是由程序语言定义的具有固定意义的标志符。
本程序定义char,short,int,unsigned,long,float,double,struct,union,void,enum,const,typedef,auto,static,break,case,continue,default,do,else,for,if,return,switch,while,sizeof,printf,FILE,fopen,NULL,fclose,exit,read,closef,printf为关键字。
(2)标识符
用来表示各种名字,如变量名、数组名、过程名等等。
(3)常数
常数的类型一般有整型、实型、布尔型、文字型等等。
例如,100,3.14159。
(4)运算符
如+、-、*、/、>=、<=、==等等
(5)界符
如[、]、{、}、(、)、;、,、.等等。
具体实现过程:
用c++编写词法分析程序,从文件中读入预分析的源程序经词法分析将结果写入指定文件中。
在设计中预分析文件保存在test.txt中,输出结果保存在result.txt中。
本程序实现了
将词法分析器作为独立的一遍,词法分析结果存入文件。
用直接转向法实现状态转换图。
☻使用缓冲技术。
本程序能够识别简单的运算符,界符,常数,标示符和关键字。
其中关键字由程序所给的关键字表kt(keytable)内容指定。
如有未涉及的关键字还可以通过修改程序中表内容扩展。
对未定义的字符(不属于界符,运算符和常数)输出并显示为“其他字符”。
文中特别定义了注释符号,换行符号和空格。
在程序设计工程中一开始未注意将当前指针后退一位的情况,在输出程序结果时发现一些字符缺漏。
通过查资料【1】发现了将指针后移的用法并解决了这个问题。
设计过程中牵涉到对文件的使用如c_str(),ios:
binary的用法,get()函数的用法,fstream的两个类ifstream和ofstream的用法【2】实现文件的读写操作。
为了分析大于4kb的程序本程序使用了著名的双缓冲技术。
设计思想如下
4.状态转换图如下
5.实验工具
Vc++6.0,win7画图工具,
6.实现函数
voidget_char();//用于从buffer读取一个字符到C
intletter(intC);//判断是否是字母
intdigit(intC);//判断时候是数字或者小数点
intunderline(intC);//判断时候是下划线
intreserve(stringtoken);//判断时候是关键字
voidretract();//向前指针向后退一个
voidreturnout(stringstr1,stringstr2);//文件打印
7.结果及测试分析
实验代码
///////////////////////////////////////////词法分析程序@zhangjinrong//////////////////////////////////////////////////
/////////头文件////////////
#include
#include
#include
usingnamespacestd;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//关键字///////////
stringkt[36]={"char","short","int","unsigned","long","float","double","struct","union","void",
"enum","const","typedef","auto","static","break","case","continue","default","do","else","for","if",
"return","switch","while","sizeof","printf","FILE","fopen","NULL",
"fclose","exit","read","close","fprintf"};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//自定义变量,数组//
ifstreaminfile;//以输入(从硬盘到内存)方式打开文件
ofstreamoutfile;//输出(从内存到硬盘)方式打开文件
charbuffer1[64];//两个缓冲buffer
charbuffer2[64];
charC;//用于switch分析
stringtoken="";//多个C组成的串
char*startptr,*forwardptr;//buffer的开始指针和向前指针
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//函数声明//////////
voidget_char();//用于从buffer读取一个字符到C
intletter(intC);//判断是否是字母
intdigit(intC);//判断时候是数字或者小数点
intunderline(intC);//判断时候是下划线
intreserve(stringtoken);//判断时候是关键字
voidretract();//向前指针向后退一个
voidreturnout(stringstr1,stringstr2);//文件打印
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
main()
{
startptr=buffer1;//数组头指针
forwardptr=buffer1;//数组当前指针
buffer1[63]=buffer2[63]=-1;//数组尾数值为-1
cout<<"输入源文件的路径和文件名:
(例:
F:
1.c)"< stringstr111; cin>>str111; infile.open(str111.c_str(),ios: : binary);//二进制文件 cout<<"输入经词法分析后生成文件的路径和文件名: "< stringstr222; cin>>str222; outfile.open(str222.c_str(),ios: : trunc);//再次写入覆盖文件已有内容 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///将文件内容读入第一缓冲区///// for(inti=0;i<=62;i++) buffer1[i]=infile.get();//将文件中字符放入第一缓冲区 while (1) { token="";//多个C组成的串为空 get_char();//从数组中传递出一个字符c switch(C) { ////当首位字符为字母//////////////////////////////////////////////////////////////////////////////////////////////////// case'a': case'b': case'c': case'd': case'e': case'f': case'g': case'h': case'i': case'j': case'k': case'l': case'm': case'n': case'o': case'p': case'q': case'r': case's': case't': case'u': case'v': case'w': case'x': case'y': case'z': case'A': case'B': case'C': case'D': case'E': case'F': case'G': case'H': case'I': case'J': case'K': case'L': case'M': case'N': case'O': case'P': case'Q': case'R': case'S': case'T': case'U': case'V': case'W': case'X': case'Y': case'Z': { while(letter(C)||digit(C)||underline(C))//字母后跟字母或数字或下划线时 { token=token+C; get_char(); } if(reserve(token)==1)//如果字符串不在关键字表中输出标示符 { returnout("关键字",token); }else returnout(token,"标示符");//如果在关键字表中输出标示符 retract();/*当token已为关键字时由于执行了get_char()已读取一个字符。 为避免漏掉需回溯一个字符*/ break; } /////当首字母为数字时//////////////////////////////////////////////////////////////////////////////////////////////// case'1': case'2': case'3': case'4': case'5': case'6': case'7': case'8': case'9': case'0': { while(digit(C)==1||C=='.') { token=token+C; get_char(); } returnout("常数",token); retract(); break; } //////本程序定义为运算符所以考虑不同情况//////////////////////////////////////////////////////////////////////// case'<': { get_char();//字符为<,<=,<>三种情况 if(C=='>') returnout("<>","空格分界符"); else { retract(); returnout("<","运算符"); } break; } ////////////////////////////////////////////////////////////////////////////////////////////////////////// case'/': { get_char(); if(C=='*')//读到/*的情况一直读到*/结束 { while (1) { get_char(); while(C! ='*') get_char(); if(C=='/') break; retract(); } } elseif(C=='/')//读到//的情况一直读取字符直到这一行结束 { get_char(); while(C! ='\n') get_char(); } else { retract(); returnout("/","运算符"); } break; } ////////////简单的运算符和界符////////////////////////////////////////////////////////////////////////////// case'+': {returnout("+","运算符");break;} case'-': {returnout("-","运算符");break;} case'*': {returnout("*","运算符");break;} case'=': {returnout("=","运算符");break;} case'>': {returnout(">","运算符");break;} //case'/': {returnout("/","运算符");break;} case'(': {returnout("(","界符");break;} case')': {returnout(")","界符");break;} case'[': {returnout("[","界符");break;} case']': {returnout("]","界符");break;} case';': {returnout(";","界符");break;} case'.': {returnout(".","界符");break;} case',': {returnout(",","界符");break;} case'{': {returnout("{","界符");break;} case'}': {returnout("}","界符");break;} /////////////换行和空格///////////////////////////////////////////////////////////////////////////////////////// case'': break; case'\n': case'\r': //遇到换行符 { if(C=='\n') break; } default: { outfile<<"<"< break; } } } infile.close(); outfile.close(); system("pause"); return0; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////双缓冲的实现//// voidget_char() { if((*forwardptr)==-1)//当前指针在缓冲区(不知是那个缓冲区)末尾 { if(forwardptr==buffer1+63)//在第一buffer尾,向第二buffer读入数据 { for(inti=0;i<=62;i++) buffer2[i]=infile.get(); forwardptr=buffer2; get_char(); } elseif(forwardptr==buffer2+63)//在第二buffer尾,向第一buffer读入数据 { for(inti=0;i<=62;i++) buffer1[i]=infile.get(); forwardptr=buffer1; get_char(); } else//在不是buffer尾的位置读到了EOF,说明完成了分析 { infile.close(); outfile.close(); ofstreamout; cout<<"词法分析结果已存入文件夹中"< system("pause"); exit(-1); } } { C=(*forwardptr);//当前字符用于分析 forwardptr=forwardptr+1;//当前指针改指向下一个字符 } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////// ///自定义简单函数//// intletter(intC) { if((C>=65&&C<=90)||(C>=97)&&(C<=122)) return1; elsereturn0; } intdigit(intC) { if((C>=48)&&(C<=57)) return1; elsereturn0; } intunderline(intC) { if(C=='_') return1; elsereturn0; } intreserve(stringtoken) { for(inti=0;i<=35;i++) { if(token==kt[i]) return1; } return0; } voidretract() { if(forwardptr==buffer1)//向前指针在buffer头 forwardptr=(buffer2+63);//后退一个字符在第二缓冲区末尾 else { if(forwardptr==buffer2)//使向前指针在第二个buffer尾 forwardptr=(buffer1+63); elseforwardptr--; } } voidreturnout(stringstr1,stringstr2) { outfile<<"<"< } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////YANTAN//UNIVERSITY///SC/09/1/1/2009/2550/1128/qq/1013415421////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 参考文献 【1】XX文库《fseek用法详解》 【2】XX文库《c和c++文件读写操作》 【3】程序设计语言编译原理》国防陈火旺 【4】词法分析器的设计
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 课程设计 词法 分析器 文档 详细 代码 分析