Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Parser (fuer eigene scriptsprache)

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
08.10.2004, 16:00 Uhr
SnakeByte



tja... ich hab mir in den kopf gesetzt fuer die konfiguration/steuerung meines programms eine scriptsprache zu benutzen...
da allerdings vorhandene scriptsprachen in meinem fall zu viel overhead bedeuten wuerde (nicht diskutabel) hab ich mir meine eigene ausgedacht...

sieht etwa so aus:

Code:
$DeviceName = "I2C";
$DeviceInfo = "I2C...";
$DriverFile = "communicationI2C.dll";

$DataSetPages = 2;
$DataSetPageSize = 0xFF;

group "Parameter" (
        $read = TRUE,
        $write = TRUE
        )
{
    value [0x00] "Wert 0x00" ( $write = %Checksum([0x01],[0x02]) );
}

function Checksum(var1,var2)
{
    return (var1 ^ var2);
}


Erklaerung:
das ganze soll einen datensatz (ein array das bytes enthaelt) und dessen darstellung konfigurieren...
[0x00] liefert z.B. den wert an der adresse 0x00 im datensatz
$var sind variablen
group konfiguriert eine gruppe (hernach in der baum-ansicht ein oberpunkt)
value stellt einen wert mitsammt seiner beschriftung und parameter dar


nun hab ich die datei geladen und tokenized (heisst variablennname, schluesselwoerter, operatoren und alle sprachelemente in eigene strings gepackt und in ein stringarray gelegt (alle in der reihenfolge wie sie in der datei stehen))

so weit so gut... aber wie weiter? O_o
ich weiss dass man jetz am besten ableitungsbaeume erstellen sollte aber ich hab keine ahnung wie ich dabei vorgehn soll

u.a. ein problem ist wie ich das in objekte verpacke und moeglichst simpel (kann ruhig rekursiv sein) parse und hernach auch ausfuehre

kann mir wer tipps/anleitungen fuer das weitere vorgehen geben? ich bin langsam am verzweifeln (zerbreche mir schon 2 tage den kopf)

mfg
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
08.10.2004, 16:13 Uhr
virtual
Sexiest Bit alive
(Operator)


Nutze flex/bison.
Einen vorgeschmack bekommst Du hier: www.fun-soft.de/showtopic.php?threadid=4669
Allerdings ist das wirklich ein simples Beispiel und ließe sich auch weiterführen, eben nicht nur mathematische Terme, sondern auch Scriptsprachen. Ich habe damit schon einige Erfahrungen sammeln können und finde flex/bison einfach nur genial.

Andererseits: was den Aufwand angeht, so bist Du mit dem einbinden einer existieren Scriptsprache vermutlich besser bedient, als eine neu zu erfinden.... Mit Perl XS kann man zB wunderbar Perl in C Programme einbinden, erfordert allerdings ein wenig einarbeitungszeit,
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
08.10.2004, 18:53 Uhr
0xdeadbeef
Gott
(Operator)


Ich würd mir mal boost::spirit ankucken, das Ding ist sehr genial, um eigene Parser zu bauen. Allerdings - spirit hin oder her, ne eigene Skriptsprache ist nicht einfach umzusetzen, von daher würde ich mir das mit ner schon fertigen Sprache noch mal überlegen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
11.10.2004, 08:02 Uhr
SnakeByte



danke fuer die tips aber ich wollte das eigentlich selber schreiben weil ich lernen wollte wie sowas funktioniert
ich bin z.Z. im praktikumssemester und wenn ich schon absolut unterbezahlt bin und staendig fuer unwuerdige arbeit ausgenutzt werde will ich zumindest was lernen

mir geht es vor allem um die denkweise und um das ganze objektorientieren
im endeffekt schreib ich ja noch nichmal c++ und frag hier nur weil ich denke dass c++-coder sowas drauf haben koennten und ich das auch gern koennte

