String auf bestimmte Syntax testen

  • Hallo liebe Forenleser,

    Ich habe folgendes Problem.
    Es wird ein String eingelesen der aus folgenden Elementen besteht

    [ 0..9 ] [ ( ] [ ) ] [ +,-,/;* ] [ , ]

    Also alle Elemente die ich für einen Taschenrechner brauche ;)

    Sooo
    Nun bekomme Ich meine Eingabe in der Form

    0..9,0.9*(0..9+0..9)

    Wie stelle Ich das nun also am besten an das Ich kontrolliere ob die Syntax des eingebenden Strings stimmt ?

    Ich dachte mir vieleicht Element für Element vorgehen bestimmen welches Zeichen es ist und guck was das nachfolgende ist und gucken ob das erlaubt ist. Das ganze dann rekursiv aufrufen.

    Aber Ich denke das das dann ein riesiges Programm werden würde nur für die Syntaxkontrolle.

    Hoffe auf eure Ideen und Anregungen

  • Ein simples Beispiel für die Anwendung des Compilerbaus.

    Üblicherweise geht man mehrstufig vor:
    - Ein Tokenizer zerlegt den String in Tokens, also Zahlen, Operatoren, Klammern.
    - Ein Parser überprüft, ob die Syntax in Ordnung ist und kann auch gleich einen Baum erstellen. Bei so einfachen Parsern verwendet man üblicherweise rekursiven Abstieg (LL(n)), bei komplexeren Dingen eher etwas wie LR(n).
    - Diesen Baum wertest du dann aus (z.b. mit einem Visitor oder einer calc()-Methode in jedem Objekt des Baums).

    Für Tokenizer und Parser kannst du auch Tools verwenden, die dir die meiste Arbeit abnehmen: lex und yacc.

    Im Übrigen ist das ein Standardbeispiel - es sollte genug Literatur dazu im Google geben, wie man so was baut.

    EDIT: Wenn es dir aber nur um die Überprüfung und nicht so sehr um die Auswertung des Strings geht, dann reicht auch eine Regular Expression Library aus.

    Dipper dipper dii dipper dii dipper dii duuu

  • Wurde eh schon fast alles gesagt was wichtig ist, aber hier noch 2 Anmerkungen:

    • Auf jeden Fall http://www.antlr.org/ evaluieren, bevor Du dich auf lex/yacc stuerzt.
    • Was in deinem Fall vielleicht Sinn machen koennte: Anstatt einen neuen Interpreter fuer eine neue Sprache zu schreiben, kannst Du natuerlich auch einen bestehende Interpreter von einer anderen Sprache verwenden. Mathematische Ausdruecke auswerten koennen ja sehr viele Sprachen. Du koenntest z.b. den Ausdruck von bc oder python oder Rhino oder SQLite auswerten lassen. In diesem Fall wuerde ich aber den Ausdruck zumindest vorher mit einer Regular Expression pruefen, vor allem, wenn die Ausdruecke von einem Benutzer eingegeben werden koennen.
  • Antlr evaluieren - auf jeden Fall.

    Aber mir ist er nicht sehr sympathisch. Da mag ich flex/bison schon viel lieber. Mir geht auf die Nerven, dass der von ANTLR erzeugte Parser bei der Auswertung ständig Exceptions wirft - sehr unpraktisch, wenn man im Debugger einen Breakpoint auf Exception throw gesetzt hat.
    Und die Diagnostics versteh ich auch nicht wirklich. Die vom bison sind da schon eher verständlich, wenn man eine Ahnung vom shift/reduce-Mechanismus hat.

  • EDIT: Wenn es dir aber nur um die Überprüfung und nicht so sehr um die Auswertung des Strings geht, dann reicht auch eine Regular Expression Library aus.

    Nicht wirklich, wenn du auch die Klammerebenen kontrollieren willst. Das ist nämlich nicht regulär, dazu brauchst du schon einen Kellerautomaten.

    [font=verdana,sans-serif]"An über-programmer is likely to be someone who stares quietly into space and then says 'Hmm. I think I've seen something like this before.'" -- John D. Cock[/font]

    opentu.net - freier, unzensierter Informationsaustausch via IRC-Channel!
    Hilfe und Support in Studienangelegenheiten, gemütliches Beisammensein, von und mit Leuten aus dem Informatik-Forum!

  • Sorry aber mit den Lösungen komme Ich nicht zurecht, wahrscheinlich zu dumm,

    Ich möchte am liebsten das alles in EBNF Notation schreiben und dann den string anhand dieser EBNF Notation kontrollieren.

    Nun weiß Ich aber nicht wie Ich das in C++ definiere.
    Mach ich das über Structs oder wie genau mache Ich das.

    Ich weiß das sind sicher Anfängerfragen aber Ich bin in OOP komplett alleine und muss das mit Freitag abgeben und habe keine Ahnung was Ich tun soll.
    Und leider muss man, da Klammer enthalten sein dürfen, stark aufpassen was man tut.

  • Naja, das geht zB mit boost::spirit. Aber das könnte evtl etwas über die OOP-LVA hinaus gehen.

    [font=verdana,sans-serif]"An über-programmer is likely to be someone who stares quietly into space and then says 'Hmm. I think I've seen something like this before.'" -- John D. Cock[/font]

    opentu.net - freier, unzensierter Informationsaustausch via IRC-Channel!
    Hilfe und Support in Studienangelegenheiten, gemütliches Beisammensein, von und mit Leuten aus dem Informatik-Forum!

  • Ich möchte am liebsten das alles in EBNF Notation schreiben und dann den string anhand dieser EBNF Notation kontrollieren.


    Du kannst deine EBNF-Grammatik praktisch 1:1 in einen rekursiven Abstieg ("recursive descent") abbilden.

    Kurz gesagt machst du für jedes Nichtterminal eine Methode dieses Namens in deiner Parser-Klasse, die das überprüft, was bei dem Nichtterminal nach ::= steht.

    Der Body sieht immer recht ähnlich aus. Du schaust dir das nächste Token an und wenn es der Erwartung entspricht, baust du deinen Syntaxbaum (auch AST genannt) weiter auf. Ansonsten gibst du einen Fehler aus o.ä.

    Probleme (im Sinne von Komplexität) gibts beim rekursiven Abstieg immer erst dann, wenn du mehr als ein Zeichen Lookahead brauchst (LL(n) für n >= 2) oder wenn du sehr umfangreiche Grammatiken hast, die man besser mit (automatisch erzeugten, da händisch sehr umständlich zu erstellende FIRST- und FOLLOW-Mengen anstehen) LR(1) erschlägt. In deinem Fall seh ich das Problem aber nicht, da du mit einem Token Lookhead auskommen solltest.

    Dipper dipper dii dipper dii dipper dii duuu

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!