www.mikrocontroller.net

Forum: Projekte & Code uParse - ein kompakter und vielseitiger Parser


Autor: Rene B. (themason) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich stelle mal hier die neueste Variante meines Parsers vor.
Er ist recht "kompakt" (zw 1.5 und 1.9kB) und bietet dabei eine Menge.

Das Demo erfordert einen ATMega32 (hatte ich gerade so herumliegen, ein 
Mega8 tuts auch) mit Pegelkonverter für RS232, sowie einen 
Baudratenquarz.

In der readme.txt steht alles notwendige drin, und habe mal das 
wichtigste hier reinkopiert :


Was kann der Parser ?
---------------------

Der Parser kann Parameter wie Zahlen, Namen (16 Zeichen), Strings
(16 Zeichen), und durch Erweiterung wie in diesem Demo gezeigt Boolean 
(on,off,true,false...) und Datumsangaben (einfaches dd.mm.yy Format, 
ohne Prüfungen) verarbeiten.
Diese Parameter werden Codecs genannt. Die Codecs für Zahlen, Namen und
Strings) sind fest eingebaut, alle weiteren sind optional.
Die Befehle die der Parser erkennen kann sind in uParse_cfg.h definiert.

Beispiel :

UPARSE_ITEM(SETVAL,      "set \x02 = \x01",              FUNC_EG_SET)

UPARSE_ITEM(name  ,      text             ,              funktionsidx)

Es wird ein Eintrag SETVAL generiert (enum und datenmäßig) bestehend aus 
dem Text und einem Funktionsidx. (siehe Abschnitt UPARSE_FUNCTION).
Die Steuerzeichen \x02 und \x01 im Text rufen den gewünschten Codec auf.
\x01 bedeutet Zahl \x02 Name und \x03 String. Alles über \x03 sind
ggf. definierte User-Codecs.

Gibt der Benutzer nun "set name = 123" ein so wird die Funktion die sich
hinter  FUNC_EG_SET verbirgt (in dem Falle "vCmdSet") mit dem enum für
SETVAL und einem Parameterarray auf. Dieses Array besteht aus 4 (siehe
PARSE_DATA_ELEMENTS) Elementen. Jedes Element umfasst ein Union aus
einem 32 Bit unsigned long und einem (siehe PARSE_DATA_STR_LEN) 16-Byte
Array (für Namen usw), sowie ggf. User-Definierte Daten für die
User-Codecs. Zusätzlich gibt es einem Byte welches besagt um welchen
Datentyp es sich handelt.

In diesem Falle wäre das

stCmdDatas [0].ucType = 2     stCmdDatas [0].aucName = "name"  und
stCmdDatas [1].ucType = 1     stCmdDatas [1].ulLong  = 123

Mit diesen Parametern und dem enum für SETVAL (hier 2) wird vCmdSet 
aufgerufen.


Der Parser ist sehr flexibel was die Eingabe angeht. So werden Zahlen 
wie
0x2345, -0b110010, $1234, -5, 3827362 erkannt. Auch bei den Spaces ist 
der
Parser nicht so restriktiv. Wenn in der "Vorlage" ein Space steht können
beliebig (aber auch keins !) viele Spaces folgen bevor die Verarbeitung 
das nächste Zeichen abarbeitet. Tabs werden zu Spaces. Eine Umschaltung 
zwischen case sensitive/case insensitive ist mit dem Schalter 
PARSE_IGNORE_CASE in der Konfiguration im Abschnitt PARSE_CONFIG 
möglich.

So würde

"          sET            nAmE  =123    "

denselben Aufruf zur Folge haben. Weiterhin arbeitet der Parser so lange 
bis das EOT (\0) erkannt wurde oder ein Fehler vorliegt.
Z.B. "cmd test test = 0x345 backlight off" würde jeweils 1 mal 
FUNC_EG_CTRL, FUNC_EG_SET und FUNC_EG_TEST mit den entsprechenden 
Parametern aufgerufen werden. Im Fehlerfalle kann die Position des 
Fehlers zurückgegeben werden.

Es lässt sich weiterhin eine automatisch generierte Hilfe nutzen. Diese 
listet bei Eingabe von "help" alle bekannten Befehle auf und 
entschlüsselt die Steuerzeichen für die Codecs in Klartext. 
User-Definierte Codecs weden (soweit benannt) ebenfalls aufgelistet.

--- Zitat-Ende ---

