2010-02-16 7 views
10

Podczas analizowania, jeśli napotkam token włączania, chcę polecić YACC, aby otworzyć plik określony jako wejście i rozpocząć przetwarzanie tego. Po zakończeniu analizowania, chcę polecić YACC, aby powrócił do pliku i kontynuował przetwarzanie bezpośrednio po wyrażeniu include. Ograniczę poziom głębi dołączenia do jednego.Jak mogę zaimplementować #include konstrukcje z Flex i YACC?

Odpowiedz

6

W instrukcji podręcznika elastycznego opisano, jak to zrobić, używając yypush_buffer_state() i yypop_buffer_state(). Here jest rozdziałem podręcznika na temat korzystania z wielu buforów wejściowych. Jest pewien przykładowy kod.

+0

DigitilRoss' było dokładne i wystarczająco dokładne. Ale najlepsze praktyki wygrywają nad sprytem każdego dnia. Widziałem to 18 minut temu, a teraz mam włączanie do pracy. Dzięki za link. +1 – Jamie

4

Normalne jest komunikowanie się między fazami leksykalnymi i syntaktycznymi procesora.

Rozpoznaj więc składnię dyrektywy uwzględniania w analizatorze składni (lub, aby było łatwiej, po prostu rozpoznaj ją w lexer) i przełącz się na poziomie leksykalnym.

Na przykład tutaj jest prosty język, który rozpoznaje standardowe linie wejściowe zawierające ab lub lub .file. Kiedy widzi .someString, otwiera się jako plik włączający, a następnie wraca do odczytu standardowego wejścia.

%{ 
#include <stdio.h> 
#include <stdlib.h> 
void start_include(char *); int yylex(void); void yyerror(void *); 
#define YYSTYPE char * 
%} 
%% 
all:   all others | others; 
others:  include_rule | rule_1 | rule_2 | 'Z' { YYACCEPT; }; 
include_rule: '.' '\n' { start_include($1); }; 
rule_1:  'a' 'b' '\n' { printf("random rule 1\n"); }; 
rule_2:  'c' 'd' '\n' { printf("random rule 2\n"); }; 
%% 
FILE * f = NULL; 
void start_include(char *s) { 
     if ((f = fopen(s, "r")) == NULL) 
       abort(); 
} 
int yylex(void) { 
     int c; 
     static char s[100]; 
     if (f == NULL) 
       f = stdin; 
     c = getc(f); 
     if (c == EOF) { 
       f = stdin; 
       c = getc(f); 
     } 
     if (c == '.') { 
       scanf(" %s", s); 
       yylval = s; 
     } else if (c == EOF) 
       return 'Z'; 
     return c; 
} 

A kiedy go uruchomić ... Odpowiedź

$ cat > toplevel 
ab 
.myinclude 
ab 
$ cat > myinclude 
cd 
cd 
$ yacc ip.y && cc -Wall y.tab.c -ly && ./a.out < toplevel 
random rule 1 
random rule 2 
random rule 2 
random rule 1 
$ 
Powiązane problemy