编译原理课程设计实验报告.docx
- 文档编号:23378331
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:21
- 大小:93.56KB
编译原理课程设计实验报告.docx
《编译原理课程设计实验报告.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计实验报告.docx(21页珍藏版)》请在冰豆网上搜索。
编译原理课程设计实验报告
福建农林大学计算机与信息学院
计算机类
课程设计报告
课程名称:
编译原理
课程设计题目:
语法分析器
姓名:
左慈
系:
计算机
专业:
计算机科学与技术
年级:
2013级
学号:
指导教师:
李小林
职称:
副教授
2013~2014学年第一学期
福建农林大学计算机与信息学院计算机类
课程设计结果评定
评语:
成绩:
指导教师签字:
任务下达日期:
评定日期:
目录
1正则表达式1
1.1正则表达式1
1.2确定化(化简)后的状态转换图1
1.3分析程序代码1
1.4程序运行截图4
1.5小结4
2LL
(1)分析5
2.1LL
(1)文法5
2.2LL
(1)预测分析表5
2.3分析程序代码5
2.4程序运行截图7
2.5小结7
3算符优先分析8
3.1算符优先文法8
3.2算符优先关系表8
3.3分析程序代码8
3.4程序运行截图10
3.5小结11
4LR分析12
4.1LR文法12
4.2LR分析表12
4.3分析程序代码12
4.4程序运行截图14
4.5小结14
参考文献:
14
1正则表达式
1.1正则表达式
(a|b)*(aa|bb)(a|b)*(注:
该正规式为示例,可更改)
1.2确定化(化简)后的状态转换图
1.3分析程序代码
#include
#include
using namespace std;
const int Max=20;
typedef struct ArcNode{
int adjvex;//该弧所指向的顶点的位置
char info; //权
struct ArcNode *nextarc;//指向下一条弧的指针
}ArcNode;
typedef struct VNode{
char data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的弧的指针
}VNode;
class Nfa
{
public:
Nfa(); //构造函数,初始化nfa
int FindAdj(char c); //返回c状态的在邻接表中的序号
void AlpAdd(char c); //向字母表集合中添加表中没有的新元素c
void InitVisit(); //初始化Visited集合
void e_closure(int index); //求单一状态c的e-闭包
void e_closure(int a[]); //重载的状态集合的e-闭包
void move(int I,char a); //单一状态I的a弧转换
void move(int I[],char a); //重载的状态集合的a弧转换
void Nfa:
:
Visit_I(int *Temp); //Visited转换为集合
void Insert(int I[],int a); //向状态集合中添加新元素
int TAdd(int I[]); //状态矩阵T中加入新状态集合
void Resault(int i);
void Nfa_Dfa();
private:
int K; //状态数
int T[Max][Max]; //状态子集矩阵
VNode AdjList[Max]; //nfa,邻接表的数据结构存储
VNode Dfa[Max]; //dfa
bool Visited[Max]; //存e-闭包结果
char Alp[Max]; //字母表,0号单元用于存放个数
};
Nfa:
:
Nfa()
{
K=Alp[0]=0;
char c;
string line;
ArcNode *p;
while(cin>>c&&c!
='#')
{
AdjList[K].data=c;
AdjList[K].firstarc=new ArcNode;
AdjList[K].firstarc->nextarc=NULL;
K++;
}
getline(cin,line);
while(getline(cin,line)&&line!
="#")
{
int index=FindAdj(line[0]);
if(index!
=-1)
{
p=AdjList[index].firstarc;
while(p->nextarc)
p=p->nextarc;
p->nextarc=new ArcNode;
p->nextarc->nextarc=NULL;
p->nextarc->adjvex=FindAdj(line[4]);
p->nextarc->info=line[2];
AlpAdd(p->nextarc->info);
}
}
cout<<"------------------------------"< cout<<"Initialization completely."< cout<<"K={"; for(int i=0;i cout< cout< cout<<"∑={"; for(int i=1;i<(int)Alp[0];i++) cout< cout< for(int i=0;i { p=AdjList[i].firstarc; p=p->nextarc; while(p) { cout<<"f("< p=p->nextarc; } if(i #include intexch[4][2]={1,2,3,2,1,3,3,3}; voidjudge(char*s) { intcur=0,i=0; while(s[i]) { if(s[i]-'a'>1||s[i]<'a') break; cur=exch[cur][s[i++]-'a']; } if(s[i]==0&&cur==3) printf("%s√Right! \n\n",s); elseprintf("%s×Wrong! \n\n",s); } intmain() { charstr[100]; while (1) { printf("有限自动机,判断是否符合(a|b)*(aa|bb)(a|b)*\n"); printf("请输入字符串: "); gets(str); judge(str); } } 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分析程序代码 输入文法: E→TE'(注: 该文法为示例,可更改) E'→+TE'|ε T→FT' T'→*FT'|ε F→(E)|i 代码: #include #include chardata[5][6][10]={"12","","","12","","", "","12+","","","-","-", "34","","","34","","", "","-","34*","","-","-", "i","","",")0(","","", };//第一维0-4分别代表EE'TT'F,第二维0-5代表i+*()#-代表ε intexch(charch) { switch(ch) { case'i': return0; case'+': return1; case'*': return2; case'(': return3; case')': return4; case0: return5;//字符串结束标志代表'#'. default: return-1; } } voidjudge(char*s) { inttot=0,i=0,cur,k=exch(s[0]); charsta[100];; sta[++tot]='0'; while(tot>0) { cur=sta[tot]-'0'; if(s[i]=='')//去空格 ++tot,k=exch(s[++i]); elseif(cur+'0'==s[i])//推导出相同字符,出栈 k=exch(s[++i]); elseif(k<0||data[cur][k][0]==0)//踩空,或者出现非法字符 break; elseif(data[cur][k][0]! ='-')//不是ε,进栈继续推导 { strcpy(sta+tot,data[cur][k]); tot+=strlen(data[cur][k]); } --tot; } if(tot==0) printf("%s√Right! \n\n",s); elseprintf("%s×Wrong! \n\n",s); } intmain() { charstr[100]; printf("判断符号串是否符合文法: \n\n\tE→TE'\n\t"); printf("E'→+TE'|ε\n\tT→FT'\n\tT'→*FT'|ε\n\tF→(E)|i\n\n"); while(printf("输入符号串: ")&&gets(str)&&str[0]) judge(str); return0; } 2.4程序运行截图 2.5小结 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# intexch(charch) { switch(ch) { case'+': return0; case'-': return1; case'*': return2; case'/': return3; case'(': return4; case')': return5; case'i': return6; case0: return7;//字符串结束标志代表‘#’ default: return-1; } } charexpre[6][5]={"N+N","N-N","N*N","N/N","(=N)","i"};//为了挽回因忽略语法变量而产生的错误,在规约时检验终结符是否带了应有的操作对象。 intconfirm(char*sta,intt)//检验终结符是否带了应有的变量。 { inti,n=t; while(n>0&&sta[n]! ='<') n--; if(n>0) for(i=0;i<6;i++) if(memcmp(expre[i],sta+n+1,sizeof(char)*(t-n))==0) { sta[n]='N';//说明是有应有的操作对象,所以进行规约。 returnn; } return0; } voidjudge(char*s) { charsta[100]; inttot=0,cur,m,k,i=0; sta[++tot]=0; while(tot>0) { m=tot; do{ cur=exch(sta[m--]); }while(cur<0);//要忽略变量,直接对终结符进行比较优先级。 while(s[i]=='')//跳过空格 i++; k=exch(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=confirm(sta,tot))==0)//检验终结符是否带了应有的变量。 没有,就规约失败 tot=-1; } if(tot==0) printf("%s√Right! \n\n",s); elseprintf("%s×Wrong! \n\n",s); } intmain() { charstr[100]; printf("判断符号串是否符合文法: \n\n\tE→T|E+T|E-T\n\tT→F|T*F|T/F\n\tF→(E)|i\n\n"); while(printf("输入符号串: ")&&gets(str)&&str[0]) judge(str); return0; } 3.4程序运行截图 3.5小结 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]={ 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的产生式的左边变量和右边长度 intexch(charch) { switch(ch) { case'a': return0; case'b': return1; case'#': case'\0': return2;//字符串结束标志代表‘#'. case'S': return3; case'B': return4; default: return-1; } } voidjudge(char*s) { intint_stack[100],ti=0,tc=0,i=1,cur,k=exch(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=exch(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=exch(char_stack[tc]); } } if(ti==0) printf("%s√Right! \n\n",s); elseprintf("%s×Wrong! \n\n",s); } intmain() { charstr[100]; printf("判断符号串是否符合如下文法: \n\n\tS→BB\n\tB→aB\n\tB→b\n\n"); while(printf("输入符号串: ")&&gets(str)&&str[0]) judge(str); return0; } 4.4程序运行截图 4.5小结 参考文献: [1]杨德芳主编.编译原理实用教程[M].北京: 中国水利水电出版社,2007 [2]蒋宗礼姜守旭编著《编译原理》,北京: 高等教育出版社,2010
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 课程设计 实验 报告