Verwendung findet solch ein Parser überall da wo man Funktionsteile 
testen, Parameter setzen, Operationen antriggern muß. In Verbindung mit 
einem UART ergibt sich sehr leicht eine Kommando-Shell die es erlauben 
bequem mit dem System zu arbeiten.
In Verbindung mit einem Speichermedium und einem Dateisystem wäre 
Scripting (vllt auch ein Interpreter) möglich.
Dieser Parser ist keineswegs auf den AVR beschränkt (selbst wenn er 
"danach" programmiert worden ist; es genügt eine handvoll Makros und ess 
lässt sich auf (fast) jede Plattform portieren).


Viel Spaß damit ...

Autor: Rene B. (themason) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da diese Software anscheinend fehlerfrei ist (und um den Thread nochmal 
nach oben zu holen) :-))) kündige ich meine nächste Untat an.
Es wird (nach dem selben Prinzip, nur etwas anders aufgebaut) einen 
XML-Reader geben. Dieser wird die XML-Datei Zeichen für Zeichen 
analysieren und bei den jeweiligen Knoten (und noch in anderen 
Situationen) eine Benutzer-Funktion aufrufen in der die Daten dann 
weiter verarbeitet werden können.
Das ganze soll ebenfalls so kompakt wie möglich sein aber gleichzeitig 
eine gewisse Flexibilität geben. Woher die XML-Daten kommen ist 
zweitrangig, da der Anwender ein paar kleine Funktionen zu Verfügung 
stellen muß, damit der Parser arbeiten kann. Dadurch wird es obsolet ob 
die Daten im EEProm, im Flash, auf einer SD-Karte oder sonstwo stehen.

Mögliche Anwendungen wären :
 - einfache Konfiguration der Applikation
 - Import von Strukturierten Daten
 - Verarbeiten von Playlists/Anweisungslisten
 - alles was mir gerad nicht einfällt ...

