Wenn du einen Parser schreibst, zerlegst du die reingeworfene Formel ja erst mal. Sagen wir, du willst "1 + 2.3" parsen. Dann würdest du das in drei Teile zerlegen: "1", "+" und "2.3". Da sich der Rechner darunter noch nicht vorstellen kann, musst du dem Rechner beibringen, was er sich darunter vorzustellen hat. Normalerweise macht man so etwas mit
Opcodes. Du könntest einen Opcode für die Addition einführen, der zwei Parameter nimmt. Da man Matheparser oder Parser allgemein gerne als Stackmaschinen implementiert, nimmt sich der Opcode eben die zwei Parameter vom Stack.
Dazu musst du noch einen Schritt vorschalten: die Formel so umbasteln, das man sie sinnvoll auf einen Stack pushen kann; also: das der Rechner den Add-Opcode ohne Probleme anwenden kann. Da die Parameter des Opcodes vor der Operation auf dem Stack sein müssen, müsste dein Stack vor der Addition so aussehen:
Am weitesten unten bedeutet als erstes vom Stack geholt, wohlgemerkt
Der Additionsopcode schnappt sich die beiden (popt sie vom Stack), addiert sie und pusht das Ergebnis zurück. Der Stack sieht dann so aus:
Werden wir mal ein wenig komplizierter: "1 + 2 * 3"
Der Parser zerlegt das Ding wieder in Atome (Konstanten und Operatoren), die du am Ende in die sogenannte UPN(umgekehrte polnische Notation)-Form umwandeln kannst. Das läuft nach Operatorvorrang ab. Der *-Operator ist "wichtiger" als der +-Operator und darf daher zuerst an den Stack. Seine Parameter "2" und "3" müssen aber trotzdem auf dem Stack sein. Deshalb sieht dein Zahlenstack so aus:
Der *-Operator nimmt sich also die beiden letzten von Stack, multipliziert und schreibt zurück. Dann addiert der Add-Operator den Rest.
Sprich: es gibt nicht nur den Numeralstack für Konstanten, Variable und Ergebnisse, sondern auch einen Opstack mit den Operatoren. Der sähe im letzten Beispiel so aus:
Weiter unten bedeutet wieder: als erstes dran.
Die Urpsrungsform der Stacks kann man getrost als Bytecode des Parsers bezeichnen. Wenn du dir diesen Bytecode speicherst und den später nur noch durch die Auswertungsmethode des Parsers rennen lässt, ist der Performanceunterschied zu deinem jetzigen Parser gigantisch.
Wenn du dich nicht scheust, dir etwas anzusehen, was es schon gibt, und daraus zu lernen, dann sieh dir unbedingt den
CQParser und vielleicht noch den
ECQP oder sogar
HAM an. Letzteres würde ich dir als Neuling allerdings nicht so ganz ans Herz legen, denn der ist schon wirklich komplizierter