编译原理第二次上机实验报告软工李U172xx.docx

上传人:b****5 文档编号:6828819 上传时间:2023-01-10 格式:DOCX 页数:26 大小:68.17KB
下载 相关 举报
编译原理第二次上机实验报告软工李U172xx.docx_第1页
第1页 / 共26页
编译原理第二次上机实验报告软工李U172xx.docx_第2页
第2页 / 共26页
编译原理第二次上机实验报告软工李U172xx.docx_第3页
第3页 / 共26页
编译原理第二次上机实验报告软工李U172xx.docx_第4页
第4页 / 共26页
编译原理第二次上机实验报告软工李U172xx.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

编译原理第二次上机实验报告软工李U172xx.docx

《编译原理第二次上机实验报告软工李U172xx.docx》由会员分享,可在线阅读,更多相关《编译原理第二次上机实验报告软工李U172xx.docx(26页珍藏版)》请在冰豆网上搜索。

编译原理第二次上机实验报告软工李U172xx.docx

编译原理第二次上机实验报告软工李U172xx

 

编译原理第二次上机实验报告

 

姓名:

李x

班级:

软工140x班

学号:

U2014172xx

 

实验二 设计实现简单语言的语法分析器

1、实验目的

通过该实验,熟练应用编译原理关于语法分析的基本理论和方法;学会用C/C++高级程序设计语言设计一个语法分析器;加深对编译原理理论的分析理解,提高实际操作和解决具体问题的能力。

2、实验条件

计算机上安装C/C++编译处理软件。

3、实验内容及要求

对下述单词表与语法定义的语言设计编制一个语法分析器。

单词符号及种别表、语法及语法分析器功能、基本要求如下:

(1)单词符号及种别表

单词符号

种别编码

单词值

main

1

 

int

2

 

float

3

 

double

4

 

char

5

 

if

6

 

else

7

 

do

8

 

while

9

 

l(l|d)*

10

内部字符串

(+|-|ε)dd*(.dd*|ε)(e(+|-|ε)dd*|ε)

20

二进制数值表示

=

21

 

+

22

-

23

 

*

24

 

/

25

 

26

 

27

 

{

28

 

}

29

 

30

 

;

31

 

>

32

 

>=

33

 

<

34

 

<=

35

 

==

36

 

!

=

37

 

#

0

 

(2)语法结构定义

<表达式>:

:

=<项>{+<项>|-<项>}

<项>:

:

=<因子>{*<因子>|/<因子>}

<因子>:

:

=ID|num|(<表达式>)

num:

:

=(+|-|ε)数字数字*(.数字数字*|ε)(e(+|-|ε)数字数字*|ε)

ID:

:

=字母(字母|数字)*

字母:

:

=a|b|c…|z|A|B|C…|Z

数字:

:

=0|1|2…|9

(3)语法分析器功能及基本要求

处理用户提交的符合上述文法的源代码序列,进行语法分析,并给出语法是否正确的结论。

(1)总体设计思想

利用自上而下的分析方法;本实验所采用的是LL

(1)分析法即预测分析法;每次通过词法分析模块读入一个完整的单词,在语法分析中判断正确性,最终将结果输出。

 

(2)详细算法设计

语法分析

<表达式>:

:

=<项>{+<项>|-<项>}

<项>:

:

=<因子>{*<因子>|/<因子>}

<因子>:

:

=ID|num|(<表达式>)

num:

:

=(+|-|ε)数字数字*(.数字数字*|ε)(e(+|-|ε)数字数字*|ε)

ID:

:

=字母(字母|数字)*

字母:

:

=a|b|c…|z|A|B|C…|Z

数字:

:

=0|1|2…|9

用字母替代后写成如下:

E→T{+T|-T}

T→F{*F|/F}

F→i|n|(E)

将该扩充文法还原

EE+T|E-T|T

TT*F|T/F|F

F(E)|i|n

消除非终结符E、T的直接左递归后,文法变为

ETE’

E’+TE’|-TE’|ε

TFT’

T’*FT’|/FT’|ε

F(E)|i|n

此文法是LL

(1)文法

求出该文法的预测分析表

i

n

+

-

*

/

$

E

ETE’

ETE’

ETE’

E’(e)

E’+TE’

E’TE’

E’ε

E’ε

T

TFT’

TFT’

TF’

T’(t)

T’ε

T’ε

T’*FT’

T’/FT’

T’ε

T’ε

F

Fi

Fn

F(E)

根据预测分析表、分析栈和一个总控程序来判断一个语句是否正确;

 

(3)流程框图

 

 

(4)函数相关说明

charinput[300];//存放输入的字符串

chartoken[20];//存放符合C语言词法规则的单词

charch;//单个字符

charprevious;//ch的前一个字符

charlatter;//ch的后一个字符

charch1,ch2;//当处理注释的时候使用

inttypenum;//表示单词的种别码

intp,m,n,cx;

