2015-09-12 22 views
5

Uczę się, jak korzystać z wielokrotnych połączeń Bison i Flex. Mam już prosty kalkulator działający bez możliwości ponownego wprowadzania. Jednak po aktywowaniu funkcji ponownego wprowadzania i wprowadzeniu niezbędnych modyfikacji nie mogłem tego uruchomić.Problemy z powtórką Flex i Bisonem

Oto kod:

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; 
} 

i to jest Makefile Używam:

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 

Running make, mam następujący błąd:

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 

Ale nie zrozumieć pochodzenie tego błędu i ostrzeżenia wiadomości, na przykład:

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

Ale yyparse jest już zdefiniowane na parser.tab.h i jest zawarte w main.c. Inny przykład:

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

A wewnątrz parser.y, jestem w tym nagłówku skanera lex.yy.h.

Znalazłem te rozwiązania w internecie:

Ale żaden z nich nie działa, co powoduje podobne błędy. Jeśli ktoś mógłby mnie poprowadzić w tym zadaniu, będę wdzięczny.

wersja oprogramowania

OS: Debian (testing), Żubr: 3.0.4, Flex: 02.05.39, GCC: 5.2.1, Marka: 4,0.

Odpowiedz

3

Znalazłem rozwiązanie po odrobinę tinkering. Tak więc problemy wynikają z okrężnej zależności między flexem a bizonem.

Parser wygenerowany zadzwonić elastycznego rutynowych w ten sposób:

yychar = yylex (&yylval, scanner); 

Więc na wejściu żubrów musimy dołączyć plik nagłówka skaner lex.yy.h i to zdefiniować jako:

int yylex (YYSTYPE * yylval_param ,yyscan_t yyscanner); 

Ale YYSTYPE jest zdefiniowane w nagłówku parsera parser.tab.h, w moim przypadku powiedziałem żubrowi, że mój typ będzie double:

typedef double YYSTYPE; 

Teraz rozwiązanie. Wewnątrz scanner.l należy uwzględnić nagłówki parsera, aby flex mógł zwracać prawidłowe tokeny (nic się nie zmieniło).

Ale wewnątrz parser.y musi obejmować zarówno plik nagłówki, jeśli to tylko lex.yy.h będzie narzekać:

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

ponieważ YYSTYPE jest zdefiniowana wewnątrz parser.tab.h. I wreszcie, z jakiegoś powodu, żubr parser nie wie co yyscan_t nawet w tym nagłówku Lexer:

error: unknown type name ‘yyscan_t’ 

Jeden obejście jest określenie go unieważnić:

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

zobaczyć yyscan_t definicja: flex yyscan_t

Więc tutaj jest wynik końcowy:

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

odpowiedź zaakceptowana przez Fabricio Sanches pomógł mi rozwiązać dwa problemy:

  1. error: unknown type name ‘yyscan_t’ rzeczywiście został rozwiązany poprzez zmianę na void *.

  2. Konflikty związane z okrągłymi zależności dyktować bardzo ścisłej kolejności importu:

kodzie gdzie yyparse Flex/bizonów nazywa się:

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

Flex (Lexer.lm):

%{ 
#import "parser.h" 
%} 

Bison (Parser.ym):

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

pisałem na blogu o procesie tworzenia wklęsłym parsera przy użyciu Flex i Bison na Mac OS z przykładu jego integracja z projektem Xcode: Reentrant parser using Flex and Bison.

+0

Pytanie: Mam swoją konfigurację działającą z połączonego bloga. Czy możesz wyjaśnić, dlaczego nie mogę dołączyć plików takich jak "#include "? –

+0

Czy używasz Xcode? –

+0

Tak, jestem na tym teraz patrząc na twój przykład. –