史天永221300220语法分析实验.docx
《史天永221300220语法分析实验.docx》由会员分享,可在线阅读,更多相关《史天永221300220语法分析实验.docx(15页珍藏版)》请在冰豆网上搜索。
史天永221300220语法分析实验
《编译系统设计实践》
实验项目一:
词法分析实验
学号:
221300220
姓名:
史天永
年级:
2014级
学院:
软件学院
专业:
软件工程
实验时间:
2016-2017学年第二学期
任课教师:
陈晖
1、实验所用Pascal语言文法如下:
:
:
=.
:
:
=
:
:
=const;|ε
:
:
==|,=
:
:
=var;|ε
:
:
=|,
:
:
=procedure;;|ε
:
:
=:
=
|call
|beginend
|ifthen
|whiledo
|ε
:
:
=|;
:
:
=odd|
:
:
==|<>|<|>|<=|>=
:
:
=||
:
:
=+|-
:
:
=|
:
:
=*|/
:
:
=||()
注意:
(1)"ε"表示空串。
.
(2)和分别表示标识符和数。
2、整理出文法的终结符和非终结符:
3、整理出文法的产生式的简化形式:
4、利用下述算法构造LR
(1)项集族
SetofltemsCLOSURE(I)
{
repeat
for(I中的每个项[A—>α·Bβ,a]
for(G中的每个产生式B—>γ)
for(FIRST(βa)中的每个终结符号b)
将[B—>·γ,b]加入到集合I中;
Until不能向I中加入更多的项;
returnI
}
SetofltemsGOTO(I,X){
将J初始化为空集;
for(I中的每一个项[A—>α·Xβ,a])
将项[A—>α·Xβ,a]加入到集合J中;
returnCLOSURE(J):
}
Voiditems(G)
{
将C初始化为{CLOSURE}({[S’—>·S,$]});
repeat
for(C中的每一个项集I)
for(每一个文法符号X)
if(GOTO(I,X)非空且不在C中)
将GOTO(I,X)加入C中;
until不再有新的项集加入到C中;
}
部分LR
(1)项集族如下图所示:
5、构造LR
(1)语法分析表
5.1、根据LR
(1)项集族构造LR
(1)分析表时所遵循的流程:
5.2、部分LR
(1)分析表如下图所示,表中的移入操作用正数表示,其中正数值为666的表示Acc,归约操作用负数表示,0表示错误的状态。
6、编写LR
(1)语法分析器的驱动程序
6.1、LR
(1)驱动程序工作模型:
6.2、编写LR
(1)驱动程序的流程:
1、将状态栈初始化为0状态入栈,将文法符号栈初始化为$入栈
2、根据状态栈栈顶和当前输入指针指向的输入符号查询语法分析表进行如下工作;
移进:
若语法分析表中对应“移进”,那么当前输入符号进符号栈,并据状态转换表查得输入符号所对应的新的状态进状态栈栈顶,然后重复步骤2
归约:
若语法分析表中对应“归约”,则按指定产生式进行归约,若产生式右部的符号串长度为n,则符号栈栈顶的n个符号为句柄,所以符号栈栈顶n个符号出栈,同时,状态栈顶的n个元素也出栈,此时假设状态栈的栈顶为x,归约后将产生式左部的非终结符A进入文法符号栈,并据状态转换表查询状态x行对应的非终结符号A所对应的新状态,并将这个新的状态进入状态栈栈顶;然后重复步骤2
接受:
若动作表中对应“acc”,则分析成功,退出程序;
出错:
若动作表中对应空白,则报告错误信息,退出程序。
6.3、LR
(1)驱动程序关键源码
while(true)
{
ch=str2[str2Pointer];//从文法符号串中读取一个文法符号
v=table[state[stateTop]][findNumber(ch)];//从分析表中读取当前状态下该文法符号的值
//printf("%d%d\n",state[stateTop],findNumber(ch));
if(v>0)//说明应该移入
{
if(v==666)//说明Acc了
{
intlen=0;
for(m=0;m<=stateTop;m++)
{
printf("%d",state[m]);
if(state[m]/10==0)//说明是一位数
len+=2;
elseif(state[m]/10>0&&state[m]/10<10)//说明是两位数
len+=3;
else
len+=4;
}
temp=42-len;
while(temp--)printf("");
for(m=0;m<=symbolTop;m++)
printf("%c",symbol[m]);
temp=26-(m+1);
while(temp--)printf("");
printf("%37s%s\n",str2+str2Pointer,"接受!
");
break;
}
else
{
intlen=0;
for(m=0;m<=stateTop;m++)
{
printf("%d",state[m]);
if(state[m]/10==0)//说明是一位数
len+=2;
elseif(state[m]/10>0&&state[m]/10<10)//说明是两位数
len+=3;
else
len+=4;
}
temp=42-len;
while(temp--)printf("");
for(m=0;m<=symbolTop;m++)
printf("%c",symbol[m]);
temp=26-(m+1);
while(temp--)printf("");
printf("%37s%s\n",str2+str2Pointer,"移入");
//开始进行实际的移入操作
state[++stateTop]=v;//更新状态栈
symbol[++symbolTop]=ch;//更新符号栈
str2Pointer++;//更新输入指针往后移一位
}
}
elseif(v<0)//说明应该归约
{
intlen=0;
for(m=0;m<=stateTop;m++)
{
printf("%d",state[m]);
if(state[m]/10==0)//说明是一位数
len+=2;
elseif(state[m]/10>0&&state[m]/10<10)//说明是两位数
len+=3;
else
len+=4;
}
temp=42-len;
while(temp--)printf("");
for(m=0;m<=symbolTop;m++)
printf("%c",symbol[m]);
temp=26-(m+1);
while(temp--)printf("");
printf("%37s%s",str2+str2Pointer,"根据");
printf("%s归约\n",production[-v]);
//开始进行实际的归约操作
stateTop=stateTop-pLen[-v];//状态栈出栈
symbolTop=symbolTop-pLen[-v];//符号栈出栈
symbol[++symbolTop]=pLeft[-v];//更新符号栈
temp=table[state[stateTop]][findNumber(pLeft[-v])];
state[++stateTop]=temp;//更新状态栈
}
elseif(v==0)//说明出错了
{
intlen=0;
for(m=0;m<=stateTop;m++)
{
printf("%d",state[m]);
if(state[m]/10==0)//说明是一位数
len+=2;
elseif(state[m]/10>0&&state[m]/10<10)//说明是两位数
len+=3;
else
len+=4;
}
temp=42-len;
while(temp--)printf("");
for(m=0;m<=symbolTop;m++)
printf("%c",symbol[m]);
temp=26-(m+1);
while(temp--)printf("");
printf("%37s%s\n",str2+str2Pointer,"语法错误!
");
fprintf(fp4,"对文法符号串:
%s,解析到%s时发生语法错误!
",str2,str2+str2Pointer);
break;
}
}
6、测试数据以及截图
测试数据1:
如发现有语法错误,程序会报告发生了错误
vara,b,c;
if(a>b){*annotation*}
a=3*4*5
then
while(c>1)
doc=a+b.
测试数据2:
begin
whilea=c
end.
测试数据3:
consta=2,b=3;
varj,m,n;
begin
m:
=2;
end.