Reputation: 3243
I'm getting unexpected/missing output when running example 6 in this howto (§4.3), using flex/bison instead of lex/yacc, in a cygwin environment.
I download and unpack the example files from the download section. In the file example6.compile I substitute 'lex' with 'flex', otherwise keep it intact (the command yacc executes exec '/usr/bin/bison' -y "$@"
on cygwin). Then I run example6.compile. It runs without errors, but with a few warnings (see appendix).
I then run example6, and input the example text:
zone "." {
type hint;
file "/etc/bind/db.root";
type hint;
};
The expected output is:
A zonefile name '/etc/bind/db.root' was encountered
Complete zone for '.' found
The actual output is:
A zonefile name '' was encountered
Complete zone for '' found
Why are the values of the pseudo variables missing?
Appendix
example6.compile:
flex example6.l
yacc --verbose --debug -d example6.y
cc lex.yy.c y.tab.c -o example6
example6.l:
%{
#include <stdio.h>
#include "y.tab.h"
%}
%%
zone return ZONETOK;
file return FILETOK;
[a-zA-Z][a-zA-Z0-9]* yylval=strdup(yytext); return WORD;
[a-zA-Z0-9\/.-]+ yylval=strdup(yytext); return FILENAME;
\" return QUOTE;
\{ return OBRACE;
\} return EBRACE;
; return SEMICOLON;
\n /* ignore EOL */;
[ \t]+ /* ignore whitespace */;
%%
example6.y:
%{
#include <stdio.h>
#include <string.h>
#define YYSTYPE char *
int yydebug=0;
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str);
}
int yywrap()
{
return 1;
}
main()
{
yyparse();
}
%}
%token WORD FILENAME QUOTE OBRACE EBRACE SEMICOLON ZONETOK FILETOK
%%
commands:
|
commands command SEMICOLON
;
command:
zone_set
;
zone_set:
ZONETOK quotedname zonecontent
{
printf("Complete zone for '%s' found\n",$2);
}
;
zonecontent:
OBRACE zonestatements EBRACE
quotedname:
QUOTE FILENAME QUOTE
{
$$=$2;
}
;
zonestatements:
|
zonestatements zonestatement SEMICOLON
;
zonestatement:
statements
|
FILETOK quotedname
{
printf("A zonefile name '%s' was encountered\n", $2);
}
;
block:
OBRACE zonestatements EBRACE SEMICOLON
;
statements:
| statements statement
;
statement: WORD | block | quotedname
Warnings when compiling:
example6.l: In function ‘yylex’:
example6.l:10:7: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
[a-zA-Z][a-zA-Z0-9]* yylval=strdup(yytext); return WORD;
^
example6.l:11:7: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
[a-zA-Z0-9\/.-]+ yylval=strdup(yytext); return FILENAME;
^
example6.y:19:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
main()
^
example6.y: In function ‘main’:
example6.y:21:2: warning: implicit declaration of function ‘yyparse’ [-Wimplicit-function-declaration]
yyparse();
^
y.tab.c: In function ‘yyparse’:
y.tab.c:1164:16: warning: implicit declaration of function ‘yylex’ [-Wimplicit-function-declaration]
yychar = yylex ();
Upvotes: 1
Views: 324
Reputation: 241911
The "warning" assignment makes integer from pointer without a cast
should always be considered an error, since it (almost) always is.
In this case, what the error is telling you is that you are attempting to store a pointer (the return value of strdup
, which is char*
) into an integer (yylval
).
Of course, yylval
should not be an integer. In the C code in the prologue of your yacc/bison file, you include
#define YYSTYPE char *
But that line does not end up in the header file generated by yacc/bison. (If it did, the header file would also include the definition of yyerror
, for example, which would lead to linkage problems since an executable can only have a single definition of a function.)
So you must also include that same #define
in the prologue of your (f)lex input file, before you include the bison header file (because YYSTYPE
is used in that file, for example to declare yylval
). It is a little surprising that something which claims to be a HOW-TO for lex and yacc does not get this correct; you might want to consider submitting a bugfix.
Upvotes: 2