lex / yacc程序使用多个输出文件

时间:2016-05-10 00:16:55

标签: bison flex-lexer yacc lex

我正在使用lex和yacc,我需要创建两个输出文件。我需要做什么(如果有任何函数可以创建多个文件),以及如何命名每个文件?

使用lex和yacc,我需要测试一个带有css的html文件,并从中生成两个文件,一个用html,另一个用css。基本上将hss与html分开并将其放在不同的文件中。

如果有人可以提供一个如何生成两个输出文件的简单示例。

1 个答案:

答案 0 :(得分:0)

你的问题有点宽泛,但正如收到的评论所表明的那样,有些含糊不清。但是,我想我明白你需要的是什么。首先,我将解决模糊性,然后开始解释如何实现您想要的。

你似乎忽略的是,lex和yacc并不是特别之处。它们只是用 C (或C ++)创建程序的工具,这些程序是用编译器构建的,并以正常方式运行。这些程序产生的任何输出都是由该语言代码中的普通I / O语句生成的,而不是由lex或yacc生成的。 Lex和yacc只是允许识别根据您指定的规则构建的输入的工具。工具flex和bison只是许多人使用的这些工具的模拟实现。在下面的解释中,我将使用flex和bison,但答案对于lex和yacc同样有效。

当您询问lex和yacc的两个输出文件时,可以解释为您询问它们生成的代码文件。 lex工具从其输入规则生成名为 lex.yy.c 的文件。该文件包含构建词法分析器所需的代码。它还可以输出头文件。所以我们可以像这样从flex生成两个文件:

flex --header-file=css.h --output-file=css.lex.c css.l

但我们现在知道,这不是你所要求的。

bison / yacc工具还有几个选项可用于生成多个输出文件,如下所示:

bison --defines=css-defines.h --output=css-tab.c --graph=css-graph.txt --xml=css-graph.xml css.y

但是,我们现在也知道这不是你要问的问题!

您想知道如何创建一个程序来创建两个文件,一个包含 css ,另一个包含 html 来自一个输入文件。创建不同输出文件的语句只是用 C 编写的。通过 C 语言咨询a basic tutorial,我们可以发现两个创建不同名称的输出文件,我们可以使用fprintf语句:

FILE css, html;
open(css, "file.css", "w");
open(html, "file.html", "w");
fprintf(css, "%s\n", "a:link { color:blue }");
fprintf(html, "%s\n", "<a href=\"https://stackoverflow.com/questions/37127386/\">here</a>");
fclose(css);
fclose(html);

这里我们编写了两个文件而没有使用lex和yacc工具;这也不是你问的问题,而是解决方案的一部分。

如果我们要处理包含CSS和HTML组件的(HTML)输入文件,必须有一些规则来确定哪个部分是哪个。这由HTML中的<style>标记确定。第一项任务是在一组lex规则中描述这些组件。我们需要识别开头<style>和匹配的结束</style>。其他所有东西都可以匹配为一系列字符:

%{
#ifdef PRINT
#define TOKEN(name)  printf("Token: " #name " \"%s\"\n",yytext)
#else
#define TOKEN(name)   yylval.sval=strdup(yytext); return(name)
#endif
%}
%s STYLECHARS
%%
<INITIAL>\<style[^>]*>  BEGIN(STYLECHARS);TOKEN(STYLE);
<STYLECHARS>"</style>" BEGIN(INITIAL);TOKEN(ELYTS);
<STYLECHARS>(.|\n|\r)          TOKEN(CHAR);
<INITIAL>(.|\n|\r)           TOKEN(CHAR);

这可以通过以下方式测试(使用windows; linux / mac类似,但^ D是EOF):

flex css.l
gcc -o css.exe -DPRINT css.l -lfl
.\css
<html>
<style> a:link { color:blue } </style>
<a href=\"https://stackoverflow.com/questions/37127386/\">here</a>
</html>
^Z

测试显示它识别CSS部分的起始端的标记。

我们现在可以为yacc / bison创建一组规则,以显示如何识别lex中的这些标记并将其分成两个输出文件:

%{
#include <stdio.h>
#include <strings.h>
FILE *current;
%}
%union {
    char *sval;
}
%token<sval> STYLE ELYTS  CHAR
%%
content: stuff
       | content stuff
       ;
stuff: chars
   | styles
    ;
 chars: CHAR {fprintf(current,"%s",$1);}
   ;
 styles: style content elyts
   ;
   style : STYLE { current=stderr; }
   ;
   elyts : ELYTS { current=stdout; }
   ;
%%
int main (void)
{ 
#if YYDEBUG==1
 extern int yydebug; yydebug = 1;
#endif
    current = stdout;
    return yyparse();
}
int yyerror (char *s)
{
    printf("-%s at %s !\n",s );
}
#include "lex.yy.c"

这样,在识别STYLE令牌切换输出到CSS文件时,在样式部分的末尾将其切换为HTML文件。我已将stderrstdout用于这两个文件。

这可以建立并运行:

flex css.l
bison css.y
gcc -o css.exe css.tab.c -lfl
.\css < SO.htm

并生成以下内容:

<html>
 a:link { color:blue }
<a href=\"https://stackoverflow.com/questions/37127386/\">here</a>
</html>

我们可以将CSS和HTML分开:

.\css < SO.htm > SO-html.txt 2> SO-css.txt

这可以进一步修改,以创建一个工具,可以接受文件名作为参数,并为输出生成命名文件,这就是你所要求的。

现在,您的问题很可能会被关闭为过于宽泛,但我希望我的小教程很有用。