Gibt es eine Alternative für Flex / Bison, die auf 8-Bit-Embedded-Systemen verwendet werden kann?
Schreibe ich einen kleinen interpreter für eine einfache BASIC-ähnliche Sprache wie eine übung auf einem AVR-mikrocontroller in C mit dem avr-gcc-toolchain. Allerdings Frage ich mich, ob es irgendwelche open-source-tools gibt, die mir helfen könnten, schreiben die lexer und parser.
Wenn ich schreiben würde, diese laufen auf meinem Linux-box, die ich verwenden könnte, flex/bison. Nun, ich beschränkte mich auf einen 8-bit-Plattform zu tun haben, ich Sie alle von hand, oder nicht?
InformationsquelleAutor der Frage Johan | 2010-02-11
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Habe ich implementiert einen parser für eine einfache Kommandosprache, die speziell für den ATmega328p. Dieser chip hat 32k ROM und nur 2k RAM. Der RAM ist definitiv wichtiger, Einschränkung -- wenn Sie sind nicht gebunden an einen bestimmten chip noch, wählen Sie eine mit so viel RAM wie möglich. Dadurch wird Ihr Leben viel einfacher.
Zuerst habe ich mittels flex/bison. Ich entschied mich gegen diese option für zwei wesentliche Gründe:
Nach der Ablehnung der Flex - & Bison, ging ich auf der Suche für andere-generator-tools. Hier sind ein paar, die ich in Betracht gezogen:
Vielleicht möchten Sie auch einen Blick auf Der Wikipedia-Vergleich.
Letztendlich landete ich hand-Codierung sowohl der lexer und parser.
Für die Analyse verwendete ich einen recursive-descent-parser. Ich denke, Ira Baxter bereits getan hat, einen adäquaten job für dieses Thema, und es gibt viele tutorials online.
Für meine lexer, ich schrieb Sie reguläre Ausdrücke für alle meine Endgeräte, Diagrammen erfasst die äquivalente state machine implementiert und es als eine Riesen Funktion mit
goto
's für das springen zwischen den Staaten. Das war mühsam, aber das Ergebnis hat Super funktioniert. Nebenbeigoto
ist ein großes Werkzeug für die Umsetzung von state-machines -- Sie alle Ihre Zustände können klare Etiketten direkt neben den relevanten code, es ist kein Funktionsaufruf oder state variable overhead, und es ist in etwa so schnell, wie Sie bekommen können. C ist wirklich nicht eine bessere Konstrukt für den Aufbau statischer Zustand Maschinen.Etwas zu denken: lexers sind wirklich nur eine Spezialisierung der Parser. Der größte Unterschied ist, dass reguläre Grammatiken sind in der Regel ausreichend für die lexikalische Analyse, in der Erwägung, dass die meisten Programmiersprachen haben (meist) Kontext-freie Grammatiken. Also es gibt wirklich nichts hält Sie von der Umsetzung ein lexer als recursive-descent-parser oder mit einem parser-generator zu schreiben, ein lexer. Es ist nur meist nicht so bequem, wie mit einem Spezial-tool.
InformationsquelleAutor der Antwort Steve S
Wenn Sie möchten, eine einfache Möglichkeit, um code-Parser, oder Sie sind dicht am Platz, Sie sollten hand-code eine rekursive Abstieg parser; diese sind im wesentlichen LL(1) - Parser. Dies ist besonders wirksam für Sprachen, die als "einfach" als Basic. (Ich habe mehrere von diesen zurück in die 70er Jahre!). Die gute Nachricht ist, diese enthält keinen code für die Bibliothek; genau das, was Sie schreiben.
Sind Sie ziemlich einfach zu code, wenn Sie bereits eine Grammatik.
Erste, Sie haben, um loszuwerden, von Links-rekursive Regeln (z.B., X = X-Y ).
Dies ist in der Regel Recht einfach zu tun, also lasse ich es als eine übung.
(Sie müssen nicht, dies zu tun für die Liste-Regeln bilden;
siehe Diskussion unten).
Dann, wenn Sie die BNF-Regel der form:
erstellen Sie eine Unterroutine für jedes Element in der Regel (X, A, B, C), die einen booleschen Wert zurückgibt
zu sagen: "ich sah die entsprechenden syntax-Konstrukt". Für X, code:
Ähnlich für A, B, C.
Wenn ein token ist ein terminal, code schreiben, der prüft,
der input-stream für die Zeichenkette, die macht das terminal.
E. g, für eine Reihe, überprüfen Sie, dass input-stream enthält Ziffern und Voraus
input stream, cursor Vergangenheit die Ziffern. Dies ist besonders einfach, wenn Sie
analysieren, aus einem Puffer (für BASIC, neigen Sie dazu, um eine Zeile zu Zeit)
durch einfach vorwärts nicht voran, ein buffer scan-Zeiger.
Dieser code ist im wesentlichen der lexer Teil des parsers.
Wenn Ihr BNF-Regel ist rekursiv... Mach dir keine sorgen. Nur code der rekursiven Aufrufs.
Diese Griffe Grammatik-Regeln wie:
Dieser kann codiert werden als:
Wenn Sie eine BNF-Regel mit einer alternative:
dann code P mit alternativen Möglichkeiten:
Manchmal werden Sie stoßen Liste bilden Regeln.
Diese sind in der Regel Links-rekursiv, und dieser Fall ist einfach in der Handhabung.
Beispiel:
Können Sie code dieser:
Können Sie code mehrere hundert Grammatik-Regeln in ein oder zwei Tage auf diese Weise.
Es gibt noch mehr details zu füllen, aber die Grundlagen sollten hier mehr als genug.
Wenn Sie wirklich fest auf Raum, können Sie erstellen eine virtuelle Maschine implementiert
diese Ideen. Das ist, was ich damals in den 70ern, wenn 8K 16-bit-Worte, das war das, was Sie bekommen konnte.
Wenn Sie nicht wollen, um code von hand, können Sie automatisieren es mit einem metacompiler (Meta-II) , produziert im wesentlichen die gleiche Sache. Diese sind mind-blowing technische Spaß und dauert wirklich ganze Arbeit tun, auch für große Grammatiken.
August 2014:
Bekomme ich viele Anfragen für "wie Baue ich einen AST mit einem parser". Für details zu dieser, die im wesentlichen baut diese Antwort, siehe meine andere Antwort SO https://stackoverflow.com/a/25106688/120163
Juli 2015:
Gibt es viele Leute was schreiben wollen, eine einfache Ausdrucksauswertung. Sie können dies tun, indem Sie die gleichen Arten von Dingen, die "AST-generator" - link oben deutet; nur rechnen, statt Knoten im Baum.
Hier ist eine Ausdrucksauswertung auf diese Weise getan.
InformationsquelleAutor der Antwort Ira Baxter
Können Sie mit flex/bison auf Linux mit seiner nativen gcc um den code zu generieren, dass Sie dann das cross-kompilieren mit Ihrer AVR-gcc für die embedded-Zielsystem.
InformationsquelleAutor der Antwort Paul R
GCC kann cross-kompilieren, um eine Vielzahl von Plattformen, aber Sie flex und bison auf der Plattform führen Sie den compiler auf. Sie Spucke C-code, den der compiler erstellt dann. Testen, um zu sehen, wie groß die resultierende ausführbare Datei wirklich ist. Beachten Sie, dass Sie Laufzeit-Bibliotheken (
libfl.a
etc.) Sie haben auch, um cross-kompilieren zu Ihrem Ziel.InformationsquelleAutor der Antwort ConcernedOfTunbridgeWells
Versuchen, Boost::Spirit. Es ist eine header-only-Bibliothek, die Sie können die drop-in und baut eine sehr schnelle, saubere parser vollständig in C++. Das überladen von Operatoren in C++ verwendet werden, anstatt eine spezielle Grammatik-Datei.
InformationsquelleAutor der Antwort Erik Aronesty
Anstatt neu zu erfinden das Rad, werfen Sie einen Blick auf LUA: http://www.lua.org. Es ist eine interpretierende Sprache soll eingebettet werden in andere software und verwendet auf kleine Systeme, wie embedded-Systeme. Built-in-prozedurale syntax-parsing-Baum -, Kontroll-Logik, Mathematik und variable Unterstützung — keine Notwendigkeit, neu zu erfinden, etwas, dass Tausende andere haben das bereits ausgetestet und verwendet. Und es ist erweiterbar, was bedeutet, können Sie die Grammatik, indem Sie Ihre eigenen C-Funktionen.
InformationsquelleAutor der Antwort Scott Hall