Mathe Parser



  • Hallo

    Ich wollte in meiner Freizeit einen kleinen Matheparser schreiben.
    Das Ding scheint weitgehend zu funktionieren. Schlägt aber Fehl, wenn die Reihenfolge eine Rolle Spielt.
    So funktioniert z.B. der Ausdruck 1-2-3 oder 2-2-2 nicht. 😞

    Der Fehler scheint wohl darin zu liegen, dass der Ausdruck von hinten nach vorne ausgewertet wird.

    #include <iostream>
    #include <sstream>
    #include <exception>
    #include <cmath>
    
    class wrong_argument : public std::exception
    {
    public:
    	const char* what() const throw();
    };
    
    const char* wrong_argument::what() const throw()
    {
    	return "Falsches Argument!";
    }
    
    double term(std::istream&);
    double term1(std::istream&);
    double zahl(std::istream&);
    double function(std::istream&);
    
    double function(std::istream &s)
    {
    	char c;
    	s.get(c);
    	std::cout << "Error: " << c << '\n';
    
    	throw wrong_argument();
    }
    
    double zahl(std::istream &s)
    {
    	double d;
    	char c;
    	s.get(c);
    	switch(c)
    	{
    		case '0': case '1': case '2': case '3': case '4': case '5': 
    		case '6': case '7': case '8': case '9': 
    			s.putback(c);
    			s >> d;
    			return d;
    	}
    	throw wrong_argument();
    }
    
     double parse(std::istream &s)
    {
    	return term(s);
    }
    
    double term1(std::istream &s)
    {
    	double z = zahl(s);
    	char c;	
    	s.get(c);
    	switch(c)
    	{
    		case '*':
    			return (z * term1(s));
    		case '/':
    			return (z / term1(s));
    	}
    
    	s.putback(c);
    	return z;
    }
    
    double term(std::istream &s)
    {
    	double z = term1(s);
    	char c;	
    	s.get(c);
    	switch(c)
    	{
    		case '+' :
    			return (z + term(s));
    		case '-':
    			return (z - term(s));
    	}
    
    	s.putback(c);
    	return z;
    }
    
    int main(int argc, char *argv[])
    {
    	if(argc < 2) return -1;
    	std::stringstream s(argv[1]);
    	std::cout << parse(s) << '\n';
    return 0;
    }
    

    Hat irgendjemand einen Tipp oder eine Lösung.

    MfG



  • Hallo, schau mal hier:
    http://www.stroustrup.com/Programming/

    Guck mal bei Supporting Code, da findest du vielleicht was du suchst.

    Da solltest du das hier finden:

    First "mysterious" version calculator example for Chapter 6 page 202 "Try This".
    Be-bugged calculator example for Chapter 6 exercise in debugging.
    Be-bugged calculator example for Chapter 7 exercise in debugging.



  • a+b=c schrieb:

    return (z / term1(s));
    

    a+b=c schrieb:

    return (z - term(s));
    

    Deine Operatoren sind rechtsassoziativ. Du Subtrahierst / Dividierst hier immer durch den rechten Term. Richtig wäre, nacheinander zu subtrahieren/dividieren. Meiner Meinung nach geht das nur Iterativ, ich lasse mich aber gerne eines besseren belehren.

    P.S.: Ich empfehle dir, das Lexing und Parsing zu trennen, macht einiges einfacher.
    P.P.S.: Klammern um Returnvalues sind hässlich.



  • Mach es wie Knuth und wandle den Ausdruck erst in Postfix um und parse dann den.

    Oder schau dir einmal diese fertige Lösung von Werner Salomon an.



  • @c_P_P
    Danke für den Link. Hab nun, ähnlich wie in der Stroustrup-Lösung, while-Schleifen implementiert.
    Eigentlich eine ganz simple Lösung. 😃

    @PI

    P.S.: Ich empfehle dir, das Lexing und Parsing zu trennen, macht einiges einfacher.

    Bei dem einfachen Programm kann ich mir nur schwer eine Verbesserung durch die Trennung zwischen Lexer und Parser vorstellen.



  • Je komplizierte die Ausdrücke werden, desto eher lohnt es sich. 😉





  • Lustig, dass ich erst vor ein paar Tagen ein Parser Konzept gebastelt habe... (jedoch komplexer mit Variablen, Klammern, Operatorenreihenfolge und Funktionen)



  • jjj schrieb:

    http://www.c-plusplus.net/forum/268247

    Iiiih, der arbeitet ja mit std::string. Wie langsam.



  • 314159265358979 schrieb:

    jjj schrieb:

    http://www.c-plusplus.net/forum/268247

    Iiiih, der arbeitet ja mit std::string. Wie langsam.

    Es handelt sich um einen Artikel und da zählt Geschwindigkeit nicht. Aber zum Download steht sogar eine einfache Version in C bereit. Hättest du dich mal genauer damit befasst bevor du meckerst. 😉



  • C ist aber auch doph.



  • boah PI ...



  • Da ist der gute Pi so begeistert von meiner Range Idee, will sie aber einfach nicht Range nennen. 😃
    const_string. Pff.



  • Die Idee ist nicht von dir.


Anmelden zum Antworten