Ankündigung

Einklappen
Keine Ankündigung bisher.

Hilfe beim Bau eines Parsers

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Hilfe beim Bau eines Parsers

    Ich bin im Umgang mit PHP kein Einsteiger, aber habe nun die Anforderung einen Parser für eine eigene kleine Syntax zu erzeugen. Dabei soll eine Definitionssprache für die Verarbeitung von SQL Datensätzen erkannt, geprüft und in SQL Befehle umgewandelt werden. Verschachtelungen, Funktionen oder Sprünge sind nicht vorgesehen, die Befehle werden durch Zeilenschaltungen getrennt, die einzelnen Optionen durch Komma bzw Leerzeichen.

    Ich habe versucht mich im Internet in das Thema einzulesen, aber nicht wirklich alles verstanden. Ich fürchte ich benötige einen Mentor, der mich schritt für schritt an die Lösung heranführt.

    Hier mal, was ich soweit meine verstandeb zu haben. Bitte gern kommentieren oder berichtigen!

    Um eine Syntax zu erfassen sind mehrere Durchläufe (Pass) notwendig.
    Im ersten liest man Zeichen für Zeichen ein und versucht daraus sog. Tokens zu erzeugen.
    Diese repräsentieren die einzelnen Elemente der Sprache.
    Aus einem Befehlstext wie "sort by" kann z.B. ein Token "T_SORTBY" werden. Aus einem Zuweiser "=" wird ein T_EQUAL, einem String ein T_STRING, usw. Einige Tokens haben Werte, andere nicht.
    Aus dem Tokenizer (wohl auch Lexer genannt) kommt dann eine Liste von Token/Wert Paaren.
    Der Tokenizer prüft nicht die Syntax, löst aber Sprachhilfskonstrukte wie Kommentare, Whitespace, Multilines, Escapezeichen auf.

    Anschließend folgt der Parser und versucht aus den Tokens schlau zu werden. Er prüft die Syntax und fasst die Tokens zu Sprachelementen zusammen.

    Zuletzt kommt noch der Compiler, welcher diese Elemente in den Zielcode umwandelt, in meinem Fall SQL.

    So, da ich noch weit vom Code entfernt bin, können wir auf der theoretischen Ebene bleiben. Später wären kleine Codeschnippsel natürlich hilfreich, bzw. die Diskussion meines Codes. Bitte keine fertigen Libraries zitieren. Die sind zwar sicher nützlich, aber ich will es erstmal begreifen und das geht am besten wenn man es selber macht. Mit eurer Hilfe natürlich... hoffentlich

    Ich danke schonmal im Voraus,

    Oli

  • #2
    Habe gestern die PHP-Funktion "token_get_all()" für mich entdeckt. Gibt man dieser einen beliebigen Text, kommt nur ein Kommentartoken heraus. Umschließt man diesen beliebigen Text aber mit PHP open/close Tags, also "<?" bzw. "<?php" und "?>" dann erzeugt der tokenizer aus jedem beliebigen Text tokens! Das lässt sich doch gut verwenden, oder?

    Kommentar


    • #3
      MOD: Verschoben von PHP-Einsteiger
      The string "()()" is not palindrom but the String "())(" is.

      Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
      PHP.de Wissenssammlung | Kein Support per PN

      Kommentar


      • #4
        Zitat von hausl Beitrag anzeigen
        MOD: Verschoben von PHP-Einsteiger
        Wirklich "Job und Skriptbörse"?? "Softwaredesign" hätte ich ja noch zugestimmt... aber ich suche weder einen Job, noch bin ich bereit oder in der Lage jemand für die gesuchte Information zu bezahlen.

        Kommentar


        • #5
          Dann gib mal ein Beispiel in der Form
          - Ausgangsstring
          - Zielstring (SQL oder was auch immer)
          - bereits von dir geschriebener Code
          - Schwierigkeiten wo bei, Fehlermeldungen, folgendes nicht verstanden?

          Ansonsten hört sich das in der Tat nach einer Auftragsarbeit an.

          Kommentar


          • #6
            Zitat von phreund Beitrag anzeigen
            aber ich suche weder einen Job, noch bin ich bereit oder in der Lage jemand für die gesuchte Information zu bezahlen.
            Das ist beides damit auch nicht gemeint. Von bezahlen steht nirgends was und nicht du suchst einen Job, sondern du suchst Hilfe für "dein Parser-Projekt".

            Und wie protestix erwähnte es gab bspw. noch kein konkretes Beispiel dazu.. Wenn das konkreter wird hab ich auch kein Problem damit das zu Softwaredesing zu verschieben. Momentan suchst du aber nur Hilfe für dein Projekt.

            Zitat von protestix Beitrag anzeigen
            Ansonsten hört sich das in der Tat nach einer Auftragsarbeit an.
            The string "()()" is not palindrom but the String "())(" is.

            Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
            PHP.de Wissenssammlung | Kein Support per PN

            Kommentar


            • #7
              So schaut meine Syntax aus:
              Code:
              COL ::= FIELDNAME ',' TYPE ',' LABEL ',' [ OPTION... ] ;
              Hier ein paar Beispiele:
              Code:
              servername, text, "Host-ID", aliasing="CONCAT('V',UPPER(substr(build,1,1)),UPPER(substr(vos,1,1)),LPAD(id,4,'0'))" length=10 visible
              build, enum "vmware=VMWare|xen=Xen", "Virtualisierung", required length=10 visible
              vos, enum "esxi=ESXi|esxi4=ESXi 4.x|esxi5=ESXi 5.x|esxi50=ESXi 5.0|esxi51=ESXi 5.1|p=VMWare-Player|x=Xen", "VM-OS", required length=10 visible
              bemerkung, text, "Bemerkung", length=60 visible
              provisioned, datetime, "Vergeben am/um", default="%{date.Y-m-d H:i:s}" required visible
              Möchte ich die entsprechende SQL-Abfrage für die Datenbank erzeugen und dann das Ergebnis in Form einer Tabelle darstellen. Evtl. ändere ich die Syntax auch noch, da bin ich mir noch nicht ganz in klaren. Code habe ich noch keinen geschrieben, wozu auch wenn ich noch an den Konzepten arbeite.

              Ich wollte jetzt erstmal verstehen wie man soetwas interpretiert. Mit dem o.g. Tokenizer erhalte ich daraus dann folgendes Array (nur die erste Zeile, sonst wirds zuviel, auch habe ich die Token-IDs schon mit token_name() in Konstantenbezeichner umgewandelt um es lesbarer zu machen):
              Code:
              Array
              (
                  [0] => Array
                      (
                          [0] => T_STRING
                          [1] => servername
                          [2] => 1
                      )
              
                  [1] => ,
                  [2] => Array
                      (
                          [0] => T_WHITESPACE
                          [1] =>
                          [2] => 1
                      )
              
                  [3] => Array
                      (
                          [0] => T_STRING
                          [1] => text
                          [2] => 1
                      )
              
                  [4] => ,
                  [5] => Array
                      (
                          [0] => T_WHITESPACE
                          [1] =>
                          [2] => 1
                      )
              
                  [6] => Array
                      (
                          [0] => T_CONSTANT_ENCAPSED_STRING
                          [1] => "Host-ID"
                          [2] => 1
                      )
              
                  [7] => ,
                  [8] => Array
                      (
                          [0] => T_WHITESPACE
                          [1] =>
                          [2] => 1
                      )
              
                  [9] => Array
                      (
                          [0] => T_STRING
                          [1] => aliasing
                          [2] => 1
                      )
              
                  [10] => =
                  [11] => Array
                      (
                          [0] => T_CONSTANT_ENCAPSED_STRING
                          [1] => "CONCAT('V',UPPER(substr(build,1,1)),UPPER(substr(vos,1,1)),LPAD(id,4,'0'))"
                          [2] => 1
                      )
              
                  [12] => Array
                      (
                          [0] => T_WHITESPACE
                          [1] =>
                          [2] => 1
                      )
              
                  [13] => Array
                      (
                          [0] => T_STRING
                          [1] => length
                          [2] => 1
                      )
              
                  [14] => =
                  [15] => Array
                      (
                          [0] => T_LNUMBER
                          [1] => 10
                          [2] => 1
                      )
              
                  [16] => Array
                      (
                          [0] => T_WHITESPACE
                          [1] =>
                          [2] => 1
                      )
              
                  [17] => Array
                      (
                          [0] => T_STRING
                          [1] => visible
                          [2] => 1
                      )
              
                  [18] => Array
                      (
                          [0] => T_WHITESPACE
                          [1] =>
              
                          [2] => 1
                      )
              
              )
              Der nächste Schritte wäre ja jetzt aus diesen Einzelnteilen mittels eines Parsers eine für meinen SQL-Compiler verständliche Befehlsfolge zu erzeugen. Dabei soll natürlich auch auf Syntaxfehler geprüft werden.
              Also erwarten würde mein Compiler die Anweisung so:
              Das erste Feld im Ergebnissatz entsteht aus dem SQL-Feld "servername",
              ist vom Anzeigetyp "Text", welcher durch die Option "lenght=10" sowohl für eine Eingabemaske als auch für die Ergebnisanzeige auf max. 10 Zeichen Länge begrenzt ist
              das Ergebnis ist nicht der Feldinhalt der Datenbank, sondern ein über das im alias="..." stehender SQL-Code erzeugter Wert
              der Zusatz "visible" zeigt dem Renderer an, das die Spalte angezeigt wird, also nicht ausgeblendet ist.

              Es soll also eine SQL-Anweisung in dieser Art entstehen:

              Code:
              SELECT LEFT(CONCAT('V',UPPER(substr(build,1,1)),UPPER(substr(vos,1,1)),LPAD(id,4,'0')), 10) AS 'servername' FROM vservers
              Das Ergebnis soll dann so werden:
              | Host-ID | .... |
              | VVE0001 | .... |

              Der Parser könnte annehmen das im Array-Index 0 ein T_STRING sein muss, welcher er dem Feldwert (in diesem Fall dem Aliasnamen des berechneten Wertes) zuordnet.
              Anschließend muss ein Komma zu sehen sein, weil dieses die einzelnen Felder abtrennt. WHITESPACE sollte in jedem Fall egal sein, oder?
              Nun kommt das wichtigste Element, nämlich der Typ. Diesen muss ich in einer Lookup-Tabelle prüfen ob ich ihn kenne oder nicht. Die weitere Behandlung der nachfolgenden Optionen hängt von diesem Typ ab.
              Nun muss wieder ein Komma und dann ein T_CONSTANT_ENCAPSED_STRING folgen, welches den anzuzeigenden Feldnamen repräsentiert.
              Hier könnte die Syntax zuende sein, wenn jedoch ein weiteres Komma folgt, dann kommen die Optionen bis zum Zeilenende. Die aktuelle Zeile wird in [2] eines jeden Token-Eintrages angegeben.

              Ist das so, sequentiell der richtige Weg? Oder muss ich vorher eine Art Blockprüfung machen, wie z.B. die Anzahl der vorkommenden "," (Komma) zählen ob das passt?

              Kommentar


              • #8
                Keine Ahnung warum eine so schön einfach gehaltene Syntax wie SQL sie ist , derart verkomplizieren muss.
                Ich wünsche dir aber dennoch viel Erfolg bei deinem Projekt.
                .

                Kommentar


                • #9
                  Sorry, aber hier geht es doch primär garnicht um SQL. Du wolltest ein Beispiel und ich habs gegeben. Es geht doch grundsätzlich um die Frage wie man eine "bliebige" Syntax parsen und in etwas anderes compilieren kann.

                  Kommentar


                  • #10
                    aber hier geht es doch primär garnicht um SQL Du wolltest ein Beispiel und ich habs gegeben. Es geht doch grundsätzlich um die Frage wie man eine "bliebige" Syntax parsen und in etwas anderes compilieren kann.
                    ... habe nun die Anforderung einen Parser für eine eigene kleine Syntax zu erzeugen. Dabei soll eine Definitionssprache für die Verarbeitung von SQL Datensätzen erkannt, geprüft und in SQL Befehle umgewandelt werden.
                    Wie jetzt?
                    The string "()()" is not palindrom but the String "())(" is.

                    Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                    PHP.de Wissenssammlung | Kein Support per PN

                    Kommentar


                    • #11
                      Zitat von phreund Beitrag anzeigen
                      Sorry, aber hier geht es doch primär garnicht um SQL.
                      Hmm...?'
                      Zitat von phreund Beitrag anzeigen
                      Du wolltest ein Beispiel und ich habs gegeben.
                      Was ja nichts anderes heisst, als dass man jetzt wenigstens weiss wohin der Vogel fliegt und das ist auch für andere erst einmal wichtig um eine Einschätzung der Lage vornehmen zu können.

                      Compilieren ist wieder etwas anderes und hat mit einem Parser gar nichts gemein.

                      Kommentar

                      Lädt...
                      X