Parser-Bibliothek für Funktionsparsing


  • Administrator

    drakon schrieb:

    Bin da über google rein. 😉 - Ist schneller, als über die Hauptseite..

    Mach dir ein Lesezeichen zu http://www.boost.org/libs/libraries.htm und gibt ihm den Kürzel boost 🙂
    Der Link bringt dich immer zu den aktuellen Libs und zudem hat man dort noch eine etwas bessere Übersicht, wie ich finde.

    (ok ok, das ist jetzt sehr Off-Topic, sry)

    Grüssli



  • Wenn du dich nicht wirklich mit dem Parsen auseinandersetzen willst und es "einfach nur funktionieren" (TM) soll, nimm ginac (google danach). Ich weiß aber nicht, ob der VC++ da mitspielt, das letzte mal als ich nachgeschaut habe gabs ginac nur für den g++.



  • Dravere schrieb:

    Mach dir ein Lesezeichen zu http://www.boost.org/libs/libraries.htm und gibt ihm den Kürzel boost 🙂
    Der Link bringt dich immer zu den aktuellen Libs und zudem hat man dort noch eine etwas bessere Übersicht, wie ich finde.

    [OT]
    Achja.. Links..
    Ich mache mir täglich wahrscheinlich um die 5 neue Links.. Wenn einer eine Sonderstellung haben will, dann muss er sich die verdienen. 😉 - boost ist nahe dran einen zu bekommen.. 😉
    [/OT]



  • Ich danke schonmal für eure hilfe...
    Ich habe mich noch nicht ganz entschidene, ob ich jetzt einen der von euch empfohlenen Ansätze wähle, oder meinen Parser doch noch mit GNU Bison generiere...

    Vorerst habe ich och ein anderes Problem, welches dringender ist... (siehe hier)

    LG Ben-ny



  • ich kann nur muparser.sf.net empfehlen. 🙂



  • Ich habe jetzt doch noch einmal versucht den Parser mit GNU Bison zu generieren...und zwar wie folgt:

    Die Klasse function habe ich erweitert:

    /////function.h
    class function {
    public:
    		virtual double value (double x);
    };
    
    class term : public function {
    public:
    		// this term class uses generally doubles for concrete values
            // and can only manage one variable called x 
            virtual void dump();
            virtual ~term();
            virtual void dump(int depth) = 0;
    		void indent(int depth);
    };
    
    class binary_expression : public term {
    public:
           binary_expression(term *left, term *right);
           ~binary_expression();
           virtual void dump(int depth);
    protected:
           term *_left, *_right;
           char * _name;
    };
    
    class concrete_value : public term {
    public:
           concrete_value(double value);
           virtual ~concrete_value();
           virtual double value(double x);
           virtual void dump(int depth);
    private:
           double _value;
    };
    
    class variable : public term {
    public:
           variable();
           virtual ~variable();
           virtual double value(double x);
           virtual void dump(int depth);
    };
    
    class negation : public term {
    public:    
          negation(term *value);
          virtual ~negation();
          virtual double value(double x);
          virtual void dump(int depth);
    private:
          term *_negated;
    };
    
    class addition : public binary_expression {
    public:
           addition(term *left, term *right);
           virtual ~addition();
           virtual double value(double x);
    };
    
    class subtraction : public binary_expression {
    public:
           subtraction(term *left, term *right);
           virtual ~subtraction();
           virtual double value(double x);
    };
    
    class multiplication : public binary_expression {
    public:
           multiplication(term *left, term *right);
           virtual ~multiplication();
           virtual double value(double x);
    };
    
    class division : public binary_expression {
    public:
           division(term *left, term *right);
           virtual ~division();
           virtual double value(double x);
    };
    
    class power : public binary_expression {
    public:
           power(term *left, term *right);
           virtual ~power();
           virtual double value(double x);
    };
    

    und darin einige Sachen definiert (sollte man vlt. nicht alles durchlesen...steht großteils das gleiche drin!)

    //////function.cpp
    
    term::~term() {
    }
    
    void term::dump() {
          dump(0);             
    }
    
    void term::indent(int depth) {
         while (depth --)
               putchar('\t');
    }
    
    negation::negation(term *value) {
       _negated =  value;
    }
    
    negation::~negation() {
       if (_negated != NULL) {
           delete _negated;
       }          
    }
    double negation::value(double x) {
       return (-_negated->value(x));
    }
    
    void negation::dump(int depth) {
         indent(depth);
         puts("#NEGATE");
         _negated->dump(depth + 1);
    }
    
    concrete_value::concrete_value(double value) {
             _value = value;                                      
    }
    
    concrete_value::~concrete_value(){
    }
    
    double concrete_value::value(double x) {
           return _value;
    }
    
    void concrete_value::dump(int depth) {
         indent(depth);
         printf("%f\n", _value);    
    }
    
    variable::variable() {
    }
    
    variable::~variable() {
    }
    
    double variable::value(double x) {
           return x;       
    }
    
    void variable::dump(int depth) {
         indent(depth);
         puts("x");    
    }
    
    binary_expression::binary_expression(term *left, term *right) {
          _left = left;
          _right = right;   
    }
    
    binary_expression::~binary_expression() {
          if (_left != NULL)
               delete _left;
    
          if (_right != NULL)
               delete _right;                                   
    }
    
    void binary_expression::dump(int depth) {
         indent(depth);
         puts(_name);
    
         _left->dump(depth + 1);
    
         indent(depth);
         puts("#AND");
    
         _right->dump(depth + 1);
    }
    
    addition::addition(term *left, term *right) : binary_expression(left, right) {        
         _name = "#ADD";
    }
    
    addition::~addition() {         
    }
    
    double addition::value(double x) {
           return _left->value(x) + _right->value(x);     
    }
    
    subtraction::subtraction(term *left, term *right) : binary_expression(left, right)  {  
          _name = "#SUB";                  
    }
    
    subtraction::~subtraction() {                      
    }
    
    double subtraction::value(double x) {
           return _left->value(x) - _right->value(x);     
    }
    
    multiplication::multiplication(term *left, term *right): binary_expression(left, right) {
           _name = "#MUL";
    }
    
    multiplication::~multiplication() {
    }
    
    double multiplication::value(double x) {
           return _left->value(x) * _right->value(x);
    }
    
    division::division(term *left, term *right): binary_expression(left, right) {
              _name = "#DIV";
    }
    
    division::~division() {
    }
    
    double division::value(double x) {
           return _left->value(x) / _right->value(x);     
    }
    
    power::power(term *left, term *right): binary_expression(left, right) {
               _name = "#POW";
    }
    
    power::~power() {
    }
    
    double power::value(double x) {
           return pow(_left->value(x),_right->value(x));
    }
    

    Meine main-Funktion habe ich in die von Bison verarbeitete parser.y gepackt, um nicht zu viel Zeug übergeben zu müssen!

    Dabei bekomme ich eine ganze Liste von Fehlern, durch VC++ 2008, die ihr auch unten sehen könnt!

    Was ich daran wichtig finde:

    Warum erkennt der Compiler meine Klassen-Vererbung nicht und sieht function nicht mehr als Klasse an?
    (Dazu muss man vlt wissen: einen ähnlichen Parser habe ich vor einiger Zeit in Dev-Cpp gebaut und da lief alles einwandfrei...warum jetzt nicht=)
    Ist der Aufbau von parser.tab.c (der von Bison generierten Parser-Datei) falsch oder warum hat VC++ damit Probleme (siehe unterste Fehlermeldungen)?

    Achso...zum generieren verwende ich den Befehl bison -d parser.y in der Kommandozeile, was bisher immer richtig funktioniert hat!

    ------ Neues Erstellen gestartet: Projekt: plotter, Konfiguration: Debug Win32 ------
    Die Zwischen- und Ausgabedateien für das Projekt "plotter" mit der Konfiguration "Debug|Win32" werden gelöscht.
    Kompilieren...
    draw.cpp
    function.cpp
    plot.cpp
    text.cpp
    Code wird generiert...
    Kompilieren...
    parser.tab.c
    e:\daten\benny\schule\plotter\plotter\function.h(8) : error C2061: Syntaxfehler: Bezeichner 'function'
    e:\daten\benny\schule\plotter\plotter\function.h(8) : error C2059: Syntaxfehler: ';'
    e:\daten\benny\schule\plotter\plotter\function.h(8) : error C2449: '{' auf Dateiebene gefunden - fehlt der Funktionsheader?
    e:\daten\benny\schule\plotter\plotter\function.h(11) : error C2059: Syntaxfehler: '}'
    e:\daten\benny\schule\plotter\plotter\function.h(23) : error C2061: Syntaxfehler: Bezeichner 'binary_expression'
    e:\daten\benny\schule\plotter\plotter\function.h(23) : error C2059: Syntaxfehler: ';'
    e:\daten\benny\schule\plotter\plotter\function.h(23) : error C2059: Syntaxfehler: ':'
    e:\daten\benny\schule\plotter\plotter\function.h(33) : error C2061: Syntaxfehler: Bezeichner 'concrete_value'
    e:\daten\benny\schule\plotter\plotter\function.h(33) : error C2059: Syntaxfehler: ';'
    e:\daten\benny\schule\plotter\plotter\function.h(33) : error C2059: Syntaxfehler: ':'
    e:\daten\benny\schule\plotter\plotter\function.h(43) : error C2061: Syntaxfehler: Bezeichner 'variable'
    e:\daten\benny\schule\plotter\plotter\function.h(43) : error C2059: Syntaxfehler: ';'
    e:\daten\benny\schule\plotter\plotter\function.h(43) : error C2059: Syntaxfehler: ':'
    e:\daten\benny\schule\plotter\plotter\function.h(51) : error C2061: Syntaxfehler: Bezeichner 'negation'
    e:\daten\benny\schule\plotter\plotter\function.h(51) : error C2059: Syntaxfehler: ';'
    e:\daten\benny\schule\plotter\plotter\function.h(51) : error C2059: Syntaxfehler: ':'
    e:\daten\benny\schule\plotter\plotter\function.h(61) : error C2061: Syntaxfehler: Bezeichner 'addition'
    e:\daten\benny\schule\plotter\plotter\function.h(61) : error C2059: Syntaxfehler: ';'
    e:\daten\benny\schule\plotter\plotter\function.h(61) : error C2059: Syntaxfehler: ':'
    e:\daten\benny\schule\plotter\plotter\function.h(68) : error C2061: Syntaxfehler: Bezeichner 'subtraction'
    e:\daten\benny\schule\plotter\plotter\function.h(68) : error C2059: Syntaxfehler: ';'
    e:\daten\benny\schule\plotter\plotter\function.h(68) : error C2059: Syntaxfehler: ':'
    e:\daten\benny\schule\plotter\plotter\function.h(75) : error C2061: Syntaxfehler: Bezeichner 'multiplication'
    e:\daten\benny\schule\plotter\plotter\function.h(75) : error C2059: Syntaxfehler: ';'
    e:\daten\benny\schule\plotter\plotter\function.h(75) : error C2059: Syntaxfehler: ':'
    e:\daten\benny\schule\plotter\plotter\function.h(82) : error C2061: Syntaxfehler: Bezeichner 'division'
    e:\daten\benny\schule\plotter\plotter\function.h(82) : error C2059: Syntaxfehler: ';'
    e:\daten\benny\schule\plotter\plotter\function.h(82) : error C2059: Syntaxfehler: ':'
    e:\daten\benny\schule\plotter\plotter\function.h(89) : error C2061: Syntaxfehler: Bezeichner 'power'
    e:\daten\benny\schule\plotter\plotter\function.h(89) : error C2059: Syntaxfehler: ';'
    e:\daten\benny\schule\plotter\plotter\function.h(89) : error C2059: Syntaxfehler: ':'
    e:\daten\benny\schule\plotter\plotter\plot.h(9) : error C2143: Syntaxfehler: Es fehlt ')' vor '*'
    e:\daten\benny\schule\plotter\plotter\plot.h(9) : error C2081: 'function': Name in der formalen Parameterliste ist ungültig
    e:\daten\benny\schule\plotter\plotter\plot.h(9) : error C2143: Syntaxfehler: Es fehlt '{' vor '*'
    e:\daten\benny\schule\plotter\plotter\plot.h(9) : error C2059: Syntaxfehler: 'Typ'
    e:\daten\benny\schule\plotter\plotter\plot.h(9) : error C2059: Syntaxfehler: ')'
    parser.y(19) : error C2143: Syntaxfehler: Es fehlt '{' vor '*'
    parser.tab.c(223) : error C2061: Syntaxfehler: Bezeichner 'term'
    parser.tab.c(224) : error C2059: Syntaxfehler: '}'
    parser.tab.c(810) : error C2061: Syntaxfehler: Bezeichner 'term'
    parser.tab.c(812) : error C2449: '{' auf Dateiebene gefunden - fehlt der Funktionsheader?
    parser.tab.c(826) : error C2059: Syntaxfehler: '}'
    parser.tab.c(851) : error C2143: Syntaxfehler: Es fehlt '{' vor '*'
    parser.tab.c(879) : error C2449: '{' auf Dateiebene gefunden - fehlt der Funktionsheader?
    parser.tab.c(1462) : error C2059: Syntaxfehler: '}'
    parser.y(75) : fatal error C1506: Weiterverarbeitung nach der Auflösung von Blöcken nicht möglich
    Das Buildprotokoll wurde unter "file://e:\Daten\Benny\Schule\plotter\plotter\Debug\BuildLog.htm" gespeichert.
    plotter - 46 Fehler, 0 Warnung(en)
    ========== Alles neu erstellen: 0 erfolgreich, Fehler bei 1, 0 übersprungen ==========
    

    Ich hoffe das ist jetzt nich zu viel Information und Code geworden!

    LG Ben-ny



  • Wenn die Datei die Endung .c hat, wird der MSVC++ sie als C übersetzen. Dann wirst Du mit Klassen wenig Glück haben.

    C-Code einfach als C++ zu übersetzen klappt allerdings auch nur selten. Du wirst die Funktionen der C-Datei in C++ extern "C" deklarieren und aufrufen müssen.



  • Könnte es daran liegen, dass Du die Dateien nicht mit der Erweiterung .cpp gepeichert hat und Visual C++ diese nicht im C++ Modus kompiliert sondern als C source code?



  • Das war schon mal hilfreich!
    (War von Dev-Cpp gewohnt das einfach so zu lassen und wusste nicht, dass das bei VC++ dann nicht mehr funktioniert.)
    Da Bison C++-Code erzeugt sollte das aber kein Grund für weitere Probleme sein (habe jetzt einfach parser.tab.c -> parser.tab.cpp umbenannt!)

    Trotzdem bekomme ich noch Fehler:

    ------ Neues Erstellen gestartet: Projekt: plotter, Konfiguration: Debug Win32 ------
    Die Zwischen- und Ausgabedateien für das Projekt "plotter" mit der Konfiguration "Debug|Win32" werden gelöscht.
    Kompilieren...
    draw.cpp
    function.cpp
    parser.tab.cpp
    e:\daten\benny\schule\plotter\plotter\parser.tab.c(198) : warning C4273: 'malloc': Inkonsistente DLL-Bindung.
            d:\programme\microsoft visual studio 9.0\vc\include\stdlib.h(601): Siehe vorherige Definition von 'malloc'
    e:\daten\benny\schule\plotter\plotter\parser.tab.c(205) : warning C4273: 'free': Inkonsistente DLL-Bindung.
            d:\programme\microsoft visual studio 9.0\vc\include\stdlib.h(600): Siehe vorherige Definition von 'free'
    e:\daten\benny\schule\plotter\plotter\parser.tab.c(825) : warning C4065: switch-Anweisung enthält 'default', aber keine case-Marken
    e:\daten\benny\schule\plotter\plotter\parser.y(91) : warning C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
            d:\programme\microsoft visual studio 9.0\vc\include\stdio.h(306): Siehe Deklaration von 'scanf'
    e:\daten\benny\schule\plotter\plotter\parser.y(132) : warning C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
            d:\programme\microsoft visual studio 9.0\vc\include\stdio.h(306): Siehe Deklaration von 'scanf'
    plot.cpp
    text.cpp
    Code wird generiert...
    Manifest in Ressourcen wird kompiliert...
    Microsoft (R) Windows (R) Resource Compiler Version 6.0.5724.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    Verknüpfen...
    MSVCRTD.lib(cinitexe.obj) : warning LNK4098: Standardbibliothek "msvcrt.lib" steht in Konflikt mit anderen Bibliotheken; /NODEFAULTLIB:Bibliothek verwenden.
    function.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""public: virtual double __thiscall function::value(double)" (?value@function@@UAENN@Z)".
    E:\Daten\Benny\Schule\plotter\Debug\plotter.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.
    Das Buildprotokoll wurde unter "file://e:\Daten\Benny\Schule\plotter\plotter\Debug\BuildLog.htm" gespeichert.
    plotter - 2 Fehler, 6 Warnung(en)
    ========== Alles neu erstellen: 0 erfolgreich, Fehler bei 1, 0 übersprungen ==========
    

    Hat das was mit den Linkern zu tun???
    "E:\Daten\Benny\Schule\plotter\Debug\plotter.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise."



  • In der Fehlermeldung steht ja, dass die Funktion function::value(double) nicht definiert ist.

    Allerdings linkst du die falsche CRT (siehe Linkerwarnung) - stelle sicher, dass du in jeder Konfiguration die richtige Bibliothek der C-Runtime einbindest.



  • Aus irgendeinem Grund fällt mir jetzt eine Frage ein, die ich bisher immer vergessen habe... Kann man MSVC++ eigentlich irgendwie dazu überreden, bei dateien im eigenen Projektverzeichnis in Fehlermeldungen/Warnungen (Sowas gibt es bei mir natürlich nicht, das bezieht sich nur auf Code von anderen!!! *hüstel*) irrelevante Teile des Pfads auszublenden? Je neuer die Windows-Version, desto länger werden die irgendwie, wenn man sich an die Standardpfade hält 😉


Anmelden zum Antworten