编译原理词法分析报告.docx

上传人:b****5 文档编号:8287760 上传时间:2023-01-30 格式:DOCX 页数:35 大小:110.23KB
下载 相关 举报
编译原理词法分析报告.docx_第1页
第1页 / 共35页
编译原理词法分析报告.docx_第2页
第2页 / 共35页
编译原理词法分析报告.docx_第3页
第3页 / 共35页
编译原理词法分析报告.docx_第4页
第4页 / 共35页
编译原理词法分析报告.docx_第5页
第5页 / 共35页
点击查看更多>>
下载资源
资源描述

编译原理词法分析报告.docx

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

编译原理词法分析报告.docx

编译原理词法分析报告

 

1、实验目的

1、为初等函数运算语言构造词法分析器。

2、掌握生成词法分析器的方法,加深对词法分析原理的理解。

3、掌握设计、编制并调试词法分析程序的思想和方法

2、实验内容

一、根据下面的要求设计初等函数运算语言的词法模式,并用正则式表达出来

1、初等函数运算语言的常量为实数类型,其定义方式为实数的最一般书写方式,如:

123.321。

具体要求:

不支持整数部分大于。

时首数字为0;不支持小数点后结尾为0;不支持科学记数法;不支持仅为整数时有小数点;支持负数符号,不支持正数符号。

2、初等函数运算语言的变量采用与C语言的标识符定义一样的方式:

首字符为字母或下划线;其他的为字母、数字及下划线的混合串;区分大小写;变量长度不超过32个字符。

3、初等函数运算语言需要处理的函数仅为表一中所列举的内容。

函数的格式及参数内容也如表一所示。

4、初等函数运算语言支持四则运算,其计算的符号与C语言相同,为:

+-*/。

5、初等函数运算语言的合法的分隔符包括:

空格、制表符、、分行符圆括号(左、右)、分号。

其中空格、制表符、分行符可以出现在任何两个不同的单词中间;圆括号(左、右)用于表达式中,用于改变运算的优先级,以及标识函数的参数;分号用于标识一个语句的结束。

6、初等函数运算语言支持的常量还包括:

PI,Eo其中,PI为圆周率,E为自然常数。

二、将正则式转化为最小DFA,给出该DFA的形式化表示和图形表示。

三、根据DFA给出状态转换表。

四、给出初等函数运算语言的记号表,即词法分析中,语言中的记号将分为多少类,每一类型的编码、类型、属性等内容是什么。

五、编写词法分析器,将输入的字符串转化成为记号流,便于后续的语法分析工作。

要求词法分析器中能够识别词法错误。

2.1词法模式设计/正则式

分隔符compart=\t|\n|(|)|;|空格

运算符:

operation=+|-|*|/|=|^

变量:

variable=[a~zA~Z]([a~zA~Z_0~9])*

常量:

constant=(ε|-)((0|(1~9)(0~9)*)(.(0~9)*(1~9)|ε))|PI|E

2.2DFA

注:

id表示字母,num表示数字

2.3状态转换表

id

0

1-9

下划线

减号

小数点

0

1

3

4

1

2

8

1

1

1

1

1

9

8

2

8

3

4

8

8

8

3

8

8

8

8

9

6

4

8

4

4

8

9

6

6

8

6

7

8

8

8

7

8

6

7

8

9

8

8

8

8

8

8

8

8

注:

0是初态,2,6是中间状态,1,3,4,7是终态,其中1表示标示符,3,4,7是实数,8表示不合法的状态,9表示'-'为减号

2.4记号表

符号

Sin

Cos

tg

ctg

log

lg

In

;

?

+

记号

0

1

2

3

4

5

6

7

8

9

10

11

符号

-

*

/

=

常量

变量

无法识别的标示符

^

{

}

记号

12

13

14

15

16

17

18

19

20

21

22

3、实验程序清单

#include

#include

usingnamespacestd;

#definemax10

charch='';

stringkey[7]={"sin","cos","tg","ctg","log","lg","ln"};//关键字

charcompart[6]={'\t','\n','(',')',';',''};//分隔符

charoperation[5]={'+','-','*','/','='};//运算符

//ints[8]={0,1,2,3,4,6,7,8};//状态集合,0是初态,2,6是中间状态,1,3,4,7是终态,其中1

表示标示符,3,4,7是实数,8表示不合法的状态

inttoken[23]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22};

//0表示sin,1表示cos,2表示tg,3表示ctg,4表示log,5表示lg,6表示ln,7表示(,8表

示),9表示;,10表示?

,11表示+,12表示-,13表示*,14表示/,15表示=,

//16表示常量,17表示变量,18表示不可识别标示符,19表示^,20表示逗号,21表示{,22

表示}

