词法分析实验报告.docx
《词法分析实验报告.docx》由会员分享,可在线阅读,更多相关《词法分析实验报告.docx(16页珍藏版)》请在冰豆网上搜索。
词法分析实验报告
大连民族学院
计算机科学与工程学院实验报告
实验题目:
词法分析
课程名称:
编译原理
实验类型:
□演示性□验证性□操作性□设计性□综合性
专业:
计算机科学与技术班级:
104姓名:
张家琪学号:
2010081427
实验日期:
2012年11月10日实验地点:
多媒体实验室
实验学时:
实验成绩:
指导教师签字:
2012年11月10日
实验报告正文部分(具体要求详见实验报告格式要求)
一、总体设计思想
1实验目的
设计编制并调试一个词法分析程序,加深对构造词法分析器的原理和技术的理解与应用。
2实验要求
针对计算机高级程序语言——C语言子语言,运用恰当的词法分析技术线路,设计和实现C语言子语言的词法分析器。
Ø编程语言:
C语言/JAVA语言
Ø平台选择:
Linux/Windows
Ø技术线路(任选其一)
⏹正规式→NFA→DFA→minDFA→程序设计
⏹正规文法→NFA→DFA→minDFA→程序设计
Ø词法分析器程序输出形式,参见◤输出形式设计◢
Ø词法分析器程序输出结果存入到磁盘文件中*
Ø具有出错处理功能
(带*号的实验要求为附加实验要求,可选择实现)
3词法分析器构造原理
C语言子语言词法描述——涉及的单词类如下:
(1)关键字
mainifelsewhiledoforintvoidchar
(2)运算符和界符
=
+
-
*
/
<
<=
>
>=
!
=
==
;
(
)
:
#
{
}
注:
#为结束标志符,详见◤程序框架◢
(3)标识符
正规式:
ID=letter(letter|digit)*
(4)整型常数
正规式:
NUM=digit(digit)*
二、种别码表设计及其在计算机中的存放表示
(1)单词种别码设计
单词种别码对照表
单词符号
种别码
单词符号
种别码
main
1
/
16
if
2
:
17
else
3
=
18
while
4
}
19
do
5
<
20
for
6
!
=
21
int
7
<=
22
char
8
>
23
void
9
>=
24
标识符
10
==
25
整型常数
11
;
26
{
12
(
27
+
13
)
28
-
14
#
0
*
15
(2)输出形式设计
词法分析器的输入是源程序字符串,输出是对应的单词串。
每个单词按照二元组(种别码,单词符号本身)格式输出。
例如:
假设源程序为
main()
{
x=9;
y=4;
if(x>0)
x=2*x+1/3;
}#
则词法分析器对应输出的结果是:
(1,main)(27,()(28,))(12,{)(10,x)(18,=)(11,9)(26,;)(10,y)(18,=)
(11,4)(26,;)(2,if)(27,()(10,x)(23,>)(11,0)(10,x)(18,=)(11,2)
(15,*)(10,x)(13,+)(11,1)(16,/)(11,3)(26,;)(19,})(0,#)
三、词法分析程序详细设计
1)算法构造思想
依据建立的识别单词的DFA,设计算法,其框架如下。
其中,
1syn存放单词的种别码;
2token存放符合C语言子语言词法规则的单词;
3sum存放整型常量的单词。
实现技术细节注意的几个要点:
A)标识符和关键字,属于同一构词规则,识别方法是建立一个关键字表,在识别出标识符单词时,查关键字表,以确认或区别是否是关键字,还是标识符。
B)对前导空格符、制表符和换行符,均须过滤;C)约定标识符单词32位有效。
2)主要模块算法的框图描述
四、 主要代码
#include
#include
#include
charprog[80];//存放所有输入字符
chartoken[32];//②token存放符合C语言子语言词法规则的单词;
charch;//单个字符
intsyn,p,m,n;//①syn存放单词的种别码
doublesum;//③sum存放整型常量的单词。
intcount;
intisSignal;//是否带正负号(0不带,1负号,2正号)
intisDecimal;//是否是小数
doubledecimal;//小数
intisExp;//是否是指数
intindex;//指数幂
intisNegative;//是否带负号
doubletemp;
inttemp2;
intrepeat;
voidscanner();
char*rwtab[9]={"main","if","else","while","do","for","int","char","void"};
voidmain()
{
p=0;
count=0;
isDecimal=0;
index=0;
repeat=0;
printf("\npleaseinputarangeofdata,withtheendof#:
\n");
do{
ch=getchar();
prog[p++]=ch;
}while(ch!
='#');/*#为结束标志符*/
p=0;
do{
scanner();//扫描,单词
switch(syn)
{
case11:
if(isDecimal==0)
{
//加了1个强制类型转换
printf("(%d,%d)",syn,(int)sum);
break;
}
elseif(isExp==1)
{
printf("(%d,%e)",syn,sum);
isExp=0;
isDecimal=0;
break;
}
elseif(isDecimal==1)
{
printf("(%d,%f)",syn,sum);
isDecimal=0;
break;
}
case-1:
printf("出错");
break;
default:
printf("(%d,%s)",syn,token);
}
}while(syn!
=0);
getchar();
}
voidscanner()
{
sum=0;
decimal=0;
m=0;
for(n=0;n<8;n++)
token[n]=NULL;
ch=prog[p++];//从prog中读出一个字符到ch中
while(ch=='')//跳过空字符(无效输入)
ch=prog[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=>token
ch=prog[p++];//读下一个字符
}
token[m++]='\0';
p--;//回退一格
syn=10;
//如果是"main","if","else","while","do","for","int","char","void"标识符中的一个
for(n=0;n<9;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
elseif((ch>='0')&&(ch<='9'))
{
IsNum:
if(isSignal==1)
{
//token[m++]='-';
}
while((ch>='0')&&(ch<='9'))
{
sum=sum*10+ch-'0';//ch中数字本身是当做字符存放的
ch=prog[p++];
}
if(ch=='.')
{
isDecimal=1;
ch=prog[p++];
count=0;//之前忘了清零,123.123+123.123#两个浮点数就无法识别
while((ch>='0')&&(ch<='9'))
{
//pow(x,y)计算x的y次幂
temp=(ch-'0')*pow(0.1,++count);
decimal=decimal+temp;
//AddToDec();
ch=prog[p++];
}
sum=sum+decimal;
}
if(ch=='e'||ch=='E')
{
isExp=1;
ch=prog[p++];
if(ch=='-')
{
isNegative=1;
ch=prog[p++];
}
while((ch>='0')&&(ch<='9'))
{
//指数
index=index*10+ch-'0';
ch=prog[p++];
}
//10的幂
//123e3代表123*10(3)
//sum=sum*pow(10,index);是错误的
if(isNegative)
sum=sum*pow(0.1,index);
else
sum=sum*pow(10,index);
}
if(isSignal==1)
{
sum=-sum;
isSignal=0;
}
p--;
syn=11;
}
elseswitch(ch)
{
case'<':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='!
')
{
syn=21;//<>对应21
token[m++]=ch;
}
elseif(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=20;
p--;
}
break;
case'>':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=24;
token[m++]=ch;
}
else
{
syn=23;
p--;
}
break;
case':
':
syn=17;
token[m++]=ch;
break;
case'+':
temp2=prog[p];
token[m++]=ch;
if((temp2>='0')&&(temp2<='9')&&(repeat==1))
{
isSignal=2;//isSignal正数
ch=prog[p++];
repeat=0;
gotoIsNum;
}
if(((temp2=='+')||(temp2=='-'))&&(repeat==0))//如果重复出现符号,才将后边的+,-视为正负号
{
repeat=1;
//ch=prog[p++];
}
syn=13;
break;
case'-':
temp2=prog[p];
token[m++]=ch;
if((temp2>='0')&&(temp2<='9')&&(repeat==1))
{
isSignal=1;
ch=prog[p++];//读“-”下一个字符
repeat=0;
gotoIsNum;//转到数字的识别
}
if(((temp2=='+')||(temp2=='-'))&&(repeat==0))//如果重复出现符号,才将后边的+,-视为正负号
{
repeat=1;//预言会重复
//ch=prog[p++];//读下一个字符
}
syn=14;
break;
case'*':
temp2=prog[p];
token[m++]=ch;
if(temp2=='+')
{
isSignal=2;
repeat=1;
}
elseif(temp2=='-')
{
isSignal=1;
repeat=1;
}
syn=15;
break;
case'/':
syn=16;
token[m++]=ch;
break;
case'=':
syn=18;
token[m++]=ch;
break;
case';':
syn=26;
token[m++]=ch;
break;
case'(':
temp2=prog[p];
token[m++]=ch;
if(temp2=='+')
{
isSignal=2;
repeat=1;
}
elseif(temp2=='-')
{
isSignal=1;
repeat=1;
}
syn=27;
break;
case'{':
temp2=prog[p];
token[m++]=ch;
if(temp2=='+')
{
isSignal=2;
repeat=1;
}
elseif(temp2=='-')
{
isSignal=1;
repeat=1;
}
syn=12;
break;
case'}':
temp2=prog[p];
token[m++]=ch;
if(temp2=='+')
{
isSignal=2;
repeat=1;
}
elseif(temp2=='-')
{
isSignal=1;
repeat=1;
}
syn=19;
break;
case')':
syn=28;
token[m++]=ch;
break;
case'#':
syn=0;
token[m++]=ch;
break;
default:
syn=-1;
}
}
五、设计体会与收获
通过这次试验我学会了如何设计编制并调试一个词法分析程序,加深对构造词法分析器的原理和技术的理解与应用。
也对编译原理有了更深的理解,又学会了一些小的c++的知识,程序需要不断调试才能有更好的收获,很开心又有了收获!