编译原理课程设计C++语法分析器Word格式.docx
- 文档编号:20874801
- 上传时间:2023-01-26
- 格式:DOCX
- 页数:19
- 大小:94.40KB
编译原理课程设计C++语法分析器Word格式.docx
《编译原理课程设计C++语法分析器Word格式.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计C++语法分析器Word格式.docx(19页珍藏版)》请在冰豆网上搜索。
14
1正则表达式
1.1正则表达式
(a|b)*(aa|bb)(a|b)*(注:
该正规式为示例,可更改)
1.2确定化(化简)后的状态转换图
1.3分析程序代码
#include
<
iostream>
#include
string>
using
namespace
std;
const
int
Max=20;
typedef
struct
ArcNode{
adjvex;
//该弧所指向的顶点的位置
char
info;
//权
ArcNode
*nextarc;
//指向下一条弧的指针
}ArcNode;
VNode{
data;
//顶点信息
*firstarc;
//指向第一条依附该顶点的弧的指针
}VNode;
class
Nfa
{
public:
Nfa();
//构造函数,初始化nfa
FindAdj(char
c);
//返回c状态的在邻接表中的序号
void
AlpAdd(char
//向字母表集合中添加表中没有的新元素c
InitVisit();
//初始化Visited集合
e_closure(int
index);
//求单一状态c的e-闭包
a[]);
//重载的状态集合的e-闭包
move(int
I,char
a);
//单一状态I的a弧转换
I[],char
//重载的状态集合的a弧转换
Nfa:
:
Visit_I(int
*Temp);
//Visited转换为集合
Insert(int
I[],int
//向状态集合中添加新元素
TAdd(int
I[]);
//状态矩阵T中加入新状态集合
Resault(int
i);
Nfa_Dfa();
private:
K;
//状态数
T[Max][Max];
//状态子集矩阵
VNode
AdjList[Max];
//nfa,邻接表的数据结构存储
Dfa[Max];
//dfa
bool
Visited[Max];
//存e-闭包结果
Alp[Max];
//字母表,0号单元用于存放个数
};
Nfa()
K=Alp[0]=0;
c;
string
line;
*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!
="
#"
index=FindAdj(line[0]);
if(index!
=-1)
p=AdjList[index].firstarc;
while(p->
nextarc)
p=p->
nextarc;
p->
nextarc=new
nextarc->
adjvex=FindAdj(line[4]);
info=line[2];
AlpAdd(p->
info);
cout<
"
------------------------------"
endl;
Initialization
completely."
K={"
;
for(int
i=0;
i<
K-1;
i++)
AdjList[i].data<
"
AdjList[K-1].data<
}."
∑={"
i=1;
(int)Alp[0];
Alp[i]<
Alp[Alp[0]]<
p=AdjList[i].firstarc;
while(p)
f("
info<
)="
adjvex<
if(i<
K&
AdjList[i].firstarc->
#include<
stdio.h>
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]<
'
)
break;
cur=exch[cur][s[i++]-'
];
}
if(s[i]==0&
cur==3)
printf("
%s√Right!
\n\n"
s);
elseprintf("
%s×
Wrong!
}
intmain()
charstr[100];
while
(1)
{
printf("
有限自动机,判断是否符合(a|b)*(aa|bb)(a|b)*\n"
);
请输入字符串:
"
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'
→ε
T
T→FT'
T'
F
F→i
F→(E)
2.3分析程序代码
输入文法:
E'
T→FT'
T'
F→(E)|i
代码:
string.h>
chardata[5][6][10]={"
12"
12+"
-"
"
34"
34*"
i"
)0("
};
//第一维0-4分别代表EE'
TT'
F,第二维0-5代表i+*()#-代表ε
intexch(charch)
switch(ch)
case'
i'
return0;
+'
return1;
*'
return2;
('
return3;
)'
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]-'
if(s[i]=='
)//去空格
++tot,k=exch(s[++i]);
elseif(cur+'
==s[i])//推导出相同字符,出栈
k=exch(s[++i]);
elseif(k<
0||data[cur][k][0]==0)//踩空,或者出现非法字符
elseif(data[cur][k][0]!
='
-'
)//不是ε,进栈继续推导
{
strcpy(sta+tot,data[cur][k]);
tot+=strlen(data[cur][k]);
}
--tot;
if(tot==0)
%s√Right!
elseprintf("
%s×
判断符号串是否符合文法:
\n\n\tE→TE'
\n\t"
|ε\n\tT→FT'
\n\tT'
|ε\n\tF→(E)|i\n\n"
while(printf("
输入符号串:
)&
gets(str)&
str[0])
judge(str);
2.4程序运行截图
2.5小结
实践实践验证里的唯一标准,这次课程设计主要巩固了我对LL
(1)文法的深刻认识,掌握程序实现文法判断、链表的使用等多种问题的基本方法,进一步提高了综合运用所学知识的能力。
3算符优先分析
3.1算符优先文法
E→T|E+T|E-T(注:
T→F|T*F|T/F
F→(E)|i
3.2算符优先关系表
-
/
>
<
=
3.3分析程序代码
charcom[8][8]={'
'
'
};
//0-7分别代表 +-*/()i#
/'
return6;
return7;
//字符串结束标志代表‘#’
charexpre[6][5]={"
N+N"
N-N"
N*N"
N/N"
(=N)"
//为了挽回因忽略语法变量而产生的错误,在规约时检验终结符是否带了应有的操作对象。
intconfirm(char*sta,intt)//检验终结符是否带了应有的变量。
inti,n=t;
while(n>
0&
sta[n]!
n--;
if(n>
for(i=0;
6;
i++)
if(memcmp(expre[i],sta+n+1,sizeof(char)*(t-n))==0)
{
sta[n]='
N'
//说明是有应有的操作对象,所以进行规约。
returnn;
}
inttot=0,cur,m,k,i=0;
sta[++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是要在'
左边还是右边呢,这要取决于终结符是什么,左右两边有几个变量,不过针对本程序方法,只需全部放在右边。
sta[tot]=com[cur][k];
sta[++tot]='
else
sta[++tot]=com[cur][k];
sta[++tot]=s[i++];
elseif((tot=confirm(sta,tot))==0)//检验终结符是否带了应有的变量。
没有,就规约失败
tot=-1;
\n\n\tE→T|E+T|E-T\n\tT→F|T*F|T/F\n\tF→(E)|i\n\n"
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
S3
S4
1
2
acc
5
3
6
4
r3
r1
r2
4.3分析程序代码
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+1};
//表示ri的产生式的左边变量和右边长度
b'
case'
\0'
//字符串结束标志代表‘#'
intint_stack[100],ti=0,tc=0,i=1,cur,k=exch(s[0]);
charchar_stack[100];
int_stack[++ti]=0;
while(ti>
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)
判断符号串是否符合如下文法:
\n\n\tS→BB\n\tB→aB\n\tB→b\n\n"
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 课程设计 C+ 语法 分析器