Hallo,
ich bin zur Zeit auf der Suche nach einem Parsergenerator und habe dabei
das Gespann aus Flex und Bison entdeckt. Auf dem ersten Blick macht das
genau den Eindruck, nach dem ich suche, jedoch habe ich ein Problem bei
dem generierten Code.
Der Parser soll später auf einem Mikrocontroller ausgeführt werden.
Daher habe ich zwei Anforderungen an den Code.
1. Habe ich nicht alle Bibliotheken zur Verfügung die ich benötige um
den generieren Code mit z.B. dem sdcc zu kompilieren. Allerdings, wenn
ich die Fehlermeldungen an sehe, weiß ich auch nicht wozu der Code
benötigt wird (es hängt an dem Datentyp FILE bzw. der stdio). Ich will
einfach nur ein String rein kippen, und ein Syntaxbaum raus bekommen.
Thats It. Ich will von keinem File lesen oder was auch immer das Ding
macht oder auf die Standardausgabe schreiben. Gibt es Optionen um dem
Gespann mitzuteilen, das es sich rein auf das Parsen fixieren soll? Oder
gibt es vielleicht noch eine bessere Möglichkeit?
2. Es muss der Code so klein wie möglich sein. Auch wenn es gehen
sollte, hab ich ein Interesse, das jeder unnötige Ballast raus fliegt.
Ich hab auch ein Blick in die Doku gewagt, jedoch auf die Schnelle
nichts brauchbares gefunden.
Ich bedanke mich schonmal für die Hilfe
Tobias
tobias schrieb:> Auch wenn es gehen sollte, hab ich ein Interesse, das jeder unnötige> Ballast raus fliegt.
Dann würde ich dir statt bison auf jeden Fall den byacc anraten, der
ist weniger komplex.
FILE kannst du natürlich auch irgendwie emulieren, am Ende werden sie
da nicht viel mehr als ein getc()/ungetc() machen, das müsste dann
halt die Daten aus deinem String liefern.
bison braucht eine eigene yyerror()-Funktion für Fehlermeldungen.
Für den flex Scanner-Input kannst/musst du ein eigenes YY_INPUT() Makro
definieren. flex ECHO-Output ist ein Problem, ECHO benutzt einen
FILE-Pointer. Da musst du etwas tiefer in die Details schauen wie man
den los wird. Wenn es irgendwie geht (einfache lexikalische Tokens)
würde ich sowieso den Scanner (alias Lexical Analyzer) von Hand
schreiben, statt ihn mit flex zu generieren.
Danke für die Antworten.
> FILE kannst du natürlich auch irgendwie emulieren, am Ende werden sie> da nicht viel mehr als ein getc()/ungetc() machen, das müsste dann> halt die Daten aus deinem String liefern.
Ich weiß nicht was da genau abläuft. Ich hab es auf dem PC kompiliert
und hab dort ein String rein geschmissen und hab ein Syntaxbaum raus
bekommen. Genau so wie ich das wollte.
Das Emulieren ist eine Idee, jedoch erzeugt das wieder unnützen Code.
Ich weiß auch nicht wie weit dieser Code dann beim Linken später wieder
raus geschmissen werden kann.
Ich könnte mir auch den Code zur Brust nehmen, und den Krempel via Hand
raus schmeißen, doch führt das die komplette Idee mit dem automatisch
generierten Code ins ad absurdum.
> Wenn es irgendwie geht (einfache lexikalische Tokens)> würde ich sowieso den Scanner (alias Lexical Analyzer) von Hand> schreiben, statt ihn mit flex zu generieren.
Ich bin da auch selbst noch am evaluieren. Was besonders komplexes wird
es nicht werden, und eine lexikalische Analyse ist echt schnell mit der
Hand geschrieben.
Auch bin ich am überlegen, ob ich nicht auch einfach dann den Parser
schreibe. Ich hab das zwar noch nie gemacht, aber ein LL(1) Parser
scheint wohl auch kein Hexenwerk zu sein. Es wäre zumindest ein
interessantes Projekt.
> Wenn der Mikrocontroller groß genug für "normales" C++ ist, kannst du> dir ja mal boost::spirit anschauen.
Der SDCC kann leider nur C, aber ich fürchte auch, das das viel zu
oversized ist :(
Manche Implementierungen (POSIX) bieten fmemopen, vielleicht gib's das
ja bei deinem Compiler oder du kannst was von einer bestehenden
Implementierung abkupfern:
https://github.com/lattera/glibc/blob/master/libio/fmemopen.c
Aber wie bereits gesagt: Das was du parsen willst ist bestimmt nicht
allzu kompliziert. Ein Parser-Generator ist da vermutlich wenig
sinnvoll, z.b. wenn ein handgeschriebener Parser kürzer ist als
Syntaxbeschreibung und Backend für den Parser-Generator...
tobias schrieb:> Es muss der Code so klein wie möglich sein
Der Code wird vielleicht nicht so sehr dein Problem sein...
> um den generieren Code mit z.B. dem sdcc zu kompilieren.
...weil solche Tools weniger mit Code als vielmehr mit reichlich
Datentabellen arbeiten (yacc/lex jedenfalls). Und wenn die nicht
automatisch im ROM landen, beispielsweise weil Harvard-Architektur, dann
kann es bei µCs eher im RAM als im ROM eng werden.
A. K. schrieb:> Und wenn die nicht automatisch im ROM landen, beispielsweise weil> Harvard-Architektur, dann kann es bei µCs eher im RAM als im ROM eng> werden.
Ich habe schon vor vielen Jahren mal ein Experiment gemacht, flex
und byacc so zu hacken, dass sie für den AVR die Tabellen im Flash
ablegen. Auf einem ATmega128 konnte ich damit einen simplen
BASIC-Interpreter implementieren, allerdings hatte es nur mit
externem RAM Sinn, da man ja auch das zu interpretierende Programm
irgendwo ablegen können muss. Der Flash-Footprint lag so um die 12 KiB.
Schau dir mal GOLD Parsing System (http://goldparser.org/) an.
Ist ein Parsergenerator, der Parser in vielen Sprachen erzeugen.
Gibt´s auch eine Art IDE dazu, mit der man seine Grammatik entwickeln
und testen kann.
Ups, vergessen: Eine Engine, die in Ansi C geschrieben wurde, gibt es
auch.
(http://goldparser.org/engine/1/c/index.htm)
Ich habe bisher nur die Java, C++ und VB-Engines verwendet, kann also
nicht sagen, wie gut die C-Engine funktioniert.