编译原理实验.docx

上传人:b****1 文档编号:20129068 上传时间:2023-04-25 格式:DOCX 页数:36 大小:36.54KB
下载 相关 举报
编译原理实验.docx_第1页
第1页 / 共36页
编译原理实验.docx_第2页
第2页 / 共36页
编译原理实验.docx_第3页
第3页 / 共36页
编译原理实验.docx_第4页
第4页 / 共36页
编译原理实验.docx_第5页
第5页 / 共36页
点击查看更多>>
下载资源
资源描述

编译原理实验.docx

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

编译原理实验.docx

编译原理实验

实验一:

简易扫描器的DFA设计与实现

实验原理:

词法分析器的工作原理

实验内容:

用程序模拟实现一个简易扫描器的工作过程,从输入字符串到分析完以后以(CLASSVALUE的标准格式输出实验要求:

1.源程序设计语言G[v标志符>]:

<标志符>f<标志符><字母>|v标志符><下划线>|v标志符><数字>|<字母>|<下划线>

<常数>f<整数>

V整数>f0|<非零数字><乏整数>

<泛整数>fV数字>|<数字><乏整数>|£

V关系符>f<|<=|=|>|>=|<>

V字母>

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|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

v非零数字>f1|2|3|4|5|6|7|8|9

v数字>fv非零数字>|0

2.能识别下表所列的单词符号:

单词符号

类别编码

类别码的助记符

单词之值

begin

1

BEGIN

end

2

END

if

3

IF

then

4

THEN

else

5

ELSE

标识符

6

ID

整数

7

INT

数字串

<

8

LT

<=

9

LE

=

10

EQ

<>

11

NE

>

12

GT

>=

13

GE

+

14

ADD

-

15

SUB

*

16

MUL

/

17

DIV

18

SEM

19

LB

20

RB

3.能跳过源程序中的空白格:

两个单词之间的任何空格,

制表符,回车,换行都是白空格,除了用来分隔单词以

夕卜,没有意义;

4.能跳过注释:

1)接连出现的/*到下一次接连出现的*/之间的任何文字都是注释(多行);

2)从某行接连出现的//到该行的结尾的任何文字都是注释(单行)。

实验步骤:

1.

DFA及相关语义过程;

2.

流程图(或程序的基本框架);

3.

根据实验要求编写一个能够完全遍历整个词法分析程序

的输入字符串;

4.

把课本P81程序3-4的函数编写完整。

