现在我正在接受其他事情.当我这样做时,我bison -d calc.y
在控制台中获得了许多源代码(有很多m4_define
),但它不会生成任何文件.现在我的代码是这样的:
%{ #define YYSTYPE double #include%} %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 #include 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#include 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)
怎么了?
您提供的修改代码编译几乎干净利落地-你应该#include
让printf()
使用它之前宣布.(您还应该将原型用于函数 - 例如yyerror(const char *str)
,并且通常将代码拖到21世纪.)
它甚至可以正确响应'1 2 +'.
使用单个文件,您不需要使用' bison -d
'.
如果您看到垃圾,则需要查看构建命令和构建环境.
从哪里开始?
建议:掌握O'Reilly关于Lex和Yacc(来自图书馆)或Flex和Bison(2009年8月更新/重写 - 可能还没有在图书馆中)的书.如果您需要更快的资源,那么我建议使用Unix版本7手册或GNU Bison手册 - 这两本手册都可以在线获取.特别是阅读关于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
).