Es ist normal, dass zwischen der lexikalischen und der syntaktischen Phase Ihres Prozessors kommuniziert wird.
Erkennen Sie also die Syntax für eine Include-Direktive in Ihrem Parser (oder, um die Sache zu vereinfachen, erkennen Sie sie einfach im Lexer) und nehmen Sie die Umschaltung auf der lexikalischen Ebene vor.
Hier ist zum Beispiel eine einfache Sprache, die Standard-Eingabezeilen erkennt, die ab
o cd
o .file
. Wenn es sieht .someString
es öffnet sich someString
als Include-Datei und kehrt dann zum Lesen der Standardeingabe zurück.
%{
#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;
}
Und wenn wir es ausführen...
$ 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
$