OUT(DIV,””

1.DFA及相关语义过程

START

非/或非*

非换行

空格

非空格

空格

8

非*

/

*

4

换行

OUT(SUB'”)

OUTSEM”)

OUT(LB””)

OUT(RB,””)

23

OUT(ADD,””

24

25

OUT(MUL,””)

I

/I'

/|1

!

1

29

其他

字母

i!

5

非/

6

字母,d

非字母和

d

<

18

\十一=

非=和>

非d

C=0时OUT(ID,TOKEN

10

12

xd

14

亠亠"J

OUT(EQ,

2219-

C不=0时OUT(c,”

OUT(INT,”TOKE

OUT(LE,””)

OUT(NE,””)

OUT(LT,””)

OUT(GE,””)

OUT(GT,””)

 

2.流程图(或程序的基本框架)

开始

是否文件尾

/

N

£

/

//

/

/

/

除去空格换行符合无意义字符

/

:

1

:

L卜1

除去注释

1

£

1

1

1

识别ID或标识符

1

-

I

1

\

1

1

\

识别数字

1

\

\

\

\

\

\

识别符

*

 

3.代码

#define

_CRT_SECURE_NO_WARNINGS

#include

#include

#include

#define

BEGIN1

#define

END2

#define

IF3

#define

THEN4

#define

ELSE5

#define

ID6

#define

INT7

#define

LT8

#define

LE9

#define

EQ10

#define

NE11

#define

GT12

#define

GE13

#define

ADD14

#define

SUB15

#define

MUL16

#define

DIV17

#define

SEM18

#define

LB19

#define

RB20

charTOKEN[20];

intlookup(char*);//查找标识符

voidout(int,char*);//输岀扫描结果

voidreport_error();//错误信息

//externintlookup(char*);

intlookup(char*temp){

if(strcmp(temp,"begin")==0)returnBEGIN;

else

if(strcmp(temp,"end")==0)returnEND

else

if(strcmp(temp,"if")==0)returnIF;

else

if(strcmp(temp,"then")==0)returnTHEN

else

if(strcmp(temp,"else")==0)returnELSE

else

return0;

}

//externvoidout(int,char*);

voidout(inta,char*s){

switch(a)

{

case

BEGIN:

printf(

"<%s,%s>\n"

"BEGIN","begin"

case

break;

ENDprintf(

"<%s,%s>\n",

"END"

"end");

case

break;

IF:

printf(

break;

"<%s,%s>\n",

"IF",

"if");

case

THENprintf(

break;

"<%s,%s>\n"

"THEN","then");

case

case

ELSEprintf(break;

ID:

printf(

"<%s,%s>\n"

"<%s,%s>\n",

"ELSE","else");

"ID",s);

case

break;

INT:

printf(

"<%s,%s>\n",

"INT"

s);

case

break;

LT:

printf(

break;

"<%s,%s>\n",

"LT",

"<");

case

LE:

printf(

break;

"<%s,%s>\n",

"LE",

"<=");

case

case

EQprintf(break;

NE:

printf(

"<%s,%s>\n",

"<%s,%s>\n",

"EQ",

"NE",

"=");

"<>");

case

break;

GT:

printf(

"<%s,%s>\n",

"GT",

">");

case

break;

GEprintf(

"<%s,%s>\n",

"GE",

">=");

break;

case

ADDprintf(

break;

"<%s,%s>\n",

"ADD"

"+");

case

SUBprintf(

break;

"<%s,%s>\n",

"SUB"

"-");

case

MULprintf(

"<%s,%s>\n",

"MUL"

"*");

case

break;

DIV:

printf(

"<%s,%s>\n",

"DIV"

"/");

case

break;

SEMprintf(

"<%s,%s>\n",

"SEM"

";");

case

break;

LB:

printf(

break;

"<%s,%s>\n",

"LB",

"(");

case

RB:

printf(

break;

"<%s,%s>\n",

"RB",

")");

);

default

break;

}

//externreport_error(void);

voidreport_error(){

printf("未识别字符\n");

}

voidseanner_example(FILE*fp){

charch;

inti=0,c;

ch=fgetc(fp);

if(ch==''||ch=='\n'||ch==-1)return;//略掉空格,换行符和无意义字符

if(ch=='/')//如果扫描到/

{

charch2=fgetc(fp);//取下一个字符

if(ch2=='/')//判断这个字符是不是/

{

printf("//");//条件成立构成//注释

while(ch2=fgetc(fp))

{

printf("%c",ch2);//输岀信息调试用,要跳过,注释这行即可

if(ch2=='\n'){break;}//到了行尾跳岀

}

}

elseif(ch2=='*')//判断是否多行注释

{

printf("/*");

while(ch2=fgetc(fp))

{

if(ch2=='*'){//如果遇到*

ch2=fgetc(fp);

if(ch2=='/')break;//切下一个为/跳岀

}

else

{

printf("%c",ch2);//输岀信息调试用,要跳过,注释这行即可

}

}

printf("*/\n");

return;

}

fseek(fp,-1,1);//没成立的话、文件指针回退1

}

if(isalpha(ch)){//扫描字母

TOKEN[i]=ch;i++;

while(isalnum(ch)){//字母后面带数字的也是合法ID

TOKEN[i]=ch;i++;

ch=fgetc(fp);

}

TOKEN[i]='\0';//给串打上结束符

fseek(fp,-1,1);

strncpy(TOKEN,TOKEN+1,i);//剪切字串,不要头个字符c=lookup(TOKEN);//查找是否关键字并得到返回值

if(c==0){

out(ID,TOKEN);//不是关键字则输岀ID

}

else{out(c,"");}//否则则输岀关键字

}

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);

out(INT,TOKEN);

}

else//前面都不成立的话、则查看是不是符号

switch(ch){

case'<':

ch=fgetc(fp);

if(ch=='=')out(LE,"");

elseif(ch=='>')out(NE"");

else

{

fseek(fp,-1,1);

out(LT,"");

break;

case'=':

out(EQ"");break;

case'>':

ch=fgetc(fp);

if(ch=='=')out(GE"");

elseif(ch=='>')out(NE"");

else

{

fseek(fp,-1,1);

out(GT"");

}

break;

case'+'

case'-'

:

out(ADD""

:

out(SUB""

);break;

);break;

case'*'

:

out(MUL""

);break;

case'/'

:

out(DIV,""

);break;

case'('

:

out(LB,"")

;break;

case')'

:

out(RB"")

;break;

case';'

:

out(SEM""

);break;

break;

default

:

report_error();

//报错

break;

}

return;

}

intmain(){

FILE*fp;

fp=fopen("d:

\\test.txt","r");

inttt;

while(!

feof(fp))//如果文件没到行尾则循环{

scanner_example(fp);

}

return0;

}

测试文件:

结果:

心得:

经过这次实验,虽然在课堂上写的程序有许多缺陷,但回去后,我认真的重写了一遍,实现了要求的功能,并通过这次的实验,加深了对扫描器的理解。

实验二:

自顶向下分析:

LL

(1)分析方法

实验原理:

语法分析器的工作原理

实验内容:

1、了解语法分析的其中一种自顶向下分析方式LL

(1);

2、学会构造LL

(1)分析表;

3、上机实现课本P120预测分析器的工作流程。

实验要求:

要求能对下列文法所产生的符号串进行语法分析:

1EE+T|E-T|T

2TT*F|T/F|F

3F(E)|num|id

对输入的符号在分析完之后,如果正确就报告,有误就停止。

实验步骤:

1、消除文法的左递归(①、②产生式);

2、对消除左递规后的文法分别求出各FIRST集和FOLLOW集,再构造相应的LL

(1)分析表;

3、根据参考程序(见程序设计指导),实现预测分析器的工作流程。

程序设计指导:

1、本次实验要完成的程序功能为:

用程序实现预测分

析器的工作流程,根据不断地查找指定文法得出的

LL

(1)分析表,最终判断输入串是否符合该文法的语法要求;

2、首先,在本次实验的预习报告中要先完成实验步骤中的前面两条;

3、参考程序:

charstack[50];//分析栈chara[100];//输入器

gettop(stack);//自己定义is_nonterminal(x);//自己定义is_terminal(x);//自己定义pop

(1);//自己定义push();//自己定义

intLL1driver(void)

{

stack[0]='#';

stack[1]='E';//把初始符号移入空栈

/*输入指示器指向输入器的初始位置*/

while(!

stack_empty())

x=gettop(stack);/*取当前栈顶的符号x*/

/*取当前指示器指向的位置*/

if(is_nonterminal(x))

{

/*查LL(1分析表,对应有产生式:

xdyl…y2*/

if(查表成功)

{pop

(1);//栈顶x出栈

push();/*把产生式右部的侯选式反序

(y2…y1)压入分析栈*/

}

elseprintf("语法分析过程有误!

");//查表不成

}//endifelse

if(is_terminal(x)&&x=ai)

{pop

(1);//栈顶x出栈

/*输入指示器向前推进一个位置*/}

else

if(x=ai=#)

printf("success!

");

elseprintf("error!

");

}//endwhile

}//endLLIdriver

1.消除文法的左递归(①、②产生式);

1EE+T|ET|T

ETE'

E'+TE'TE'd

2TT*F|T/F|F

TFT'

T'*FT'|/FTd'|

3F(E)|num|id

2•对消除左递规后的文法分别求出各FIRST集和FOLLOW

集,再构造相应的LL

(1)分析表;

FIRST

FLOLLOW

E

{(,num,id}

{),#}

E'

{+,-,£}

{),#}

T

{(,num,id}

{+,-,),#}

T'

{*,/,£}

{+,-,),#}

F

{(,num,id}

{*,/,+,-,),#}

 

num

id

+

-

*

/

#

E

ETE'

ETE

ETE

E'

E'+

TE'

E'-

TE'

E'

£

E'

£

T

TF

T'

TF

T'

TF

T'

T'

T

£

T

£

T*

FT'

T/

FT'

T

£

T

£

F

Fn

um

Fi

d

F(

E)

3.根据参考程序(见程序设计指导),实现预测分析器的工作流程。

#define_CRT_SECURE_NO_WARNINGS

#include

#include

structanlysis

{

charvn;

charvt;

charrs[20];

}productions[19]={

},

{

'E'

'n'

"TX"

{

'E'

'i'

"TX"

},

{

'E'

'('

"TX"

},

{

X

'+'

"+TX"

},

{

X

11

J-

"-TX"

},

{

X

')'

""},

{

X

""},

{

'T'

'n'

"FY"

},

{

'T'

'i'

"FY"

},

{

'T'

'('

"FY"

},

{

Y

'*'

5

"*F丫"

},

{

Y

7'

"/FY"},

{

Y

'+'

""},

{

Y

11

J-

""},

{

Y

')'

""},

{

Y

'#'

""},

{

'F'

'n'

"n"},

{'F','i',"i"},

{'F','(',"(E)"},

};

charstack[50],a[50],token[20];

chargettop()|

{

chartop;|

intj=strlen(stack)-1;

top=stack[j];returntop;

}

intis_vn(charx)

{

inti,c;|

for(i=0;i<19;i++)

{

if(productions[i].vn==x)

{

c=1;

returnc;

}

}

c=0;

returnc;|

}

voidpop()|

{

intj;

j=strlen(stack)-1;stack[j]='\0';

}

voidpush()

{

strcat(stack,token);

}

voidinv()|

{

chartemp;

intn=strlen(token);inti,j,m=(n-2)/2;for(i=0;i<=m;i++){

j=n-1-i;

temp=token[i];

token[i]=token[j];

token[j]=temp;

}

}

void

LL1driver(

chara[])

{

stack[0]=

#;

stack[1]='E';

printf("\nstack=%s,a=%s",stack,a);

intk=0;

charx;

do

{

start:

x=gettop();

if(is_vn(x))

{

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

{

if((productions[i].vt==a[k])&&(productions[i].vn==x))

{

for(intj=0;j<20;j++)

{

token[j]=productions[i].rs[j];

}

inv();

pop();

push();

printf("\nstack=%s,a[k]=%c",stack,a[k]);gotostart;

}

}

printf("\nerror");

return;

}

else

if(x!

='#')

{

if(a[k]==x)

pop();

a[k+1]);

printf("\nstack=%s,a[k]=%c",stack,

}

else

{

printf("\nerror");

return;

}

}

else

if(a[k]=='#'&&x=='#')

{

printf("\nsuccess");

return;

}

elseprintf("error");

k++;

}while(strlen(stack)!

=0);

}

voidmain()

{

printf("pleaseinputstring:

");

scanf("%s",a);

LL1driver(a);

getchar();

getchar();

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

当前位置:首页 > 党团工作 > 入党转正申请

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

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