现在我正在接受其他事情。当我执行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)
有什么问题?
答案 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'。yylex()
和main()
上设置返回类型。yylval
。幸运的是,Bison的“zzz.tab.h”文件可以正确地执行此操作;它并不像看起来那么简单。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 。