2015-09-12 12 views
5

Sto imparando come utilizzare i rientranti Bison e Flex insieme. Ho già un semplice calcolatore che funziona senza la capacità di rientro. Tuttavia, quando ho attivato la funzionalità di rientro e ho apportato le modifiche necessarie, non ho potuto farlo funzionare.Problemi con reentrant Flex e Bison

Ecco il codice:

scanner.l

%{ 
#include <stdio.h> 
#include "parser.tab.h" 
%} 

%option 8bit reentrant bison-bridge 
%option warn noyywrap nodefault 
%option header-file="lex.yy.h" 

DIGIT [0-9] 

%% 

"+" { return ADD; } 
"-" { return SUB; } 
"*" { return MUL; } 
"/" { return DIV; } 
{DIGIT}+ { *yylval = atof(yytext); return NUM; } 
\n  { return EOL; } 
[ \t] { } 
.  { printf("What is this: %s.\n", yytext); } 
%% 

parser.y

%{ 
#include <stdio.h> 
#include "lex.yy.h" 

void yyerror(yyscan_t scanner, char const *msg); 
%} 

%define api.value.type {double} 
%define parse.error verbose 
%define api.pure 
%lex-param {yyscan_t scanner} 
%parse-param {yyscan_t scanner} 

%token NUM EOL     
%left ADD SUB 
%left MUL DIV 

%% 

input: %empty 
| input line 
; 

line: EOL { printf("|> ");} 
| exp EOL { printf("|R> %.4lf\n", $exp); } 
; 

exp: NUM { $$ = $1; } 
| exp ADD exp { $$ = $1 + $3; } 
| exp SUB exp { $$ = $1 - $3; } 
| exp MUL exp { $$ = $1 * $3; } 
| exp DIV exp { $$ = $1/$3; } 
; 

%% 

void yyerror(yyscan_t scanner, char const *msg) { 
    fprintf(stderr, "Error: %s\n", msg); 
} 

main.c

#include <stdio.h> 
#include "parser.tab.h" 
#include "lex.yy.h" 

int main(void) { 

    yyscan_t scanner; 

    yylex_init(&scanner); 
    yyset_in(stdin, scanner); 

    yyparse(scanner); 

    yylex_destroy(scanner); 

    return 0; 
} 

e questo è il Makefile che sto usando:

all: calc.x 

parser.tab.c parser.tab.h: parser.y 
    bison -d parser.y 

lex.yy.c lex.yy.h: scanner.l parser.tab.h 
    flex scanner.l 

calc.x: lex.yy.c lex.yy.h parser.tab.c parser.tab.h 
    gcc main.c parser.tab.c lex.yy.c -o calc.x 

clean: 
    rm calc.x lex.yy.c lex.yy.h parser.tab.c parser.tab.h *.o 

esecuzione make, ho ottenuto il seguente errore:

In file included from main.c:2:0: 
parser.tab.h:66:14: error: unknown type name ‘yyscan_t’ 
int yyparse (yyscan_t scanner); 
      ^
main.c: In function ‘main’: 
main.c:12:3: warning: implicit declaration of function ‘yyparse’ [-Wimplicit-function-declaration] 
    yyparse(scanner); 
^
In file included from parser.y:5:0: 
lex.yy.h:282:1: error: unknown type name ‘YYSTYPE’ 
YYSTYPE * yyget_lval (yyscan_t yyscanner); 
^ 
lex.yy.h:284:18: error: unknown type name ‘YYSTYPE’ 
void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner); 
       ^
lex.yy.h:332:17: error: unknown type name ‘YYSTYPE’ 
       (YYSTYPE * yylval_param ,yyscan_t yyscanner); 
       ^
parser.tab.c: In function ‘yyparse’: 
parser.tab.c:1130:16: warning: implicit declaration of function ‘yylex’ [-Wimplicit-function-declaration] 
     yychar = yylex (&yylval, scanner); 
       ^
Makefile:10: recipe for target 'calc.x' failed 
make: *** [calc.x] Error 1 

Ma io non capisco l'origine di questo errore e di allarme messaggi, ad esempio:

