请大家邦看看这个yacc的的文件
产生式是:
i -> i vi
i -> LD | LDI
vi -> OR | ORI | vo
vo -> AND | ANI
*.y文件是:
/*myplc3.y*/
%{
#define YYSTYPE double /*定义语义值的C数据类型*/
#include <math.h>
#include <stdio.h>
#include <ctype.h>
int yylex (void);
void yyerror (char const *);
char sssss[][10]={"LD\0","OR\0","LDI\0","OR\0","AND\0","ANB\0"};
int i=0;
%}
%token ANB ORB LD LDI OR ORI AND ANI OUT SPC MPS MRD MPP STL /*ID*/
/*%left LD LDI OUT SPC*/
%%
i : i vi
| LD /*ID*/
| LDI /*ID*/
;
vi : OR /*ID*/
| ORI /*ID*/
| vo
;
vo : AND /*ID*/
| ANI /*ID*/
;
%%
int yylex(void)
{
char x[20];
strcpy(x,sssss);
i++;
if(i>2) return -1;
else
if (strcmp(x,"LD")) {printf("i=%d,x=%s\n",i-1,x);return LD;}
else
if (strcmp(x,"LDI")) {printf("i=%d,x=%s\n",i-1,x);return LDI;}
else
if (strcmp(x,"OR")) {printf("i=%d,x=%s\n",i-1,x);return OR;}
else
if (strcmp(x,"ORI")) {printf("i=%d,x=%s\n",i-1,x);return ORI;}
else
if (strcmp(x,"AND")) {printf("i=%d,x=%s\n",i-1,x);return AND;}
else
if (strcmp(x,"ANI")) {printf("i=%d,x=%s\n",i-1,x);return ANI;}
else
if (strcmp(x,"ANB")) {printf("i=%d,x=%s\n",i-1,x);return ANB;}
else
if (strcmp(x,"ORB")) {printf("i=%d,x=%s\n",i-1,x);return ORB;}
}
void yyerror (char const *s)
{
fprintf (stderr, "%s\n", s);
}
int main()
{
return yyparse();
}
词法分析程序中用数组模拟输入token,现在是输入最简单的两个:LD OR
编译:
d:\>yacc -d -v myplc3.y
d:\>gcc y.tab.c
d:\>a
运行结果是:
i=0,x=LD
i=1,x=OR
syntax error
为什么有语法错呢?难道这产生式还有错么?
谢谢
[ 本帖最后由 liuzq71 于 2009-2-12 13:13 编辑 ]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
你的程序写错了,
比如
if (strcmp(x,"LD")) {printf("i=%d,x=%s\n",i-1,x);return LD;}
我想你的意思应该是
if (!strcmp(x,"LD")) {printf("i=%d,x=%s\n",i-1,x);return LD;}
吧
再者,
strcpy(x,sssss);
这不每次copy的内容一样吗?
多谢 cjaizss 版主 一直以来对我的帮助
终于解决了错误了,现在能处理象下图这样的语法(多层嵌套)了:
未命名998877.JPG (19.94 KB, 下载次数: 1)
下载附件
2009-02-12 21:02 上传
......
以下的yacc的*.y文件的手写词法分析函数yylex()中用数组来模拟输入
编译:
d:\>yacc -d -v myplc3.y
d:\>gcc y.tab.c
d:\>a
//myplc3.y
%{
#define YYSTYPE double //定义语义值的C数据类型
#include <math.h>
#include <stdio.h>
#include <ctype.h>
#include "y.tab.h"
int yylex();
void yyerror (char const *s);
char *strs[]={"LD","OR","LDI","OR","AND","ANB","LD","OR","LDI","OR","AND","ORB","ANB"};
int lines[]={LD,OR,LDI,OR,AND,ANB,LD,OR,LDI,OR,AND,ORB,ANB},i;
%}
%token ANB ORB LD LDI OR ORI AND ANI OUT SPC MPS MRD MPP STL //ID
//%left LD LDI OUT SPC
%%
i : i i ANB
| i i ORB
| i vi
| LD //ID
| LDI //ID
;
vi : OR //ID
| ORI //ID
| vo
;
vo : AND //ID
| ANI //ID
;
%%
int yylex()
{
int j=i++;
if(i>13) return -1; //结束输入
else
{
printf("%s\n",strs[j]);
return lines[j];
}
}
void yyerror (char const *s)
{
fprintf (stderr, "%s\n", s);
}
int yywrap()
{
return 1;
}
int main()
{
return yyparse();
}
[ 本帖最后由 liuzq71 于 2009-2-12 21:14 编辑 ]
呵呵,不用谢。我的回复能给你带来一点方便,至少我也是欣慰的
cjaizss 版主请再邦助一下好么:下面的*.y文件,用yacc处理时没提示冲突,
//myplc.y
%{
#define YYSTYPE double //定义语义值的C数据类型
#include <math.h>
#include <stdio.h>
#include <ctype.h>
#include "y.tab.h"
int yylex();
void yyerror (char const *s);
char *strs[]={"STL","LD","LD","ORB","STL","LD","OR","RET"};
int lines[]={STL,LD,LD,ORB,STL,LD,OR,RET},i;
%}
%token ANB ORB LD LDI OR ORI AND ANI OUT SPC MPS MRD MPP STL RET //ID
//%left LD LDI OUT SPC
%start stc1
%%
stc1 : i
i : i i ANB
| i i ORB
| i vi
| LD
| LDI
;
vi : OR
| ORI
| vo
;
vo : AND
| ANI
;
%%
int yylex()
{
int j=i++;
if(i> return -1; //结束输入
else
{
printf("%s\n",strs[j]);
return lines[j];
}
}
void yyerror (char const *s)
{
fprintf (stderr, "%s\n", s);
}
int yywrap()
{
return 1;
}
int main()
{
return yyparse();
}
可换成如下,添加了stc2之后就有两个shift/reduce冲突了,为什么啊?是不是我将产生式改写错了?
//myplc.y
%{
#define YYSTYPE double //定义语义值的C数据类型
#include <math.h>
#include <stdio.h>
#include <ctype.h>
#include "y.tab.h"
int yylex();
void yyerror (char const *s);
char *strs[]={"STL","LD","LD","ORB","STL","LD","OR","RET"};
int lines[]={STL,LD,LD,ORB,STL,LD,OR,RET},i;
%}
%token ANB ORB LD LDI OR ORI AND ANI OUT SPC MPS MRD MPP STL RET //ID
//%left LD LDI OUT SPC
%start stc2
%%
stc1 : i //o
;
stc2 : stc2x RET //EBNF: stc2 -> stc2x {stc2x} RET ,stc2是步进指令块
| stc2x stc2
;
stc2x : STL stc1 //EBNF: stc2x -> STL stc1 {stc1} ,stc2x是单个步进指令
| stc2x stc1;
i : i i ANB
| i i ORB
| i vi
| LD
| LDI
;
vi : OR
| ORI
| vo
;
vo : AND
| ANI
;
%%
int yylex()
{
int j=i++;
if(i> return -1; //结束输入
else
{
printf("%s\n",strs[j]);
return lines[j];
}
}
void yyerror (char const *s)
{
fprintf (stderr, "%s\n", s);
}
int yywrap()
{
return 1;
}
int main()
{
return yyparse();
}
[ 本帖最后由 liuzq71 于 2009-2-16 09:30 编辑 ]
无论如何,起始字符只有一个stc1
所以,在这里,你的stc2/stc2x都是没有用的规则.
当然这与你想要的答案没有必然联系,但是你还是先改了再说吧
stc1 : i //o
;
stc2 : stc2x RET //EBNF: stc2 -> stc2x {stc2x} RET ,stc2是步进指令块
| stc2x stc2
;
stc2x : STL stc1 //EBNF: stc2x -> STL stc1 {stc1} ,stc2x是单个步进指令
| stc2x stc1;
i : i i ANB
| i i ORB
| i vi
| LD
| LDI
;
vi : OR
| ORI
| vo
;
vo : AND
| ANI
;
版主你好:
6楼 的程序1中是%start stc1,而程序2是%start stc2,而程序2中有2个shift/recude conflicts,为什么呢?
另外,右边的EBNF转化成左边的BNF是否正确?
stc2 : stc2x RET //EBNF: stc2 -> stc2x {stc2x} RET ,stc2是步进指令块
| stc2x stc2
;
stc2x : STL stc1 //EBNF: stc2x -> STL stc1 {stc1} ,stc2x是单个步进指令
| stc2x stc1;
哦,没看到,呵呵.
这里的语法其实没有歧异,但是必须要看后面的字符(后面甚至无穷远处)才可以被规约,但YACC可能就看不到这么远,所以YACC意识不到这里的无歧义性.
也就是说:
(注意:非终结字符最好不要用单个小写字母,这属于计算原理里的规矩,,虽然计算机里会用小写字母,但好象没看过有人用单个小写字母,所以你用i是不太规范的)
比如
大写是非终结字符,小写是终结字符.
S->A ;
S->A S;
A->A A b;
A->c
以上虽没有歧异,但按照yacc的处理,
对于AA*,yacc不知道怎么处理了