Rekursiven Parser beschleunigen



  • Floyd schrieb:

    Lässt sich das beschleunigen ? Z.B. indem der Parser irgendwie anstatt in eine Zahl zu parsen, eine Funktion erstellt (???), die sowas macht ? Dann müsste man einmal parsen und alles weitere würde beschleunigt von statten gehen.

    Du kannst anhand der Formel einfach C- oder C++-Code erstellen, einen Compiler das Ganze als minimale DLL kompilieren lassen und sie laden. Hört sich umständlich an, ist aber imho recht flott realisiert.



  • lass dern parser keinen double zurückgeben, sondern eine

    class ParseDing{
       virtual double eval()=0;
    };
    class Summe:public ParseDing{
       ParseDing* links;
       ParseDing* rechts;
       double eval(){
          return links->eval()+rechts->eval();
       }
    };
    class Produkt...
    

    damit kannste einen total übersichtlichen parsebaum bauen. der ist dann auch recht fix im interpretieren.



  • Du kannst die Gleichung einmalig als Baum darstellen und diesen dann auswerten. Somit wird nur einmal geparst.



  • @ Volkard: Ja, an eine solche Parse-Klasse dachte ich auch schon. Was da rauskommt ist doch aber praktisch eine Art Kette bzw. Baum ,oder ?

    Daher meine frage:..
    @Knivil: Wie genau meinst du das ? Im Sinne von Binärbäumen mit Zeigern auf das jeweils nächste Element ? Wo ist der Unterschied (evtl. Vorteil) zu Volkards Lösung ?



  • Volkards Lösung ist bereits so ein Parse-Baum. Stichwort Abstract Syntax Tree.



  • Schon mal dran gedacht, dass Posts mit einem Abstand von ... 1 Minute vom anderen nicht gelesen wurde? Warum wundert es dich, dass gleiche Ideen dargelegt werden?



  • @knivil: Sorry, so war das nicht gemeint. Ich dachte, es wären vielleicht noch nennenswerte Unterschiede vorhanden gewesen.

    Mhh... Ok, wie wird so eine Parserklasse praktisch umgesetzt ?
    Ich nehme an, ich baue eine Klasse

    class ParseMathString {
    
    public : 
        ParseMathSring( const char* MathString );
        double Evaluate();
    
    private :
         char* MathString;
    };
    

    die dann in der evaluate Funktion den ParseTree baut. Wie handhabe ich den, sprich wie sorge ich z.B. dafür, dass ich ihn erneut abrufen kann. Die Lebensdauer der dort erzeugten ParseDings-Klassen ( siehe Beitrag von Volkard ) wäre ja nur entlang der Evaluate Funktion.
    Macht man das, z.B. dann so :

    typedef vector<ParseDing> Expression;
    
    class ParseMathString {
    
    public : 
        ParseMathString( const char* MathString );
        Expression evaluate();
    
    private :
         char* MathString ;
         vector<Expression> evaluatedStrings ; 
    };
    

    dann müsste man irgendwie dafür sorgen, dass die ganzen Zeiger usw. noch gelten, oder ??



  • Floyd schrieb:

    ich benutze zur Zeit die VCL vom Builder...

    Wenn du das nicht unbedingt selbst schreiben willst, könntest du JclExprEval aus der JEDI Code Library benutzen. Die enthaltenen Klassen können einen Parse-Tree generieren.



  • Schreib die Typen fuer deine Knoten des Gleichungsbaums: Sowas musste ich schon mal machen. Ist die selbe Idee, die oben schon mal angesprochen wurde: exp.h exp.cpp. Mit Hilfe von flex und bison wurde der Scanner bzw. Parser aus scanner.l und parser.y automatisch generiert. Dazu empfehle ich aber die entsprechenden Tutorials zu flex und bison. Aufgerufen wird das ganze von odeparser.h. Optimal ist es nicht, heute wuerde ich es wohl etwas anders machen, aber nicht grossartig anders.



  • Hey cool, Tools die Parsercode generieren, also MetaParser...

    Flex und Bison - werde ich ausprobieren.

    EDIT:
    Eine Frage dazu habe ich noch: Lässt sich der Code händisch einigermaßen erweitern ? Ich hätte zum Beispiel gerne die Möglichkeit Variablen (string name, double value ) in einer Datei zu deklarieren, sodass er diese erkennt und die entsprechenden Werte einsetzt. Das sollte aber nicht als eine Art Makro fungieren, sondern direkt im ParseTree mit vorhanden sein .
    Ich sehe den Code ja, daher die Frage: ist das wirklich eine Arbeitsaufwandsreduzierung ?



  • Ja das geht, aber wenn man es richtig machen moechte, dann kann ich dir noch weitere Lektuere empfehlen: z.B. Struktur und Interpretation von Computerprogramme. Bison z.B. ist die GNU-Variante von YACC, wes uebersetzt bedeuted: yet another compiler compiler, was schon alles sagt. Andere sind z.B. boost::spirit oder boost::spirit2, habe die abder noch nie benutzt/gebraucht.


Anmelden zum Antworten