chararr[32];

intstate=0;

ints=0;

booltag=0;//tag=0表示'-'为负数的负号,tag=1表示'-'为减号

FILE*fp;

intIsKey(stringc)

{//判断是否为关键字

for(inti=0;i<7;i++)

{

if(key[i].compare(c)==0)returni;//返回下标,下标和其token记号一致

}

return-1;

}

boolIsLetter(charc)

{//判断是否为字母

if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A')))

return1;

else

return0;

}

boolIsNum(charc)

{//判断是否为1-9的数字

if(c>='1'&&c<='9')

return1;

else

return0;

}

boolIsUnderline(charc)

{//判断是否为下划线

if(c=='_')

return1;

else

return0;

}

voidmove(charch,ints)

{//在状态s接收字符ch后,移动的新状态

//arr=arr+ch;

switch(s)

{

case0:

{

if(ch=='_'||IsLetter(ch))

state=1;

else

{

if(ch=='0')

state=3;

else

if(IsNum(ch))

state=4;

else

if(ch=='-')

state=2;

else

state=8;

}

break;

}

case1:

{

if(IsNum(ch)||ch=='_'||IsLetter(ch)||ch=='0')

state=1;

else

if(ch=='-')

state=9;

else

state=8;

break;

}

case2:

{

if(ch=='0')

state=3;

else

if(IsNum(ch))

state=4;

else

state=8;

break;

}

case3:

{

if(ch=='.')

state=6;

else

if(ch=='-')

state=9;

else

state=8;

break;

}

case4:

{

if(IsNum(ch)||ch=='0')

state=4;

else

if(ch=='-')

state=9;

else

if(ch=='.')

state=6;

else

state=8;

break;

}

case6:

{

if(ch=='0')

state=6;

else

if(IsNum(ch))

state=7;

else

state=8;

break;

}

case7:

{

if(ch=='0')

state=6;

else

if(IsNum(ch))

state=7;

else

if(ch=='-')

state=9;

else

state=8;

break;

}

case8:

{

if(ch=='-')

state=9;

else

state=8;

break;

}

}//switch

}

voidjudge(chararr[])

{

if(s==3||s==4||s==7)

cout<<"("<

else

{

if(s==1)

{

if(!

strcmp(arr,"PI")||!

strcmp(arr,"E"))

cout<<"("<

else

{

if(IsKey(arr)==-1)

cout<<"("<

else

cout<<"("<

}

}

else

if(s==9)

cout<<"("<

if(s==8)

cout<<"("<

}

switch(ch)

{

case'+':

cout<<"("<

case'*':

cout<<"("<

case'=':

cout<<"("<

case'/':

cout<<"("<

case'^':

cout<<"("<

case'(':

cout<<"("<

case')':

cout<<"("<

case';':

cout<<"("<

case',':

cout<<"("<

case'{':

cout<<"("<

case'}':

cout<<"("<

case'?

':

cout<<"("<

case'':

case'/t':

case'/n':

{}

}

}

voidanalyse(FILE*fp)

{

inti=0;

while(ch!

='EOF')

{

chararr[32]={'\0'};

while(ch!

='('&&ch!

=')'&&ch!

='

'&&ch!

='\t'&&ch!

='\n'&&ch!

='{'&&ch!

='}'&&ch!

=','&&ch!

='?

'&&ch!

='-'

&&ch!

='^'&&ch!

=';'&&ch!

='+'&&ch!

='*'&&ch!

='/'&&ch!

='='&&ch!

='EOF')

{

if(i<32)

{

arr[i]=ch;

move(ch,s);

s=state;

}

i++;

ch=fgetc(fp);

}//while

judge(arr);

if(ch=='-')

{

chararr[32]={'\0'};

i=0;

while(ch!

='('&&ch!

=')'&&ch!

='

'&&ch!

='\t'&&ch!

='\n'&&ch!

='{'&&ch!

='}'&&ch!

=','&&ch!

='?

'

&&ch!

='^'&&ch!

=';'&&ch!

='+'&&ch!

='*'&&ch!

='/'&&ch!

='='&&ch!

='EOF')

{

move(ch,s);

s=state;

arr[i]=ch;

if(state!

=9)

{

i++;

ch=fgetc(fp);

}

else

{//s=9为减号时

chararr[32]={'\0'};

break;

}

}//while

judge(arr);

s=0;

i=0;

ch=fgetc(fp);

}

else

{

chararr[32]={'\0'};

ch=fgetc(fp);

i=0;

s=0;

}

}//while

}

voidmain()

