J'essaye de compiler un exemple du livre flex and Bison
. Je me demandais pourquoi j'avais l'erreur de construction suivante et comment puis-je la corriger?
/* recognize tokens for the calculator and print them out */ %{ # include "fb1-5.tab.h" %} %% "+" { return ADD; } "-" { return SUB; } "*" { return MUL; } "/" { return DIV; } "|" { return ABS; } "(" { return OP; } ")" { return CP; } [0-9]+ { yylval = atoi(yytext); return NUMBER; } \n { return EOL; } "//".* [ \t] { /* ignore white space */ } . { yyerror("Mystery character %c\n", *yytext); } %%
Makefile:
/* simplest version of calculator */ %{ # include <stdio.h> %} /* declare tokens */ %token NUMBER %token ADD SUB MUL DIV ABS %token OP CP %token EOL %% calclist: /* nothing */ | calclist exp EOL { printf("= %d\n> ", $2); } | calclist EOL { printf("> "); } /* blank line or a comment */ ; exp: factor | exp ADD exp { $$ = $1 + $3; } | exp SUB factor { $$ = $1 - $3; } | exp ABS factor { $$ = $1 | $3; } ; factor: term | factor MUL term { $$ = $1 * $3; } | factor DIV term { $$ = $1 / $3; } ; term: NUMBER | ABS term { $$ = $2 >= 0? $2 : - $2; } | OP exp CP { $$ = $2; } ; %% main() { printf("> "); yyparse(); } yyerror(char *s) { fprintf(stderr, "error: %s\n", s); }
fb1-5.y
fb1-5: fb1-5.l fb1-5.y bison -d fb1-5.y flex fb1-5.l cc -o fb1-5.tab.c lex.yy.c -lfl
fb1- 5.l:
$ make bison -d fb1-5.y fb1-5.y: warning: 3 shift/reduce conflicts [-Wconflicts-sr] flex fb1-5.l cc -o fb1-5.tab.c lex.yy.c -lfl fb1-5.l: In function âyylexâ: fb1-5.l:27:3: warning: implicit declaration of function âyyerrorâ; did you mean âperrorâ? [-Wimplicit-function-declaration] . { yyerror("Mystery character %c\n", *yytext); } ^~~~~~~ perror /tmp/cctl5WLj.o: In function `yylex': lex.yy.c:(.text+0x32f): undefined reference to `yylval' lex.yy.c:(.text+0x363): undefined reference to `yyerror' collect2: error: ld returned 1 exit status Makefile:2: recipe for target 'fb1-5' failed make: *** [fb1-5] Error 1
3 Réponses :
Je suppose que le problème est ici
cc -o lex.yy.c fb1-5.tab.c -lfl
Merci. (1) pouvez-vous expliquer pourquoi l'erreur dans mon message? (2) exécutez votre commande, cc: error: fb1-5.tab.c: No such file or directory
. (3) Le fichier de sortie de flex
est-il toujours lex.yy.c
? Peut-il y avoir plus d'un fichier flex d'entrée dans le même répertoire, et donc en écrasant les uns les autres?
@tim: vous pouvez dire à flex quel nom de fichier utiliser avec l'option -o
, tout comme cc
. Dans les deux cas, vous devez suivre l'option avec le nom du fichier de sortie souhaité. (Quel est le problème avec votre appel cc
.)
êtes-vous sûr que bison -d fb1-5.y produit réellement fb1-5.tab.c?
non si vous le compilez avec le même nom, il l'écrasera s'il se compile avec succès
Il y a deux problèmes distincts ici.
yyerror
n'est pas déclaré dans votre scanner (ou, pour ce mattet dans votre analyseur). Bison ne génère pas de déclaration pour cela, vous devez donc le déclarer dans n'importe quelle unité de traduction qui l'utilise.
cc -o fb1-5.tab.c lex.yy.c -lfl
indique au compilateur C de compiler lex.yy.c
en plaçant le l'exécutable résultant (la sortie du compilateur) dans fb1-5.tab.c
. Ce n'est pas ce que vous vouliez. Il écrase l'analyseur généré par un exécutable et ne compile pas l'analyseur généré avec le résultat que les symboles définis dans l'analyseur ne sont pas disponibles pour l'éditeur de liens.
Merci. (1) yyerror
est défini dans fb1-5.y
. (2) cc -o fb-1.5 fb1-5.tab.c lex.yy.c -lfl -ly
ne fonctionne pas, car cc: erreur: fb1-5.tab .c: aucun fichier ou répertoire de ce type
@tim: le fait que yyerror
soit défini dans l'analyseur ne rend pas sa déclaration disponible dans le lexer. Le compilateur se plaint que yyerror n'est pas déclaré, ce qui est différent de l'éditeur de liens se plaignant qu'il n'est pas défini.
Je ne sais pas pourquoi bison ne crée pas fb1-5.tab.c
; cela avait probablement à voir avec un peu de bizarrerie dans votre distribution. Ajoutez -o fb1-5.tab.c
à votre commande bison.
J'ai utilisé le fichier make dans le livre, ce qui ne semble pas correct.
@tim: le makefile dans le livre dit -o $ @
. Vous avez omis le $ @
. (Mais $ @
est une syntaxe de création. Cela ne fonctionnera pas sur la ligne de commande.)
pourquoi le livre ne spécifie-t-il pas -ly
? N'est-ce pas nécessaire? Quelles sont exactement les bibliothèques à lier?
@tim: vraiment ni -ly ni -lfl ne sont nécessaires. Les deux bibliothèques définissent une implémentation par défaut de main ()
. (Celui de -ly
appelle yyparse
et celui de -lfl
appelle yylex
.) - lfl
contient également une implémentation par défaut de yywrap
; ajoutez plutôt % option noyywrap
à votre prologue flex.
Qu'est-ce que bison --version
imprime? Et qu'en est-il de quel bison
?
Les deux bibliothèques sont-elles nécessaires au programme et à la liaison? Si oui, comment cc
les trouve-t-il? bison (GNU Bison) 3.0.4
/ usr / bin / bison
Quelle ligne ajouter au fichier flex? Je trouve que sans -lfl
cc
signale une erreur, alors que sans -ly
cela fonctionne toujours, et je ne comprends toujours pas la raison.
@tim: veuillez relire mon commentaire précédent (commençant par "vraiment ni l'un ni l'autre")
Vous devez changer votre makefile en:
fb1-5: fb1-5.l fb1-5.y bison -b fb1-5 -d fb1-5.y flex fb1-5.l gcc -o fb1-5 fb1-5.tab.c lex.yy.c -lfl -ly
pour produire le fichier de sortie correct et avoir une implémentation standard de yyerror
Merci. Quelles sont exactement les bibliothèques à lier?
@Tim liby définit une implémentation yyerror ()
(si aucune autre n'est définie), -lfl
fournit une implémentation par défaut yywrap
. Au moins sur mon système, d'autres systèmes peuvent gérer cela autrement. Habituellement, -ly
et -ll
(ou -lfl
) doivent être spécifiés pour être sûrs sur de nombreuses plates-formes.
Vous avez votre propre implémentation de yyerror ()
, donc vous n'auriez probablement pas besoin de -ly
pour cela, mais cela ne fait pas de mal.
cc: error: fb1-5.tab.c: aucun fichier ou répertoire de ce type