实验报告五SLR 分析表的生成以及语法分析.docx
《实验报告五SLR 分析表的生成以及语法分析.docx》由会员分享,可在线阅读,更多相关《实验报告五SLR 分析表的生成以及语法分析.docx(32页珍藏版)》请在冰点文库上搜索。
实验报告五SLR分析表的生成以及语法分析
《编译原理》实验报告
实验序号:
5 实验项目名称:
SLR分析表的生成以及语法分析
学 号
姓 名
专业、班
实验地点
指导教师
实验时间
一、实验目的及要求
通过本实验掌握自下而上的语法分析方法,能根据文法产生其对应的SLR分析表;并能利用该分析表进行语法分析,即分析词法分析器输出的记号流,输出对应文法的产生式。
二、实验设备(环境)及要求
装有VC++的PC机
三、实验内容与步骤
源程序代码:
#include
#include
#include
#include
#include
#include
usingnamespacestd;
structtoken//token结构体
{
intcode;
intnum;
token*next;
};
token*token_head,*token_tail;//token队列
structnumber//number结构体
{
intnum;
intvalue;
number*next;
};
number*number_head,*number_tail;//number队列
structstr//string结构体
{
intnum;
stringword;
str*next;
};
str*string_head,*string_tail;//string队列
structivan//表达式结构体
{
charleft;
stringright;
intlen;
};
ivancss[20];//20个表达式
structpank//action表结构体
{
charsr;
intstate;
};
pankaction[46][18];//action表
intgo_to[46][11];//go_to表
structike//分析栈结构体,双链
{
ike*pre;
intnum;
intword;
ike*next;
};
ike*stack_head,*stack_tail;//分析栈首尾指针
voidscan();//按字符读取源文件
intjudge(charch);//判断输入字符的类型
voidout1(charch);//写入token.txt
voidout2(charch,stringword);//写入number.txt
voidout3(charch,stringword);//写入string.txt
voidinput1(token*temp);//插入结点到队列token
voidinput2(number*temp);//插入结点到队列number
voidinput3(str*temp);//插入结点到队列string
voidoutput();//输出三个队列的内容
voidoutfile();//输出三个队列的内容到相应文件中
voidyufa_initialize();//初始化语法分析数据结构
intyufa_main(inta);//语法分析主体部分
intID1(inta);//给输入字符编号,转化成action表列编号
stringID10(inti);//给输入字符反编号
intID2(charch);//给非终结状态编号,转化成go_to表列编号
intID20(charch);//给非终结状态编号
charID21(intj);//给非终结状态反编号
voidadd(ike*temp);//给ike分析栈链表增加一个结点
voiddel();//给ike分析栈链表删除一个结点
FILE*fp;//文件
intwordcount;//标志符计数
intnumcount;//整型常数计数
interr;//标志词法分析结果正确或错误
intnl;//读取行数
voidmain()
{
token_head=newtoken;
token_head->next=NULL;
token_tail=newtoken;
token_tail->next=NULL;
number_head=newnumber;
number_head->next=NULL;
number_tail=newnumber;
number_tail->next=NULL;
string_head=newstr;
string_head->next=NULL;
string_tail=newstr;
string_tail->next=NULL;//初始化三个队列的首尾指针
wordcount=0;//初始化字符计数器
numcount=0;//初始化常数计数器
err=0;//初始化词法分析错误标志
nl=1;//初始化读取行数
scan();
if(err==0)
{
charm;
cout<<"词法分析正确完成!
"<";
cin>>m;
output();
if(m=='y')
{
cout<<"结果同时保存在token.txt、number.txt和sting.txt三个文件中,请打开查看"<outfile();
}
}
yufa_initialize();//初始化语法分析数据结构
token*temp;
temp=newtoken;
temp=token_head->next;
intp,q;
p=0;
q=0;
cout<"<while(temp!
=NULL)
{
intw;
w=ID1(temp->code);
p=yufa_main(w);
if(p==1)break;
if(p==0)
temp=temp->next;
if(temp==NULL)q=1;
}//语法分析
if(q==1)
while
(1)
{
p=yufa_main(17);
if(p==3)break;
}//最后输入$来完成语法分析
cout<system("pause");
}
voidscan()
{
charch;
stringword;
chardocument[50];
intflag=0;
cout<<"请输入源文件路径及名称:
";
cin>>document;
cout<if((fp=fopen(document,"rt"))==NULL)
{
err=1;
cout<<"无法找到该文件!
"<return;
}
while(!
feof(fp))
{
word="";
ch=fgetc(fp);
flag=judge(ch);
if(flag==1)
out1(ch);
elseif(flag==2)
out2(ch,word);
elseif(flag==3)
out3(ch,word);
elseif(flag==4||flag==5||flag==6)
continue;
else
{
cout<非法字符!
"<err=1;
}
}
fclose(fp);
}
intjudge(charch)
{
intflag=0;
if(ch=='='||ch=='+'||ch=='*'||ch=='>'||ch==':
'||ch==';'||ch=='{'||ch=='}'||ch=='('||ch==')')
flag=1;//界符
elseif('0'<=ch&&ch<='9')
flag=2;//数字
elseif(('a'<=ch&&ch<='z')||('A'<=ch&&ch<='Z'))
flag=3;//字母
elseif(ch=='')
flag=4;//空格
elseif(feof(fp))
flag=5;//结束
elseif(ch=='\n')
{
flag=6;//换行
nl++;
}
else
flag=0;//非法字符
return(flag);
}
voidout1(charch)
{
intid;
switch(ch)
{
case'=':
id=1;break;
case'+':
id=2;break;
case'*':
id=3;break;
case'>':
id=4;break;
case':
':
id=5;break;
case';':
id=6;break;
case'{':
id=7;break;
case'}':
id=8;break;
case'(':
id=9;break;
case')':
id=10;break;//界符编码
default:
id=0;
}
token*temp;
temp=newtoken;
temp->code=id;
temp->num=-1;
temp->next=NULL;
input1(temp);
return;
}
voidout2(charch,stringword)
{
token*temp;
temp=newtoken;
temp->code=-1;
temp->num=-1;
temp->next=NULL;
number*temp1;
temp1=newnumber;
temp1->num=-1;
temp1->value=-1;
temp1->next=NULL;
intflag=0;
word=word+ch;
ch=fgetc(fp);
flag=judge(ch);
if(flag==1)
{
numcount++;
temp->code=26;
temp->num=numcount;
input1(temp);
temp1->num=numcount;
inti,num_value=0,num_length;//字符串转化为数字
char*num_head;
num_head=&word[0];
num_length=strlen(num_head);
for(i=num_length-1;i>=0;i--)
num_value=num_value+(int(word[i])-48)*pow(10,(num_length-i-1));
temp1->value=num_value;//把数字的值赋给结点
input2(temp1);
out1(ch);
}
elseif(flag==2)
out2(ch,word);//形成字符串
elseif(flag==3)
{
err=1;
cout<数字后面跟字母!
"<return;
}
elseif(flag==4||flag==5||flag==6)
{
numcount++;
temp->code=26;
temp->num=numcount;
input1(temp);
temp1->num=numcount;
inti,num_value=0,num_length;//字符串转化为数字
char*num_head;
num_head=&word[0];
num_length=strlen(num_head);
for(i=num_length-1;i>=0;i--)
num_value=num_value+(int(word[i])-48)*pow(10,(num_length-i-1));
temp1->value=num_value;//把数字的值赋给结点
input2(temp1);
return;
}
else
{
err=1;
cout<非法字符!
"<return;
}
}
voidout3(charch,stringword)
{
token*temp;
temp=newtoken;
temp->code=-1;
temp->num=-1;
temp->next=NULL;
str*temp1;
temp1=newstr;
temp1->num=-1;
temp1->word="";
temp1->next=NULL;
intflag=0;
word=word+ch;
ch=fgetc(fp);
flag=judge(ch);
if(flag==1||flag==4||flag==5||flag==6)
{
if(word=="and"||word=="if"||word=="then"/*||word=="else"*/||word=="while"||word=="do"||word=="int")
{
if(word=="and")
temp->code=31;
elseif(word=="if")
temp->code=32;
elseif(word=="then")
temp->code=33;
//elseif(word=="else")
//temp->code=34;
elseif(word=="while")
temp->code=35;
elseif(word=="do")
temp->code=36;
elseif(word=="int")
temp->code=37;//关键字编码
input1(temp);
if(flag==1)
out1(ch);
elseif(flag==4||flag==5||flag==6)
return;
}
elseif(flag==1)
{
wordcount++;
temp->code=25;
temp->num=wordcount;
input1(temp);
temp1->num=wordcount;
temp1->word=word;
input3(temp1);
out1(ch);
}
elseif(flag==4||flag==5||flag==6)
{
wordcount++;
temp->code=25;
temp->num=wordcount;
input1(temp);
temp1->num=wordcount;
temp1->word=word;
input3(temp1);
}
return;
}
elseif(flag==2||flag==3)
out3(ch,word);//形成字符串
else
{
err=1;
cout<非法字符!
"<return;
}
}
voidinput1(token*temp)
{
if(token_head->next==NULL)
{
token_head->next=temp;
token_tail->next=temp;
}
else
{
token_tail->next->next=temp;
token_tail->next=temp;
}
}
voidinput2(number*temp)
{
if(number_head->next==NULL)
{
number_head->next=temp;
number_tail->next=temp;
}
else
{
number_tail->next->next=temp;
number_tail->next=temp;
}
}
voidinput3(str*temp)
{
if(string_head->next==NULL)
{
string_head->next=temp;
string_tail->next=temp;
}
else
{
string_tail->next->next=temp;
string_tail->next=temp;
}
}
voidoutput()
{
cout<<"token表内容如下:
"<token*temp1;
temp1=newtoken;
temp1=token_head->next;
while(temp1!
=NULL)
{
cout<code;
if(temp1->num==-1)
{
cout<}
else
{
cout<<""<num<}
temp1=temp1->next;
}
cout<<"常数表内容如下:
"<number*temp2;
temp2=newnumber;
temp2=number_head->next;
while(temp2!
=NULL)
{
cout<num<<""<value<temp2=temp2->next;
}
cout<<"符号表内容如下:
"<str*temp3;
temp3=newstr;
temp3=string_head->next;
while(temp3!
=NULL)
{
cout<num<<""<word<temp3=temp3->next;
}
}
voidoutfile()
{
ofstreamfout1("token.txt");//写文件
ofstreamfout2("number.txt");
ofstreamfout3("string.txt");
token*temp1;
temp1=newtoken;
temp1=token_head->next;
while(temp1!
=NULL)
{
fout1<code;
if(temp1->num==-1)
fout1<else
fout1<<""<num<temp1=temp1->next;
}
number*temp2;
temp2=newnumber;
temp2=number_head->next;
while(temp2!
=NULL)
{
fout2<num<<""<value<temp2=temp2->next;
}
str*temp3;
temp3=newstr;
temp3=string_head->next;
while(temp3!
=NULL)
{
fout3<num<<""<word<temp3=temp3->next;
}
}
/****************************以上是词法,以下是语法**************************/
voidyufa_initialize()
{
stack_head=newike;
stack_tail=newike;
stack_head->pre=NULL;
stack_head->next=stack_tail;
stack_head->num=0;
stack_head->word='!
';
stack_tail->pre=stack_head;
stack_tail->next=NULL;//初始化栈分析链表
css[0].left='Q';
css[0].right="P";
css[1].left='P';
css[1].right="id()L;R";
css[2].left='L';
css[2].right="L;D";
css[3].left='L';
css[3].right="D";
css[4].left='D';
css[4].right="id:
int";
css[5].left='E';
css[5].right="E+T";
css[6].left='E';
css[6].right="T";
css[7].left='T';
css[7].right="T*F";
css[8].left='T';
css[8].right="F";
css[9].left='F';
css[9].right="(E)";
css[10].left='F';
css[10].right="id";
css[11].left='B';
css[11].right="BandB";
css[12].left='B';
css[12].right="id>id";
css[13].left='M';
css[13].right="id=E";
css[14].left='S';
css[14].right="ifBthenM";
css[15].left='S';
css[15].rig