Fireplace

C++ Kleiner Interpreter

Yuuri schrieb:
Der Interpreter kann aber nur einfache Gleichungen aufschlüsseln oder? Mir schwebt da was wie z.B. 1/5x^4+2x^2+1 oder solche Scherze wie e-Funktionen und Logarithmen ein (kurz gesagt Kurvendiskussion). Wenn er auch solche "komplexen" Gleichungen aufschlüsselt, würde ich mal einen Blick rein werfen.

Natürlich kann er das. Es ist so wie er im Buch steht ein vollständiger Lisp-Interpreter. Du gibst
ihm halt einfach alle Operatoren, die du brauchst als Primitive mit, dann kann er das. Exponentiation
ist entweder ein Einzeiler, oder du schreibst eine winzige Funktion, die das implementiert selbst.
Gibt ja schön schnelle Algorithmen dafür.

€: Ein Beispiel für numerische Differentiation ist auch drin, wenn du sowas haben willst und später
kommt ein Programm, das symbolische Ableitungen durchführen kann. Das ist aber relativ simpel,
denn SICP ist immer noch ein Buch für Einsteiger. Zum Beispiel kann jeder Operator nur zwei Operanden
haben, so dass der symbolische differentiator z.B. nicht (* 1 2 3 4) sondern (* 1 (* 2 (* 3 4))) ausgibt.
Das bekommt man also nicht fertig vorgekaut, sondern muss das Programm entsprechend erweitern.

Das nötige Handwerkszeug dazu bekommt man von SICP allerdings. Und es ist auf beliebige Sprachen
und nicht nur Lisp anwendbar. Das erfordert dann natürlich entsprechende Portierarbeit. An die Syntax
von Lisp ist man auch nicht gebunden. Man muss dann nur den Teil, der den fertigen Ausdruck baut,
statt einer S-Expression einen "normalen" mathematischen Ausdruck bauen lassen.

€2: Ein Beispiel dazu:
Der symbolische Ableiter hat eine Funktion der Art (MAKE-SUM A B), die den Ausdruck (+ A B) ausgibt
(Also jeweils den Wert der Variablen A und B). Stattdessen muss man die Funktion halt ändern, dass
sie A + B ausgibt und das war es dann schon erstmal.

Das Programm spuckt immer richtige Ergebnisse aus, aber dafür halt oft unschöne. Da ist dann halt
Arbeit gefragt, die über ein Buch für Einsteiger hinausgeht. Statt (expt x 4), das für x^4 steht, gibt
der ähnlich den obigen Beispiel dann (* x (* x (* x x))) aus. Das ist natürlich mathematisch korrekt,
aber übelst hässlich ausgedrückt.
 
Zuletzt bearbeitet:
jetzt wo ich lisp sehe, fällt mir noch eine alternative ein: SML. der open-source interperter hier und das problem ist vom tisch :)
 
Vielleicht hast du mich falsch verstanden. Es geht nicht darum, dass ich empfehle, seine Idee umzuwerfen und das
Ganze in Lisp zu schreiben, sondern darum, dass es ein sehr sehr gutes Lehrbuch gibt, das grundlegende Konzepte
der Programmierung behandelt (darunter auch das Auswerten mathematischer Ausdrücke) und als Beispiel zur
Vermittlung dieser Konzepte nun einmal Lisp benutzt.

Die Umsetzung dieser Konzepte kann man natürlich dann in jeder Sprache machen, die man mag. Nur sollte man sie
erstmal kennenlernen. Und dazu ist SICP großartig.
 
die EBNF

Code:
Ausdruck ::= Term { '+'|'-' Term}
Term ::= Faktor { '*'|'/' Faktor}
Faktor ::= zahl | '(' Ausdruck ')' | '-' Ausdruck

ist so zu verstehen:
Ein Ausdruck z.B. 3*2+1 besteht aus einer Sequenz durch '+' oder '-' verbundenen Folge von Termen. Die Terme im Beispiel sind 3*2 und 1.
Analog ist ein Term ist eine Sequenz von Faktoren verbunden durch '*' oder '/'. Im Beispiel (Term1 => Faktoren 3, 2 und Term2 => Faktor 1).
Ein Faktor ist entweder eine Zahl, ein geklammerter Ausdruck oder ein negierter Ausdruck.
Die Sequenzen können auch aus nur einem Element bestehen, die geschweiften Klammern {} bedeuten Wiederholung inklusive 0-mal. Der vertikale Strich | ist die Alternative. Damit solltest du nun klar kommen.
 
Zuletzt bearbeitet:
@master bratak: Das mit Filtern von Leerzeichen etc. ist der völlig falsche Weg. Verwende einen Lexer, der zieht dir automatisch alle Schlüsselzeichen und Zahlen etc. als Tokenstream aus der Eingabe heraus. Das musst du dann durch einen Parser laufen lassen, so dass im Ergebnis ein Operatorbaum herauskommt, den du dann Top-Down durchevaluieren kannst, und schon hast du das Ergebnis der Rechnung.

Diese Filterei etc. bringt dich nicht ans Ziel!
 
Waren Scanner/Lexer nicht nur etwas für den Compilerbau?
Meinst du ich soll einen 'fertigen' Lexer/Scaner nutzen?
 
deine Funktion entfernt ja schon die Leerzeichen das würde sonst
strtok gleich mit erledigen, de noch vorhandenen Leerzeichen wäre ja für
strtok die Trennzeichen.

so oder ähnkich könnte die Funktion aussehen,
vorausgesetzt es bleibt bei deinen einfachen Eingaben wie 2 + 3.

Ansonsten würde ich mir mal die string Funtionen genauer anschauen, da gibt es
noch string::find und string ::substr usw. damit könnte mann die Eingaben parsen und in
mehere Tokens zerlegen.

Code:
bool  tokenize ( string Line,  string& rOperantA, string& rOperantB, string& rOperator)
{

      char* tToken;
      tToken= strtok (Line ," ");                              //erste initialisierung
      
      if (tToken!= NULL)     rOperantA = tToken;
      else                           return false;
      
      tToken= strtok (NULL," ");
      
       if (tToken!= NULL)    rOperator = tToken;
       else                          return false;
     
      tToken= strtok (NULL," ");

      if (tToken!= NULL)    rOperantB = tToken;
      else                         return false;

     return true;   
}

Ich würd dir außerdem empfehlen dir deinen Interpreten auf Classenbasis zu erstellen.
wird auf Dauer übersichtlicher und ist einfacher zu warten und zu erweitern.

Fals deine Programme plattformübergreifent seien sollen solltest du noch wissen,
das strtok in unix/linux Kreisen doch eher verpöhnt ist.
Wenn du nur für Windows codest, schau dir mal die CString Klasse der MFC an, die ist sehr
mächtig im Funktionsumfang
 
Zuletzt bearbeitet: (war noch nich fertig, zu früh auf Enter gedrückt)
warum ist strtok in linuxkreisen den verpöhnt? Ich arbeite mit Linux & code nur für Linux, also irgendwelche peziellen M$ Funktionen sind nicht
 
Die Antwort findest du hier in einen schon etwas älteren Thread.
incl. einer guten Lösung mit Hilfe der string Funktionen und der vector Klasse.
alles standart C++ , Post #4-6,

mfg
 
nimm flex und bison, damit kann jedes kleine kind einen solchen interpreter coden.
 
Zurück
Oben