Hallo zusammen ich möchte mich mal mit dem Thema Lex/Yacc befassen. Gestern habe ich mir mal Lex ein wenig angeschaut. Eigentlich keine riesen Hexerei. Aber Lex allein taugt im Prinzip nicht viel, oder? Jetzt habe ich mir mal für den Text, den ich parsen möchte, eine Datei mit dieser Backus Naur Form angelegt. Wikipedia hilft, es ist relativ einfach, wenn man mal ein paar Beispiele durchgelesen hat. Allerdings frage ich mich jetzt ein paar Sachen. a) wie komme ich jetzt mit Hilfe dieser Backus Naur Form auf ein C-Programm? eigentlich brauche ich hierzu Lex doch gar nicht, oder? Ich meine, man müsste eine Zerlegung in Tokens schon anhand der Backus-Datei vornehmen können, wozu braucht man dann Lex? b) jetzt noch fast die wichtigere Frage: Zwar erhalte ich beispielsweise mit Lex ein lauffähiges Programm, welches verschiedene Tokens unterscheiden kann. Dann kann man beispielsweise in der Konsole einen Text eingeben, und das Programm zerlegt den dan. Ansich eine ganz nette Spielerei, aber wenn ich z.B. eine INI-Datei parsen möchte (als triviales Beispiel) dann nützt mir das von Lex generierte Programm wenig. Wie baue ich also etwas, was ich mit Lex generiert habe, in mein bestehendes C-Programm ein? und noch wichtiger: Der generierte Quelltext ist total aufgeblasen und nahezu unlesbar, ist das wirklich dafür gedacht, 1:1 so verwendet zu werden?
lex: Scanner-Generator: Erkennt die "Wörter" (== Token) einer Sprache yacc: Parser-Generator: Erkennt, ob ein Eingabetext einer definierten Grammatik entspricht. Üblicherweise ruft der Parser den Scanner auf, wenn er ein neues Token aus dem Eingabetext braucht. Konkret: Der aus der in Backus-Naur geschriebenen Grammatik vom yacc erzeugte Parser ruft den lex-generierten Scanner auf. >Der generierte Quelltext ist total aufgeblasen und nahezu >unlesbar, ist das wirklich dafür gedacht, 1:1 so verwendet zu werden? Wieso willst Du den überhaupt lesen? Völlig unötig. Und: Wie willst Du beurteilen können, ob "aufgeblasen" oder nicht, ohne die Grundlagen zu kennen? Ansonsten: Scanner kann man auch "von Hand" schreiben. Empfehlung: Hole Dir die Bison (GNU Version von Yacc) und Flex (GNU Version von lex) Manuals und lese die durch. Oder besser noch: Befasse Dich mit den Grundlagen des Compilerbaus. Da gibt es sicher genug Material in den Weiten des Internets. Ansonsten: Wirth: Compilerbau oder Aho, Sethi, Ullman: Principles of Compiler Design (Drachenbuch)
>Aho, Sethi, Ullman: Principles of Compiler Design (Drachenbuch)
Bzw: Compilers: Principles, Techniques, and Tools
Tobias Plüss schrieb: > a) wie komme ich jetzt mit Hilfe dieser Backus Naur Form auf ein > C-Programm? > eigentlich brauche ich hierzu Lex doch gar nicht, oder? Ich meine, man > müsste eine Zerlegung in Tokens schon anhand der Backus-Datei vornehmen > können, wozu braucht man dann Lex? Der Scanner geht die Eingabedatei halt Wort für Wort (Token für Token) durch und gibt die gefundenen Token an den Parser. Ist eigtl nicht besonders aufwendig und kann man natürlich auch leicht selbst machen, wie oben schon gesagt. > b) jetzt noch fast die wichtigere Frage: > Zwar erhalte ich beispielsweise mit Lex ein lauffähiges Programm, > welches verschiedene Tokens unterscheiden kann. Dann kann man > beispielsweise in der Konsole einen Text eingeben, und das Programm > zerlegt den dan. Ansich eine ganz nette Spielerei, aber wenn ich z.B. > eine INI-Datei parsen möchte (als triviales Beispiel) dann nützt mir das > von Lex generierte Programm wenig. Wie baue ich also etwas, was ich mit > Lex generiert habe, in mein bestehendes C-Programm ein? und noch > wichtiger: Der generierte Quelltext ist total aufgeblasen und nahezu > unlesbar, ist das wirklich dafür gedacht, 1:1 so verwendet zu werden? Du brauchst natürlich die zweite Komponente - z. B. yacc - auch noch. Erst dann werden die Token in einen wie auch immer gearteten Zusammenhang gesetzt und interpretiert, indem z.B. eine einstprechende Baumstruktur erstellt wird. Am besten du postet mal konkreten Code, sonst ist das alles sehr schwammig. Von Punkt b) her zu urteilen, vermute ich, dass du irgendwas falsch machst ;)
Tobias Plüss schrieb: > eigentlich brauche ich hierzu Lex doch gar nicht, oder? Ich meine, man > müsste eine Zerlegung in Tokens schon anhand der Backus-Datei vornehmen > können, wozu braucht man dann Lex? Ja, kann man. Dann wird die Grammatik aber relativ groß und undurchsichtig. Das ist der weniger wichtige Grund, warum man lex getrennt verwendet. Der wichtigere ist, daß die Grammatik, die yacc erkennt, kontextfrei ist. Das ist viel zu mächtig für die reine Tokenerkennung, da kann lex deutlich effizienter zu Werke gehen.
Tobias Plüss schrieb: > wie komme ich jetzt mit Hilfe dieser Backus Naur Form auf ein > C-Programm? Eigentlich ist der Yacc-Quellcode erstmal (auf der linken Seite) eine recht reine BNF. Diese allein kann man natürlich vom Yacc parsen lassen, aber dann bekommst du (als Rückgabewert von yyparse()) letztlich nur heraus, ob das Dokument auf deine Grammatik gepasst hat oder nicht. Daher willst du normalerweise anschließend beim Erkennen der einzelnen syntaktischen Konstrukte auch irgendwas ausführen lassen. Das ist das, was rechts neben der BNF in geschweiften Klammern steht. Compiler bauen sich dann einen Syntaxbaum auf, für den Anfang kann man auch einfach erstmal ein paar printf()s da hinsetzen. Und nein, den generierten Code muss man nicht mehr lesen können. Das ist ein Compiler Compiler (naja, daher kommt zumindest der Name :), und auch den (Assembler-)Code, den dein C-Compiler so generiert, musst du nicht unbedingt lesen können. Die Quelldatei ist die .y-Datei, nur an dieser wird herum geändert.
Ich glaub, ihr habt seinen Post nicht genau gelesen. Ihr redet alle von
yacc, der TO nimmt aber (bisher) nur lex her, hat er zumindest
geschrieben.
> Zwar erhalte ich beispielsweise mit Lex ein lauffähiges Programm,
Er meint auch, dass er mit lex ein fertiges Programm erhält. Entweder er
hat das Zusammenspiel Scanner/Parser nicht verstanden und nimmt nur
einen Scanner her, oder er hat sich nur falsch ausgedrückt....
Jonas K. schrieb: > der TO nimmt aber (bisher) nur lex her, hat er zumindest geschrieben. Hat aber in der Überschrift auch den Yacc drin. Erst damit setzt man dann die BNF um. Über Sinn und Unsinn der Trennung von Scanner und Parser hatten ja andere bereits philosophiert.
Tobias Plüss schrieb: > ich möchte mich mal mit dem Thema Lex/Yacc befassen. Wie wärs mit flex/bison? > Gestern habe ich mir mal Lex ein wenig angeschaut. Eigentlich keine > riesen Hexerei. Aber Lex allein taugt im Prinzip nicht viel, oder? Kommt drauf an wofür. Als Tokenizer taugt er. Der ist aber meist nur ein Teil einer Lösung. > Der generierte Quelltext ist total aufgeblasen und nahezu > unlesbar, Das ist bei automatisch generiertem Quellcode normal. Erst recht bei tabellenbasiertem Code. > ist das wirklich dafür gedacht, 1:1 so verwendet zu werden? Ja. Der ist definitiv nicht dafür gedacht, ihn zu verstehen oder gar drin rumzuschreiben.
Wenn dich ein ähnlicher Parser für C++ aber ohne Zwischencode interessiert, kannst du einen Blick auf http://boost-spirit.com werfen.
Hallo allerseits! danke schon mal für die vielen Infos :-) Zum generierten Code kann ich nur folgendes sagen. Irgendwie muss ich den ja in ein bestehendes Programm integrieren können. Also wie gehe ich dann da vor? wenn mir Lex (oder meinetwegen auch Yacc) da schon eine main()-Funktion rein baut, dann kann ich das so ja nicht verwenden. Also muss ich dann ja noch dauernd an dem generierten Code rum ändern .... :-/ Den "Workflow" stelle ich mir so vor: entweder man benutzt Lex und bekommt dann die Tokens. Was meines Erachtens nicht extrem nützlich ist. Oder aber man benutzt Yacc. Dann muss man sich eine BNF Datei erstellen und hat dann einen Parser für dieses Format. Jedenfalls wenn ich Lex auf meinen Rechner laufen lasse, bekomme ich da nichts raus, was ich an Yacc weiter verfüttern könnte, sondern es kommt C-Code raus. Ein Beispiels suche ich heute Abend hervor, habe jetzt grade hier keines zur Hand. Gruss!
>Irgendwie muss ich >den ja in ein bestehendes Programm integrieren können. Also wie gehe ich >dann da vor? wenn mir Lex (oder meinetwegen auch Yacc) da schon eine >main()-Funktion rein baut, dann kann ich das so ja nicht verwenden. Also >muss ich dann ja noch dauernd an dem generierten Code rum ändern .... Nun lies Dir doch ersteinmal die Dokumentation dazu in Ruhe durch und erzeuge mal lexer und yacc für eine kleine Beispielgrammatik. Das macht doch keinen Sinn, Dir hier das zu erklären, was ohnehin in der Dokumentation steht.
Tobias Plüss schrieb: > Hallo allerseits! > > danke schon mal für die vielen Infos :-) > > Zum generierten Code kann ich nur folgendes sagen. Irgendwie muss ich > den ja in ein bestehendes Programm integrieren können. Ja. Da gibt es eine Funktion und die rufst du auf. In einem Beispielcode wirst du sicherlich fündig. > dann da vor? wenn mir Lex (oder meinetwegen auch Yacc) da schon eine > main()-Funktion rein baut, dann kann ich das so ja nicht verwenden. Schau die mal die Yacc Doku an. http://pubs.opengroup.org/onlinepubs/7908799/xcu/yacc.html Such nach main() in der Doku. Die erklärt dir, wie sich die Sache wirklich verhält.
> entweder man benutzt Lex und bekommt dann die Tokens. Was > meines Erachtens nicht extrem nützlich ist. > Oder aber man benutzt Yacc. Nicht 'entweder oder'. Sondern 'und'. Lex und Yacc arbeiten als Duo zusammen. Man kann sie einzeln benutzen. Muss aber nicht. Das volle Potential kann man mit beiden zusammen ausschöpfen. Studier bitte die Doku und ein paar Beispiele dazu. Auf den ersten Blick sieht das alles etwas verwirrend aus. Es ist aber einfacher, als es zunächst aussieht.
A. K. schrieb: >> ich möchte mich mal mit dem Thema Lex/Yacc befassen. > > Wie wärs mit flex/bison? Lex taucht doch (wenn man nicht gerade ein Solaris benutzt) praktisch immer in seiner Inkarnation als Flex auf. (Mir ist zumindest kein weiteres plug-kompatibles Opensource-Pendant bekannt.) Bison ist wie viele GNU-Dinge, creeping featurism. ;-) Letztlich aber auch so einigermaßen eine Obermenge von Yacc. Im Gegensatz zu lex gibt es aber mit dem byacc noch eine einigermaßen schlanke Opensource-Alternative. flex und byacc habe ich sogar schon mal auf den AVR portiert ;-) (wobei die wesentliche Änderung darin bestand, die Tabellen im Flash aufzubauen und dort abzurufen). So ab einem ATmega128 aufwärts ist das durchaus sogar benutzbar. Das "Grundrauschen" ist halt schon recht voluminös, aber ob wenn man Scanner und Parser dann erweitert, bleiben sie trotzdem recht effektiv.
Hallo, also ich habe mir mal noch das Video hier angeschaut: http://www.youtube.com/watch?v=__-wUHG2rfM es ist einigermassen aufschlussreich und das aller erste mal, wo ich sehe, dass Lex und Yacc tatsächlich zusammen benutzt werden. Im Prinzip könnte man aber auch (wenn man wollte) Lex alleine benutzen und dann mittels einer FSM die erkannten Tokens durchgehen und mit yytext den Text jedes Tokens ermitteln, oder? @Jörg Also du hast einen mit flex und byacc generierten Parser auf dem AVR laufen? Hast du denn malloc() umgehen können? sind ein paar Aufrufe dazu drin. Leider.
Tobias Plüss schrieb: > es ist einigermassen aufschlussreich und das aller erste mal, wo ich > sehe, dass Lex und Yacc tatsächlich zusammen benutzt werden. Ach nö, so ungewöhnlich ist diese Kombination nun nicht. AVRDUDE beispielsweise parst seine Konfigurationsdateien damit. > Im Prinzip könnte man aber auch (wenn man wollte) Lex alleine benutzen > und dann mittels einer FSM die erkannten Tokens durchgehen und mit > yytext den Text jedes Tokens ermitteln, oder? Eher geht man den umgekehrten Weg, einen Yacc- oder Bison-Parser, aber einen handgefeilten Scanner. Sowas macht beispielsweise der GCC. > @Jörg > Also du hast einen mit flex und byacc generierten Parser auf dem AVR > laufen? Ja. > Hast du denn malloc() umgehen können? sind ein paar Aufrufe dazu > drin. Leider. "Ein Gespenst geht um in Micocontroller-Land, das Gespenst des malloc()." :-) Weißt du, das Ding hat so viel Grundrauschen, ich glaube so um die 10 oder 12 KiB an Code, warum soll man sich da um malloc() eine Rübe machen? Ich versteh' die Philosophie nicht, warum sich jeder lieber einen riesigen statischen Speicherklotz ans Bein binden würde, um dynamische Probleme damit zu lösen. Hauptsache, kein malloc() … Nein, da war natürlich ein malloc() drin. Beispielanwendung war ein (mehr oder minder gelungener) BASIC-Interpreter, der für seine Programmzeilen sowieso dynamischen Speicher brauchte. Das habe ich aber alles auf einem ATmega128 mit externem SRAM damals probiert.
Jörg Wunsch schrieb: > Eher geht man den umgekehrten Weg, einen Yacc- oder Bison-Parser, > aber einen handgefeilten Scanner. Sowas macht beispielsweise der GCC. Beim GCC ist schon seit längerem auch der Parser handgefeilt.
>Beim GCC ist schon seit längerem auch der Parser handgefeilt.
Warum hat man das eigentlich gemacht? Weiss das jemand? Warum ist ein
yacc/bison parser nicht ausreichend resp. passend gewesen?
Hallo nochmals, noch eine kurze Frage. Ich habe jetzt genauso wie in dem Video mal einen Parser gemacht um eine INI Datei zu lesen. Der hat funktioniert. Jetzt versuche ich etwas komplizierteres: mein zu parsender String enthält sowas: filename=/home/tobias/test.txt;address=0xafff4b8c wie zerlege ich das gescheit in Token? Ich dachte mir folgendes. 1. Token: filename (TOK_FILENAME) 2. Token: Gleich = (TOK_EQ) 3. Token: ? (TOK_FULLPATH) 4. Token: Strichpunkt ; (TOK_SEMICOLON) 5. Token: wieder = 6. Token: 0x[0-9a-fA-F]{8} (TOK_HEX) Für das Token Nr. 3 müsste ich ja dann einen Regex String finden, der auf einen Pfad passt, oder? Und meine BNF für YACC lautet dann: entry: TOK_FILENAME TOK_EQ TOK_FULLPATH TOK_SEMICOLON TOK_ADDR TOK_EQ TOK_HEX ein mögliches Problem wäre dann allerdings, wenn der Pfad eine Hexzahl enthalten würde, also z.B. /home/tobias/ordner0x12345678/test.txt (ok, niemand benennt seine Ordner hexadezimal, aber könnte ja trotzdem vorkommen...)
Tobias Plüss schrieb: > 1. Token: filename (TOK_FILENAME) > 2. Token: Gleich = (TOK_EQ) > 3. Token: ? (TOK_FULLPATH) > 4. Token: Strichpunkt ; (TOK_SEMICOLON) > 5. Token: wieder = > 6. Token: 0x[0-9a-fA-F]{8} (TOK_HEX) Gleichheitszeichen und Semikolon würde ich nicht als separate Tokens vereinbaren; vom lex nicht erkannte Dinge werden ohnehin zum Yacc durchgereicht.
1 | assign_stmt: |
2 | LET VAR_INT '=' expr_int { if (interprete) setivar($2, $4); } |
3 | | VAR_INT '=' expr_int { if (interprete) setivar($1, $3); } |
4 | | LET VAR_REAL '=' expr_real { if (interprete) setrvar($2, $4); } |
5 | | VAR_REAL '=' expr_real { if (interprete) setrvar($1, $3); } |
6 | | LET VAR_STR '=' expr_str { if (interprete) setstrvar($2, $4); } |
7 | | VAR_STR '=' expr_str { if (interprete) setstrvar($1, $3); } |
8 | ; |
> Für das Token Nr. 3 müsste ich ja dann einen Regex String finden, der > auf einen Pfad passt, oder? Ja, z. B.
1 | [-/a-zA-Z0-9_.]+ |
Mal in der Annahme, dass du deine Dateinamen auf diese Zeichenmenge begrenzen willst, damit die Grammatik auch eindeutig bleibt. Ansonsten kannst du natürlich immer noch vorschreiben, dass ein Dateiname in Anführungszeichen stehen muss. > ein mögliches Problem wäre dann allerdings, wenn der Pfad eine Hexzahl > enthalten würde, also z.B. /home/tobias/ordner0x12345678/test.txt An sich nicht, weil ja nach dem Dateinamen grundsätzlich erstmal ein Semikolon stehen muss. Ein Dateiname, der mit 0x beginnt, würde allerdings nicht passen, denn der würde als Hexzahl fehlinterpretiert und damit an der Stelle eines Dateinamens nicht zulässig sein. Ausweg: Anführungszeichen um Dateinamen vorschreiben. Außerdem geht natürlich folgender schräger Hack:
1 | entry: TOK_FILENAME TOK_EQ TOK_FULLPATH TOK_SEMICOLON TOK_ADDR TOK_EQ TOK_HEX | |
2 | TOK_FILENAME TOK_EQ TOK_HEX TOK_SEMICOLON TOK_ADDR TOK_EQ TOK_HEX |
3 | ; |
;-) Wenn die zweite Alternative vorliegt, ist ja klar, dass der Dateiname mit 0x beginnt. :)
:
Bearbeitet durch Moderator
Tobias Plüss schrieb: > filename=/home/tobias/test.txt;address=0xafff4b8c > > 3. Token: ? (TOK_FULLPATH) Das ist doch kein Problem, wenn das erste Zeichen ein / sein muss und das Ende immer ein Semikolon ist. (lookahead) Man könnte auch, um Problemen vorzubeugen, den Pfad in Anführungszeichen"" oder '' packen...
:
Bearbeitet durch User
Jörg Wunsch schrieb: > und damit an der Stelle eines Dateinamens nicht zulässig sein. Ausweg: > Anführungszeichen um Dateinamen vorschreiben. Oder zumindest eine 2.te Form eines Dateinamens ermöglichen, in der der Name in Anführungszeichen eingeschlossen werden kann (womit automatisch klar ist, dass ein " in einem Dateinamen nicht mehr zulässig ist). Das löst dann auch das leidige Problem mit einem Dateinamen
1 | C:\Benutzer\Alle\Doumente und sonstiger Schwachsinn\Joke.txt |
in dem die Leerzeichen zu allerhand Parse-Problemen führen. Ein Dateinamen ist dann einfach eine Abfolge von Zeichen, die mit einem " beginnt und mit einem " endet (und sinnvollerweise wird man ein paar andere Sonder-Zeichen auch noch ausschliessen, so dass man weitgehend mit der Nicht-Anführungszeichen Version kompatibel ist). Wobei die " natürlich nicht zum eigentlichen Namen gehören.
:
Bearbeitet durch User
Hallo zusammen, so ich habe jetzt meine Dateinamen mit Anführungszeichen versehen. Und nun funktioniert mein Parser zuverlässig! zunächst habe ich die Yaccdatei erstellt. Und meine Grammatik mit BNF definiert. Dabei habe ich herausgefunden, welche Zeichen ich als Token verwenden muss. @Jörg Wunsch: Was macht es für einen Unterschied, ob ich das Komma als Token nehme oder nicht? Nach dem erstellen der Yaccdatei kannte ich meine zu verwendenden Token und habe diese in einer Lexdatei eingetragen. Es scheint nun also, als würde mein Parser das gewünschte tun. Allerdings möchte ich den jetzt in ein C++ Programm einbinden und anhand der gelesenen Daten jeweils eine Instanz einer Klasse erzeugen und in eine Liste eintragen. Kann ich denn das Yacc/Lex-Programm so einfach in ein anderes Projekt einbinden? Mit extern "C" wird es ja dann schwierig, eine Klasse zu erstellen... :-)
Tobias Plüss schrieb: > Was macht es für einen Unterschied, ob ich das Komma als Token nehme > oder nicht? Mehr Schreibarbeit: du musst bereits im Scanner für jedes Zeichen ein Token anlegen. Ansonsten kannst du den Rest "durchfallen" lassen:
1 | ... |
2 | |
3 | [ \t] { /* ignore */ } |
4 | |
5 | [\n] { return '\n'; } |
6 | . { return yytext[0]; } |
Ich finde auch, dass sich
1 | entry TOK_FILENAME '=' TOK_STRING ';' TOK_ADDR '=' TOK_HEX |
etwas schneller lesen lässt als:
1 | entry: TOK_FILENAME TOK_EQ TOK_FULLPATH TOK_SEMICOLON TOK_ADDR TOK_EQ TOK_HEX |
> Kann ich denn das Yacc/Lex-Programm so einfach in > ein anderes Projekt einbinden? Mit extern "C" wird es ja dann schwierig, > eine Klasse zu erstellen... :-) Meines Wissens haben Flex und Bison auch C++-Support. Aber da musst du mal Doku wälzen.
Tobias Plüss schrieb: > eine Liste eintragen. Kann ich denn das Yacc/Lex-Programm so einfach in > ein anderes Projekt einbinden? Mit extern "C" wird es ja dann schwierig, > eine Klasse zu erstellen... :-) Ich habs selber noch nie gemacht. Aber hier hab ich ein Beispielprojekt gefunden, der scheinbar den Lex/Yacc benutzt und die Brücke zurück zu C++ schafft. http://www.telos.de/de/compiler/lex-yacc-und-c/ Würde ich mal studieren (makefile nicht vergessen), wie er das gemacht hat. Auch die Anmerkungen hier http://tldp.org/HOWTO/Lex-YACC-HOWTO-5.html dürften nicht uninteressant sein. Generell: Bei Fragen dieser Art kannst du davon ausgehen, dass du nicht der erste bist, der sowas probiert. Da gibt es also mit Sicherheit da draussen im Web jemanden, der schon lange vor dir diese Problemstellung hatte, sie gelöst hat und auch Willens war, den Lösungsweg in Form einer Web Seite bereit zu stellen.
Karl Heinz schrieb: > Würde ich mal studieren (makefile nicht vergessen), wie er das gemacht > hat. Ah!
1 | CFLAGS = -Wall |
2 | OBJFILES = easypars.o easyscan.o main.o global.o ast.o interpret.o |
3 | |
4 | easy : $(OBJFILES) |
5 | g++ -o easy $(OBJFILES) |
6 | easypars.cpp : easypars.yy global.h |
7 | bison -t -d -o easypars.cpp easypars.yy |
8 | easyscan.cpp : easyscan.l |
9 | flex -i easyscan.l |
10 | mv lex.yy.c easyscan.cpp |
11 | |
12 | global.o: global.cpp global.h |
13 | g++ -c $(CFLAGS) -c global.cpp |
14 | main.o: main.cpp global.h |
15 | g++ -c $(CFLAGS) main.cpp |
16 | ast.o: ast.cpp ast.h |
17 | g++ -c $(CFLAGS) ast.cpp |
18 | easyscan.o : easyscan.cpp global.h easypars.hpp |
19 | g++ -c $(CFLAGS) easyscan.cpp |
20 | easypars.o: easypars.cpp global.h |
21 | g++ -c $(CFLAGS) easypars.cpp |
22 | clean: |
23 | rm $(OBJFILES) |
24 | rm easy.exe |
25 | rm easypars.cpp easypars.hpp easyscan.cpp |
Er behandelt einfach die Ergebnisse von bison und flex (yacc und lex) als wären sie cpp Files und jagt sie durch den C++ Compiler. Ja, wenn das geht und der erzeugte Code soweit durch den C++ Compiler geht, dann kann man das natürlich machen und somit löst sich das Problem in Luft auf.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.