Ich bin dabei, meine eigene Programmiersprache zu erstellen, die ich zu Lernzwecken verwende. Ich habe bereits das Lexer und ein rekursives Descent-Parser für eine Teilmenge meiner Sprache geschrieben (derzeit unterstütze ich mathematische Ausdrücke wie + - * /
und in Klammern). Der Parser gibt mir einen abstrakten Syntaxbaum zurück, auf dem ich die Evaluate
Methode aufrufe, um das Ergebnis des Ausdrucks zu erhalten. Alles funktioniert gut. Hier ist ungefähr meine aktuelle Situation (Codebeispiele in C #, obwohl dies ziemlich sprachunabhängig ist):
public abstract class Node
{
public abstract Double Evaluate();
}
public class OperationNode : Node
{
public Node Left { get; set; }
private String Operator { get; set; }
private Node Right { get; set; }
public Double Evaluate()
{
if (Operator == "+")
return Left.Evaluate() + Right.Evaluate();
//Same logic for the other operators
}
}
public class NumberNode : Node
{
public Double Value { get; set; }
public Double Evaluate()
{
return Value;
}
}
Ich möchte den Algorithmus jedoch von den Baumknoten entkoppeln, da ich das Open / Closed-Prinzip anwenden möchte, damit ich nicht jede Knotenklasse erneut öffnen muss, wenn ich beispielsweise die Codegenerierung implementieren möchte. Ich habe gelesen, dass das Besuchermuster dafür gut ist. Ich habe ein gutes Verständnis dafür, wie das Muster funktioniert, und die Verwendung von Doppelversand ist der richtige Weg. Aber aufgrund der rekursiven Natur des Baumes bin ich mir nicht sicher, wie ich es angehen soll. So würde mein Besucher aussehen:
public class AstEvaluationVisitor
{
public void VisitOperation(OperationNode node)
{
// Here is where I operate on the operation node.
// How do I implement this method?
// OperationNode has two child nodes, which may have other children
// How do I work the Visitor Pattern around a recursive structure?
// Should I access children nodes here and call their Accept method so they get visited?
// Or should their Accept method be called from their parent's Accept?
}
// Other Visit implementation by Node type
}
Das ist also mein Problem. Ich möchte es sofort angehen, während meine Sprache nicht viele Funktionen unterstützt, um später ein größeres Problem zu vermeiden.
Ich habe dies nicht in StackOverflow gepostet, weil ich nicht möchte, dass Sie eine Implementierung bereitstellen. Ich möchte nur, dass Sie Ideen und Konzepte mitteilen, die ich möglicherweise übersehen habe und wie ich damit umgehen sollte.