河工大版编译原理实验报告文档格式.docx
《河工大版编译原理实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《河工大版编译原理实验报告文档格式.docx(26页珍藏版)》请在冰豆网上搜索。
then
4
THEN
else
5
ELSE
标识符
6
ID
字母打头的字母数字串
无符号常数
7
UCON
机内二进制表示
<
8
LT
=
9
LE
10
EQ
>
11
NE
12
GT
13
GE
:
14
IS
+
15
PL
-
16
MI
*
17
MU
18
DI
表I语言中的各类单词符号及其分类码表
图I识别表I所列语言中的部分单词的DFA及相关的语义过程
图I中所出现的语义变量及语义函数的含义和功能说明如下:
Ø
函数GETCHAR:
每调用一次,就把扫描指示器当前所指示的源程序字符送入字符变量ch,然后把扫描指示器前推一个字符位置。
字符数组TOKEN:
用来依次存放一个单词词文中的各个字符。
函数CAT:
每调用一次,就把当前ch中的字符拼接于TOKEN中所存字符串的右边。
函数LOOKUP:
每调用一次,就以TOKEN中的字符串查保留字表,若查到,就将相应关键字的类别码赋给整型变量c;
否则将c置为零。
函数RETRACT:
每调用一次,就把扫描指示器回退一个字符位置(即退回多读的那个字符)。
函数OUT:
一般仅在进入终态时调用此函数,调用的形式为OUT(c,VAL)。
其中,实参c为相应单词的类别码或其助记符;
实参VAL为TOKEN(即词文)或为空串。
函数OUT的功能是,在送出一个单词的内部表示之后,返回到调用该词法分析程序的那个程序。
需要将程序一中的整常数扩展为无符号常数,以满足题目的要求。
描述无符号数的右线性文法G1[<
无符号数>
]如下:
〈无符号数〉→d〈余留无符号数〉
〈无符号数〉→·
〈小数部分〉
〈无符号数〉→d
〈余留无符号数〉→d〈余留无符号数〉
〈余留无符号数〉→·
〈十进小数〉
〈余留无符号数〉→E〈指数部分〉
〈余留无符号数〉→d
〈十进小数〉→E〈指数部分〉
〈十进小数〉→d〈十进小数〉
〈十进小数〉→d
〈小数部分〉→d〈十进小数〉
〈小数部分〉→d
〈指数部分〉→d〈余留整指数〉
〈指数部分〉→+〈整指数〉
〈指数部分〉→-〈整指数〉
〈指数部分〉→d
〈整指数〉→d〈余留整指数〉
〈整指数〉→d
〈余留整指数〉→d〈余留整指数〉
〈余留整指数〉→d
图II所示为上述文法的状态转换图,其中编号0、1、2、…、6分别代表非终结符号<
、<
余留无符号数>
十进小数>
小数部分>
指数部分>
整指数>
及<
余留整指数>
。
图II文法G1[<
]的状态转换图
表II包含语义处理过程的识别无符号数的状态矩阵
#include<
stdlib.true;
各种数
{
TOKEN[0]=ch;
ch=fgetc(fp);
i=1;
while(isdigit(ch)||ch=='
.'
||ch=='
E'
||ch=='
e'
)e的指数小数
if(ch=='
){checkdot=1;
}
elseif(ch=='
checke=1;
TOKEN[i]=ch;
i++;
if(ch=='
+'
){TOKEN[i]=ch;
continue;
}
else
{TOKEN[i]=ch;
*if(ch=='
-'
)TOKEN[i]=ch;
}*
TOKEN[i]='
\0'
;
fseek(fp,-1,1);
if(checkdot==1)
out(UCON,TOKEN);
elseif(checke==1)
二进制数
out(INT,TOKEN);
整型
else
switch(ch)输出
{
case'
'
ch=fgetc(fp);
if(ch=='
='
)out(LE,"
"
);
elseif(ch=='
)out(NE,"
else
{
fseek(fp,-1,1);
TOKEN[i]=ch;
out(LT,"
}
break;
out(EQ,"
break;
case'
)out(IS,"
report_error();
)out(GE,"
out(GT,"
out(PL,"
break;
out(MI,"
*'
out(MU,"
out(DI,"
\n'
fseek(fp,-1,1);
report_enter();
\r'
:
out(ENT,"
\n"
'
\t'
default:
report_error();
}
ch=fgetc(fp);
t=fgetc(fp);
fseek(fp,-1,1);
}
return;
char*KeyWordTable[MAX_KEY_NUMBER]={"
begin"
"
end"
if"
then"
else"
KEY_WORD_END};
关键字
intlookup(char*token)
{
intn=0;
while(strcmp(KeyWordTable[n],KEY_WORD_END))*strcmp比较两串是否相同,若相同返回0*
if(!
strcmp(KeyWordTable[n],token))*比较token所指向的关键字和保留字表中哪个关键字相符*
returnn+1;
*根据单词分类码表I,设置正确的关键字类别码,并返回此类别码的值*
break;
n++;
return0;
*单词不是关键字,而是标识符*
voidreport_error(){
printf("
error"
voidout(intc,char*v){
char*cl="
"
switch(c)
case1:
cl="
BEGIN"
case2:
END"
case3:
IF"
case4:
THEN"
case5:
ELSE"
case6:
ID"
case7:
INT"
case8:
LT"
case9:
LE"
case10:
EQ"
case11:
NE"
case12:
GT"
case13:
GE"
case14:
IS"
case15:
PL"
case16:
MI"
case17:
MU"
case18:
DI"
case19:
UCON"
(%s,%s)\n"
cl,v);
输出
intmain(void)
char*fname="
file.txt"
FILE*fp;
if((fp=fopen(fname,"
r"
))==NULL)
Error!
--Can'
topenfile."
getchar();
exit
(1);
else{
scanner_example(fp);
fclose(fp);
return1;
建立一个名为file.txt的文件,键入“ifmyid>
=1.5E-2+100thenx:
=y”并保存,运行得到如下结果:
结果:
自我评鉴
词法分析的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
通过本试验的完成,更加加深了对词法分析原理的理解。
在实验过程中开始不能实现指数部分的识别,但在老师的悉心指导下我经过更改可以成功识别了指数。
由于我的编程功底并不是很好,并不能很好的实现要求中的所有功能,但我已经尽力去使自己的程序符合题目要求。
实验二语法分析程序实现
通过设计、编制、调试一个典型的语法分析程序(任选一种有代表性的语法分析方法,如算符优先法、递归下降法、LL
(1)、SLR
(1)、LR
(1)等,作为编制语法分析程序的依据),对扫描器所提供的单词序列进行语法检查和结构分析,实现并进一步掌握常用的语法分析方法。
实验内容
选择对各种常见高级程序设计语言都较为通用的语法结构作为分析对象,给出其文法描述(注意应与所采用的语法分析方法比较贴近),设计并实现一个完整的语法分析程序(分析过程可暂不嵌入任何语义动作)。
对算术表达式的一个简化子集,根据如下其语法结构的BNF定义G2[<
算术表达式>
],任选学过的一种语法分析方法,针对运算对象为无符号数(和变量)的四则运算,编制一个语法分析程序。
G2[<
]:
→<
项>
|<
+<
-<
因式>
*<
运算对象>
|(<
若将语法范畴<
和<
分别用E、T、F和i代表,则G2可写成:
E→T|E+T|E-TT→F|T*F|TFF→i|(E)
基本思路
对以下文法进行语法分析:
E->
E+T|T
T->
T*F|F
F->
(E)|i
实验采用文法:
前后文无关文法
SLR
(1)分析表:
产生式编号:
0E’->
E1E->
E+T2E->
E-T3E->
T4T->
T*F5T->
TF6T->
F
7F->
(E)8F->
i
基本项目:
E’->
E
项目集:
I0:
·
EE->
E+TE->
E-TE->
TT->
T*FT->
TFT->
FF->
(E)F->
I1:
GOTO(I0,E)
E·
E->
+TE->
-T
I2:
GOTO(I0,T)
T·
T->
*FT->
F
I3:
GOTO(I0,F)T->
F·
I4:
GOTO(I0,()
(·
E)E->
I5:
GOTO(I0,i)F->
i·
I6:
GOTO(I1,+)
E+·
I7:
GOTO(I1,-)
E-·
I8:
GOTO(I2,*)
T*·
I9:
GOTO(I2,)
I10:
GOTO(I4,E)
(E·
)E->
I11:
GOTO(I6,T)
E+T·
I12:
GOTO(I7,T)
E-T·
I13:
GOTO(I8,F)T->
T*F·
I14:
GOTO(I9,F)T->
TF·
I15:
GOTO(I10,))
(E)·
实验设计流程:
程序代码
stdio.(void);
voidPrint(int,char*);
voidCheckExperience(int*);
ReadIn();
voidGetChars(char*str)
inti=0,num[10]={};
intresult=0;
intj=0;
charretstr[strlen(str)];
memset(retstr,0,strlen(str));
do{
for(i=j;
i<
strlen(str);
i++)
if(str[j]=='
elseif(isalpha(str[j]))对字母开头的标识符和关键字的检测
charnewstr[strlen(str)];
memset(newstr,0,strlen(str));
ints=0;
for(intt=j;
t<
50;
t++)
if((!
isalnum(str[t]))&
&
(!
isalpha(str[t])&
(str[t]!
)))如果出现了不是数字和字母的字符,记录位置作为下个字符串的开始,跳出
j=t;
elseif((str[t]=='
))
j=t+1;
newstr[s]=str[t];
s++;
newstr[s++]='
result=CheckKeyword(newstr);
strcpy(retstr,newstr);
elseif(str[j]=='
j++;
elseif(isalnum(str[j]))首字母是数字
doublenum;
intcheck=0;
charstr1[50],str2[50];
ints=0,r=0;
if(str[t]=='
check=1;
if(check==1)
if((str[t]=='
j=t+2;
str1[s]=str[t];
str1[s++]='
charrem=str[j-1];
if(!
(isalnum(str[t])))
str2[r]=str[t];
r++;
str2[r++]='
doublenum1=atof(str1);
floatnum2=atof(str2);
if(rem=='
num=num1*pow(10,num2);
num=num1pow(10,num2);
((isalnum(str[t]))||(str[t]=='
)||(str[t]=='
))||(str[t]=='
num=atof(newstr);
charstr[20];
sprintf(str,"
%g"
num);
strcpy(retstr,str);
result=7;
if(str[j+1]=='
result=9;
j=j+2;
elseif(str[j+1]=='
result=11;
result=8;
result=10;
j=j+1;
if((isalnum(str[j+1]))||isalpha(str[j+1]))
result=12;
result=13;
elseif((str[j]=='
)&
(str[j+1]=='
result=14;
result=15;
result=16;
result=17;
result=18;
result=0;
%d"
result);
Print(result,retstr);
num[i]=result;
}while(j<
strlen(str));
*for(intt=0;
10;
%d"
num[t]);
CheckExperience(num);
intCheckKeyword(char*string)
intre=0;
if(strcmp(string,"
)==0)
re=1;
elseif(strcmp(string,"
re=2;
re=3;
re=4;
re=5;
re=6;
returnre;
voidReadIn(void)
FILE*stream;
stream=fopen("
"
charstr[40];
while(fgets(str,40,stream)!
=NULL){
intl=strlen(str);
str[l-1]='
GetChars(str);
voidPrint(inta,char*str)printouttheresult
switch(a)
case0:
printf("
(BEGIN,NULL)\n"
br