ich stell mir das ganze rekursiv vor... heisst ich hab erstmal eine klasse/funktion/methode die den globalen bereich "parst"... sobald ein token auf einen neuen block hinweist (z.B. "(") sollte eine entsprechende klasse/funktion/methode aufgerufen werden die diesen teil parst, dann durch weitere rekursionen in die tiefe geht (bei mehrfach-verschachtelungen) und hernach beim ende des blocks (z.B. ")") wieder an die hauptschleife zurueck gibt die dann nach dem naechsten block sucht...
das schreit quasi nach einer gemeinsamen funktion die nach bloecken sucht allerdings kann ich diese nicht ueberall verwenden da verschiedene bloecke verschiedene unterbloecke haben koennen
z.B. () kann kein {} als unterblock haben aber z.B. ""
{} kann fast alle unterbloecke haben aber keine () direkt
ein "group" MUSS von einem namen gefolgt werden worauf ein () folgen KANN, muss aber nicht; muss aber von einem {}-block abgeschlossen werden
etwa so:
Code:
group "<Name>" [\( <parameter> \)] \{ <unterbloecke> \}


also wie wuerdet ihr eine klasse (ich denke das waere die sinnigste loesung) implementieren die sowas kann?
[wirr]basis klasse die das kann und entsprechen in die end-klassen inhertieren sodass diese genau das koennen was sie koennen sollen? [/wirr]

Dieser Post wurde am 11.10.2004 um 08:30 Uhr von SnakeByte editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
11.10.2004, 09:58 Uhr
Bruder Leif
dances with systems
(Operator)


Moin!

Ich würde erst mal einen kleinen Scanner schreiben, der die Datei in einzelne Tokens zerlegt und Leerzeichen, Kommentare etc. überliest, Stringkonstanten und Variablen als solche erkennt usw.
Dann ein Parser, der in mehrere Funktionen unterteilt ist, die jeweils EIN Sprachkonstrukt erkennen können, und sich gegenseitig mit steigender Priorität aufrufen.
Wenn Du z.B. mathematische Ausdrücke parsen willst, z.B. 12+3*($hallo-5), kannst Du Prioritäten festlegen:

0 Konstante, Klammer, Variable
1 *, /
2 +, -

Im Parser hast Du dann eine Funktion Prio0(...), eine Prio1(...) usw. Prio0(...) prüft, ob das nächste Token, das der Scanner liefert, eine Zahlenkonstante, eine öffnende Klammer oder eine Variable ist, und hört ansonsten mit dem Parsen auf. Eine Zahlenkonstante wird 1:1 zurückgegeben, bei einer öffnenden Klammer muß der Parser sich selbst nochmal aufrufen (weil eigenständiger Ausdruck), bei einer Variable wird deren Wert zurückgegeben.
Analog holt Prio1(...) erstmal den linken Teil eines Ausdrucks (also Prio1), prüft dann, ob eine Punktrechnung folgt; falls ja, wird der rechte Teil des Ausdrucks geholt (diesmal Prio0), gerechnet, und das Ergebnis zurückgegeben. Prio2 analog, Prio3, 4, 5..... soviel Du willst.

Stell Dir erst mal eine vereinfachte Grammatik für Deine Scriptsprache auf. Nach Lehrbuch würde das etwa so aussehen:

Strichrechnung ::= <Strichrechnung> +|- <Punktrechnung>
Punktrechnung ::= <Punktrechnung> *|/ <Konstante>
Konstante ::= <Zahl> | <Klammerausdruck> | <Variable>
Zahl ::= <Ziffer>+ (mindestens eine Ziffer)
Ziffer ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
Variable ::= $<Bezeichner>
Klammerausdruck ::= "(" <Ausdruck> ")"
Bezeichner ::= <Buchstabe>+
Buchstabe ::= ...usw...

