北邮编译原理词法分析报告程序报告材料.docx

上传人:b****3 文档编号:26511909 上传时间:2023-06-20 格式:DOCX 页数:23 大小:19KB
下载 相关 举报
北邮编译原理词法分析报告程序报告材料.docx_第1页
第1页 / 共23页
北邮编译原理词法分析报告程序报告材料.docx_第2页
第2页 / 共23页
北邮编译原理词法分析报告程序报告材料.docx_第3页
第3页 / 共23页
北邮编译原理词法分析报告程序报告材料.docx_第4页
第4页 / 共23页
北邮编译原理词法分析报告程序报告材料.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

北邮编译原理词法分析报告程序报告材料.docx

《北邮编译原理词法分析报告程序报告材料.docx》由会员分享,可在线阅读,更多相关《北邮编译原理词法分析报告程序报告材料.docx(23页珍藏版)》请在冰豆网上搜索。

北邮编译原理词法分析报告程序报告材料.docx

北邮编译原理词法分析报告程序报告材料

程序设计一

词法分析程序

 

一.实验题目和要求 

题目:

词法分析程序的设计与实现。

 

实验容:

设计并实现C语言的词法分析程序,要求如下。

 

(1)、可以识别出用C语言编写的源程序中的每个单词符号,并以记号的形式输出每个单词符号。

 

(2)、可以识别并读取源程序中的注释。

 

(3)、可以统计源程序汇总的语句行数、单词个数和字符个数,其中标点和空格不计算为单词,并输出统计结果 

(4)、检查源程序中存在的错误,并可以报告错误所在的行列位置。

 

(5)、发现源程序中存在的错误后,进行适当的恢复,使词法分析可以继续进行,通过一次词法分析处理,可以检查并报告源程序中存在的所有错误。

 实验要求:

 

方法1:

采用C/C++作为实现语言,手工编写词法分析程序。

 

方法2:

通过编写LEX源程序,利用LEX软件工具自动生成词法分析程序。

 

二.程序设计思路

采用C++来编写此程序。

根据书上的函数、变量提示写出各种函数、整体框架。

大部分变量名称与书上相同。

画出符号间转换自动机模型,之后根据自动机写函数、错误判断。

缓冲区用数组完成,标记位置的指针用int型来表示。

用lnum存储语句行数,wordnum存储单词个数,charnum存储字符个数。

标点和空格不计算为单词。

错误所在的行列位置存储在error.txt文件当中。

 

3.程序运行结果举例

Code.txt:

#include

main()

