编译原理课程设计词法分析器文档附详细代码分析Word文档下载推荐.docx
《编译原理课程设计词法分析器文档附详细代码分析Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计词法分析器文档附详细代码分析Word文档下载推荐.docx(15页珍藏版)》请在冰豆网上搜索。
☻使用缓冲技术
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<
iostream>
fstream>
string>
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的开始指针和向前指针
//函数声明//////////
//文件打印
main()
{
startptr=buffer1;
//数组头指针
forwardptr=buffer1;
//数组当前指针
buffer1[63]=buffer2[63]=-1;
//数组尾数值为-1
cout<
<
输入源文件的路径和文件名:
(例:
F:
1.c)"
endl;
stringstr111;
cin>
>
str111;
infile.open(str111.c_str(),ios:
:
binary);
//二进制文件
输入经词法分析后生成文件的路径和文件名:
stringstr222;
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'
c'
d'
e'
f'
g'
h'
i'
j'
k'
l'
m'
n'
o'
p'
q'
r'
s'
t'
u'
v'
w'
x'
y'
z'
A'
B'
C'
D'
E'
F'
G'
H'
I'
J'
K'
L'
M'
N'
O'
P'
Q'
R'
S'
T'
U'
V'
W'
X'
Y'
Z'
while(letter(C)||digit(C)||underline(C))//字母后跟字母或数字或下划线时
token=token+C;
}
if(reserve(token)==1)//如果字符串不在关键字表中输出标示符
returnout("
关键字"
token);
}else
returnout(token,"
标示符"
);
//如果在关键字表中输出标示符
retract();
/*当token已为关键字时由于执行了get_char()已读取一个字符。
为避免漏掉需回溯一个字符*/
break;
/////当首字母为数字时////////////////////////////////////////////////////////////////////////////////////////////////
1'
2'
3'
4'
5'
6'
7'
8'
9'
0'
while(digit(C)==1||C=='
.'
)
常数"
//////本程序定义为运算符所以考虑不同情况////////////////////////////////////////////////////////////////////////
'
//字符为<
<
=,<
三种情况
if(C=='
空格分界符"
else
运算符"
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/'
*'
)//读到/*的情况一直读到*/结束
while(C!
='
}
elseif(C=='
)//读到//的情况一直读取字符直到这一行结束
\n'
/"
////////////简单的运算符和界符//////////////////////////////////////////////////////////////////////////////
case'
+'
:
{returnout("
+"
break;
}
case'
-'
-"
*"
="
//case'
('
("
界符"
)'
)"
['
["
]'
]"
}
."
'
{'
{"
}'
}"
/////////////换行和空格/////////////////////////////////////////////////////////////////////////////////////////
'
\r'
//遇到换行符
default:
outfile<
"
C<
换行符>
infile.close();
outfile.close();
system("
pause"
return0;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////双缓冲的实现////
voidget_char()
if((*forwardptr)==-1)//当前指针在缓冲区(不知是那个缓冲区)末尾
if(forwardptr==buffer1+63)//在第一buffer尾,向第二buffer读入数据
buffer2[i]=infile.get();
forwardptr=buffer2;
elseif(forwardptr==buffer2+63)//在第二buffer尾,向第一buffer读入数据
else//在不是buffer尾的位置读到了EOF,说明完成了分析
ofstreamout;
词法分析结果已存入文件夹中"
exit(-1);
C=(*forwardptr);
//当前字符用于分析
forwardptr=forwardptr+1;
//当前指针改指向下一个字符
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
///自定义简单函数////
intletter(intC)
if((C>
=65&
&
=90)||(C>
=97)&
(C<
=122))
return1;
elsereturn0;
intdigit(intC)
=48)&
=57))
intunderline(intC)
_'
intreserve(stringtoken)
=35;
if(token==kt[i])
return1;
voidretract()
if(forwardptr==buffer1)//向前指针在buffer头
forwardptr=(buffer2+63);
//后退一个字符在第二缓冲区末尾
else
if(forwardptr==buffer2)//使向前指针在第二个buffer尾
forwardptr=(buffer1+63);
elseforwardptr--;
voidreturnout(stringstr1,stringstr2)
str1<
"
str2<
>
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////YANTAN//UNIVERSITY///SC/09/1/1/2009/2550/1128/qq/1013415421//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
参考文献
【1】XX文库《fseek用法详解》
【2】XX文库《c和c++文件读写操作》
【3】程序设计语言编译原理》国防陈火旺
【4】词法分析器的设计