【发布时间】:2020-10-25 08:49:49
【问题描述】:
我正在关注经典的 Kernighan & Pike Unix 编程环境;特别是涵盖 yacc 的章节。 在第一个示例中,使用 yacc 准备了一个名为 hoc1 的基本计算器。
按照本书我准备以下代码:
%{
#define YYSTYPE double
%}
%token NUMBER
%left '+' '-'
%left '*' '/'
%%
list:
| list '\n'
| list expr '\n' { printf("\t%.8g\n", $2); }
;
expr: NUMBER { $$ = $1; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| '(' expr ')' { $$ = $2; }
;
%%
#include <stdio.h>
#include <ctype.h>
char *progname;
int lineno = 1;
int main(int argc, char *argv[]) {
progname = argv[0];
yyparse();
}
int yylex(void) {
int c;
/* Left trim all spaces/tabs */
while((c=getchar()) == ' ' || c == '\t');
/* Return 0 if EOF */
if(c== EOF) {
return 0;
}
/* Return NUMBER if number */
if(c=='.' || isdigit(c)) {
ungetc(c,stdin);
scanf("%lf", &yylval);
return NUMBER;
}
/* Count lines */
if(c=='\n') {
lineno++;
}
return c;
}
void yyerror(char *s) {
warning(s, (char *)0);
}
void warning(char *s, char *t) {
fprintf(stderr, "%s: %s", progname, s);
if(t) {
fprintf(stderr, " %s", t);
}
fprintf(stderr, " near line %d\n", lineno);
}
但我在编译程序时遇到以下错误:
~/tutorials/unix_programming_environment/hoc1 % yacc hoc1.y
~/tutorials/unix_programming_environment/hoc1 % cc y.tab.c -o hoc1
hoc1.y:64:2: warning: implicit declaration of function 'warning' is invalid in C99 [-Wimplicit-function-declaration]
warning(s, (char *)0);
^
hoc1.y:68:6: error: conflicting types for 'warning'
void warning(char *s, char *t) {
^
hoc1.y:64:2: note: previous implicit declaration is here
warning(s, (char *)0);
^
1 warning and 1 error generated.
我既不理解警告也不理解错误。
编辑:在 FreeBSD 12.1 中使用 yacc
【问题讨论】:
-
@zwol:为什么你认为问题是
yacc中的一个错误,而不是他们在使用之前没有声明warning? -
请记住,这本书出版于 1984 年,早在标准 C 出现之前。当时也没有可靠的
void类型。也没有<stdlib.h>。 -
@EricPostpischil 哎呀。我没有注意到滚动条,所以我认为错误代码来自解析器框架。
-
其实这本书使用的是K&R风格(我没用过)。因此,我尝试将示例改编为 ANSI C89。