Viel Spaß!
--
Mit 40 Fieber sitzt man nicht mehr vor dem PC.
Man liegt im Bett.
Mit dem Notebook.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
11.10.2004, 14:36 Uhr
SnakeByte



hmm
gut... den "Tokenizer" hab ich jetzt...
hernach hab ich ne liste in der jedes wort(variablen, schluesselwoerter, etc) und jeder operator als eigenes "Token" aufgelistet sind...

jetzt hab ich mir das so vorgestellt:

text aus der scriptdatei: $variable = \"Text\";
-> tokens: "$variable" "=" "\"" "Text" "\"" ";"
und dann laeuft meine hauptschleife, laesst ein variablen-pruef-objekt (neben anderen solchen pruef-objekten) testen ob es sich um eine variable handelt (erkennt es auch an dem $), prueft dann ob eine zuweisung folgt (folgt auch wegen dem = ) und prueft dann ob es sich um eine zahl oder um einen text handelt (in diesem fall text wegen der "").. ende der anweisung (";")

nun is aber mein problem... wie leg ich das so ab dass ich aus meinem programm sinnvoll darauf zugreifen kann?

ich haette mir das so vorgestellt: (pseudo hash)
global["$variable"] liefert mir einen string "Text" zurueck

wo es jetzt bei mir haengt ist die sache mit der implementierung...
ich haette die parser fuer die verschiedenen bloecke gerne als klassen implementiert die von einer gemeinsamen parser-basis die grundsaetze erben... aber mir faellt dazu einfach nichts ein was wirklich "schoen" und "effizient" aussieht

Dieser Post wurde am 11.10.2004 um 14:38 Uhr von SnakeByte editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
11.10.2004, 19:07 Uhr
Hans
Library Walker
(Operator)


Hi,

um meiner "Charakterisierung" mal wieder gercht zu werden, einige Literaturhinweise:
Zum einen dieses Buch, das "wohl das Stadardwerk schlechthin" ist, weil es schon seit Jahren auf dem Markt ist...


Bei Amazon: Teil 1 ;Teil 2

Und, etwas kürzer, weil Parser nur ein Thema unter vielen sind, das hier:

Bei Amazon


Dann noch, eben gefunden, das hier. Könnte noch ganz gut sein....

Bei Amazon

Soweit der "Rundgang durch die Bibliothek"
Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
12.10.2004, 08:12 Uhr
SnakeByte



du hast bei mir den wunden punkt gefunden... buecher
ich hab zwar nichts dagegen hin und wieder was nachzuschlagen aber bei buechern fehlt mir einfach immer die suchfunktion

"Reallife should have some kind of search function... I need my socks!"

inzwischen bin ich (hoffentlich) schon n ganzes stueck weiter...
mitlerweile hab ich einige elemente eingebaut:
- tokenizer (zerlegt die scriptdatei in tokens)
- execution tree (ist eigentlich nur ein objekt das ein array von unterobjekten enthaelt die in der untersten ebene einzelne tokens enthalten)
- parser (nimmt die tokens und fuettert damit den executiontree)
- interpreter (interpretiert je nach bedarf den executiontree)

wenn jetzt mein programm aus der script-datei beispielsweise eine variable (group/function/values/etc fast gleich aufgebaut) auslesen will sieht das etwa so aus:

Script["$variable"]
dadurch wird auf das (oben genannte) objekt mit dem array zugegriffen und ueber eine hash-table (die array-indizes enthaelt) indirekt auf die execution-tree-zweige zugegriffen...
wenn ein solcher zweig (anhand des namens) gefunden wurde wird damit der interpreter gefuettert und angeschossen
dieser durchlaeuft den zweig und interpretiert ihn (rekursiv) und liefert dann am ende das ergebnis zurueck (in diesem fall den wert von $variable)

wenn jemand verbesserungsvorschlaege hat... lassts mich wissen

mfg

Dieser Post wurde am 12.10.2004 um 08:14 Uhr von SnakeByte editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: