编译原理报告 8.docx
《编译原理报告 8.docx》由会员分享,可在线阅读,更多相关《编译原理报告 8.docx(29页珍藏版)》请在冰豆网上搜索。
![编译原理报告 8.docx](https://file1.bdocx.com/fileroot1/2023-4/18/ca424246-1c1b-4d0a-bc98-62cdc02c676e/ca424246-1c1b-4d0a-bc98-62cdc02c676e1.gif)
编译原理报告8
课程设计报告
题目:
设计词法语法分析器
课程名称:
编译原理上机实验
专业班级:
信息安全1302班
学号:
姓名:
指导教师:
报告日期:
2015年11月2日
计算机科学与技术学院
1.词法分析
1.1实验目的
设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
1.2实验要求
1.待分析的简单语言的词法
(1)关键字:
beginifthenwhiledoend
所有的关键字都是小写
(2)运算符和界符:
:
=+-*/<<=<>>>==;()#
(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:
ID=letter(letter|digit)*
NUM=digitdigit*
(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2各种单词符号对应的种别码
单词符号
种别码
单词符号
种别码
begin
1
{
21
if
2
}
22
then
3
23
while
4
:
24
Do
5
:
=
25
End
6
;
26
letter(letter|digit)*
10
>
27
digitdigit*
11
>=
28
+
13
<
29
-
14
<>
30
*
15
<=
31
/
16
!
32
(
17
=
33
)
18
==
34
[
19
#
0
]
20
3词法分析程序的功能
输入:
所给文法的源程序字符串
输出:
二元组(syn,token或sum)构成的序列。
其中:
syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:
对源程序
beginx:
=9;ifx>0thenx:
=2*x+1/3;end#
的源文件,经词法分析后输出如下序列:
(1,begin)(10,‘x‘)(25[,:
=)(11,9)(26,;)(2,if)…
1.3词法分析程序的算法思想
算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字种类,拼出相应的单词符号。
1.主程序示意图
主程序示意图如图1.1所示。
其中初值包括如下两个方面。
图1.1
(1)关键字表的初值。
char*rwtab[6]={“begin”,”if”,”then”,”while”,”do”,”end”};
关键字是一种特殊的标识符,每一个关键字都应该有一个与其对应的编号,否则在后续的操作中将无法再进行下去。
(2)程序中需要用到的主要变量声明有如下几个:
typedefstruct
{
inttypenum;
char*word;
}WORD;
charinput[255];
chartoken[255]="";
intp_input;
intp_token;
charch;
2.扫描子程序的算法思想
首先设置3个变量:
token用来存放构成单词符号的字符串或者是整形单词;
input用于存储输入的程序;
p_input,p_token分别用于记录当前两数组所用到的位置;
结构类型WORD包含两个变量,其中typenum用于记录数据标号(相当于syn),word用于记录当前的数据。
扫描子程序主要部分流程如图C.2所示。
图C.2
1.4词法分析程序的C语言实现
1..4.1代码实现
**************************head.h**********************************
#include
#include
#include
#define_KEY_WORD_END"waitingforyourexpanding"
typedefstruct
{
inttypenum;
char*word;
}WORD;
charinput[255];
chartoken[255]="";
intp_input;
intp_token;
charch;
char*rwtab[]={"begin","if","then","while","do","end",_KEY_WORD_END};
**************************head.h**********************************
**************************cifa.h**********************************
/*从输入缓冲区读一个字符到ch*/
charm_getch()
{
ch=input[p_input];
p_input++;
returnch;
}
/*去掉空白*/
voidgetbc()
{
while(ch==''||ch==10)
{
ch=input[p_input];
p_input++;
}
}
/*拼接单词*/
voidconcat()
{
token[p_token]=ch;
p_token++;
token[p_token]='\0';
}
/*判断是否为字母*/
intletter()
{
if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return1;
elsereturn0;
}
/*判断是否为数字*/
intdigit()
{
if(ch>='0'&&ch<='9')return1;
elsereturn0;
}
/*检索关键字表格*/
intreserve()
{
inti=0;
while(strcmp(rwtab[i],_KEY_WORD_END))
{
if(!
strcmp(rwtab[i],token))
{
returni+1;
}
i++;
}
return10;
}
/*回退一个字符*/
voidretract()
{
p_input--;
}
/*数字转换成二进制*/
char*dtb()
{
//charxx[255];
returnNULL;
}
/*词法扫描程序*/
WORD*scaner()
{
WORD*myword=newWORD;
myword->typenum=10;
myword->word="";
p_token=0;
m_getch();
getbc();
if(letter())
{
while(letter()||digit())
{
concat();
m_getch();
}
retract();
myword->typenum=reserve();
myword->word=token;
returnmyword;
}
elseif(digit())
{
while(digit())
{
concat();
m_getch();
}
retract();
myword->typenum=11;
myword->word=token;
returnmyword;
}
elseswitch(ch)
{
case'=':
m_getch();
if(ch=='=')
{
myword->typenum=39;
myword->word="==";
returnmyword;
}
retract();
myword->typenum=25;
myword->word="=";
returnmyword;
break;
case'+':
myword->typenum=13;
myword->word="+";
returnmyword;
break;
case'-':
myword->typenum=14;
myword->word="-";
returnmyword;
break;
case'*':
myword->typenum=15;
myword->word="*";
returnmyword;
break;
case'/':
myword->typenum=16;
myword->word="/";
returnmyword;
break;
case'(':
myword->typenum=27;
myword->word="(";
returnmyword;
break;
case')':
myword->typenum=28;
myword->word=")";
returnmyword;
break;
case'[':
myword->typenum=29;
myword->word="[";
returnmyword;
break;
case']':
myword->typenum=30;
myword->word="]";
returnmyword;
break;
case'{':
myword->typenum=31;
myword->word="{";
returnmyword;
break;
case'}':
myword->typenum=32;
myword->word="}";
returnmyword;
break;
case',':
myword->typenum=33;
myword->word=",";
returnmyword;
break;
case':
':
m_getch();
if(ch=='=')
{
myword->typenum=18;
myword->word=":
=";
returnmyword;
}
retract();
myword->typenum=17;
myword->word=":
";
returnmyword;
break;
case';':
myword->typenum=26;
myword->word=";";
returnmyword;
break;
case'>':
m_getch();
if(ch=='=')
{
myword->typenum=24;
myword->word=">=";
returnmyword;
}
retract();
myword->typenum=23;
myword->word=">";
returnmyword;
break;
case'<':
m_getch();
if(ch=='=')
{
myword->typenum=22;
myword->word="<=";
returnmyword;
}
retract();
myword->typenum=20;
myword->word="<";
returnmyword;
break;
case'!
':
m_getch();
if(ch=='=')
{
myword->typenum=40;
myword->word="!
=";
returnmyword;
}
retract();
myword->typenum=-1;
myword->word="ERROR";
returnmyword;
break;
case'#':
m_getch();
myword->typenum=0;
myword->word="#";
returnmyword;
break;
case'\0':
myword->typenum=1000;
myword->word="OVER";
returnmyword;
break;
default:
myword->typenum=-1;
myword->word="ERROR";
returnmyword;
}
}
*****************************cifa.h*******************************
******************************main.cpp*******************************
#include"head.h"
#include"cifa.h"
#include"yufa2.h"//语法部分的实现,后续给出利用C++实现的代码
intmain()
{
intover=1;
WORD*oneword=newWORD;
printf("EnterYourwords(endwith#):
\n");
scanf("%[^#]s",input);
p_input=0;
do
{
p_token=0;
m_getch();
if(ch!
='#')
{
retract();
oneword=scaner();
if(oneword->typenum!
=1000)
{
if(oneword->typenum!
=10)printf("(%d,%s)",oneword->typenum,oneword->word);
elseprintf("(%d,'%s')",oneword->typenum,oneword->word);
}
}
}while(oneword->typenum!
=1000&&oneword->typenum!
=-1);
printf("\n\n");
p_input=0;
p_token=0;
yufayf(scaner(),0);
yf.lrparser();
return0;
}
********************************main.cpp****************************
1.4.2测试数据:
说明:
因为我的程序是直接把语法和词法一起调用了一下,所以出现了“语句错误”(无法识别if)。
2.语法分析
2.1实验目的
编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
2.2实验要求
利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
1.待分析的简单语言的语法
用扩充的BNF表示如下:
(1)<程序>:
:
=begin<语句串>end
(2)<语句串>:
:
=<语句>{;<语句>}
(3)<语句>:
:
=<赋值语句>
(4)<赋值语句>:
:
=ID:
=<表达式>
(5)<表达式>:
:
=<项>{+<项>|-<项>}
(6)<项>:
:
=<因子>{*<因子>|/<因子>}
(7)<因子>:
:
=ID|NUM|(<表达式>)
2.实验要求说明
输入单词串,以“#“结束,如果是文法正确的句子,则输出成功信息,打
印“success”,否则输出“error”。
例如:
输入begina:
=9;x:
=2*3;b:
=a+xend#
输出success
输入x:
=a+b*cend#
输出error
2.3语法分析程序的算法思想
(1)主程序示意图如图2.1所示。
图2.1
(2)递归向下分析程序示意图如图2.2所示。
(3)语句串分析过程示意图如图2.3所示。
(4)statement语句分析函数流程如图2.4、图2.5、图2.6、图2.7所示。
图2.3递归下降分析程序示意图
图2.4语句串分析示意图
图2.5statement语句分析函数示意图
图2.6expression表达式分析函数示意图
图2.7term分析函数示意图
图2.8factor分析过程示意图
2.4语法分析程序的C++语言实现
2.4.1代码实现
*************************yufa2.h***********************************
classyufa
{
friendWORD*scaner();
private:
WORD*oneword;
intkk;
public:
yufa(WORD*x,intk)
{
oneword=x;
kk=k;
}
voidexpression();
voidfactor();
voidterm();
voidstatement();
voidyucu();
voidlrparser();
};
voidyufa:
:
factor()
{
if(oneword->typenum==10||oneword->typenum==11)oneword=scaner();
elseif(oneword->typenum==27)
{
oneword=scaner();
expression();
if(oneword->typenum==28)oneword=scaner();
else
{
printf("')'错误\n");
kk=1;
}
}
else
{
printf("表达式错误\n");
kk=1;
}
return;
}
voidyufa:
:
term()
{
factor();
while(oneword->typenum==15||oneword->typenum==16)
{
oneword=scaner();
factor();
}
return;
}
voidyufa:
:
expression()
{
term();
while(oneword->typenum==13||oneword->typenum==14)
{
oneword=scaner();
term();
}
return;
}
voidyufa:
:
statement()
{
if(oneword->typenum==10)
{
oneword=scaner();
if(oneword->typenum==18)
{
oneword=scaner();
expression();
}
else
{
printf("赋值号错误\n");
kk=1;
}
}
else
{
printf("语句错误\n");
kk=1;
}
return;
}
voidyufa:
:
yucu()
{
statement();
while(oneword->typenum==26)
{
oneword=scaner();
statement();
}
return;
}
voidyufa:
:
lrparser()
{
if(oneword->typenum==1)
{
oneword=scaner();
yucu();
if(oneword->typenum==6)
{
oneword=scaner();
if(oneword->typenum==1000&&kk==0)
{
printf("success\n");
}
}
else
{
if(kk!
=1)printf("缺end\n");
kk=1;
}
}
else
{
printf("begin错误\n");
kk=1;
}
return;
}
*********************************yufa2.h******************************
2.4.2实例检测
说明:
程序所识别的赋值号应该为:
=而不是=所以报错
说明:
end前面不能有分号,所以报错。
说明:
语法正确。
3.实验心得
通过本次实验,我亲自动手实现了词法语法分析程序的设计,通过这次设计也使我对语法词法分析有了更加深刻的理解。
总体来说,这两个小实验都还是比较简单的,基本上书上都有相应的流程图和大体的程序框架,只要了解了其基本的思想,写出来不算太难。
在整个实验实现的过程中,我在语法分析程序上吃了一点小亏。
因为一开始是直接看了书上的流程图,感觉没什么问题就按照书上的框架写了一份代码,然后考虑到流程图中都会有对数据的操作,于是便自己在每个函数里面都加了一个参数,结果硬是把自己给绕了进去,怎么调都不正确。
后来仔细的又把流程一步步走了一遍,发现其实这几个函数中使用的数据并没有什么太大的相关性,每一个函数调用scaner的时候都可以直接用全局变量的形式来进行更改。
想通了之后,为了便于变量的管理,我就把这几个函数加上一个变量用C++写成了一个类的形式进行了封装,这样程序看起来结构更清晰一些,也实现了相应的功能。
本次实验让我学会了递归向下的词法分析过和,同时也让我学会了写程序要多动脑,先把问题想明白了再来写代码,不然的话,错误可就不是一般的多了