使用野牛时的错误

时间:2009-10-11 16:05:07

标签: c parsing bison

现在我正在接受其他事情。当我执行bison -d calc.y时,我在控制台中获得了许多源代码(包含许多m4_define),但它不会生成任何文件。现在我的代码是这样的:

%{
#define YYSTYPE double
#include <math.h>
%}
%token NUM
%%
input:    /* empty */
        | input line
;

line:     '\n'
        | exp '\n'  { printf ("\t%.10g\n", $1); }
;

exp:      NUM             { $$ = $1;         }
        | exp exp '+'     { $$ = $1 + $2;    }
        | exp exp '-'     { $$ = $1 - $2;    }
        | exp exp '*'     { $$ = $1 * $2;    }
        | exp exp '/'     { $$ = $1 / $2;    }
      /* Exponentiation */
        | exp exp '^'     { $$ = pow ($1, $2); }
      /* Unary minus    */
        | exp 'n'         { $$ = -$1;        }
;
%%

/* Lexical analyzer returns a double floating point 
   number on the stack and the token NUM, or the ASCII
   character read if not a number.  Skips all blanks
   and tabs, returns 0 for EOF. */

#include <ctype.h>
#include <stdio.h>

yylex ()
{
  int c;

  /* skip white space  */
  while ((c = getchar ()) == ' ' || c == '\t')  
    ;
  /* process numbers   */
  if (c == '.' || isdigit (c))                
    {
      ungetc (c, stdin);
      scanf ("%lf", &yylval);
      return NUM;
    }
  /* return end-of-file  */
  if (c == EOF)                            
    return 0;
  /* return single chars */
  return c;                                
}

yyerror (s)  /* Called by yyparse on error */
     char *s;
{
  printf ("%s\n", s);
}

main ()
{
  yyparse ();
}

原始问题

我正在尝试创建自己的开发语言,但它很难开始,因为我开始,我遇到很多错误,我不知道如何解决。这是我的代码:

#include <ctype.h>
#include <stdio.h>

yylex ()
{
  int c;

  /* skip white space  */
  while ((c = getchar ()) == ' ' || c == '\t')  
    ;
  /* process numbers   */
  if (c == '.' || isdigit (c))                
    {
      ungetc (c, stdin);
      scanf ("%lf", &yylval);
      return NUM;
    }
  /* return end-of-file  */
  if (c == EOF)                            
    return 0;
  /* return single chars */
  return c;                                
}

main ()
{
  yyparse ();
}

calc.y源代码文件:

%token NUM
%%
input:
        | input line
;

line:     '\n'
        | exp '\n'  { printf ("\t%.10g\n", $1); }
;

exp:      NUM             { $$ = $1;         }
        | exp exp '+'     { $$ = $1 + $2;    }
        | exp exp '-'     { $$ = $1 - $2;    }
        | exp exp '*'     { $$ = $1 * $2;    }
        | exp exp '/'     { $$ = $1 / $2;    }
      /* Exponentiation */
        | exp exp '^'     { $$ = pow ($1, $2); }
      /* Unary minus    */
        | exp 'n'         { $$ = -$1;        }
;
%%

现在编译日志:

C:\Documents and Settings\Nathan Campos\Desktop>gcc calc.tab.c -lm -o rpcalc
calc.tab.c: In function `yylex':
calc.tab.c:15: error: `yylval' undeclared (first use in this function)
calc.tab.c:15: error: (Each undeclared identifier is reported only once
calc.tab.c:15: error: for each function it appears in.)
calc.tab.c:16: error: `NUM' undeclared (first use in this function)

有什么问题?

4 个答案:

答案 0 :(得分:6)

修订答案

您提供的修改后的代码几乎干净地编译 - 您应该#include <stdio.h>以便在使用之前声明printf()。 (您还应该将原型用于函数 - 例如yyerror(const char *str),并且通常将代码拖到21世纪。)

它甚至可以正确回应'1 2 +'。

使用单个文件,您无需使用“bison -d”。

如果您看到垃圾,则需要查看构建命令和构建环境。


原始答案

从哪里开始?

建议:在Lex and Yacc(来自图书馆)或Flex and Bison(2009年8月更新/重写 - 可能尚未在图书馆中)获取O'Reilly书籍。如果您需要更快的资源,那么我建议使用Unix Version 7手册或GNU Bison manual - 两者都可以在线获取。特别是阅读关于Lex和Yacc的第7版文件;你并没有尝试做原始描述中没有涉及的内容(尽管C代码在C89标准之前已经过了十年或更长时间)。

  • 您需要使用bison -d生成包含令牌编号的标头。对于源文件'zzz.y',这将生成C代码'zzz.tab.c'和'zzz.tab.h'。
  • 您需要在主程序中包含“zzz.tab.h”。
  • 您需要使用C99,因此应在yylex()main()上设置返回类型。
  • 您需要声明yylval。幸运的是,Bison的“zzz.tab.h”文件可以正确地执行此操作;它并不像看起来那么简单。
  • 您可能希望在词法分析器(-3.1416)中允许使用负数。您可能也希望允许显式正数(+3.1416)。
  • 您可能需要确保'$$'和朋友的类型为double,而不是默认类型int#define YYSTYPE double)。

答案 1 :(得分:2)

IIRC,yylval由Bison宣布,但你必须提供类型。如果没有这个,编译器会感到困惑并且会产生误导性错误。

您需要定义YYSTYPE。在你的情况下,你可以使用“#define YYSTYPE double”。在语法中,在靠近顶部的%{...%}块中执行此操作。

%union也可用于将YYSTYPE声明为联合。

这看起来像Bison手册标准的rpcalc示例,所以我假设你可以很容易地查找“YYSTYPE”和“%union”。

答案 2 :(得分:1)

在.y文件中添加以下行:

void yyerror(char *errorinfo);
int yylex(void);

您还需要定义由flex生成的令牌类型:

%token NUM

等等。

编辑:Flex and Bison(O'Reilly)是一个很好的资源。

答案 3 :(得分:0)

您尚未在任何地方声明变量 yylval