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.