2017-01-11 3 views
1

Je reçois une sortie inattendue/manquante lors de l'exécution de l'exemple 6 dans this howto (§4.3), en utilisant flex/bison au lieu de lex/yacc, dans un environnement cygwin.bison: pseudo variables vides

Je télécharge et déballe le example files de la section téléchargement. Dans le fichier example6.compile, je remplace 'lex' par 'flex', sinon je le garde intact (la commande yacc exécute exec '/usr/bin/bison' -y "[email protected]" sur cygwin). Ensuite, je lance example6.compile. Il fonctionne sans erreurs, mais avec quelques avertissements (voir annexe). Je lance alors exemple6, et entrez le texte exemple:

zone "." { 
     type hint; 
     file "/etc/bind/db.root"; 
     type hint; 
}; 

Le résultat attendu est:

A zonefile name '/etc/bind/db.root' was encountered 
Complete zone for '.' found 

La sortie réelle est:

A zonefile name '' was encountered 
Complete zone for '' found 

Pourquoi les valeurs du pseudo variables manquantes?

Annexe

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 

Avertissements lors de la compilation:

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(); 

Répondre

2

Le « avertissement » assignment makes integer from pointer without a cast doit toujours être considéré comme une erreur, car il (presque) toujours.

Dans ce cas, ce que l'erreur vous indique est que vous essayez de stocker un pointeur (la valeur de retour de strdup, qui est char*) dans un entier (yylval).

Bien sûr, yylval ne doit pas être un nombre entier. Dans le code C dans le prologue de votre yacc/fichier bison, vous devez inclure

#define YYSTYPE char * 

Mais cette ligne ne se termine pas dans le fichier d'en-tête généré par yacc/bison. (Si tel était le cas, le fichier d'en-tête inclurait également la définition de yyerror, ce qui entraînerait des problèmes de liaison, car un exécutable ne peut avoir qu'une seule définition de fonction.)

Vous devez également inclure cette même définition #define dans le prologue de votre fichier d'entrée (f) lex, avant d'inclure le fichier d'en-tête bison (car YYSTYPE est utilisé dans ce fichier, par exemple pour déclarer yylval). Il est un peu surprenant que quelque chose qui prétend être un HOW-TO pour lex et yacc ne soit pas correct; vous pourriez envisager de soumettre un correctif.

+0

Oui, ça marche! NB! '#define YYSTYPE char *' doit être placé au-dessus de '#include" y.tab.h "' dans le fichier (f) lex pour qu'il fonctionne correctement. – matthiash

+0

@matthiash: Oui, j'aurais dû le mentionner. Je l'ai ajouté maintenant. – rici