Autor: Gerhart (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was macht man mit so einem Parser?
Schilder doch bitte mal einen Anwendungsfall aus der Praxis-

Autor: Rene B. (themason) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was man mit dem Parser machen kann habe ich ja schon beschrieben :

 - Debugshell
 - Monitorprogramm
 - Steuern

In Verbindung mit einem PC Programm muß man dann nur noch die Befehle 
rüberschicken, und man kann beim Sniffen direkt im Klartext lesen was 
passiert. Bei Binärdaten ist das nicht ganz so einfach, da man ja immer 
ein spezielles Programm benötigt, welches das Protokoll unterstützt. So 
reicht ein einfaches Terminalprogramm um alles steuern zu können, und 
man hat nicht das Problem das wenn sich etwas an den Funktionen ändert 
jedesmal das PC-Programm ändern muß bzw dann passt die Version nicht mit 
der SW im uC zusammen usw ....
Mit einem Terminal kann man alles direkt erreichen.

In Verbindung mit einer SD-Karte :

 - Steuerskripte
 - Interpretersprache

Auf größeren Systemen mit mehr Speicher (teste ich gerade)

 - Ansätze für einen Compiler

Ob das praxisauglich ist weiß ich nicht. Aber zum Debuggen ist es sehr 
hilfreich.
Und um sich beispielsweise ein Single-Chip-Computer-System aufzubauen 
sicherlich auch. Ob man sowas in professionellen Geräten benötigt weiß 
ich nicht. Aber eine Debugshell kann beim Entwickeln immer hilfreich 
sein denke ich.

Mein spzieller Anwendungsfall ist mein Audio-Projekt. Mit dem Parser 
kann ich da folgendes machen :
 - Einstellen des Codecs
 - Auslesen/Beschreiben des EEProms/DataFlashs
 - Berechnen der Tabellen und speichern im Datenflash
 - Setzen/Auslesen der Werte für die Audio/Steuermodule
 - Ändern der konfiguration/Verbindungen der Audio/Steuermodule (dadurch 
wird das ganze erst zum Modular-System)
 - Disassemblieren und Assemblieren des Programms für den DSP
 - Auslesen der Speicherbereiche für den DSP.

Autor: John Schmitz (student)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rene,

das Thema interessiert mich brennend. Aber ich habe keine Ahnung von 
Parsern, eventuell solltest Du "umgangssprachlich" ein wenig helfen:

Also, meine Anwendung sieh so aus:

Ich sende über Funk von einem PC Befehle und Parameter an einen MC. Der 
wiederum steuert ein Gefährt an. Es soll eine Rückmeldung (Info, 
Success, Warning, Fatal, ... etc.) für den ausgeführten Befehl 
zurückgegeben werden.

Verstehe ich es richtig, dass ich für jeden Befehl, bzw. Typ den ich 
interpretieren will, eine Routine in einem Definitions-File angebe, die 
dann nach der Befehlserkennung angesprungen wird und den angegeben 
Parameter verarbeitet ?

Wobei Befehle aus einem einzelnen Buchstaben oder mehreren Buschstaben 
bestehen können ?

Migration auf einen Mega 256x sollte ohne weiteres lediglich durch 
UART-Anpassung gehen ?

LG

Autor: Rene B. (themason) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@John

>Verstehe ich es richtig, dass ich für jeden Befehl, bzw. Typ den ich
>interpretieren will, eine Routine in einem Definitions-File angebe

Kann man so machen. Man kann aber auch eine Routine für alle Befehle 
oder Befehle die zusammengehören. (z.b. Parameter setzen, Gefährt 
bewegen, Debug-Aufrufe, Statusabfrage). Man bekommt ja die Befehlsnummer 
(zu der es einen enum gibt) und kann/muß diese dann per switch/case 
Methode entsprechend "auswerten" (sprich den gewünschten Befehl 
ausführen).

Wenn du mit Typ einen Datentyp meinst der keine Zahl/String/Name ist, 
sondern beispielsweise ein bool, ein Datum, eine IP-Adresse, oder 
sonstwie geartete Daten die von Text -> Binär umgesetzt werden müssen, 
musst du einen Codec schreiben, der die "Eingabe" (man wird dann vom 
Parser aufgerufen) prüft und in Binärdaten umsetzt. Dieser Codec lässt 
sich für jeden x-beliebigen Befehl (der in UPARSE_ITEM definiert ist) 
einsetzen.


>Wobei Befehle aus einem einzelnen Buchstaben oder mehreren Buschstaben
>bestehen können ?

Richtig. Die Eingabe wird Zeichen für Zeichen mit der Befehlsliste 
verglichen und bei den Steuerzeichen in der Befehlsliste wird die 
Eingabe auf den jeweiligen Datentyp geprüft.
Ob der Befehl aus einem Zeichen, oder einem halben Roman besteht ist 
letztenendes egal.

>Migration auf einen Mega 256x sollte ohne weiteres lediglich durch
>UART-Anpassung gehen ?

Der Parser selbst hat keine UART Unterstützung. Dem Parser ist es 
letztenendes egal wo der Input herkommt. Das kann ein UART, ein Flash, 
ein EEProm, oder eine SD-Karte sein. Der Parser selbst benötigt nur 
einen Zeiger auf den zu bearbeitenden Eingabestring im RAM.
Also bei einem UART würde dieser Zeichen für Zeichen entgegennehmen und 
alles bis auf \x0a oder \x0d wegspeichern. Bei einem \x0a oder \x0d 
würde der Eingabestring mit \0 abeschlossen und der Parser mit diesem 
String aufgerufen werden (natürlich nicht aus dem Interrupt heraus :-)).
Bei einer SD-Karte würde man ähnlich verfahren. Zeile bis zum CRLF 
einlesen und im RAM speichern und bei CRLF den Parser dann aufrufen 
(Eingabestring vorher abschließen).

Dadurch das der Parser keine IO Routinen anspricht/benutzt kann dieser 
auf jedem System (egal ob AVR, ARM, PC oder sonstwas) eingesetzt werden.
Er dient also lediglich der Umsetzung zw. Klartext-Befehlen und Aufruf 
mit den übergebenen Parametern in Binärform.

Beispiel :

uParse_cfg.h :

UPARSE_ITEM(MOVE_FWD,     "move ffw",  FUNC_MOVE)
UPARSE_ITEM(MOVE_BWD,     "move back",  FUNC_MOVE)
UPARSE_ITEM(MOVE_LFT,     "move left",  FUNC_MOVE)
UPARSE_ITEM(MOVE_RGT,   ´ "move right",  FUNC_MOVE)
UPARSE_ITEM(MOVE_DIR_STP, "move \x01, \x01", FUNC_MOVE)
UPARSE_ITEM(MOVE_DIR,     "move \x01",  FUNC_MOVE)


Der Parser versteht danach 6 Befehle (mehr).
 - move ffw
 - move back
 - move left
 - move right
 - move zahl, zahl
 - move zahl

