Der Interpreter

Der eigentliche Vorteil einer Verwendung von C++ im Zusammenhang mit Lex und Yacc zeigt sich, sobald man die erzeugten Datenstrukturen tatsächlich verwenden möchte. Das Modul (interpret.cpp) implementiert die calc-Methode der Klasse (Expression). Die Idee ist, dass jeder Ausdruck sich selbst berechnen kann, weshalb die Auswertemethode auch in dieser Klasse plaziert wurde. Berechnen heißt, einen Rückgabewert als Zeichenkette zurückzuliefern und ggf. Seiteneffekte wie das Zuweisen von Variablen durchzuführen. Die Werte von Variablen werden in einer einfachen Map (SymbolTable) gespeichert. Eine solche (SymbolTable) wird der Calc-Methode übergeben. Zweck dieses Parameters ist es, bei einem Aufruf der Methode eine ggf. vorbelegte Tabelle mitzugeben. Diese Funktionalität benötigt man, um z.B. Parameter an einen Funktionsaufruf übergeben zu können. Ferner kann man auf diese Weise ohne jeden Aufwand lokale Variablen verwirklichen, indem eine Funktion durch eine Sequenz von Aufrufen von (calc) abgearbeitet wird. Dies ist möglich, da auch Funktionsdefinitionen als (Expressions) abgelegt werden. An diese Aufrufe wird eine Symboltabelle übergeben, die neben den globalen Variablen auch die Argumente und lokalen Variablen enthält. Der Rest des Interpreters ist quasi selbsterklärend. Für jeden Typ von Operationen wird die entsprechende Aktion durchgeführt und der Rückgabewert ermittelt. Neue Operationen und Konstrukte lassen sich hier beliebig einbauen, wobei sich Schleifen, Sprünge etc. am besten durch ihre C-Äquivalente realisieren lassen. Alle Werte werden konsequent als (strings) abgelegt und nur bei Bedarf in Zahlen umgewandelt. Dies ermöglicht das einfache Hinzufügen von Operationen, die sich auf Zeichenketten beziehen.