如何使用Flex和YACC实现#include结构?

12

在解析过程中,如果我遇到一个include标记,我想要指示YACC打开指定的输入文件并开始解析它。一旦解析完成,我想要指示YACC返回原文件并直接继续解析include表达式后面的内容。我将限制include深度级别为一。

2个回答

9

弹性手册介绍了如何使用yypush_buffer_state()和yypop_buffer_state()实现此功能。

这里是官方手册中关于使用多个输入缓冲区的章节,其中包含一些示例代码。


1
DigitilRoss的回答非常详细,而且准确无误。但是最佳实践总是胜过聪明才智。我18分钟前看到了这个,现在我已经有了可用的包含文件。感谢提供链接。+1 - Jamie

5

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

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

例如,这是一种简单的语言,它识别标准输入行,其中包含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
$ 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接