{

intnum,n=0,m,l,t;

printf("pleaseinputaninteger:

");

scanf("%d",&num);//dsfsdf

for(l=0;num!

=0;l++){

m=num%10;//sdfafda

for(t=0;t!

=l;t++)

m=m*2;//dafdaf

n=nm;

num=num/10;/*dafdas2323*/

}

printf("//theresultis%d//",n);

return0;

}

 

窗口运行结果:

=============================================================

*词法分析系统*

=============================================================

请输入需要分析的文件名称:

code.txt

-------------------------------------------------------------

处理完毕。

共出现1个错误。

共有21行,33个单词,236个字符。

结果请在token_table.txt中查看。

=============================================================

请按任意键继续...

 

Token.txt;

单词记号

##

includeid

stdioid

hid

>relop,GT

mainid

((

))

{{

intint

numid

,

nid

=relop,EQ

0num

,

mid

,

lid

,

tid

;;

printfid

((

))

;;

scanfid

((

,

&&

numid

))

;;

forfor

((

lid

=relop,EQ

0num

;;

numid

!

=RELOP,UE

0num

;;

lid

++

++

))

{{

mid

=relop,EQ

numid

%%

10num

;;

forfor

((

tid

=relop,EQ

0num

;;

tid

!

=RELOP,UE

lid

;;

tid

++

++

))

mid

=relop,EQ

mid

**

2num

;;

nid

=relop,EQ

nmid

;;

numid

=relop,EQ

numid

//

10num

;;

}}

printfid

((

,

nid

))

;;

returnreturn

0num

;;

}}

 

Error.txt:

1.在第1行第15列出现非法字符

Note.txt:

line6.双引号间字符:

pleaseinputaninteger:

line7.双引号间字符:

%d

line7.ddsfsdf

line10.ssdfafda

line12.ddafdaf

line14.dafdas2323

line17.双引号间字符:

//theresultis%d//

 

Count.txt:

共有21行,33个单词,236个字符。

 

四.源代码

头文件:

#include

#include

#include

#include

#include

#include

usingnamespacestd;

全局变量:

constintMAXBUFFER=62;//缓冲区容量

constintLB=30;//左缓冲区大小

constintLRB=61;//左+右缓冲区大小

constintKEY=32;//关键字个数

fstreamcode_file;

intum;//列数

intlb_end,rb_end,forward;//左右缓冲区结束位置,向前指针

intlready,rready;//标记左右缓冲区是否已经录入过容

charbuffer[MAXBUFFER];//缓冲区

charC;//当前读入的字符

stringtoken;//存放单词的字符串

intkeynum,errornum;//关键字的序列号;error的个数

intlnum,wordnum,charnum;//语句数单词数字符数

char*key[KEY]={"auto","const","double","float","int","short","struct"

"unsigned","break","continue","else","for","long","signed"

"switch","void","case","default","enum","goto","register"

"static","typedef","volatile","char","do","extern","if"

"return","sizeof","union","while"};//关键字表

函数:

voidfillbuf(intx)

{

if(x==0){//填充左半区

if(lready==0){//左半区未填充

code_file.read(buffer,LB);//读入LB个字符到buffer左半区中

if(code_file.gcount()!

=lb_end)

//如果读入的字符不足LB个在之后添加EOF

buffer[code_file.gcount()]=EOF;

}

else

lready=0;

}

else{//填充右半区

if(rready==0){

code_file.read(buffer+LB+1,LB);

//读入LB个字符到buffer右半区中

if(code_file.gcount()!

=LB)

buffer[code_file.gcount()+LB+1]=EOF;

}

else

rready=0;

}

}

voidget_nbc();

voidget_char()

{

C=buffer[forward];//获取当前字符

if(C==EOF)

return;

elseif(C=='\n'){

um=0;//列=0

lnum++;//+1行

}

elseif(C>=33&&C<=126){

charnum++;//字母或数字或符号的话+1字符

//cout<<"第"<

um++;

}

forward++;

if(buffer[forward]==EOF){

if(forward==lb_end){

//到左区结束位置填充右半区

fillbuf

(1);

forward++;

}

if(forward==rb_end){

//到右区结束位置填充左半区向前指针回到开始位置

fillbuf(0);

forward=0;

}

}

}

 

voidretract()

{//向前指针后退一个字符

charnum--;

um--;

if(forward==0){

lready=1;//避免重新读取

forward=rb_end-1;//后退一个字符

}

elseif(forward==lb_end){

rready=1;

forward--;

}

elseforward--;

}

voidget_nbc()

{//若C中的字符为空字符则反复调用直到非空字符为止

while(C==''||C=='\t'||C=='\0'||C=='\n')

get_char();

retract();

}

intreserve(stringword)

{//查关键字表返回0表示token中的字符串是标识符1表示关键字

for(keynum=0;keynum

if(pare(key[keynum])==0)

return1;

}

return0;

}

 

主函数:

main(){

cout<<"============================================================="<

cout<<"*词法分析系统*"<

cout<<"=============================================================="<

cout<<"请输入需要分析的文件名称:

"<

chars[30];//存储文件名称

cin>>s;

code_file.open(s);

intp;

while(code_file==NULL){

cout<<"无此文件,打开失败。

请重新输入:

"<

cin>>s;

code_file.open(s);

}

//初始化

lb_end=LB;rb_end=LRB;forward=0;

lready=rready=0;

lnum=1;

um=0;

wordnum=charnum=0;

buffer[lb_end]=buffer[rb_end]=EOF;

fillbuf(0);

errornum=0;

cout<<"-------------------------------------------------------------"<

fstreamtoken_table,error,count,note;

error.open("error.txt",ios_base:

:

out);//保存错误

count.open("count.txt",ios_base:

:

out);//保存语句数单词数字符数计数

note.open("note.txt",ios_base:

:

out);//保存注释

token_table.open("token.txt",ios_base:

:

out);//输出的记号

token_table<<"单词\t\t记号"<

while(C!

=EOF){

get_char();

token="";

if((C>64&&C<91)||(C>96&&C<123)||C=='_'){

//标示符判断字母或者下划线开头

token=token+C;

get_char();

while((C>64&&C<91)||(C>96&&C<123)

||(C>47&&C<58)||C=='_'){

//字母或数字或下划线

token=token+C;

get_char();

}

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();

wordnum++;//这是一个单词

if(reserve(token)==0)//这是一个标识符

token_table<

else//这是一个关键字

token_table<

}

elseif(C=='"'){

get_char();

while(C!

='"'){

token=token+C;

get_char();

}

note<<"line"<

"<

}

elseif(C==''||C=='\t'||C=='\0'||C=='\n')

get_nbc();

elseif(C>47&&C<58){//数字判断

while(C>47&&C<58){

token=token+C;

get_char();

}

if(C=='.'){

token=token+C;

get_char();

if(C>47&&C<58){

//小数点后必须有数字否则报错

token=token+C;

get_char();

while(C>47&&C<58){

token=token+C;

get_char();

}

if(C=='E'||C=='e'){

token=token+C;

get_char();

if(C=='+'||C=='-'){

//E后面可以是+-号

if(C>47&&C<58){

//+-后面必须有数字否则报错

token=token+C;

get_char();

while(C>47&&C<58){

token=token+C;

get_char();

}

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();//后退一位后退出

}

else{

retract();

errornum++;

error<

"行"<<"第"<

<

}

}

elseif(C>47&&C<58){

//E后面也可以是数字其他情况则报错

token=token+C;

get_char();

while(C>47&&C<58){

token=token+C;

get_char();

}

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();//后退一位后退出

}

else{

retract();

errornum++;

error<

<

}

}

else{//退出

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();

}

}

else{//记录错误退出此if重新判断

retract();

errornum++;

error<

"<

}

}

elseif(C=='E'||C=='e'){

token=token+C;

get_char();

if(C=='+'||C=='-'){//E后面可以是+-号

if(C>47&&C<58){//+-后面必须有数字否则报错

token=token+C;

get_char();

while(C>47&&C<58){

token=token+C;

get_char();

}

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();//后退一位后退出

}

else{

retract();

errornum++;

error<

<<"第"<

}

}

elseif(C>47&&C<58){

//E后面也可以是数字其他情况则报错

token=token+C;

get_char();

while(C>47&&C<58){

token=token+C;

get_char();

}

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();//后退一位后退出

}

else{

retract();

errornum++;

error<

<

}

}

else{

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();

}

token_table<

}

else{

switch(C){

case'<':

//<或者<=或者<>

get_char();

if(C=='=')

token_table<<"<=\t\trelop,LE"<

elseif(C=='>')

token_table<<"<>\t\trelop,NE"<

else{

token_table<<"<\t\trelop,LT"<

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();

}

break;

case'>':

//>或者>=

get_char();

if(C=='=')

token_table<<">=\t\trelop,GE"<

else{

token_table<<">\t\trelop,GT"<

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();

}

break;

case'=':

//=

token_table<<"=\t\trelop,EQ"<

break;

case':

':

//:

=或者:

get_char();

token_table<

\t\t:

"<

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();

break;

case'!

':

//!

=

get_char();

if(C=='=')

token_table<<"!

=\t\tRELOP,UE"<

else{

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();

token_table<<"!

\t\t!

"<

}

break;

case'/':

//过滤注释

get_char();

if(C=='/'){//过滤掉//开头的注释

get_char();

note<<"line"<

while(C!

='\n'){

note<

et_char();

}

note<

}

elseif(C=='*'){//过滤掉/*开头的注释

note<<"line"<

while

(1){

get_char();

while(C!

='*'){

note<

get_char();

}

get_char();

if(C=='/'){

note<

break;

}

else{

note<<"*"<

}

}

}

else{

if(C!

=''&&C!

='\t'&&C!

='\0'&&C!

='\n')

retract();

token_table<<"/\t\t/"<

}

break;

case'#':

case'+':

case'-':

case'(':

case')':

case'[':

case']':

case';':

case'%':

case',':

case'*':

case'&':

case'{':

case'}':

token_table<

break;

default:

errornum++;error<

}

}

}

cout<<"处

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 成人教育 > 成考

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1