I am following the classic Kernighan & Pike The Unix Programming Environment; specifically the chapter that covers yacc. In the first example, a basic calculator named hoc1 is prepared with yacc.
Following the book I prepare the following code:
%{
#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);
}
But I get the following error while compiling the program:
~/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.
I do not understand neither the warning or the error.
Edit: using yacc in FreeBSD 12.1
Move the definition of the yyerror
function after the definition of the warning
function or put this line before the yyerror
function:
void warning(char *, char *);
This compiler message:
hoc1.y:64:2: warning: implicit declaration of function 'warning' is invalid in C99 [-Wimplicit-function-declaration]
tells you that the function warning
is being used before any declaration of it is seen. This results in an implicit declaration due to the history of the C language.
This compiler message:
hoc1.y:68:6: error: conflicting types for 'warning'
tells you that the actual definition of warning
has a different type than that of the implicit declaration from above.
This solution to this is to declare warning
before using it, which you can do either by putting the definition (which is a declaration) before the use or by putting a separate declaration before the use.