编译原理实验报告Word格式文档下载.doc
《编译原理实验报告Word格式文档下载.doc》由会员分享,可在线阅读,更多相关《编译原理实验报告Word格式文档下载.doc(15页珍藏版)》请在冰点文库上搜索。
输出符号表;
输出常数表;
有限自动机的状态转换图:
e
ddd
+|--1/+/-
11
+①d②.③d④e⑤⑥d⑦
d-
-1/+/-
l/d-1/+/-
12
-1
l⑧-
13
-1
b⑨b⑩-
14
-1
-
15
-1
-
其中:
d为数字,l为字母,b为界符,-1代表其它符号(如在状态8处遇到了非字母或数字的其它符号,会变换到状态12)。
关键字表和界符表:
Program
;
Begin
:
End
(
Var
)
While
Do
=
Repeat
+
Until
-
For
*
To
/
If
>
Then
Else
==
<
四、主要数据结构
①状态转换矩阵:
intaut[10][7]={2,0,0,0,8,9,15,
2,3,5,11,0,0,11,
4,0,0,0,0,0,0,
4,0,5,11,0,0,11,
7,0,0,6,0,0,0,
7,0,0,0,0,0,0,
7,0,0,11,0,0,11,
8,0,0,0,8,0,12,
0,0,0,0,0,10,14,
0,0,0,0,0,0,13};
②关键字表:
charkeywords[30][12]={“program”,”begin”,”end”,”var”,”while”,”do”,
”repeat”,”until”,”for”,”to”,”if”,”then”,”else”,“;
”,”:
”,”(“,”)”,”,”,”:
=”,”+”,”-“,”*”,”/”,
”>
”,”>
=”,”==”,“<
”,“<
=”};
③符号表:
charID[50][12];
//表中存有源程序中的标识符
④常数表:
floatC[20];
⑤其它变量:
structtoken
{intcode;
intvalue};
//Token结构
structtokentok[100];
//Token数组
ints;
//当前状态
intn,p,m,e,t;
//尾数值,指数值,小数位数,指数符号,类型
floatnum;
//常数值
charw[50];
//源程序缓冲区
inti;
//源程序指针,当前字符为w[i]
charstrTOKEN[12];
//当前已经识别出的单词
五、实验核心代码
intmain(intargc,char*argv[])
FILE*fp;
ints;
//当前状态*有限自动机中的状态
fp=fopen("
exa.txt"
"
r"
);
while(!
feof(fp))
{
fgets(w,50,fp);
i=0;
//*处理一行
do
{
printf("
%c"
w[i]);
//测试显示每个token的首字母
//*处理一个token
while(w[i]=='
'
)//滤空格
i++;
if(w[i]>
='
a'
&
w[i]<
z'
)//判定单词类别*是字母(关键字或标识符)
{
ptr=col2;
num_map=2;
}
elseif(w[i]>
0'
9'
)//*是数字(常量的开头)
ptr=col1;
num_map=4;
elseif(strchr(col3[0].str,w[i])==NULL)//*其他字符算为非法字符
printf("
非法字符%c\n"
continue;
else//界符
ptr=col3;
num_map=1;
i--;
//*向后退一个字符
s=1;
//开始处理一个单词
while(s!
=0)
act(s);
if(s>
=14)//*判断是否是终止状态*是终止状态,则形成一个token
break;
//getchar()*读取下一个字符
s=find(s,w[i]);
//状态转换
if(s==0)
strTOKEN[i_str]='
\0'
;
词法错误:
%s\n"
strTOKEN);
}while(w[i]!
=10);
}
printf("
关键字表:
"
//输出结果
for(i=0;
i<
30;
i++)
printf("
%s"
keywords[i]);
printf("
\n"
Token序列:
num_token;
(%d,%d)"
tok[i].code,tok[i].value);
符号表:
num_ID;
ID[i]);
常数表:
num_C;
%d"
C[i]);
fclose(fp);
HelloWorld!
return0;
//*状态转换后,达到新的状态之后,记录的变化
voidact(ints)
intcode;
switch(s)
case1:
n=0;
m=0;
p=0;
t=0;
e=1;
num=0;
i_str=0;
strTOKEN[i_str]='
//其它变量初始化
break;
case2:
n=10*n+w[i]-48;
break;
case3:
t=1;
case4:
m++;
case5:
case6:
if(w[i]=='
-'
)e=-1;
case7:
p=10*p+w[i]-48;
case8:
strTOKEN[i_str++]=w[i];
//将ch中的符号拼接到strTOKEN的尾部;
break;
case9:
case10:
//将ch中的符号拼接到strTOKEN的尾部;
case11:
num=n*pow(10,e*p-m);
//计算常数值
tok[i_token].code=2;
tok[i_token++].value=InsertConst(num);
//生成常数Token
num_token++;
break;
case12:
strTOKEN[i_str]='
code=Reserve(strTOKEN);
//查关键字表
if(code)
{tok[i_token].code=code;
tok[i_token++].value=0;
}//生成关键字Token
else
{tok[i_token].code=1;
tok[i_token++].value=InsertID(strTOKEN);
}//生成标识符Token
num_token++;
case13:
//查界符表
{tok[i_token].code=code;
}//生成界符Token
else
strTOKEN[strlen(strTOKEN)-1]='
//单界符
i--;
code=Reserve(strTOKEN);
//查界符表
tok[i_token].code=code;
//生成界符Token
num_token++;
case14:
code=Reserve(strTOKEN);
//查界符表
tok[i_token].code=code;
//生成界符Token
//*状态转换
intfind(ints,charch)
inti,col=7;
structmap*p;
p=ptr;
num_map;
if(strchr((p+i)->
str,ch))
col=(p+i)->
col;
}
returnaut[s][col];
//*向常量表中插入常量
intInsertConst(doublenum)
inti;
if(num==C[i])
returni;
C[i]=(int)num;
num_C++;
returni;
intReserve(char*str)
num_key;
if(!
strcmp(keywords[i],str))
return(i+3);
//*向符号表中插入新的符号
intInsertID(char*str)
for(i=0;
strcmp(ID[i],str))//*符号已经存在,则返回地址
strcpy(ID[i],str);
num_ID++;
六、实验结果
实验思考题:
1.扫描器的任务是什么?
答:
词法分析程序又称扫描器,任务有:
(1)识别单词
——从用户的源程序中把单词分离出来;
(2)翻译单词
——把单词转换成机内表示,便于后续处理。
2.扫描器、识别器、翻译器三者之间的关系是怎样的?
扫描器、识别器、翻译器三者之间的关系是:
扫描器的实现要通过识别器和翻译器
1.为什么说有限自动机是词法分析的基础?
因为词法分析的包括:
识别---识别单词的有限自动机。
和翻译---根据有限自动机所识别出的对象,完成从单词串到单词的TOKEN串的翻译。
我们可以看出,不论是识别还是分析,都是应用有限自动机,所以可以说有限自动机是词法分析的基础。
实验2:
中间代码生成器的设计
熟悉算术表达式的语法分析与中间代码生成原理。
(1)设计语法制导翻译生成表达式的四元式的算法;
(2)编写代码并上机调试运行通过。
输入——算术表达式
输出——语法分析结果
相应的四元式序列
(3)本实验已给出递归子程序法的四元式属性翻译文法的设计,鼓励学生在此基础上进行创新,即设计LL
(1)分析法或LR(0)分析法的属性翻译文法,并根据这些属性翻译文法,使用扩展的语法分析器实现语法制导翻译。
三、设计概要
(1)算术表达式文法
G(E):
Eà
Eω0T|T
Tà
Tω1F|F
Fà
i|(E)
(2)文法变换
G’(E)Eà
T{ω0T}
Tà
F{ω1F}
(3)属性翻译文法:
Eà
T{ω0“push(SYN,w)”T“QUAT”}
Tà
F{ω1“push(SYN,w)”F“QUAT”}
i“push(SEM,entry(w))”|(E)
push(SYN,w)—当前单词w入算符栈SYN;
·
push(SEM,entry(w))—当前w在符号表中的入口值压入语义栈SEM;
·
QUAT—生成四元式函数
i.T=newtemp;
ii.QT[j]=(SYN[k],SEM[s-1],SEM[s],T);
j++;
iii.pop(SYN,_);
pop(SEM,_);
push(SEM,T);
(4)递归下降子程序:
·
数据结构:
SYN—算符栈;
SEM—语义栈;
E:
入口T:
入口
TF
nω0?
nω1?
yy
出口push(SYN,w)出口push(SYN,w)
read(w)QUATread(w)QUAT
F:
入口主程序:
Zà
E
(?
ni?
nerr
read(w)read(w)
push(SEM,entry(w))E
E
errn#?
errn)?
y
y输出四元式序列
read(w)
结束
开始
出口
四、实验核心代码
voidmain()//主函数
{ t=1;
cout<
<
输入表达式,以#结束:
endl;
Z();
stringits(inta){ //整形变成字符串形函数
stringd;
charb='
c;
while(a!
=0){
i=a%10;
a=a/10;
c=(int)b+i;
d=c+d;
returnd;
charF(charw){ //F自动机
stringtheWord;
if(w>
w<
||w>
A'
Z'
){
theWord=w;
//当前字符是字母
markStack.push(theWord);
//则压栈
elseif(w=='
('
){ //是左括号
cin>
>
w;
//则读取下一字符
w=E(w);
if(w!
)'
){//不是右括号则输入有误,报错
cerr<