请大家邦看看这个yacc的的文件

发布于 2022-09-23 15:14:26 字数 4400 浏览 13 评论 0

产生式是:
    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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

格子衫的從容 2022-09-30 15:14:26

你的程序写错了,
比如
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的内容一样吗?

℡寂寞咖啡 2022-09-30 15:14:26

原帖由 cjaizss 于 2009-2-12 19:28 发表
你的程序写错了,
比如
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); ...

多谢 cjaizss 版主 一直以来对我的帮助

傾城如夢未必闌珊 2022-09-30 15:14:26

终于解决了错误了,现在能处理象下图这样的语法(多层嵌套)了:

未命名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 编辑 ]

别再吹冷风 2022-09-30 15:14:26

呵呵,不用谢。我的回复能给你带来一点方便,至少我也是欣慰的

土豪我们做朋友吧 2022-09-30 15:14:26

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 编辑 ]

江南烟雨〆相思醉 2022-09-30 15:14:26

无论如何,起始字符只有一个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  
;

慕巷 2022-09-30 15:14:26

版主你好:

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;  

鹿港巷口少年归 2022-09-30 15:14:26

哦,没看到,呵呵.
这里的语法其实没有歧异,但是必须要看后面的字符(后面甚至无穷远处)才可以被规约,但YACC可能就看不到这么远,所以YACC意识不到这里的无歧义性.

以酷 2022-09-30 15:14:26

也就是说:
(注意:非终结字符最好不要用单个小写字母,这属于计算原理里的规矩,,虽然计算机里会用小写字母,但好象没看过有人用单个小写字母,所以你用i是不太规范的)
比如
大写是非终结字符,小写是终结字符.
S->A ;
S->A S;
A->A A b;
A->c
以上虽没有歧异,但按照yacc的处理,
对于AA*,yacc不知道怎么处理了

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文