bei Erkennen einer dieser Befehle wird die Funktion die hinter 
"FUNC_MOVE" steht mit dem entsprechenden enum (MOVE_FWD, MOVE_BWD, 
MOVE_LFT, MOVE_RGT, MOVE_DIR_STP, MOVE_DIR) und den Parametern 
aufgerufen.

Beispiele :

move 3, 30 ->
  enum = MOVE_DIR_STP, stCmdDatas [0].ulLong = 3, stCmdDatas [1].ulLong 
= 30

move fwd ->
  enum = MOVE_FWD

Es bleibt dem Benutzer überlassen ob er alle Befehle in einer 
Aufrufer-Funktion (wie z.b. FUNC_MOVE) oder über mehrere Funktionen 
verteilt.

Die Erweiterung um neue Befehle erfolgt derart einfach das es im Prinzip 
nicht mehr einfacher geht.
Man muß nur einen Text-Befehl in der uParse_cfg.h hinzufügen und (im 
Falle einer schon vorhandenen Aufrufer-Funktion mit switch/case) den 
case für den neuen Enum hinzufügen.

uParse_cfg.h
------------

UPARSE_ITEM(SET_PORT_A,  "set port a = \x01", PORT_FUNC)

Ausführendes C-Modul, Funktion die hinter PORT_FUNC steht
---------------------------------------------------------

case SET_PORT_A : PORTA = stCmdDatas [0].ulLong; break;

Fertig !

Hoffe das Prinzip ist klar geworden. Dem Parser ist es egal wo der 
Eingabestring herkommt und was die Funktion die diesen Befehl ausführen 
soll damit macht. Der Parser geht nur Zeile für Zeile in seiner Liste 
durch, und wenn er einen Befehl gefunden hat der zu der Eingabe passt 
wird die Funktion die hinter dem Befehl steht aufgerufen mit dem Enum 
des Befehls und den umgewandelten Parametern.

Man kann das wie schon erwähnt für Steuerzwecke (Steuerung über einen PC 
mti Terminal-Programm, einem PC Programm welches Befehle im Klartext 
über die Leitung schickt, eine SD-Karte mit einem Script, oder oder oder 
...),
oder Einstellen von Parametern oder eben zu Debugzwecken (es ist einfach 
nur praktisch eine Funktion testen zu können indem man einen bestimmten 
Befehl eingibt, und diese Funktion dann mit evtl. übergebenen Parametern 
aufgerufen wird).

Hoffe ich konnte etwas Klarheit in die Sache bringen.

Autor: John Schmitz (student)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rene,

danke erst einmal: Das ist genau, wonach ich schon lange gesucht habe.

Brauche etwas Zeit zur Implementierung, werde mich aber in jedem Falle 
hier wieder melden.

Grüße

Autor: Rene B. (themason) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@john

Freut mich das du den Parser brauchen kannst.
Die Implementierung dürfte recht einfach sein. Für das Interfacing musst 
du dir im Prinzip nur die main.c anschauen. Dann sollte alles klar 
werden.
Wenn nicht, frag einfach.
Du kannst ja vorstellen was du gemacht hast, und deine Erfahrungen dazu 
posten.
Bin für Feedback immer dankbar.

