-2

I am working with lex and yacc, and I need to create two output files. What do I need to do (if there is any function to make multiple files), and how do I name each file?

Using lex and yacc, I need to test an html file with css in it, and from that generate two files, one with html, and the other with css. Basically separate css from html and put it in different files.

If someone could provide a simple example of how to generate two output files.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Leon
  • 23
  • 6
  • 1
    Do you mean that you need to create two different parsers? Or that in the course of handling your input you will produce various output files? – rici May 10 '16 at 00:50
  • Just one lex and one yacc file will produce two output files. – Leon May 10 '16 at 01:06
  • 2
    *lex* produces one output file, and *yacc* can produce 1, 2, or 3 depending on what options you select: a .c, a .h, and the other one whose name I forget containing all the state information. If you want the *generated code* to produce multiple output files, all you have to do is write the necessary code. Unclear what you're asking. – user207421 May 10 '16 at 01:12
  • Using lex and yacc, I need to test an html file with css in it, and from that generate two files, one with html, and the other with css. Basically separate css from html and put it in diferent files. – Leon May 10 '16 at 20:20

1 Answers1

1

Your question is a little broad, but also, as indicated by the comments received, somewhat ambiguous. However, I think I understand what you need are asking. First I'll address the ambiguity and then get down to explain how to achieve what you want.

What you seem to have overlooked is that there is nothings special about lex and yacc. They are just tools that create programs in C (or C++) that are built with the compilers and run in the normal way. Any output made by those programs is generated by the normal I/O statements in the code of that language, and not by lex or yacc. Lex and yacc are just tools that permit the recognition of input that is structured according to the rules you specify. The tools flex and bison are just analogue implementations of these tools that many people use. In the following explanations I will be using flex and bison, but the answer would be equally valid for lex and yacc.

When you ask about two output files for lex and yacc it could be interpreted that you are asking about the code files they generate. The lex tool generates a file called lex.yy.c from it input rules. This file contains the code necessary for building a lexical analyser. It can also output a header file. So we can generate two files from flex like this:

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

But we know now, that is not what you were asking about.

The bison/yacc tool also has several options for generating several output files, like this:

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

But, also, we know now that is not what you were asking about either!

You wanted to know how to make a program that creates two files, one containing css and the other html from one single input file. The statements to create different output files are just written in C. Consulting a basic tutorial on the C language we can find that two create differently names output files we can use the fprintf statements:

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);

Here we have written two files without using the lex and yacc tools; which is also not what you asked, but part of the solution.

If we are to process an (HTML) input file containing both CSS and HTML components there must be some rules to determine which part is which. This is determined by the <style> tag in HTML. The first task is to describe these components in a set of lex rules. We need to recognise the opening <style> and the matching closing </style>. Everything else can just be matched as a sequence of characters:

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

This can be tested in the following manner (using windows; linux/mac is similar but ^D is 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

The testing shows that it recognises the tags for the start end end of the CSS sections.

We can now create a set of rules for yacc/bison that show how these tokens from lex can be recognised and divided up into two output files:

%{
#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"

This, on recognising the STYLE token switches output to the CSS file, and at the end of the style section switches it to an HTML file. I have used stderr and stdout for these two files.

This can be built and run thus:

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

and generates the following:

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

We can separate the CSS and HTML thus:

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

This can be further modified to make a tool that can accept the file names as arguments and generate named files for the output, which is what you asked.

Now, probably, your question will be closed as too broad, but I hope my little tutorial was useful.

Community
  • 1
  • 1
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129