2010-02-16 1 views
10

Lors de l'analyse, si je rencontre un jeton d'inclusion, je souhaite que YACC ouvre le fichier spécifié comme entrée et commence à l'analyser. Une fois cette analyse terminée, je souhaite que YACC retourne au fichier et continue l'analyse directement après l'expression include. Je vais restreindre le niveau de profondeur d'inclusion à un.Comment puis-je implémenter des constructions #include avec Flex et YACC?

Répondre

6

Le manuel flexible explique comment procéder en utilisant yypush_buffer_state() et yypop_buffer_state(). Here est la section du manuel sur l'utilisation de plusieurs tampons d'entrée. Il y a un exemple de code.

+0

DigitilRoss de réponse était complète et assez précis. Mais les meilleures pratiques l'emportent sur l'intelligence chaque jour. J'ai vu ça il y a 18 minutes et maintenant j'ai travaillé. Merci pour le lien. +1 – Jamie

4

Il est normal de communiquer entre les phases lexicale et syntaxique de votre processeur. Donc, reconnaissez la syntaxe d'une directive include dans votre analyseur (ou, pour simplifier les choses, reconnaissez-la simplement dans le lexeur) et faites la commutation au niveau lexical. Par exemple, voici un langage simple reconnaissant les lignes d'entrée standard contenant ab ou cd ou .file. Lorsqu'il voit .someString, il ouvre someString en tant que fichier d'inclusion, puis revient à la lecture de l'entrée standard.

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

Et quand nous courons ...

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