Autor: Harry L. (mysth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rene,
bevor ich anfang, mich durch deinen gesamten Code zu wühlen, frag ich 
lieber kurz hier, ob dir spontan zu folgendem Problem was einfällt:
Ich hab deinen Parser mit dem Beispielprogramm für einen atmega644 
übersetzt. Ausser einigen Register-Namen für die UART und den Namen der 
ISR hab ich nichts verändert.
Die Startmeldung erscheint, ich kann etwas eingeben, aber sobald ich 
Enter drück ist das ding bis zum nächsten Reset tot.

Hab ich was übersehen?

Harry

Autor: Rene B. (themason) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Harald

Wenn du mit AVR-Studio arbeitest, mußt du in den Projekt-Optionen 
"Unsigned Chars" wegclicken. Hatte ich vergessen zu erwähnen. Asche auf 
mei Haupt.

Ich verwende signed chars (ist bei Abfragen einfacher). Bei unsigned 
chars hängt das Dingen nur. Muß das nochmal beheben, sodas es unabhängig 
davon ist (also casting noch vervollständigen).

Ein weiteres kleines Problem (habe ich schon behoben, aber noch nicht 
hochgeladen) ist das 0 als Zahlenwert nicht erkannt wird. 0x0 sollte 
hingegen schon erkannt werden.
Werde die korrigierte Version hier noch hochladen.

Autor: Harry L. (mysth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rene,
ich arbeite nicht mit AVR-Studio, sondern mit Eclips.
Da der Parser in ein bereits vorhandenes Projejt intgriert werden soll, 
kann ich auf unsigned chars nicht verzichten (genauso wenig wie auf 
signed)

So ist das leider keine sehr saubere Lösung!

Ein Hinweis zum Schluss: achte bitte bei der Benennung von Dateien auch 
auf Gross- Klein-Schreibung. In dem von dir bereitgestellten Code wird 
die include-Datei nicht gefunden, da das P im Dateinamen gross 
geschrieben wurde, dies aber im übrigen Quelltext nicht berücksichtigt 
wurde.

Gruss

Harry

Autor: Rene B. (themason) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Harald

Na ja. Wenn man nur mit AVR Studio und Visual Studio arbeitet hat man 
vllt nicht die Ambitionen es noch auf Eclipse zu Testen.
Da das ganze auf der Windows-Plattform Entwickelt worden ist hab ich 
mich bei Dateinamen erstmal nicht um Groß/Kleinschreibung gekümmert.

Aber die Sache mit den unsigned/signed chars werde ich noch ändern. Da 
ich selbst öfter mal drüber stolpere denke ich muß ich da wohl mal 
aufräumen.
Ich mache mal eine neue Version fertig und werde diese Hochladen.

Autor: Rene B. (themason) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier das angekündigte Update.

Sry an all diejenigen die den Parser versucht haben zu nutzen und dabei 
Startschwierigkeiten hatten.
Es ist nun behoben :
 - signed/unsigned-"Problematik"
 - Problem mit der Eingabe von 0, 1 als Zahl (0x0 oder $0 wären 
gegangen)
 - soweit ich Testen konnte Groß/Kleinschreibung in Dateinamen für die 
Linux-Leute

Für weiteres Feedback wäre ich dankbar.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hattest ja schon mal sowas gemacht. Damals war es leider schon so, 
dass man nicht unbedingt die richtige Anwendung dafür hat.

Ich überlege gerade, wo ich das mal einsetzen könnte. Irgendwie ne 
Kommandozeile über eine serielle Schnittstelle wär mal was... Hm.

Wenn ich sowas jedenfalls mal brauche und ich keine Lust habe sowas 
selber zu machen (Das werde ich sicher nicht haben), dann weiß ich ja wo 
ich sowas finden kann! ;-)

Autor: Rene B. (themason) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Simon

ich geb zu das es kein Fading-LED, keine TCP/IP-Implementation, keine 
FAT16/32 ist, aber wie du schon sagtest : Kommandozeile für den uC via 
serielle Schnittstelle (oder wenn man einen VGA/BAS-Teil hat auch direkt 
am Fernsehen) ist eine Möglichkeit.
Ich finde es einfach nur bequem wenn ich selbstgeschriebene Funktionen 
"mal eben" schnell testen kann.
Oder wenn ich ein System habe das dynamisch Code von SD-Karte nachladen 
kann könnte ich sogar eine gewisse DOS-Funktionalität nachbilden.
Oder das Grundgerüst für einen BASIC (oder sonstwas) Interpreter.

Autor: didadu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für Haussteuerung:

"Tür auf"
"Licht WZ AN" (Wohnzimmer)
"Toaster EIN"
"Brotintoasterwerfer Scheibe 1" (1 Stück)
"Fenster zu"
"Rolladen hoch"
"Alles AUS"

usw.

Autor: G. B. (garyb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rene,

lach - nachdem du meinem Thread deine Werbung aufgedrückt hast... 
revanchiere ich mich ;O)

Hallo Leute - hier ist noch ein Parser - find das ulkig vor Wochen hab 
ich gar nichts gefunden und auf einmal...

Beitrag "Re: Einfacher Interpreter für Komandozeilen/Befehlszeilen"

Aber wenn ich das sehe verfolgen wir beide etwas unterschiedliche 
Konzepte.
Was mir bei einem gut gefällt ist die Möglichkei mit den "Token" mit 
denen ich ein Kommando wie "set" noch parameterieren kann ohne 
zusätzlich Code zu erzeugen.

Dafür erscheint mir meiner erst einmal etwas übersichtlicher, aber das 
liegt im Auge des Betrachters und da bin ich eindeutig befangen ;O)
Ich werde die Anregung mal mitnehmen. Vielleicht mergen wir die Threads 
dann ;)

Good coding,
Gary

