农林大学 编译原理课程设计.docx

上传人:b****4 文档编号:4262269 上传时间:2022-11-28 格式:DOCX 页数:33 大小:152.08KB
下载 相关 举报
农林大学 编译原理课程设计.docx_第1页
第1页 / 共33页
农林大学 编译原理课程设计.docx_第2页
第2页 / 共33页
农林大学 编译原理课程设计.docx_第3页
第3页 / 共33页
农林大学 编译原理课程设计.docx_第4页
第4页 / 共33页
农林大学 编译原理课程设计.docx_第5页
第5页 / 共33页
点击查看更多>>
下载资源
资源描述

农林大学 编译原理课程设计.docx

《农林大学 编译原理课程设计.docx》由会员分享,可在线阅读,更多相关《农林大学 编译原理课程设计.docx(33页珍藏版)》请在冰豆网上搜索。

农林大学 编译原理课程设计.docx

农林大学编译原理课程设计

福建农林大学计算机与信息学院计算机类

课程设计结果评定

评语:

成绩:

指导教师签字:

任务下达日期:

评定日期:

目录

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;i

for(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;j

output[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;i

location[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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1