农林大学 编译原理课程设计.docx
《农林大学 编译原理课程设计.docx》由会员分享,可在线阅读,更多相关《农林大学 编译原理课程设计.docx(33页珍藏版)》请在冰豆网上搜索。
农林大学编译原理课程设计
福建农林大学计算机与信息学院计算机类
课程设计结果评定
评语:
成绩:
指导教师签字:
任务下达日期:
评定日期:
目录
1正则表达式1
1.1正则表达式1
1.2确定化(化简)后的状态转换图1
1.3分析程序代码1
1.4程序运行截图1
1.5小结2
2LL
(1)分析错误!
未定义书签。
2.1LL
(1)文法3
2.2LL
(1)预测分析表3
2.3分析程序代码4
2.4程序运行截图6
2.5小结7
3算符优先分析7
3.1算符优先文法8
3.2算符优先关系表8
3.3分析程序代码8
3.4程序运行截图17
3.5小结18
4LR分析19
4.1LR文法19
4.2LR分析表19
4.3分析程序代码19
4.4程序运行截图22
4.5小结22
参考文献:
22
1正则表达式
1.1正则表达式
(a|b)*(aa|bb)(a|b)*(注:
该正规式为示例,可更改)
1.2确定化(化简)后的状态转换图
1.3分析程序代码
#include"stdio.h"
ints[7][2]={{1,2},{3,2},{1,4},{3,5},{6,4},{6,4},{3,5}};//状态转换图
voidmain()
{printf("★★★★★★有限自动机★★★★★★\n");
printf("文法规则:
\n");
printf("(a|b)*(aa|bb)*(a|b)*\n\n");
printf("----------------------------------------------------------\n");
printf("请输入字符串:
\n");
charch;
inti,j,t,flag;
i=0;
t=1;//判断输入是否正确
flag=0;//判断句子是否正确
while((ch=getchar())!
='\n')
{if(ch=='a')j=0;
if(ch=='b')j=1;
if(ch!
='a'&&ch!
='b')
{t=0;//输入有误
break;
}i=s[i][j];}
flag=i;
if(flag>=3&&t)//flag>2时可终结
printf("\n输入字符串正确!
\n\n");
else
printf("\n输入字符串错误!
\n\n");
}
1.4程序运行截图
1、输入正确的字符串:
2、输入错误的字符串:
1.5小结
在这次课程设计,对正则文法和状态转换图和有限自动机的理论有了更深的了解,将理论应用于实际应用中。
2、LL
(1)分析
2.1LL
(1)文法
E→TE'(注:
该文法为示例,可更改)
E'→+TE'|ε
T→FT'
T'→*FT'|ε
F→(E)|i
2.2LL
(1)预测分析表
i
+
*
(
)
#
E
E→TE'
E→TE'
E'
E'→+TE'
E'→ε
E'→ε
T
T→FT'
T→FT'
T'
T'→ε
T'→*FT'
T'→ε
T'→ε
F
F→i
F→(E)
2.3分析程序代码
#include
#include
#include
#include
#include
usingnamespacestd;
//存储分析预测表每个位置对应的终结符,非终结符,产生式
structNode1
{charvn;
charvt;
chars[10];
}MAP[20];
intk;
//用R代表E',W代表T',e代表空
charG[10][10]={"E->TR","R->+TR","R->e","T->FW","W->*FW","W->e","F->(E)","F->i"};//存储文法中的产生式
charVN[6]={'E','R','T','W','F'};//存储非终结符
charVT[6]={'i','+','*','(',')','#'};//存储终结符
charSELECT[10][10]={"(,i","+","),#","(,i","*","+,),#","(","i"};//存储文法中每个产生式对应的SELECT集
charRight[10][8]={"->TR","->+TR","->e","->FW","->*FW","->e","->(E)","->i"};
stackstak,stak1,stak2;
boolcompare(char*a,char*b)//比较字符
{inti,la=strlen(a),j,lb=strlen(b);
for(i=0;ifor(j=0;j{if(a[i]==b[j])
return1;}return0;}
char*Find(charvn,charvt)
{inti;
for(i=0;i{if(MAP[i].vn==vn&&MAP[i].vt==vt)
returnMAP[i].s;
}return"error";}
char*Analyse(char*word)
{charp,action[10],output[10];
inti=1,j,l=strlen(word),k=0,l_act,m;
while(!
stak.empty())
stak.pop();
stak.push('#');
stak.push('E');printf("________________________________________________________________________________\n");
printf("\n对符号串%s的分析过程\n",word);
printf("步骤栈顶元素剩余输入串推到所用产生式或匹配\n");
p=stak.top();
while(p!
='#')
{printf("%7d",i++);
p=stak.top();
stak.pop();
printf("%6c",p);
for(j=k,m=0;joutput[m++]=word[j];//推导出相同字符,出栈
output[m]='\0';
printf("%10s",output);
if(p==word[k])//在输入的字符串在首尾加#是用于判断否结束
{if(p=='#')
{printf("接受\n");
return"成功";}
printf("%c匹配\n",p);
k++;}else
{strcpy(action,Find(p,word[k]));
if(strcmp(action,"error")==0)
{printf("没有可用的产生式\n");
return"ERROR";}
printf("%c%s\n",p,action);
intl_act=strlen(action);
if(action[l_act-1]=='e')
continue;
for(j=l_act-1;j>1;j--)
stak.push(action[j]);}}
if(strcmp(output,"#")!
=0)
return"错误";}
intmain()
{charsource[100];
inti,j,flag,l,m;
printf("LL
(1)文法\n");
printf("\n★★★★★★为了区分E'和后面的”,用R表示E',W表示T',e表示空字符串★★★★★★\n\n");
printf("该文法的产生式如下:
\n");
for(i=0;i<8;i++)
printf("%s\n",G[i]);
printf("---------------------------------------------------------------\n");
//判断是否是LL
(1)文法
flag=1;
for(i=0;i<8;i++)
{for(j=i+1;j<8;j++)
{if(G[i][0]==G[j][0])
{if(compare(SELECT[i],SELECT[j]))
{flag=0;break;}}}
if(j!
=8)
break;}
if(flag)
printf("\n有相同左部产生式的SELECT集合的交集为空,所以文法是LL
(1)文法。
\n");
else
printf("\n有相同左部产生式的SELECT集合的交集不为空,所以文法不是LL
(1)文法。
\n");
printf("---------------------------------------------------------------\n");
//预测分析表
for(i=0,k=0;i<8;i++)
{l=strlen(SELECT[i]);
for(j=0;j{MAP[k].vn=G[i][0];
MAP[k].vt=SELECT[i][j];
strcpy(MAP[k].s,Right[i]);
k++;}}
printf("\nLL
(1)文法的预测分析表如下:
\n\n");
printf("");
for(i=0;i<6;i++)
printf("%10c",VT[i]);
printf("\n");
for(i=0;i<5;i++)
{printf("---------------------------------------------------------------\n");
printf("%10c",VN[i]);
for(j=0;j<6;j++)
{for(m=0;m{if(VN[i]==MAP[m].vn&&VT[j]==MAP[m].vt)
{printf("%10s",MAP[m].s);
break;}}
if(m==k)
printf("");}
printf("\n");}
/*预测分析程序Analyse函数*/
printf("在输入字符串时要在后面加一个#,否则程序将无法正常运行!
\n\n");
printf("\n");
printf("请输入一个测试的字符串:
");
while(cin>>source)
{printf("\n分析结果:
%s\n\n",Analyse(source));
while
(1)
{chard;
cout<<"是否继续?
(Y/N)";
cin>>d;
if(d=='Y'||d=='y')
{printf("\n");
printf("在输入字符串时要在后面加一个#,否则程序将无法正常运行!
\n\n");
printf("\n");
printf("请输入一个测试的字符串:
");break;}
if(d=='n'||d=='N')
{return0;}}}return0;}
2.4程序运行截图
1、初始界面:
2、成功的字符串:
(i)#
成功的字符串:
i+i*i#
3、不成功的字符串:
ii*#
2.5小结
在这次课程设计中,对LL
(1)算法中基础理论和基本知识的有了更深的理解,能更灵活应用的所学的知识。
不仅学会程序实现文法判断、结构体和数组的使用等多种问题的基本方法,能将所学的理论知识应用于实践中。
3算符优先分析
3.1算符优先文法
E→T|E+T|E-T(注:
该文法为示例,可更改)
T→F|T*F|T/F
F→(E)|i
3.2算符优先关系表
+
-
*
/
(
)
i
#
+
>
>
<
<
<
>
<
>
-
>
>
<
<
<
>
<
>
*
>
>
>
>
<
>
<
>
/
>
>
>
>
<
>
<
>
(
<
<
<
<
<
=
<
)
>
>
>
>
>
>
i
>
>
>
>
>
>
#
<
<
<
<
<
<
=
3.3分析程序代码
#include
#include
#include
#definerow50
#definecol50
#defineSIZE50
//两个重要结构体的定义
//FIRSTVT表或LASTVT表中一个表项(A,a)结构体的初始化
typedefstruct
{charnonterm;//非终结符
charterm;//终结符
}StackElement;
//存放(A,a)的栈的初始化
typedefstruct
{StackElement*top;
StackElement*bottom;
intstacksize;
}stack;
//初始化(A,a)栈
voidInitStack(stack&S)
{S.bottom=newStackElement[SIZE];
if(!
S.bottom)
cout<<"存储空间分配失败!
"<S.top=S.bottom;
S.stacksize=SIZE;
}
//判断(A,a)栈是否为空
boolifEmpty(stackS)
{if(S.top==S.bottom)returntrue;//如果栈为空,则返回true
elsereturnfalse;//否则不为空,返回false
}
//插入栈顶(A,a)元素
voidInsert(stack&S,StackElemente)
{if(S.top-S.bottom>=S.stacksize)
cout<<"栈已满,无法插入!
"<else
{S.top->nonterm=e.nonterm;
S.top->term=e.term;
S.top++;}}
//弹出栈顶(A,a)元素
StackElementPop(stack&S)
{StackElemente;
e.nonterm='\0';
e.term='\0';
if(S.top==S.bottom)
{cout<<"栈为空,无法进行删除操作!
"<returne;}
else{S.top--;
e.nonterm=S.top->nonterm;
e.term=S.top->term;
returne;}}
//终结符与非终结符的判断函数(布尔类型)
boolTerminalJud(charc)
{if(c>='A'&&c<='Z')returnfalse;//非终结符返回false
elsereturntrue;//终结符返回true
}
//判断非终结符在first表中是否已存在
boolItemJud(charfirst[][col],intfrist_len,charC)
{for(inti=0;i{if(first[i][0]==C)
returntrue;//如果first表中已存在此非终结符,则返回true
}returnfalse;}
//读文件函数
intreadfile(charsen[][col])
{charaddr[50];
cout<<"请输入算符优先文法的描述的地址:
"<cin>>addr;
ifstreamfin;
fin.open(addr,ios:
:
in);
if(!
fin)
{cout<<"Cannotopenfile!
\n"<for(inti=0;!
fin.eof();i++)
{fin>>sen[i];
cout<}returni;}
//FIRSTVT表和LASTVT表中表项(非终结符)的初始化
voidItemInit(charsen[][col],charfirst[][col],charlast[][col],intsen_len,int&frist_len)
{inti;
frist_len=1;
first[0][0]=sen[0][0];
last[0][0]=sen[0][0];
for(i=1;i{if(TerminalJud(sen[i][0])==false&&ItemJud(first,frist_len,sen[i][0])==false)//k是当前first和last表的长度
{first[frist_len][0]=sen[i][0];
last[frist_len][0]=sen[i][0];
frist_len++;}}}
voidFirstVt(charsen[][col],charfirst[][col],intsen_len,intfrist_len)//frist_len是first表的行数sen_len是产生式的个数
{StackElementDFS,record[SIZE];
stackOperator;//创建存放(A,a)的栈
InitStack(Operator);
inti,j,r=0;
for(i=0;i{for(j=3;sen[i][j]!
='\0';j++)
{if(TerminalJud(sen[i][j])==true)//遇到的第一个终结符压入
{intexist=0;
DFS.nonterm=sen[i][0];
DFS.term=sen[i][j];
for(inti1=0;i{if(record[i1].nonterm==sen[i][0]&&record[i1].term==sen[i][j])
{exist=1;
break;}}
record[r].nonterm=sen[i][0];
record[r].term=sen[i][j];
if(exist==0)
{Insert(Operator,DFS);//A-aBA-aC(A,a)压栈两次?
record[r].nonterm=sen[i][0];
record[r].term=sen[i][j];
r++;}break;}}}
intlocation[col];//辅助数组,用来记录first表中放入终结符的位置
for(i=0;ilocation[i]=1;
while(!
ifEmpty(Operator))
{intexist=0;//标志位,记录即将入栈的元素是否已经存在
StackElementIDElement,DElement;
DElement=Pop(Operator);//弹出栈顶元素
for(i=0;i{if(first[i][0]==DElement.nonterm)
{intn=location[i];
first[i][n]=DElement.term;//将终结符填入相应的first表中
location[i]++;
break;}}
for(j=0;j{if(sen[j][3]==DElement.nonterm)//找出能推出当前非终结符的产生式的左部
{IDElement.nonterm=sen[j][0];
IDElement.term=DElement.term;
//判断将要放进栈里的元素曾经是否出现过,若没有,才压入栈
for(intr0=0;r0{if(record[r0].nonterm==IDElement.nonterm&&record[r0].term==IDElement.term)
{exist=1;
break;}}
if(exist==0)
{Insert(Operator,IDElement);
record[r].nonterm=IDElement.nonterm;
record[r].term=IDElement.term;
r++;}}}}}
voidLastVt(charsen[][col],charlast[][col],intsen_len,intfrist_len)//firstvt表与lastvt表行数一样first_len表示last表的行数
{inti,j,i1,j1;
charc,record[row][col]={'\0'};
for(i=0;i{for(j=0;sen[i][j]!
='\0';j++)
{record[i][j]=sen[i][j];}
j=j-1;
for(i1=3,j1=j;i1{c=record[i][i1];
record[i][i1]=record[i][j1];
record[i][j1]=c;}}
FirstVt(record,last,sen_len,frist_len);}
//判断非终结符在term表中是否已存在
boolTermTableJud(ch