main.c:12:3: warning: implicit declaration of function ‘yyparse’ 

Ma yyparse è già definito a parser.tab.h ed è incluso in main.c. Un altro esempio:

parser.tab.h:66:14: error: unknown type name ‘yyscan_t’ 

E dentro parser.y, sto tra cui l'intestazione dello scanner lex.yy.h.

ho trovato queste soluzioni su Internet:

Ma nessuno di essi funziona, causando errori simili. Se qualcuno mi può guidare in questa ricerca, te ne sarò grato.

Versione software

OS: Debian (testing), Bison: 3.0.4, Flex: 2.5.39, GCC 5.2.1, Marchio: 4.0.

risposta

3

Ho trovato una soluzione dopo aver armeggiato un po '. Quindi i problemi nascono da una dipendenza circolare tra flex e bisonti.

Il parser generati chiamare routine di flex in questo modo:

yychar = yylex (&yylval, scanner); 

Così nell'input bisonti dobbiamo includere il file di intestazione dello scanner lex.yy.h ed è definiscono come:

int yylex (YYSTYPE * yylval_param ,yyscan_t yyscanner); 

Ma YYSTYPE è definito nell'intestazione del parser parser.tab.h, nel mio caso ho detto a bison che il mio tipo sarà double:

typedef double YYSTYPE; 

Ora la soluzione. All'interno di scanner.l è necessario includere le intestazioni del parser in modo che il flex possa restituire i token corretti (nulla è cambiato).

Ma all'interno del parser.y è necessario includere sia il file header, se si include solo il lex.yy.h si lamentano:

lex.yy.h:282:1: error: unknown type name ‘YYSTYPE‘ 

perché YYSTYPE è definita all'interno parser.tab.h. E, infine, per qualche ragione, il parser bisonti non sa cosa yyscan_t anche con l'indicazione dell'header lexer:

error: unknown type name ‘yyscan_t’ 

Una soluzione consiste nel definire a vuoto:

%lex-param {void *scanner} 
%parse-param {void *scanner} 

vedere yyscan_t definizione: flex yyscan_t

ecco il risultato finale:

scanner.l

%{ 
#include <stdio.h> 
#include "parser.tab.h" 
%} 

%option 8bit reentrant bison-bridge 
%option warn noyywrap nodefault 
%option header-file="lex.yy.h" 

//rest of the scanner 

parser.y

%{ 
#include <stdio.h> 
#include "parser.tab.h" 
#include "lex.yy.h" 

void yyerror(yyscan_t scanner, char const *msg); 
%} 

%define api.value.type {double} 
%define parse.error verbose 
%define api.pure 
%lex-param {void *scanner} 
%parse-param {void *scanner} 

//rest of the input 

main.c

#include <stdio.h> 

#include "parser.tab.h" 
#include "lex.yy.h" 

int main(void) { 

    yyscan_t scanner; 

    yylex_init(&scanner); 
    yyset_in(stdin, scanner); 

    yyparse(scanner); 

    yylex_destroy(scanner); 

    return 0; 
} 
0

risposta accettata da Fabricio Sanches mi ha aiutato a risolvere due problemi:

  1. error: unknown type name ‘yyscan_t’ è stato effettivamente risolto passando a void *.

  2. conflitti legati alle dipendenze circolari dettare molto rigoroso ordine di importazioni:

codice in cui yyparse Flex/Bison si chiama:

#import "parser.h" 
#import "lexer.h" 

Flex (Lexer.lm):

%{ 
#import "parser.h" 
%} 

Bison (Parser.ym):

%{ 
#import "parser.h" 
#import "lexer.h" 
%} 

Ho scritto post sul blog circa il processo di creazione di parser rientrante utilizzando Flex e Bison su Mac OS con l'esempio di la sua integrazione con il progetto Xcode: Reentrant parser using Flex and Bison.

+0

Domanda: Ho impostato la configurazione dal tuo blog collegato. Potresti spiegare perché non posso includere file come "#include "? –

+0

Usi Xcode? –

+0

Sì, ci sto lavorando proprio ora guardando il tuo esempio. –