主题:关于语法分析器
yusky
[专家分:10] 发布于 2005-05-10 22:47:00
我编写了一个程序,但是达不到要求,现请各位大大帮帮忙
文法:G[S]:S->aBc|bAB
A->aAb|b
B->b|入
自上而下句型分析,判断baabbb是否该文法的句型
希望大家能帮忙交流交流.
回复列表 (共10个回复)
沙发
hk18 [专家分:2230] 发布于 2005-05-12 11:59:00
看看你的程序?
板凳
yusky [专家分:10] 发布于 2005-05-12 20:08:00
//程序:自顶向下语法分析器
//文法G[s]:S->aBc|bAB
// A->aAb|b
// B->b|λ
#include<iostream.h>
#include <string.h>
#include <stdlib.h>
#define stack_size 20
#define stackincrement 10
char Vn[3]={'S','A','B'};
char Vt[4]={'a','b','c','#'};
typedef struct {
char *bottom;
char *top;
int size;
}stack;
int Initstack(stack &s) //初始化栈
{
s.bottom=(char *)malloc(stack_size*sizeof(char));
if(!s.bottom) exit(-1);
s.top=s.bottom;
s.size=stack_size;
return(1);
}
int push(stack &s,char e) //入栈
{
if(s.top-s.bottom>=s.size){
s.bottom=(char *)realloc(s.bottom,(stack_size+stackincrement)*sizeof(char));
if(!s.bottom) exit(-1);
s.top=s.bottom+s.size;
s.size+=stackincrement;
}
*s.top++=e;
return(1);
}
int pop(stack &s,char *e) //出栈
{
if(s.top==s.bottom) return(0);
*e=*--s.top;
return(1);
}
int is_Vt(char Vt[],int n,char a) //LL分析分法X=Vt的处理情形
{
int i;
for(i=0; i<n; i++)
if(a==Vt[i])
break;
if(i==n&&a!=Vt[n-1]) return(0);
else return(1);
}
int is_Vn(char Vn[],int n,char a) //LL分析分法X=Vn的处理情形
{
int i;
for(i=0; i<n; i++)
if(a==Vn[i])
break;
if(i==n&&a!=Vn[n-1]) return(0);
else return(1);
}
void main()
{
char x,ch;
int i=0,index=0;
char st[20];
stack s;
cout<<"LL 语法分析分法----自顶向下分析:"<<endl;
cout<<"文法G[s]:S->aBc|bAB,A->aAb|b,B->b|λ "<<endl;
cout<<endl;
cout<<"\t 输入要分析的字符串(length<20,end by '#'):"<<endl;
cin>>st[0];
while(st[i]!='#'){
i++;
cin>>st[i];
}
Initstack(s);
push(s,'#');
push(s,'S');
ch=st[index];
index++;
while(1){
pop(s,&x);
if(is_Vn(Vn,3,x)){
if(x=='S'&&ch=='a'){
push(s,'c'); push(s,'B'); push(s,'a');
}
if(x=='S'&&ch=='b'){
push(s,'B'); push(s,'A'); push(s,'b');
}
if(x=='A'&&ch=='a'){
push(s,'b'); push(s,'A'); push(s,'a');
}
if(x=='A'&&ch=='b'){
push(s,'b');
}
if(x=='B'&&ch=='b'){
push(s,'b');
}
if(x=='B'&&ch=='c'){
push(s,'$');
}
if(x=='B'&&ch=='#'){
push(s,'$');
}
}
if(is_Vt(Vt,4,x)){
if(x==ch){
if(x!='#'){
ch=st[index];
index++;
}
else{
for(int j=0; j<i; j++)
cout<<st[j];
cout<<"是G[s]文法的句子!"<<endl;
break;
}
}
else{
for(int j=0; j<i; j++)
cout<<st[j];
cout<<"不是G[s]文法的句子!"<<endl;
break;
}
}
if(x=='$') continue;
}
}
如果有人再编写一个出来让我看看就更好啦
3 楼
hk18 [专家分:2230] 发布于 2005-05-13 11:55:00
我是以前看的编译原理,现在有点模糊了!
有时间我看看,我们可以qq联系!
我资料里有.
4 楼
弧度 [专家分:0] 发布于 2005-06-01 01:53:00
我想用C++做语法分析器,但我不会用C++,能否教一下
劳驾了
5 楼
yingyuan [专家分:20] 发布于 2005-06-02 22:36:00
看了你的程序,整个思想采用顺势的结构,但其中有些地方逻辑错误,如在最后的main 循环里的判断流程有点错误。。如果采用并发的思想,先对文法:G[S]:S->aBc|bAB
A->aAb|b
B->b|入
进行优化,将A->aAb|b改为A->aa*b*b|b,然后弄个缓存,意思就是如baabbb
先进b,进入s->b,进a后启动A判断,A->a,进a,缩a为A->aa*,知道,判断完A的P判断,如果成立则进行S的缩进,s->aA,再进行B的p判断。如果行进行s的P判断
意思就是将S的p判断分解为A和B的P判断,如果中间A和B哪个错误。则结束,不为文法。如果最后S的P判断总体成立,就是“#”
则文法成立。
6 楼
wq5223 [专家分:0] 发布于 2005-06-02 23:25:00
大虾多多,偶才知道,自己如风中灰尘.偶很想学,刚刚楼上那位大虾的一段猫字,犹如天书般的印在偶滴心中,试在令在下佩服佩服,如愿收小弟为徒,终生报答.联系QQ107726888
7 楼
chujidiy [专家分:20] 发布于 2005-06-09 22:18:00
顶一下!!
在认真学习。。。
8 楼
chujidiy [专家分:20] 发布于 2005-06-09 23:21:00
我认真看了一下代码,发现作者为栈分配了空间,在结束后却没有释放。 :)
你的数组char Vn[3]={'S','A','B'}; 应该是表示非终结符吧,
而数组char Vt[4]={'a','b','c','#'};应该是终结符吧。 -- 我是个菜鸟
如果出栈的字符是‘B’,而读取的字符是‘a’, 那么这时应该是要出错的,而程序中是没有考虑的。
对于yingyuan大哥的分析,我就看懂了“如果最后S的P判断总体成立,就是“#””...
为什么可以优化将A->aAb|b改为A->aa*b*b|b,这里的*是表示什么意思?
:)
9 楼
compiler [专家分:80] 发布于 2005-06-09 23:26:00
要对递归下降的语法分析有个概念。在这个驱动程序中,主要要构造LL(1)语法分析表。把递归转化为非递归 ,然后维护一张表格。借鉴动态规划上的算法。你写的只是一个驱动,用来匹配的。对语法分析主要是是了解它的构造。
而对于LL(1)预测分析表的构造 主要是为每个非终结符构造FIRST和FOLLOW集合。了解这两个算法很重要,在语言的具体实现中,主要是一些字符串的处理。
下面 简单的说说关于FIRST和FOLLOW的构造问题。
首先对构造FIRST集合 ,我们有下列的算法。
for all non-terminals A do set FIRST(A) = { }
while there are changes to any FIRST(A) do
for each production A->X1X2...Xn do
k = 1,continue = true
while continue = true and k <= n do
add FIRST(Xk)-{e} to FIRST(A)
if e is not in FIRST(Xk)
continue = false
k = k + 1
if continue = true then add e to FIRST(A)
这个算法基本上可以构造一段程序了 。
再其次给出构造FOLLOW集合的算法
set FOLLOW(start-symbol) = {$} // $ 是终结符号。
for any non-terminals != start-symbol set FOLLOW(A) = {}
for any production A->X1X2...Xn do
if Xi is a nonterminal add FIRST(Xi+1Xi+2..Xn)-{e} to FOLLOW(Xi)
ifF e is in FIRST(Xi+1Xi+2..Xn) then
add FOLLOW(A) to FOLLOW(Xi)
// 结束
希望对你有一定的作用。
10 楼
compiler [专家分:80] 发布于 2005-06-09 23:27:00
还要再说一点,对构造LL(1)分析表 先要做的是消去左递归和回朔(提取左因子) 这两个算法我觉得还是比较复杂的。主要需要一定的数学功底
祝你好运!
我来回复