2010-02-16 12 views
10

durante el análisis, si me encuentro con un símbolo incluyen quiero instruir a YACC para abrir el archivo especificado como entrada y para comenzar a analizar esto. Una vez que este análisis finalice, quiero instruir a YACC que regrese al archivo y continúe el análisis directamente después de la expresión de inclusión. Restringiré el nivel de profundidad de inclusión a uno.¿Cómo puedo implementar #include constructs con Flex y YACC?

Respuesta

6

El manual flex cubre cómo hacer esto utilizando yypush_buffer_state() y yypop_buffer_state(). Here es la sección del manual sobre el uso de múltiples buffers de entrada. Hay un código de muestra.

+0

DigitilRoss' fue exhaustiva, y lo suficientemente precisa. Pero las mejores prácticas triunfan sobre la astucia cualquier día. Vi esto hace 18 minutos y ahora tengo trabajo incluido. Gracias por el enlace. +1 – Jamie

4

Es normal para la comunicación entre las fases léxicas y sintácticas de su procesador.

Por lo tanto, reconozca la sintaxis de una directiva de inclusión en su analizador (o, para facilitar las cosas, simplemente identifíquela en el lector lex) y realice la conmutación en el nivel léxico. Por ejemplo, este es un lenguaje simple que reconoce las líneas de entrada estándar que contienen ab o cd o .file Cuando ve .someString abre someString como un archivo de inclusión y luego vuelve a leer la entrada estándar.

%{ 
#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; 
} 

Y cuando lo ejecutamos ... respuesta

$ 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 
$