编译原理语法分析实验报告.docx
《编译原理语法分析实验报告.docx》由会员分享,可在线阅读,更多相关《编译原理语法分析实验报告.docx(37页珍藏版)》请在冰点文库上搜索。
编译原理语法分析实验报告
编译原理
实验报告-语法分析
班级:
XXX
学号:
XXX
姓名:
XXX
年月日
1、摘要:
用递归子程序法实现对pascal的子集程序设计语言的分析程序
2、实验目的:
通过完成语法分析程序,了解语法分析的过程和作用
3、任务概述
实验要求:
对源程序的内码流进行分析,如为文法定义的句子输出”是”否则输出”否”,根据需要处理说明语句填写写相应的符号表供以后代码生成时使用
4、实验依据的原理
递归子程序法是一种自顶向下的语法分析方法,它要求文法是LL
(1)文法。
通过对文法中每个非终结符编写一个递归过程,每个过程的功能是识别由该非终结符推出的串,当某非终结符的产生式有多个候选式时,程序能够按LL
(1)形式唯一地确定选择某个候选式进行推导,最终识别输入串是否与文法匹配。
递归子程序法的缺点是:
对文法要求高,必须满足LL
(1)文法,当然在某些语言中个别产生式的推导当不满足LL
(1)而满足LL
(2)时,也可以采用多向前扫描一个符号的办法;它的另一个缺点是由于递归调用多,所以速度慢占用空间多,尽管这样,它还是许多高级语言,例如PASCAL,C等编译系统常常采用的语法分析方法。
为适合递归子程序法,对实验一词法分析中的文法改写成无左递归和无左共因子的BNF如下:
<程序>→<程序首部><分程序>。
<程序首部>→PROGRAM标识符;
<分程序>→<常量说明部分><变量说明部分><过程说明部分><复合语句>
<常量说明部分>→CONST<常量定义><常量定义后缀>;|ε
<常量定义>→标识符=无符号整数
<常量定义后缀>→,<常量定义><常量定义后缀>|ε
<变量说明部分>→VAR<变量定义><变量定义后缀>|ε
<变量定义>→标识符<标识符后缀>:
<类型>;
<标识符后缀>→,标识符<标识符后缀>|ε
<变量定义后缀>→<变量定义><变量定义后缀>|ε
<类型>→INTEGER|LONG
<过程说明部分>→<过程首部><分程序>;<过程说明部分后缀>|ε
<过程首部>→PROCEDURE标识符<参数部分>;
<参数部分>→(标识符:
<类型>)|ε
<过程说明部分后缀>→<过程首部><分程序>;<过程说明部分后缀>|ε
<语句>→<赋值或调用语句>|<条件语句>|<当型循环语句>|<读语句>
|<写语句>|<复合语句>|ε
<赋值或调用语句>→标识符<后缀>
<后缀>→:
=<表达式>|(<表达式>)|ε
<条件语句>→IF<条件>THEN<语句>
<当型循环语句>→WHILE<条件>DO<语句>
<读语句>→READ(标识符<标识符后缀>)
<写语句>→WRITE(<表达式><表达式后缀>)
<表达式后缀>→,<表过式><表达式后缀>|ε
<复合语句>→BEGIN<语句><语句后缀>END
<语句后缀>→;<语句><语句后缀>|ε
<条件>→<表达式><关系运算符><表达式>|ODD<表达式>
<表达式>→+<项><项后缀>|-<项><项后缀>|<项><项后缀>
<项后缀>→<加型运算符><项><项后缀>|ε
<项>→<因子><因子后缀>
<因子后缀>→<乘型运算符><因子><因子后缀>|e
<因子>→标识符|无符号整数|(<表达式>)
<加型运算符>→+|-
<乘型运算型>→*|/
<关系运算符>→=|<>|<|<=|>|>=
5、程序设计思想
为每个非终结符设计一个识别的子程序,寻找该非终结符也就是调用相应的子程序。
由于单词在语法分析中作为一个整体,故在语法识别中仅使用其内码。
在这里将词法分析作为语法分析的一个子程序,当语法分析需要单词时,就调用相应的词法分析程序获得一个单词。
语法分析的作用是识别输入符号串是否是文法上定义的句子,即判断输入符号串是否是满足“程序”定义的要求。
也就是当语法识别程序从正常退出表示输入符号串是正确的“程序”;若从出错退出,则输入符号串不是正确的“程序”。
出错时,可以根据读字符的位置判断出错的位置。
表2-1为非终结符和函数名对照表。
表2-1非终符和函数名对照表
非终结符
函数名
非终结符
函数名
<程序>
program
<程序首部>
proghead
<分程序>
block
<常量说明部分>
consexpl
<常量定义>
consdefi
<变量说明部分>
varexl
<常量定义后缀>
conssuff
<变量定义>
vandefi
<变量定义后缀>
varsuff
<>过程说明部分>
procdefi
<类型>
typeil
<过程首部>
procedh
<过程说明部分后缀>
procsuff
<赋值或调用语句>
assipro
<语句>
sentence
<后缀>
suffix
<条件语句>
ifsent
<读语句>
read
<当型循环语句>
whilsent
<标识符后缀>
idsuff
<写语句>
write
<复合语句>
compsent
<表达式后缀>
exprsuff
<语句后缀>
sentsuff
<条件>
conditio
<项后缀>
termsuff
<表达式>
express
<项>
term
<因子后缀>
factsuff
<参数部分>
argument
<因子>
factor
<加型运算符>
addoper
<乘型运算符>
muloper
<关系运算符>
respoper
表2-2为词法分析中的内码单词对照表。
表2-2内部码对照表
内码
单词
内码
单词
内码
单词
内码
单词
1
PROGRAM
2
CONST
3
VAR
4
INTEGER
5
LONG
6
PROCEDURE
7
IF
8
THEN
9
WHILE
10
DO
11
READ
12
WRITE
13
BEGIN
14
END
15
ODD
16
+
17
-
18
*
19
/
20
=
21
<>
22
<
23
<=
24
>
25
>=
26
.
27
28
;
29
:
30
:
=
31
(
32
)
33
无符号整数
34
标识符
35
#
6、实验结果分析
样例1:
正确的pascal子集程序代码
PROGRAMtest;
CONSTb=3;
VARx:
INTEGER;y:
LONG;
PROCEDUREc(d:
INTEGER);
BEGIN
d(5);
x:
=d+4;
y:
=b*2+2;
END;
BEGIN
WHILEx<10DOx:
=x+b;
IFx>5THENx:
=2*x-b;
END.
运行结果1:
样例2:
错误的pascal子集程序代码
test;
CONSTb=3;
VARx:
INTEGER;y:
;
PROCEDUREc(d:
INTEGER);
BEGIN
d(5);
x:
=d+4;
y:
=b*2+;
END;
BEGIN
WHILEx<10DOx:
=x+b;
IFx>5x:
=2*x-b;
END
运行结果2:
7、总结
通过本次实验,我能够用递归子程序法设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,更加了解了语法分析的过程和作用。
附件:
LEX代码:
%{
#include
#include
#include
FILE*fp;
intline=1;
%}
delim[""\t]
whitespace{delim}+
backspace[\n]
program[pP][rR][oO][gG][rR][aA][mM]
const[cC][oO][nN][sS][tT]
var[vV][aA][rR]
integer[iI][nN][tT][eE][gG][eE][rR]
long[lL][oO][nN][gG]
procedure[pP][rR][oO][cC][eE][dD][uU][rR][eE]
if[iI][fF]
then[tT][hH][eE][nN]
while[wW][hH][iI][lL][eE]
do[dD][oO]
read[rR][eE][aA][dD]
write[wW][rR][iI][tT][eE]
begin[bB][eE][gG][iI][nN]
end[eE][nN][dD]
odd[oO][dD][dD]
add\+
minus-
multiply\*
div\/
equal=
m21<>
m22<
m23<=
m24>
m25>=
m27,
m26\.
m28;
m29:
m30:
=
m31\(
m32\)
constant([0-9])+
identfier[A-Za-z]([A-Za-z]|[0-9])*
%%
{program}{fprintf(fp,"%d%d\n",1,line);}
{const}{fprintf(fp,"%d%d\n",2,line);}
{var}{fprintf(fp,"%d%d\n",3,line);}
{integer}{fprintf(fp,"%d%d\n",4,line);}
{long}{fprintf(fp,"%d%d\n",5,line);}
{procedure}{fprintf(fp,"%d%d\n",6,line);}
{if}{fprintf(fp,"%d%d\n",7,line);}
{then}{fprintf(fp,"%d%d\n",8,line);}
{while}{fprintf(fp,"%d%d\n",9,line);}
{do}{fprintf(fp,"%d%d\n",10,line);}
{read}{fprintf(fp,"%d%d\n",11,line);}
{write}{fprintf(fp,"%d%d\n",12,line);}
{begin}{fprintf(fp,"%d%d\n",13,line);}
{end}{fprintf(fp,"%d%d\n",14,line);}
{odd}{fprintf(fp,"%d%d\n",15,line);}
{add}{fprintf(fp,"%d%d\n",16,line);}
{minus}{fprintf(fp,"%d%d\n",17,line);}
{multiply}{fprintf(fp,"%d%d\n",18,line);}
{div}{fprintf(fp,"%d%d\n",19,line);}
{equal}{fprintf(fp,"%d%d\n",20,line);}
{m21}{fprintf(fp,"%d%d\n",21,line);}
{m22}{fprintf(fp,"%d%d\n",22,line);}
{m23}{fprintf(fp,"%d%d\n",23,line);}
{m24}{fprintf(fp,"%d%d\n",24,line);}
{m25}{fprintf(fp,"%d%d\n",25,line);}
{m26}{fprintf(fp,"%d%d\n",26,line);}
{m27}{fprintf(fp,"%d%d\n",27,line);}
{m28}{fprintf(fp,"%d%d\n",28,line);}
{m29}{fprintf(fp,"%d%d\n",29,line);}
{m30}{fprintf(fp,"%d%d\n",30,line);}
{m31}{fprintf(fp,"%d%d\n",31,line);}
{m32}{fprintf(fp,"%d%d\n",32,line);}
{constant}{__int64maxnum=0xffffffff;
if(strlen(yytext)>10)
printf("line%dconstanterror:
'%s'\n",line,yytext);
else
fprintf(fp,"%d%d\n",33,line);}
{identfier}{if(strlen(yytext)>20){
printf("line%didentfiererror:
'%s'\n",line,yytext);
}
else
fprintf(fp,"%d%d\n",34,line);}
{whitespace}{}
{backspace}{if(strcmp(yytext,"\n")==0){line++;}}
%%
voidmain()
{
yyin=fopen("example.txt","r");
fp=fopen("data.txt","w");
fclose(fp);
fp=fopen("data.txt","a");
yylex();/*starttheanalysis*/
fclose(yyin);
fclose(fp);
}
intyywrap()
{
return1;
}
主程序代码:
#include
#include
#include
#include"lex.yy.c"
usingnamespacestd;
inttoken[2000][2]={NULL};
inth=0;
inti,j,p=0;
voidprogram();
voidblock();
voidconsdefi();
voidconssuff();
voidvarsuff();
voidtypeil();
voidprocsuff();
voidsentence();
voidifsent();
voidwhilsent();
voidwrite();
voidexprsuff();
voidconditio();
voidexpress();
voidfactsuff();
voidfactor();
voidmuloper();
voidproghead();
voidconsexpl();
voidvarexl();
voidvandefi();
voidprocdefi();
voidprocedh();
voidassipro();
voidsuffix();
voidread();
voididsuff();
voidcompsent();
voidsentsuff();
voidtermsuff();
voidterm();
voidargument();
voidaddoper();
voidrespoper();
voidprogram()
{
proghead();
block();
if(token[h][0]==26)
{
h++;
if(token[h][0]==0)
{
printf("语法分析完成\n");
}
}
else
{
p=1;printf("第%d行缺少.\n",token[h-1][1]);
}
return;
}
voidproghead()
{
if(token[h][0]==1)
{
h++;
if(token[h][0]==34)
{
h++;
if(token[h][0]==28)
{
h++;
}
else
{
p=1;printf("第%d行缺少;\n",token[h-1][1]);
}
}
else
{
p=1;printf("第%d行缺少标识符\n",token[h-1][1]);
}
}
else
{
p=1;printf("第%d行缺少PROGRAM\n",token[h][1]);
if(token[h][0]==34)
{
h++;
if(token[h][0]==28)
{
h++;
}
}
}
}
voidblock()
{
consexpl();
varexl();
procdefi();
compsent();
return;
}
voidconsexpl()
{
if(token[h][0]!
=6&&token[h][0]!
=3&&token[h][0]!
=13)
{
if(token[h][0]==2)
{
h++;
consdefi();
conssuff();
if(token[h][0]==28)
{
h++;
}
else
{
p=1;printf("第%d行缺少;\n",token[h-1][1]);
}
}
else
{
p=1;printf("第%d行缺少CONST\n",token[h][1]);
consdefi();
conssuff();
if(token[h][0]==28)
{
h++;
}
}
}
return;
}
voidconsdefi()
{
if(token[h][0]==34)
{
h++;
if(token[h][0]==20)
{
h++;
if(token[h][0]==33)
{
h++;
}
else
{
p=1;printf("第%d行缺少无符号整数\n",token[h-1][1]);
}
}
else
{
p=1;printf("第%d行缺少=\n",token[h-1][1]);
}
}
else
{
p=1;printf("第%d行缺少标识符\n",token[h-1][1]);
if(token[h][0]==20)
{
h++;
if(token[h][0]==33)
{
h++;
}
}
}
return;
}
voidconssuff()
{
if(token[h][0]!
=6&&token[h][0]!
=3&&token[h][0]!
=13)
{
if(token[h][0]==28)return;
if(token[h][0]==27)
{
h++;
consdefi();
conssuff();
}
else
{
p=1;printf("第%d行缺少,\n",token[h-1][1]);
consdefi();
conssuff();
}
}
return;
}
voidvarexl()
{
if(token[h][0]!
=6&&token[h][0]!
=13)
{
if(token[h][0]==3)
{
h++;
vandefi();
varsuff();
}
else
{
p=1;printf("第%d行缺少VAR\n",token[h][1]);
vandefi();
varsuff();
}
}
return;
}
voidvandefi()
{
if(token[h][0]==34)
{
h++;
idsuff();
if(token[h][0]==29)
{
h++;
typeil();
if(token[h][0]==28)
{
h++;
}
else
{
p=1;printf("第%d行缺少;\n",token[h-1][1]);
}
}
else
{
p=1;printf("第%d行缺少:
\n",token[h-1][1]);
}
}
else
{
p=1;printf("第%d行缺少标识符\n",token[h-1][1]);
idsuff();
if(token[h][0]==29)
{
h++;
typeil();
if(token[h][0]==28)
{
h++;
}
}
}
return;
}
voididsuff()
{
if(token[h][0]==4||token[h][0]==5)
{
return;
}
if(token[h][0]!
=32&&token[h][0]!
=29)
{
if(token[h][0]==27)
{
h++;
if(token[h][0]==34)
{
h++;
idsuff();
}
else
{
p=1;printf("第%d行缺少标识符\n",token[h-1][1]);
}
}
else
{
p=1;printf("第%d行缺少,\n",token[h-1][1]);
}
}
return;
}
voidvarsuff()
{
if(token[h][0]!
=6&&token[h][0]!
=13)
{
vandefi();
varsuff();
}
return;
}
voidtypeil()
{
if(token[h][0]==4||token[h][0]==5)
{
h++;
}
else
{
p=1;printf("第%d行缺少INTEGER或LONG\n",token