编译原理完整解析.docx
《编译原理完整解析.docx》由会员分享,可在线阅读,更多相关《编译原理完整解析.docx(37页珍藏版)》请在冰点文库上搜索。
编译原理完整解析
天津大学仁爱学院
编译原理
实验报告
计算机科学与技术系
学生姓名:
王玲玲
指导教师:
孙林娟
班级:
计科四班
实验日期:
2015年12月22日
实验名称:
词法分析器的实现过程
一、实验名称
模拟词法分析器的转化过程
二、实验目的
1、学习各个词法分析器的装换过程
2、掌握状态转换图的画法
3、合并各个状态转换图,使之合并成完整的状态转换图。
4、根据状态装换图,用代码实现词法分析器的编译过程
设计、编制、调制一个词法分析子程序-识别单词,加深对词法分析原理的理解。
三、实验工具
VC++6.0
四、实验描述
对不同的关键字,表示符,无符号整常数,运算符或分解符进行区分。
1、用状态装画图,表示每一项固定符号
2、合并所有的状态转换,完成完整的状态装换图
3、通过状态转换图,写出相应的代码
4、测试代码正确性
程序实现的是一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字,标识符,常数,运算符,分隔符五大类,并依次输出各个单词的内部编码及单词符号自身值。
五、设计思想
设计词法分析器的过程中,虽然没有实际将所有的状态转换图建立,但是所用的思想是根据状态转换表实现对单词的识别,首先构造一个保留字表,然后,没输入一个字符就检测应该进入什么状态。
根据不同的装换识别单词。
六、实验过程
实验1:
1、C语言子集
(1)关键字:
beginifthenwhiledoend所有关键字都是小写。
(2)运算符和界符:
:
=+–*/<<=<>>>==;()#
(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:
ID=letter(letter|digit)*
NUM=digitdigit*
(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。
2、各种单词符号对应的种别码
单词符号
种别码
单词符号
种别码
begin
1
:
17
if
2
:
=
18
then
3
>
20
while
4
<>
21
do
5
<=
22
end
6
<
23
letter(letter|digit)*
10
>=
24
digitdigit*
11
=
25
*
13
;
26
/
14
(
27
+
15
)
28
-
16
#
0
单词符号种别码单词符号种别码
begin1:
17
if2:
=18
then3>20
while4<>21
do5<=22
end6<23
letter(letter|digit)*10>=24
digitdigit*11=25
*13;26
/14(27
+15)28
-16#0
3、词法分析程序的功能
输入:
所给文法的源程序字符串。
输出:
二元组(syn,token或sum)构成的序列。
其中:
syn为单词种别码;
token为存放的单词自身字符串;
sum为整型常数。
4、状态装换图
5、实验方法、步骤(或:
程序代码或操作过程)
(1)程序代码
#include
#include
#include
charprog[80],token[8];
charch;
intsyn,p,m=0,n,row,sum=0;
char*rwtab[6]={"begin","if","then","while","do","end"};
voidscaner()
{
for(n=0;n<8;n++)token[n]=NULL;
ch=prog[p++];
while(ch=='')
{
ch=prog[p];
p++;
}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
m=0;
while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
token[m++]=ch;
ch=prog[p++];
}
token[m++]='\0';
p--;
syn=10;
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
elseif((ch>='0'&&ch<='9'))
{
{
sum=0;
while((ch>='0'&&ch<='9'))
{
sum=sum*10+ch-'0';
ch=prog[p++];
}
}
p--;
syn=11;
if(sum>32767)
syn=-1;
}
elseswitch(ch)
{
case'<':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='>')
{
syn=21;
token[m++]=ch;
}
elseif(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=23;
p--;
}
break;
case'>':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=24;
token[m++]=ch;
}
else
{
syn=20;
p--;
}
break;
case':
':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=18;
token[m++]=ch;
}
else
{
syn=17;
p--;
}
break;
case'*':
syn=13;token[0]=ch;break;
case'/':
syn=14;token[0]=ch;break;
case'+':
syn=15;token[0]=ch;break;
case'-':
syn=16;token[0]=ch;break;
case'=':
syn=25;token[0]=ch;break;
case';':
syn=26;token[0]=ch;break;
case'(':
syn=27;token[0]=ch;break;
case')':
syn=28;token[0]=ch;break;
case'#':
syn=0;token[0]=ch;break;
case'\n':
syn=-2;break;
default:
syn=-1;break;
}
}
voidmain()
{p=0;
row=1;
cout<<"Pleaseinputstring:
"<do
{cin.get(ch);
prog[p++]=ch;
}
while(ch!
='#');
p=0;
do
{
scaner();
switch(syn)
{
case11:
cout<<"("<case-1:
cout<<"Errorinrow"<"<case-2:
row=row++;break;
default:
cout<<"("<}
}
while(syn!
=0);
}
(2)创建编辑程序
(3)连接、编译和调试程序
(4)运行程序
(5)测试
给定源程序
beginx:
=8;ifx>0thenx:
=2*x+1/5;end#
输出结果
实验2:
1、C语言子集
(1)关键字:
Intforif所有关键字都是小写。
(2)运算符和界符:
+=+=++*{}#
(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:
ID=letter(letter|digit)*
NUM=digitdigit*
(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。
2、各种单词符号对应的种别码
单词符号种别码单词符号种别码
Int1*9
if2=10
For3{11
+6}12
++7#13
+=8
letter(letter|digit)*4
digitdigit*5
3、词法分析程序的功能
输入:
所给文法的源程序字符串。
输出:
二元组(syn,token或sum)构成的序列。
其中:
syn为单词种别码;
token为存放的单词自身字符串;
sum为整型常数。
4、状态装换图
5、实验方法、步骤(或:
程序代码或操作过程)
(1)程序代码
#include
#include
#include
charprog[80],token[8];//token给8个存储空间
charch;//一个单词
intsyn,p,m=0,n,row,sum=0;//syn:
单词类别,token:
对相应row:
行数,sum:
存放常数
char*rwtab[10]={"int","if","for"};//定义关键字
voidscaner()
{
for(n=0;n<8;n++)token[n]=NULL;
ch=prog[p++];//将一个单词给了ch
while(ch=='')
{
ch=prog[p];//ch为空格的话,
p++;
}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
m=0;
while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
token[m++]=ch;
ch=prog[p++];
}
token[m++]='\0';
p--;
syn=5;
for(n=0;n<3;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
elseif((ch>='0'&&ch<='9'))
{
{
sum=0;
while((ch>='0'&&ch<='9'))
{
sum=sum*10+ch-'0';
ch=prog[p++];
}
}
p--;
syn=4;
if(sum>32767)
syn=-1;
}
elseswitch(ch)
{
case'+':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='+')
{
syn=7;
token[m++]=ch;
}
elseif(ch=='=')
{
syn=8;
token[m++]=ch;
}
else
{
syn=6;
}
break;
case'*':
syn=9;token[0]=ch;break;
case'=':
syn=10;token[0]=ch;break;
case'{':
syn=11;token[0]=ch;break;
case'}':
syn=12;token[0]=ch;break;
case'#':
syn=0;token[0]=ch;break;
case'\n':
syn=-2;break;
default:
syn=-1;break;
}
}
voidmain()
{
p=0;
row=1;
cout<<"Pleaseinputstring:
"<do
{
cin.get(ch);
prog[p++]=ch;
}
while(ch!
='#');
p=0;
do
{
scaner();
switch(syn)
{
case3:
cout<<"("<case-1:
cout<<"Errorinrow"<"<case-2:
row=row++;break;
default:
cout<<"("<}
}
while(syn!
=0);
}
(2)创建编辑程序
(3)连接、编译和调试程序
(4)运行程序
(5) 测试
For444{xxx+=y}x*y=z
输出结果
实验2:
1、C语言子集
(1)关键字:
Voidcharintfloatdoubleshortlongsignedunsignedstruct所有关键字都是小写。
(2)运算符和界符:
++++=----=//=**=%%====><>=>><=<<&&&|||!
!
=()[]{};,#
(3)其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:
ID=letter(letter|digit)*
NUM=digitdigit*
(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。
2、各种单词符号对应的种别码
单词符号种别码单词符号种别码
Void1==25
Char2>26
int3<27
float4>=28
double5>>29
Short6<30
Long7<=31
Signed8<<32
Unsigned9&33
Struct10&&34
+13|35
++14||36
+=15!
37
-16!
=38
--17(39
-=18)40
/19[41
/=20]42
*21{43
*=22}44
%=23;45
=24#46
letter(letter|digit)*11
digitdigit*5
3、词法分析程序的功能
输入:
所给文法的源程序字符串。
输出:
二元组(syn,token或sum)构成的序列。
其中:
syn为单词种别码;
token为存放的单词自身字符串;
sum为整型常数。
4、状态装换图
5、实验方法、步骤(或:
程序代码或操作过程)
(1)程序代码
#include
#include
#include
charprog[80],token[8];
charch;
intsyn,p,m=0,n,row,sum=0;
char*rwtab[10]={"void","char","int","float","double","short","long","signed","unsigned","struct"};
voidscaner()
{
for(n=0;n<8;n++)token[n]=NULL;
ch=prog[p++];
while(ch=='')
{
ch=prog[p];
p++;
}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
{
m=0;
while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch=='_'))
{
token[m++]=ch;
ch=prog[p++];
}
token[m++]='\0';
p--;
syn=12;
for(n=0;n<10;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
elseif((ch>='0'&&ch<='9'))
{
{
sum=0;
while((ch>='0'&&ch<='9'))
{
sum=sum*10+ch-'0';
ch=prog[p++];
}
}
p--;
syn=11;
if(sum>32767)
syn=-1;
}
elseswitch(ch)
{
case'+':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='+')
{
syn=14;
token[m++]=ch;
}
elseif(ch=='=')
{
syn=15;
token[m++]=ch;
}
else
{
syn=13;
p--;
}
break;
case'-':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='-')
{
syn=17;
token[m++]=ch;
}
elseif(ch=='=')
{
syn=18;
token[m++]=ch;
}
else
{
syn=16;
p--;
}
break;
case'/':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=20;
token[m++]=ch;
}
else
{
syn=19;
p--;
}
break;
case'*':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=21;
p--;
}
break;
case'%':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=24;
token[m++]=ch;
}
else
{
syn=23;
p--;
}
break;
case'=':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=26;
token[m++]=ch;
}
else
{
syn=25;
p--;
}
break;
case'>':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=28;
token[m++]=ch;
}
elseif(ch=='>')
{
syn=29;
token[m++]=ch;
}
else
{
syn=27;
p--;
}
break;
case'<':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=31;
token[m++]=ch;
}
elseif(ch=='<')
{
syn=32;
token[m++]=ch;
}
else
{
syn=30;
p--;
}
break;
case'&':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='&')
{
syn=34;
token[m++]=ch;
}
else
{
syn=33;
p--;
}
break;
case'|':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='|')
{
syn=36;
token[m++]=ch;
}
else
{
syn=35;
p--;
}
break;
case'!
':
m=0;token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=38;
token[m++]=ch;
}
else
{
syn=37;
p--;
}
break;
case'(':
syn=39;token[0]=ch;break;
case')':
syn=40;token[0]=ch;break;
case'[':
syn=41;token[0]=ch;break;
case']':
syn=42;token[0]=ch;break;
case'{':
syn=43;token[0]=ch;
|
|