doubledecimal;//记录小数

doublesum;//存放数字

intindex;//存放指数

intisNum;//是否是数字

intisDecimal;//记录是否为小数

intisExp;//记录是否为指数

intisNegative;//是否带负号(对于指数)

intisNegative1;//是否为负数

charX,a;

charstack[200];

voidscanner();

char*rwtab[11]={"main","int","float","double","char","if","else","while","do","end"};

//记录预测分析表,0表示没有产生式,其他数字表示产生式的序号

intList[5][9]={

{1,2,0,0,0,0,3,0,0},

{0,0,4,5,0,0,0,6,7},

{8,9,0,0,0,0,10,0,0},

{0,0,11,12,13,14,0,15,16},

{17,18,0,0,0,0,19,0,0}

};

charreturnResult()函数返回n、i、e、+、-、*、/、(、);

voidscanner()扫描函数判断种别码

boolisVT(charx)判断是否为终结符

boolcheckList(intx,inty)查询是否在分析表中

intgetX()、intgetY()获取要查询数组M[X,a]元素的下标

voidmakeTop()把栈顶放入X中

voidpush(intxy)将y1y2...yn逆序放入S栈中

intmain()主函数

(5)输入与输出(包括出错处理)

输入以$结束回车即可运行程序

输出success!

或者unsuccess!

或者error!

unsuccess!

出错分为两种情况

1.词法错误:

error!

unsuccess!

2.词法正确但语法错误:

unsuccess!

 

(6)程序运行结果(屏幕截图)

 

(7)词法分析器使用说明

打开编译器VS或者VC++;文件新建项目;

将代码复制粘贴,编译运行,按照提示输入即可使用;

(8)心得与体会

加强了自己对于LL

(1)分析法的理解与记忆;第二次试验难度要大于第一次;主要难在求预测分析表;开始由于预测分析表求错误导致程序运行一直出错也不知道到底bug出在哪里,后来才发现自己预测分析表求错了;对于词法分析实验一已经给出,预测分析总控制程序算法书本上已经给出;所以最大的难点就是求预测分析表;这需要足够的耐心和细心才能保证FIRSE集和FOLLOW集不多一个,也不漏掉其中一个;后期需要加强练习;

 

(9)源程序清单

//语法编译器01.cpp:

定义控制台应用程序的入口点。

//

#include"stdafx.h"

#include

#include

#include

charinput[300];//存放输入的字符串

chartoken[20];//存放符合C语言词法规则的单词

charch;//单个字符

charprevious;//ch的前一个字符

charlatter;//ch的后一个字符

charch1,ch2;//当处理注释的时候使用

inttypenum;//表示单词的种别码

intp,m,n,cx;

doubledecimal;//记录小数

doublesum;//存放数字

intindex;//存放指数

intisNum;//是否是数字

intisDecimal;//记录是否为小数

intisExp;//记录是否为指数

intisNegative;//是否带负号(对于指数)

intisNegative1;//是否为负数

charX,a;

charstack[200];

voidscanner();

char*rwtab[11]={"main","int","float","double","char","if","else","while","do","end"};

//记录预测分析表,0表示没有产生式,其他数字表示产生式的序号

intList[5][9]={

{1,2,0,0,0,0,3,0,0},

{0,0,4,5,0,0,0,6,7},

{8,9,0,0,0,0,10,0,0},

{0,0,11,12,13,14,0,15,16},

{17,18,0,0,0,0,19,0,0}

};

charreturnResult()

{

scanner();

switch(typenum)

{

case20:

return'n';//表示返回一个数字number

case10:

return'i';//表示返回id

case22:

return'+';

case23:

return'-';

case24:

return'*';

case25:

return'/';

case26:

return'(';

case27:

return')';

case0:

return'$';

default:

return'e';//表示error!

}

}

voidscanner()

{

cx=0;//用来记录小数点后面的位数

m=0;

sum=0;

decimal=0;

index=0;

isDecimal=0;

isNegative=0;

isNegative1=0;

isExp=0;

for(n=0;n<8;n++)

token[n]='\0';

ch=input[p++];

//处理回车换行空格

while((ch=='')||(ch==9)||(ch==10))

{

ch=input[p++];

}

//处理注释

if(ch=='/')

{

ch1=input[p];

if(ch1=='*')

{

do

{

ch=input[p++];

ch2=input[p];

}while((ch!

='*')||(ch2!

='/'));

p=p+1;

ch=input[p++];

}

 

}

 

if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z')))//如果当前ch为字母

{

while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9')))

{

token[m++]=ch;

ch=input[p++];

}

token[m++]='\0';

typenum=10;//10表示l(l|d)*

p=p-1;//回退一步

for(n=0;n<10;n++)

if(strcmp(rwtab[n],token)==0)

{

typenum=n+1;

break;

 

}

}

 

elseif((ch>='0')&&(ch<='9'))

{

isNum:

while((ch>='0')&&(ch<='9'))

{

sum=sum*10+(ch-'0');

ch=input[p++];

}

if(ch=='.')

{

isDecimal=1;

ch=input[p++];

while(ch>='0'&&ch<='9')

{

cx=cx+1;

decimal=decimal*10+(ch-'0');

ch=input[p++];

}

if(ch=='')

{

typenum=-1;

return;

}

for(inta=0;a

decimal=decimal*0.1;

sum=sum+decimal;

}

if((ch=='e')||(ch=='E'))

{

isExp=1;

ch=input[p++];

if(ch=='-')

{

isNegative=1;//表示指数为负数

ch=input[p++];

}

if(ch=='+')

{

isNegative=0;//表示指数为正

ch=input[p++];

}

if(ch=='')

{

typenum=-1;

return;

}

 

while((ch>='0')&&(ch<='9'))

{

index=index*10+(ch-'0');

ch=input[p++];

}

if(isNegative==1)//如果指数为负数

{

for(intk=0;k

sum=sum*0.1;

}

else

{

for(intk=0;k

sum=sum*10;

}

}

if(isNegative1==1)

sum=sum*(-1);

p--;//回退一步

typenum=20;//表示为数字

}

//运算符、界运算符

else{

 

switch(ch)

{

case'=':

typenum=21;

token[m++]=ch;

break;

case'+':

previous=input[p-2];

latter=input[p];

//当+号前面为空或者(或者=并且后面为数字时,+表示正负号;

if(((previous=='')||(previous=='(')||(previous=='='))&&((latter>='0')&&(latter<='9')))

{

isNegative1=0;//表示此+号为正负号

ch=input[p++];

gotoisNum;

}

//当+号前面为+、-、*、/号且后面为数字时,-号表示正负号;

elseif(((previous=='+')||(previous=='-')||(previous=='*')||(previous=='/'))&&((latter>='0')&&(latter<='9')))

{

isNegative1=0;

ch=input[p++];

gotoisNum;

}

//如果+号后面是+、-号,则表示为加减号

elseif((latter=='+')||(latter=='-'))

{

typenum=22;

token[m++]=ch;

break;

}

//如果+号后面是字母;

elseif(((latter>='a')&&(latter<='z'))||((latter>='A')&&(latter<='Z')))

{

typenum=22;

token[m++]=ch;

break;

}

elseif((((previous>='a')&&(previous<='z'))||((previous>='A')&&(previous<='Z'))||((previous>='0')&&(previous<='9')))&&((latter>=0)||(latter<='9')))

{

typenum=22;

token[m++]=ch;

break;

}

else

{

typenum=-1;

break;

}

case'-':

previous=input[p-2];

latter=input[p];

//当-号前面为空或者(或者=并且后面为数字时,-表示正负号;

if(((previous=='')||(previous=='(')||(previous=='='))&&((latter>='0')&&(latter<='9')))

{

isNegative1=1;//表示此+号为正负号

ch=input[p++];

gotoisNum;

}

//当-号前面为+、-、*、/号且后面为数字时,-号表示正负号;

elseif(((previous=='+')||(previous=='-')||(previous=='*')||(previous=='/'))&&((latter>='0')&&(latter<='9')))

{

isNegative1=1;

ch=input[p++];

gotoisNum;

}

//如果-号后面是+、-号,则表示为加减号

elseif((latter=='+')||(latter=='-'))

{

typenum=23;

token[m++]=ch;

break;

}

//如果-号后面是字母;

elseif(((latter>='a')&&(latter<='z'))||((latter>='A')&&(latter<='Z')))

{

typenum=23;

token[m++]=ch;

break;

}

//如果前面为字母或者数字且后面为数字,则表示-号

elseif((((previous>='a')&&(previous<='z'))||((previous>='A')&&(previous<='Z'))||((previous>='0')&&(previous<='9')))&&((latter>=0)||(latter<='9')))

{

typenum=23;

token[m++]=ch;

break;

}

else

{

typenum=-1;

break;

}

case'*':

typenum=24;

token[m++]=ch;

break;

case'/':

typenum=25;

token[m++]=ch;

break;

case'>':

token[m++]=ch;

ch=input[p++];

if(ch=='=')

{

typenum=33;

token[m++]=ch;

}

else

{

typenum=32;

p--;

}

break;

case'<':

token[m++]=ch;

ch=input[p++];

if(ch=='=')

{

typenum=35;

token[m++]=ch;

}

else

{

typenum=34;

p--;

}

break;

case'(':

typenum=26;

token[m++]=ch;

break;

case')':

typenum=27;

token[m++]=ch;

break;

case'{':

typenum=28;

token[m++]=ch;

break;

case'}':

typenum=29;

token[m++]=ch;

break;

case':

':

typenum=30;

token[m++]=ch;

break;

case';':

typen

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

当前位置:首页 > 职业教育 > 职高对口

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

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