编译原理课程设计.docx
- 文档编号:5885686
- 上传时间:2023-01-01
- 格式:DOCX
- 页数:23
- 大小:236.09KB
编译原理课程设计.docx
《编译原理课程设计.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计.docx(23页珍藏版)》请在冰豆网上搜索。
编译原理课程设计
福建农林大学计算机与信息学院
计算机类
课程设计报告
课程名称:
编译原理
课程设计题目:
语法分析器
姓名:
系:
专业:
年级:
学号:
指导教师:
职称:
2011~2012学年第一学期
福建农林大学计算机与信息学院计算机类
课程设计结果评定
评语:
成绩:
指导教师签字:
任务下达日期:
评定日期:
目录
1正则表达式1
1.1正则表达式1
1.2确定化(化简)后的状态转换图1
1.3分析程序代码1
1.4程序运行截图2
1.5小结2
2LL
(1)分析3
2.1LL
(1)文法3
2.2LL
(1)预测分析表3
2.3分析程序代码4
2.4程序运行截图8
2.5小结8
3算符优先分析9
3.1算符优先文法9
3.2算符优先关系表9
3.3分析程序代码10
3.4程序运行截图12
3.5小结12
4LR分析13
4.1LR文法13
4.2LR分析表13
4.3分析程序代码14
4.4程序运行截图16
4.5小结16
参考文献:
16
1正则表达式
1.1正则表达式
(a|b)*(aa|bb)(a|b)*
1.2确定化(化简)后的状态转换图
1.3分析程序代码
程序要求:
用户输入一个符号串,程序判断是否符合给定正则表达式。
#include
intstr[4][2]={1,2,3,2,1,3,3,3};
voidcompare(char*s)
{
intcur=0,i=0;
while(s[i])
{
if(s[i]-'a'>1||s[i]<'a')
break;
cur=str[cur][s[i++]-'a'];
}
if(s[i]==0&&cur==3)
printf("\n字符串%s符合给定的的正则表达式!
\n\n",s);
else
printf("\n字符串%s不符合给定的的正则表达式!
\n\n",s);
}
intmain()
{
charstr[50];
while
(1)
{
printf("请输入字符串,判断是否符合(a|b)*(aa|bb)(a|b)*正则式:
\n");
scanf("%s",str);
compare(str);
}
return0;
}
1.4程序运行截图
1.5小结
对计算机系统而言,正则表达式和正则文法相比具有明显的优势,所以有的人往往首选用正则表达式来表示正则语言。
算符优先分析方法的基本思想是只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系,不考虑非终结符之间的优先关系,在归约过程中只要找到可归约串就归约,并不考虑归约到那个非终结符。
这次实验使我更加深印象。
2LL
(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
usingnamespacestd;
#include"string.h"
#definemaxsize20
//定义产生式结构体
structproduction
{
chartoken;
inttokens[6];
};
//定义堆栈结构
structstack
{
charstackwords[maxsize];
intstack_top;
};
classLLOneParse
{
public:
voidinitial();
intanalyzer(char*words);
private:
voidpush_stack(intnum);
intseekkeyword(charword);
intseektoken(charword);
private:
structproductionvariable[5];
structstackastack;
charproduce[7][6];
};
voidLLOneParse:
:
initial()
{
//初始化堆栈
astack.stack_top=1;
astack.stackwords[0]='#';
astack.stackwords[1]='E';
//初始化产生式
strcpy(produce[1],"DT");
strcpy(produce[2],"DT+");
strcpy(produce[3],"HF");
strcpy(produce[4],"HF*");
strcpy(produce[5],")E(");
strcpy(produce[6],"i");
//初始化二维表
variable[0].token='E';
variable[0].tokens[0]=1;
variable[0].tokens[1]=-1;
variable[0].tokens[2]=-1;
variable[0].tokens[3]=1;
variable[0].tokens[4]=-1;
variable[0].tokens[5]=-1;
variable[1].token='D';
variable[1].tokens[0]=-1;
variable[1].tokens[1]=2;
variable[1].tokens[2]=-1;
variable[1].tokens[3]=-1;
variable[1].tokens[4]=0;
variable[1].tokens[5]=0;
variable[2].token='T';
variable[2].tokens[0]=3;
variable[2].tokens[1]=-1;
variable[2].tokens[2]=-1;
variable[2].tokens[3]=3;
variable[2].tokens[4]=-1;
variable[2].tokens[5]=-1;
variable[3].token='H';
variable[3].tokens[0]=-1;
variable[3].tokens[1]=0;
variable[3].tokens[2]=4;
variable[3].tokens[3]=-1;
variable[3].tokens[4]=0;
variable[3].tokens[5]=0;
variable[4].token='F';
variable[4].tokens[0]=6;
variable[4].tokens[1]=-1;
variable[4].tokens[2]=-1;
variable[4].tokens[3]=5;
variable[4].tokens[4]=-1;
variable[4].tokens[5]=-1;
}
//产生式进栈
voidLLOneParse:
:
push_stack(intnum)
{
inti=0;
if(num!
=0)
{
while(produce[num][i]!
='\0')
{
astack.stack_top++;
astack.stackwords[astack.stack_top]=produce[num][i];
i++;
}
}
}
intLLOneParse:
:
seekkeyword(charword)
{
inti=0;
for(i=0;i<5;i++)
if(word==variable[i].token)
returni;
return0;
}
intLLOneParse:
:
seektoken(charword)
{
switch(word)
{
case'i':
return0;
case'+':
return1;
case'*':
return2;
case'(':
return3;
case')':
return4;
case'#':
return5;
default:
return-1;
}
}
intLLOneParse:
:
analyzer(char*words)
{
intindex=0;//字符指针
inti=0;
intmarki=-1;//标记找到的字符
intmarkj=-1;
while(astack.stackwords[astack.stack_top]!
='#')
{
//堆栈指向终结符的情况
if(seektoken(astack.stackwords[astack.stack_top])!
=-1)
{
if(seektoken(words[index])==seektoken(astack.stackwords[astack.stack_top]))
{
astack.stack_top--;
index++;
continue;
}
else
return0;
}
marki=seekkeyword(astack.stackwords[astack.stack_top]);//寻找匹配变量
markj=seektoken(words[index]);//寻找匹配字符
//判断表达式是否有对应的产生式
if(markj!
=-1)
{
if(variable[marki].tokens[markj]!
=-1)
{
astack.stack_top--;
push_stack(variable[marki].tokens[markj]);//压入堆栈
}
else
return0;
}
else
return0;
}
if(words[index]=='#')
return1;
else
return0;
}
intmain(intargc,char*argv[])
{
LLOneParsellOneParse;
charuserinput[maxsize];
llOneParse.initial();//调用初始化函数
cout<<"请输入字符串以#号结束:
";
cin>>userinput;
if(llOneParse.analyzer(userinput)>0)//调用程序
cout<<"是给定句子的文法"< else cout<<"不是给定句子的文法"< return0; } 2.4程序运行截图 2.5小结 通过本次课程设计的LL (1)文法设计,使我对LL (1)文法有了更加深刻的理解,通过LL (1)文法在分析过程中可以不需要回溯,其效率高。 通过本次的LL (1)文法设计,使我知道FIRST,FOLLOW集是实现LL (1)文法的必要条件。 虽然在编程过程中仍然是错误不断,但通过本次的编程,进一步提高了我的编程能力,虽然这一次我使用c++来实现,主要是因为c++是面向对象的。 总之,通过本次的课程设计,知道了要实现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 charcom[8][8]={ '>','>','<','<','<','>','<','>', '>','>','<','<','<','>','<','>', '>','>','>','>','<','>','<','>', '>','>','>','>','<','>','<','>', '<','<','<','<','<','=','<','', '>','>','>','>','-','>','-','>', '>','>','>','>','-','>','-','>', '<','<','<','<','<','-','<','=', };//0-7分别代表 +-*/()i# intstr(charc) { switch(c) { case'+': return0; case'-': return1; case'*': return2; case'/': return3; case'(': return4; case')': return5; case'i': return6; case'#': case0: return7;//字符串结束标志代表'#'. default: return-1; } } charstr1[6][5]={"N+N","N-N","N*N","N/N","(=N)","i"}; //为了挽回因忽略语法变量而产生的错误,在规约时检验终结符是否带了应有的操作对象。 intquery(char*sta,intt)//检验终结符是否带了应有的变量。 { inti,n=t; while(n>0&&sta[n]! ='<') n--; if(n>0) for(i=0;i<6;i++) if(memcmp(str1[i],sta+n+1,sizeof(char)*(t-n))==0) { sta[n]='N';//说明是有应有的操作对象,所以进行规约。 returnn; } return0; } voidcompare(char*s) { charsta[100]; inttot=0,cur,m,k,i=0; sta[++tot]=0; while(tot>0) { m=tot; do{ cur=str(sta[m--]); }while(cur<0);//要忽略变量,直接对终结符进行比较优先级。 while(s[i]=='')//跳过空格 i++; k=str(s[i]); if(cur==k&&cur==7) tot=0;//规约成功,结束标记。 elseif(k<0||com[cur][k]=='-')//踩空或者输入非法符 tot=-1; elseif(com[cur][k]! ='>')//遇到'>',准备规约 { if(sta[tot]=='N')//这里一个小问题就是变量N是要在'<'左边还是右边呢, //这要取决于终结符是什么,左右两边有几个变量,不过针对本程序方法,只需全部放在右边。 { sta[tot]=com[cur][k]; sta[++tot]='N'; } else sta[++tot]=com[cur][k]; sta[++tot]=s[i++]; } elseif((tot=query(sta,tot))==0)//检验终结符是否带了应有的变量。 没有,就规约失败 tot=-1; } if(tot==0) printf("\n符号串%s是给定方法的句子! \n\n",s); else printf("\n符号串%s不是给定方法的句子! \n\n",s); } intmain() { charstr[100]; printf("\n判断符号串是否符合如下文法: \n\nE→T|E+T|E-T\nT→F|T*F|T/F\nF→(E)|i\n\n"); do { printf("输入符号串: "); scanf("%s",str); compare(str); }while (1); return0; } 3.4程序运行截图 3.5小结 通过本次的课程设计中的算符优先分析,使我知道了算符优先分析是在某个句型中相邻的任意两个终结符当作算符,然后定义算符之间的某种优先关系,利用这种优先关系来寻找句柄进行规约,是一种简单又实用的方法。 本次的算符优先文法主要是通过创建算符优先关系矩阵来实现的,主要利用FIRSTOP和LASTOP来实现。 4LR分析 4.1LR文法 (0)S'→S(注: 该文法为示例,可更改) (1)S→BB (2)B→aB (3)B→b 4.2LR分析表 ACTION GOTO a b # S B 0 S3 S4 1 2 1 acc 2 S3 S4 5 3 S3 S4 6 4 r3 r3 r3 5 r1 r1 r1 6 r2 r2 r2 4.3分析程序代码 源程序: #include #include intaction[7][5]={//定义ACTION表格 3,4,0,1,2, 0,0,-4,0,0, 3,4,0,0,5, 3,4,0,0,6, -3,-3,-3,0,0, -1,-1,-1,0,0, -2,-2,-2,0,0 };//负数代表此时可规约,即r,第二维0-5分别代表ab#SB,-4表示acc intcnt[]={0,'S'*10+2,'B'*10+2,'B'*10+1};//表示ri的产生式的左边变量和右边长度 intstr(charc) { switch(c) { case'a': return0; case'b': return1; case'#': case'\0': return2;//字符串结束标志代表'#'. case'S': return3; case'B': return4; default: return-1; } } voidcompare(char*s) { intint_stack[100],ti=0,tc=0,i=1,cur,k=str(s[0]); charchar_stack[100]; int_stack[++ti]=0; while(ti>0) { cur=int_stack[ti]; if(k<0||action[cur][k]==0)//踩空,或者出现非法字符 ti=-1; elseif(action[cur][k]>0)//入栈,等待规约 { int_stack[++ti]=action[cur][k];//数字栈 char_stack[++tc]=s[i];//字符栈 k=str(s[i++]); } elseif(action[cur][k]==-4)//规约完成,说明是符合要求 ti=0; else//可以规约 { --i;//说明输入的字符s[i-1]还没有用,此时它不进栈,故i--,以便下次取到的是要s[i-1]; ti-=cnt[-action[cur][k]]%10;//取ri的长度,出栈这么多个的字符 tc-=cnt[-action[cur][k]]%10; char_stack[++tc]=cnt[-action[cur][k]]/10;//取产生式的左边变量,进行规约。 k=str(char_stack[tc]); } } if(ti==0) printf("\n符号串%s是给定方法的句子! \n\n",s); else printf("\n符号串%s不是给定方法的句子! \n\n",s); } intmain() { charstr[100]; printf("\n判断符号串是否符合如下文法: \n\nS→BB\nB→aB\nB→b\n\n"); do { printf("请输入符号串: "); scanf("%s",str); compare(str); }while (1); return0; } 4.4程序运行截图 4.5小结 通过本次的LR分析使我使我知道LR分析是一种有效的自底向上语法分析技术,它适用于一大类上下无关文法的语法分析,其基本原理是: 将句柄(某个产生式的右
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 课程设计
![提示](https://static.bdocx.com/images/bang_tan.gif)