2016-05-10 12 views
-2

Ich arbeite mit lex und yacc, und ich muss zwei Ausgabedateien erstellen. Was muss ich tun (wenn es eine Funktion gibt, um mehrere Dateien zu erstellen) und wie benenne ich jede Datei?lex/yacc Programme mit mehreren Ausgabedateien

Mit lex und yacc muss ich eine html-Datei mit css darin testen und daraus zwei Dateien erzeugen, eine mit html und die andere mit css. Im Grunde trennen CSS aus HTML und legen Sie es in verschiedenen Dateien.

Wenn jemand ein einfaches Beispiel zum Generieren von zwei Ausgabedateien bereitstellen könnte.

+1

Meinen Sie, dass Sie zwei verschiedene Parser erstellen müssen? Oder dass Sie bei der Bearbeitung Ihrer Eingaben verschiedene Ausgabedateien erstellen? – rici

+0

Nur eine Lex- und eine Yacc-Datei erzeugen zwei Ausgabedateien. – Leon

+2

* lex * erzeugt eine Ausgabedatei und * yacc * kann 1, 2 oder 3 ergeben, je nachdem, welche Optionen Sie auswählen: a .c, a .h und die andere, deren Name ich vergesse, die alle Statusinformationen enthält. Wenn Sie möchten, dass der * generierte Code * mehrere Ausgabedateien erzeugt, müssen Sie nur den erforderlichen Code schreiben. Unklar, was du verlangst. – EJP

Antwort

0

Ihre Frage ist ein wenig breit, aber auch, wie durch die Kommentare angezeigt, etwas mehrdeutig. Aber ich denke, ich verstehe, was Sie brauchen, fragen Sie. Zuerst werde ich die Mehrdeutigkeit ansprechen und dann erklären, wie man das erreicht, was man will.

Was Sie scheinbar übersehen haben, ist, dass es nichts spezielles über Lex und Yacc gibt. Sie sind nur Werkzeuge, die Programme in C (oder C++) erstellen, die mit den Compilern erstellt werden und auf die normale Weise ausgeführt werden. Jede von diesen Programmen ausgegebene Ausgabe wird von den normalen I/O-Anweisungen im Code dieser Sprache und nicht von lex oder yacc erzeugt. Lex und Yacc sind nur Werkzeuge, die die Erkennung von Eingabe ermöglichen, die nach den von Ihnen angegebenen Regeln strukturiert ist. Die Tools flex und bison sind nur analoge Implementierungen dieser Tools, die von vielen genutzt werden. In den folgenden Erklärungen werde ich Flex und Bison verwenden, aber die Antwort wäre gleichermaßen gültig für Lex und Yacc.

Wenn Sie nach zwei Ausgabedateien für lex und yacc fragen, könnte es so interpretiert werden, dass Sie nach den Codedateien fragen, die sie generieren. Das Lex-Tool erzeugt eine Datei mit dem Namen lex.yy.c aus diesen Regeln. Diese Datei enthält den Code, der zum Erstellen eines lexikalischen Analysators erforderlich ist. Es kann auch eine Header-Datei ausgeben. So können wir zwei Dateien von flex wie folgt generieren:

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

Aber wir wissen jetzt, das ist nicht, was Sie gefragt haben.

Der Bison/yacc-Tool auch mehrere Optionen zur Erzeugung mehrere Ausgabedateien, wie diese hat:

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

Aber auch, wissen wir jetzt, dass nicht das, was Sie entweder fragten über!

Sie wollten wissen, wie ein Programm zu machen, die zwei Dateien erstellt, einen css und den anderen html aus einer einzigen Eingabedatei enthält. Die Anweisungen zum Erstellen verschiedener Ausgabedateien werden nur in C geschrieben. Beratung a basic tutorial auf der C Sprache können wir feststellen, dass zwei unterschiedlich Namen Ausgabedateien erstellen, können wir die fprintf Anweisungen verwenden:

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

Hier haben wir zwei Dateien geschrieben, ohne die lex und yacc-Tools; Das ist auch nicht das, was Sie gefragt haben, sondern Teil der Lösung.

Wenn wir eine (HTML) Eingabedatei verarbeiten wollen, die sowohl CSS- als auch HTML-Komponenten enthält, müssen einige Regeln existieren, um festzustellen, welcher Teil welcher ist. Dies wird durch den Tag <style> in HTML bestimmt. Die erste Aufgabe besteht darin, diese Komponenten in einer Reihe von Lex-Regeln zu beschreiben.Wir müssen die Öffnung <style> und die passende Schließung erkennen. Alles andere können nur als Folge von Zeichen angepasst werden:

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

Dies kann auf die folgende Weise getestet werden (unter Verwendung von Fenstern; Linux/MAC ist ähnlich, aber^D ist 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 

Der Test zeigt, dass er die Tags für das Anfangsende der CSS-Abschnitte erkennt.

Wir haben jetzt eine Reihe von Regeln für yacc/Bison, die zeigen, wie diese Token von lex in zwei Ausgabedateien erstellen können erkannt und aufgeteilt werden können:

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

Dieses auf die STYLE-Token zu erkennen Schaltet die Ausgabe in die CSS-Datei um und schaltet sie am Ende des Stilbereichs in eine HTML-Datei um. Ich habe stderr und stdout für diese zwei Dateien verwendet.

Dies kann so gebaut und betrieben werden:

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

und erzeugt die folgenden:

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

Damit haben wir die CSS und HTML trennen kann:

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

Dies kann weiter modifiziert, um ein Werkzeug zu machen, das die Dateinamen als Argumente akzeptiert und benannte Dateien für die Ausgabe erzeugt, die i s was du gefragt hast.

Nun, wahrscheinlich wird Ihre Frage als zu breit geschlossen, aber ich hoffe, mein kleines Tutorial war nützlich.