2010-07-21 15 views
5

Sto tentando di imparare un flex/bisonte e sto leggendo Flex & Bison di John Levine (O'Reilly). C'è un esempio che mi serve per correre, ma non riesco a farlo funzionare come ottengo il seguente errore:Riferimento indefinito a yyparse (flex & bison)

/tmp/ccKZcRYB.o: In function `yylex': 
fb3-1.lex.c:(.text+0x2bd): undefined reference to `yylval' 
/tmp/cclBqnOk.o: In function `main': 
fb3-1funcs.c:(.text+0x420): undefined reference to `yyparse' 
collect2: ld returned 1 exit status 

Ho quattro file di origine:

fb3-1 .h:

/* 
* Declarations for calculator fb3-1 
*/ 

/* Interface to the lexer */ 
extern int yylineno; /* from lexer */ 
void yyerror(char *s, ...); 

/* nodes in the abstract syntax tree */ 
struct ast { 
    int nodetype; 
    struct ast *l; 
    struct ast *r; 
}; 

struct numval { 
    int nodetype; /* type K for constant */ 
    double number; 
}; 

/* build an AST */ 
struct ast *newast(int nodetype, struct ast *l, struct ast *r); 
struct ast *newnum(double d); 

/* evaluate an AST */ 
double eval(struct ast *); 

/* delete and free an AST */ 
void treefree(struct ast *); 

fb3-1.l

/* recognise tokens for the calculator */ 
%option noyywrap nodefault yylineno 
%{ 
#include "fb3-1.h" 
#include "fb3-1.tab.h" 
%} 

/* float exponent */ 
EXP  ([Ee][-+]?[0-9]+) 

%% 

"+" | 
"-" | 
"*" | 
"/" | 
"|" | 
"(" | 
")"  { return yytext[0]; } 
[0-9]+"."[0-9]*{EXP}? | 
"."?[0-9]+{EXP}? { yylval.d = atof(yytext); return NUMBER; } 

\n  { return EOL; } 
"//".* 
[ \t] { /* ignore whitespace */ } 
.  { yyerror("Mystery character %c\n", *yytext); } 
%% 

fb3-1.y

/* calculator with AST */ 

%{ 
#include <stdio.h> 
#include <stdlib.h> 
#include "fb3-1.h" 
%} 

%union { 
    struct ast *a; 
    double d; 
} 

/* declare tokens */ 
%token <d> NUMBER 
%token EOL 

%type <a> exp factor term 

%% 
calclist: /* nothing */ 
| calclist exp EOL { 
    printf("=%4.4g\n",eval($2)); 
    treefree($2); 
    printf("> "); 
    } 

    | calclist EOL { printf("> "); } /* blank line or a comment */ 
    ; 

exp: factor 
| exp '+' factor { $$ = newast('+', $1, $3); } 
| exp '-' factor { $$ = newast('-', $1, $3); } 
; 

factor: term 
| factor '*' term { $$ = newast('*', $1, $3); } 
| factor '/' term { $$ = newast('/', $1, $3); } 
; 

term: NUMBER { $$ = newnum($1); } 
| '|' term { $$ = newast('|', $2, NULL); } 
| '(' term { $$ = $2; } 
| '-' term { $$ = newast('M', $2, NULL); } 
; 

%% 

fb3-1funcs.c

#include <stdio.h> 
#include <stdlib.h> 
#include <stdarg.h> 
#include "fb3-1.h" 

struct ast * newast(int nodetype, struct ast *l, struct ast *r) 
{ 
    struct ast *a = malloc(sizeof(struct ast)); 

    if(!a) { 
     yyerror("out of space"); 
     exit(0); 
    } 

    a->nodetype = nodetype; 
    a->l = l; 
    a->r = r; 
    return a; 
} 

struct ast * newnum(double d) 
{ 
    struct numval *a = malloc(sizeof(struct numval)); 

    if(!a) { 
     yyerror("out of space"); 
     exit(0); 
    } 

    a->nodetype = 'K'; 
    a->number = d; 
    return (struct ast *)a; 
} 

double eval (struct ast *a) 
{ 
    double v; 

    switch(a->nodetype) { 
     case 'K': v = ((struct numval *)a)->number; break; 

     case '+': v = eval(a->l) + eval(a->r); break; 
     case '-': v = eval(a->l) + eval(a->r); break; 
     case '*': v = eval(a->l) + eval(a->r); break; 
     case '/': v = eval(a->l) + eval(a->r); break; 
     case '|': v = eval(a->l); if(v < 0) v = -v; break; 
     case 'M': v = -eval(a->l); break; 
     default: printf("internal error: bad node %c\n", a->nodetype); 
    } 
} 

void treefree(struct ast *a) 
{ 
    switch(a->nodetype) 
    { 
     /* two subtrees */ 
     case '+': 
     case '-': 
     case '*': 
     case '/': 
      treefree(a->r); 

     /* one subtree */ 
     case '|': 
     case 'M': 
      treefree(a->l); 

     /* no subtree */ 
     case 'K': 
      free(a); 
      break; 

     default: printf("internal error: free bad node %c\n", a->nodetype); 
    } 
} 

void yyerror(char *s, ...) 
{ 
    va_list ap; 
    va_start(ap, s); 

    fprintf(stderr, "%d: error: ", yylineno); 
    vfprintf(stderr, s, ap); 
    fprintf(stderr, "\n"); 
} 

int main() 
{ 
    printf("> "); 
    return yyparse(); 
} 

per costruire il:

bison -d fb3-1.y 
flex -ofb3-1.lex.c fb3-1.l 
cc -o [email protected] fb3-1.tab.c fb3-1.lex.c fb3-1funcs.c 

Io corro Ubuntu 10.04 x64, con i pacchetti "flex" e "bison" installati. Qualcuno sa perché questo errore sta accadendo e come risolverlo? Grazie in anticipo :)

+0

hey man, hai la risposta giusta da questa calcolatrice? mi dà una strana risposta –

+0

@MohammadGhorbani Scusa compagno che non ricordo! Non ho toccato nessun flex-bisonte o qualsiasi cosa ad esso correlata dal 2010, quindi tutto ciò mi sembra incomprensibile ora! – Tom

risposta

3

risolto, il comando

cc -o [email protected] fb3-1.tab.c fb3-1.lex.c fb3-1funcs.c 

Dovrebbe essere

cc -o fb3 fb3-1.tab.c fb3-1.lex.c fb3-1funcs.c 

Non certo perché il libro non ha specificato che per l'esempio.

0

Ho letto anche quel capitolo e credo che l'autore stia indicando che il codice dovrebbe essere inserito in un "Makefile" per automatizzare il processo di compilazione di tali file.

$ @ è un'espansione variabile utilizzata negli script di shell bash (tra l'altro) e probabilmente fa la stessa cosa in make o è esattamente la stessa cosa che sta implementando make.

+1

No, '$ @' per la shell significa "gli argomenti di questo script/funzione", mentre '$ @' per Make significa "il target corrente", che è destinato a essere 'fb3' qui, infatti. – akim

Problemi correlati