matthiash
matthiash

Reputation: 3243

bison: empty pseudo variables

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

Answers (1)

rici
rici

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

Related Questions