2010-02-16 47 views
10

在分析过程中,如果遇到包含令牌,我想指示YACC打开指定为输入的文件并开始解析。一旦这个解析完成,我想要指示YACC返回到文件并在include表达式之后直接继续解析。我将限制包含深度级别为1。如何使用Flex和YACC实现#include构造?

回答

6

flex手册介绍了如何使用yypush_buffer_state()和yypop_buffer_state()来执行此操作。 Here是使用多个输入缓冲区的手册部分。有一些示例代码。

+0

DigitilRoss'答案是彻底的,并不够准确。但是最佳实践胜过任何一天的聪明。我在18分钟前看到了这个,现在我已经开始工作了。感谢您的链接。 +1 – Jamie 2011-12-20 04:49:10

4

在处理器的词法和句法阶段之间进行通信是正常的。

因此,要在解析器中识别include指令的语法(或者为了简化起见,只需在词法分析器中识别它)并在词法级别进行切换即可。

例如,下面是一个简单的语言,用于识别包含abcd.file的标准输入行。当它看到.someString它将someString作为包含文件打开,然后返回到读取标准输入。

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

当我们运行...

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