{

charin_fn[30];

FILE*fp;

cout<<"请输入源文件名(包括路径和后缀名):

";

for(;;)

{

cin>>in_fn;

if((fp=fopen(in_fn,"r"))!

=NULL)//意思是文件指针fpin在调用fopen打开文件如果失

败,则会成为一个空指针!

break;//文件顺利打开后,指向该流的文件指针就会

被返回。

else

cout<<"文件路径错误!

请输入源文件名(包括路径和后缀名):

";

}

cout<<"\n********************分析如下*********************"<

ch=fgetc(fp);

chararr[32]={'\0'};

arr[0]=ch;

//fseek(fp,-1,1);

analyse(fp);

fclose(fp);

cout<

inta;

cin>>a;

}

4、调试过程和运行结果

 

5、程序的主要部分及其功能说明

由DFN得到的状态转换程序:

voidmove(charch,ints)

{//在状态s接收字符ch后,移动的新状态

switch(s)

{

//状态0时,当接收到字符ch为字母或下划线时状态S转移到状态1,ch为0时转

移到状态3,ch为1-9时转移到状态4,ch为‘-’时,转移到状态2,否则转移到

状态8

case0:

{

if(ch=='_'||IsLetter(ch))

state=1;

else

{

if(ch=='0')

state=3;

else

if(IsNum(ch))

state=4;

else

if(ch=='-')

state=2;

else

state=8;

}

break;

}

case1:

{

if(IsNum(ch)||ch=='_'||IsLetter(ch)||ch=='0')

state=1;

else

if(ch=='-')

state=9;

else

state=8;

break;

}

case2:

{

if(ch=='0')

state=3;

else

if(IsNum(ch))

state=4;

else

state=8;

break;

}

case3:

{

if(ch=='.')

state=6;

else

if(ch=='-')

state=9;

else

state=8;

break;

}

case4:

{

if(IsNum(ch)||ch=='0')

state=4;

else

if(ch=='-')

state=9;

else

if(ch=='.')

state=6;

else

state=8;

break;

}

case6:

{

if(ch=='0')

state=6;

else

if(IsNum(ch))

state=7;

else

state=8;

break;

}

case7:

{

if(ch=='0')

state=6;

else

if(IsNum(ch))

state=7;

else

if(ch=='-')

state=9;

else

state=8;

break;

}

case8:

state=8;

}//switch

}

从文件读字符,并进行词法分析,当读入的字符不为运算符和界符时就往下读,

并将读到的字符存入数组arr,当遇到运算符和界符时调用judge(arr)进行分析,输出

arr所存字符串及其属性,当遇到‘-’时,需要判断它是表示减号还是表示负数的

负号,主要是根据其状态来判断,如果输入‘-’后,若其状态没有调到状态9,则

其为负数的负号,否则为减号。

主要程序如下:

voidanalyse(FILE*fp)

{

inti=0;

while(ch!

='EOF')

{

chararr[32]={'\0'};

while(ch!

='('&&ch!

=')'&&ch!

='

'&&ch!

='\t'&&ch!

='\n'&&ch!

='{'&&ch!

='}'&&ch!

=','&&ch!

='?

'&&ch!

='-'

&&ch!

='^'&&ch!

=';'&&ch!

='+'&&ch!

='*'&&ch!

='/'&&ch!

='='&&ch!

='EOF')

{

if(i<32)

{

arr[i]=ch;

move(ch,s);

s=state;

}

i++;

ch=fgetc(fp);

}//while

judge(arr);

if(ch=='-')//如果遇到‘-’

{

chararr[32]={'\0'};

i=0;

while(ch!

='('&&ch!

=')'&&ch!

='

'&&ch!

='\t'&&ch!

='\n'&&ch!

='{'&&ch!

='}'&&ch!

=','&&ch!

='?

'

&&ch!

='^'&&ch!

=';'&&ch!

='+'&&ch!

='*'&&ch!

='/'&&ch!

='='&&ch!

='EOF')

{

move(ch,s);

s=state;

arr[i]=ch;

if(state!

=9)

{

i++;

ch=fgetc(fp);

}

else

{//s=9为减号时

chararr[32]={'\0'};

break;

}

}//while

judge(arr);

s=0;

i=0;

ch=fgetc(fp);

}

else

{//是除‘-’外的运算符和界符时

chararr[32]={'\0'};

ch=fgetc(fp);

i=0;

s=0;

}

}//while

}

6、实验收获体会

通过实验,我理解了如何通过DFA的状态转换来构造词法分析器,掌握了生成词法分析器的方法,加深了对词法分析原理的理解。

同时在编程的过程中提高了编程能力。

7、改进意见

该词法分析器所能识别的字符串是有限的,不够完全,像main,void,double,int等许多关键字都没有定义到关键字的数组里面去,仅能被识别为一个变量。

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

当前位置:首页 > 初中教育

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

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