Autor: Rene B. (themason) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Gary,

das ist nur gerecht :-)))

Vllt hätte ich meinen Parser "Erweiterter einfacher Parser für 
Kommandozeilen" nennen sollen gg.
Aber die unterschiedlichen Konzepte sind schon sichtbar, wobei ich es 
bei meinem Parser vorteilhaft finde das dort Parameter direkt als 
Binärwerte umgesetzt werden (Zahlen, oder wie im Beispiel Bool, Datum, 
oder sonstiges) können und quasi direkt "mundgerecht" serviert werden 
:-) und die Zubereitung dieser Werte kann sogar durch eigene Zutaten 
erweitert werden, um mal kulinarisch zu bleiben :-)

Autor: Michael Hammer (mueli)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rene,

zuerst einmal Danke für Deinen inspirierenden Code zum Thema kompakter 
Parser. Ich selbst benötige etwas sehr Ähnliches zum Bedienen eines GSM 
Modems (parsing of AT command response). Zum Einen habe ich einige 
zusätzliche Anforderungen (andere features benötige ich wieder nicht), 
zum Anderen handelt es sich bei dem Projekt leider um ein closed source 
Projekt. D.h. ich bin genötigt einen eigenen Parser zu schreiben. Soweit 
zu meiner Geschichte.

Ich habe jetzt noch eine Frage zur Genese Deines Projektes. Bei der 
ersten Variante (uShell) hast Du noch auf eine Trennung von Tokenizer 
und Parser gesetzt (analog zu einem Konzept wie flex, bison) - bei 
dieser neuen Variante setzt Du nun auf ein zeichenweises parsen. (bitte 
korrigiere mich falls ich falsch liege).

Warum hast Du das umgestellt? Was waren die Nachteile des Token 
basierten Konzeptes?

Vom Gefühl her hätte ich gesagt, dass die Klassifizierung in Tokens 
effektiver ist als die Einordnung der Zeichen in Klassen wie Du es jetzt 
machst. Ich würde mich über Rückmeldung freuen.

Grüße, Michael

Autor: Rene B. (themason) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit der Trennung in Tokenizer und Parser bei der uShell hast du 
richtig erkannt :-) Ich hatte das damals gemacht weil ich versucht habe 
ohne "Eingangspuffer" auszukommen. Ich habe allerdings lediglich den 
Eingangspuffer für die Tokens eingespart. Die erkannten Tokens landen 
dann aber dennoch in einem Puffer. Das eigentlich besondere an der 
uShell ist eben die Tokenerkennung. Es wird zu jeden Token ein Bit 
gesetzt ob das aktuelle Zeichen noch in übereinstimmung mit dem Token 
steht. Wenn nicht, wird dieses Token auch nicht weiter untersucht.

Letztenendes habe ich umgestellt da mir die Erstellung der "Sätze" die 
der Interpreter verstteht einfach zu umständlich war. Erst Tokens 
definieren, dabei aufpassen das diese nicht schon existieren. Dann das 
umständliche Zusammenbauen der Tokens zu einem Satz. Irgendwie war mir 
das alles zu lästig. Außerdem hat es mehr Platz benötigt als der neue 
Interpreter.
Und da man die zeichenweise Verarbeitung ja nicht unbedingt im Interrupt 
machen sollte, kommt man um einen Eingangspuffer ohnehin nicht herum.
Der neue Parser ist zwar langsamer dadurch das er eben alle Sätze immer 
durchsucht, aber dafür ist dieser kompakter und für die meisten (meiner 
Anwendungen) ausreichend.

Die Einteilung in Klassen kam eigentlich daher das ich versucht habe 
einen kompakten XML-Parser zu programmieren. Dieser besteht wie der neue 
Parser auch aus 2 Tabellen. Eine für die Zeichenklasse, die andere als 
Statemachine. Das war der Ausgangspunkt meinen Parser zu überarbeiten. 
Den ursprünglichen XML-Parser hab ich noch nicht eingesetzt, ist aber 
für die Möglichkeiten die er bietet eben sehr kompakt. Evtl stelle ich 
den hier auch nochmal vor, wenn ich denn mal ein AVR-Demo dazu fertig 
habe :-)

Freut mich aber das sich jemand mal mit meinen Interpretern 
auseinandersetzt bzw durch meinen Code inspiriert worden ist :-)
Falls ich dir bei deinem Problem helfen kann bzw noch weitere 
Inspiration geben kann, gerne ...  schreib mir einfach ne PN.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.