2016-05-25 6 views
1

Ich habe einen Interpreter, der die polnische Notation löst. Ich habe alle Operationen und Zahlen in Token und ich habe eine Liste von Token. So zum Beispiel - - 5 4 2 ist eine Liste mit diesen Token:Interpreter Rekursive Polnische Notation mit Token-Liste

SubtractionToken, SubtractionToken, NumberToken, NumberToken, NumberToken, STOPToken.

Beispiel Token:

class SubstractToken : IBinaryOperation 
{ 
    public Number Interpret(Number value1, Number value2) 
    { 
     Number c = new Number(value1.Value() - value2.Value()); 
     return c; 
    } 
} 

class Number : IToken 
{ 
    private int value; 

    public Number(int val) 
    { 
     value = val; 
    } 

    public int Value() 
    { 
     return value; 
    } 

} 

Also, ich kann nicht verstehen, wie rekursive Funktion, um diese Probleme zu lösen. Denn wenn ich SubtractionToken.Inrerpret (Wert, Wert) muss ich die Werte geben von numberTokens was Subtrahieren von sich selbst sein sollte, aber was passiert, wenn das nächste Token ein Operationstoken ist? oder wir haben - 5 - 7 2? Ich weiß nicht, wie man eine solche rekursive Funktion implementiert, die erkennt, dass die erste Operation durchgeführt werden sollte - 7 2 dann - 5 und Ergebnis von (- 7 2), erinnere mich an die Ergebnisse und zurück an die vorherigen nicht durchgeführten Operationen. Irgendeine Hilfe?

+0

Klingt, als ob Sie mehr eines Parsers als eines Interpreters benötigen. – stuartd

+0

@stuartd: OP versucht wahrscheinlich zur gleichen Zeit zu analysieren und zu interpretieren. – IAbstract

+0

Werfen Sie einen Blick auf [diese] (http://codereview.stackexchange.com/questions/48632/math-equation-as-string-to-reverse-polish-notation-parser). Ich habe das vor etwa 2 Jahren als Lernprojekt geschrieben. Es kann sicherlich verbessert werden, aber es sollte helfen. – JRLambert

Antwort

3

Sie tun dies normalerweise mit einem Auswertungsstapel, der die Ergebnisse speichert, die Sie bisher gesehen haben. Wenn Sie in der Eingabe auf eine Zahl stoßen, drücken Sie sie auf den Stapel, und wenn Sie auf eine binäre Operation (z. B. '-') stoßen, blättern Sie zwei Werte aus dem Stapel, interpretieren Sie sie und drücken Sie das Ergebnis. Etwas wie:

public static Number Evaluate(List<IToken> tokens, Stack<Number> eval) { 
    if(tokens.Count == 0) { 
     if(eval.Count != 1) throw new InvalidArgumentException("Invalid expression"); 
     return eval.Pop(); 
    } 
    var tok = tokens[tokens.Count-1]; 
    tokens.RemoveAt(tokens.Count-1); 
    if (tok is Number) { 
     eval.Push(tok); 
    } 
    else if(tok is IBinaryOperation) { 
     var result = ((IBinaryOperation)tok).Evaluate(eval.Pop(), eval.Pop()); 
     eval.Push(result); 
    } 
    //handle other cases 
    return Evaluate(tokens, eval); 
} 

Dies könnte leicht eine iterative Funktion gemacht werden, falls erforderlich.

+0

Keine Rangfolge, obwohl. Nicht sicher, wo das in den OP-Bereich passt. – IAbstract

+0

Ok, was brauche ich, wenn ich auch Unary-Operationen habe? Wäre es in Ordnung, wenn ich 'else if hinzufügen (tok isUnaryOperation) { var result = ((IUnaryOperation) tok) .Evaluate (eval.Pop()); eval.Push (Ergebnis) '? – Blabla

+0

@IAbstract - In RPM gibt es keine Rangordnung.Es könnte in der Quellgrammatik sein, aber das würde von dem Parser gehandhabt werden. – Lee

0

Es scheint, dass Sie versuchen, das polnische Präfix ohne Klammern zu interpretieren, so dass Sie die Anzahl der Operanden pro Operator kennen müssten (keine Restargumente). Der STOPToken ist überflüssig oder vielleicht nur um kurze oder lange Ausdrücke einzufangen?

Wenn Sie eval Ihre Liste von Tokens und es zufällig sein SubtractionToken Sie pop es aus der Liste und führen Sie Eval zweimal (eins für jedes Argument) und mit den Ergebnissen wenden Sie Ihre Funktion und die Antwort zurück.

Beispiel: Wenn die Token sind - - 2 3 4 X

top is -, takes two arguments 
    top is -, takes two arguments 
    top is 2 
    top is 3, we have 2 arguments apply 
    5 
    top is 4, we have two arguments apply 
9 , finished (X is left on stack) 
check if X is the top to ensure the expression is valid 

Vielleicht ist die reson für Haltestelle ist - - 5 X

top is -, takes two arguments 
    top is -, takes two arguments 
    top is 5 
    top is X --> throw exception since the stop token is illegal as argument 

nun für eine veränderbare Datenstruktur Sie nur die Token aus Pop, aber für eine funktionsfähige Version Sie müssten sowohl die Werte als auch die Token zurückgeben, die noch gelesen werden können, und die zweite eval muss diese verwenden, um ihren Ausdruck zu holen, sonst werden Sie gelesen der gleiche Ausdruck zweimal.