Я в процесі створення власної мови програмування, яку я роблю для цілей навчання. Я вже написав лексеру та рекурсивний аналізатор спуску для підмножини моєї мови (на даний момент я підтримую математичні вирази, такі як + - * /
дужки). Аналізатор передає мені Абстрактне синтаксичне дерево, на якому я називаю Evaluate
метод отримання результату виразу. Все працює добре. Ось приблизно моя поточна ситуація (приклади коду в C #, хоча це досить багато мови)
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;
}
}
Однак я хотів би роз'єднати алгоритм від вузлів дерева, тому що я хочу застосувати відкритий / закритий принцип, тому мені не доведеться відкривати кожен клас вузлів, коли я хочу реалізувати генерацію коду, наприклад. Я читав, що шаблон для відвідувачів хороший для цього. Я добре розумію, як працює схема, і що використання подвійної відправки - це шлях. Але через рекурсивний характер дерева, я не впевнений, як я повинен підходити до нього. Ось як виглядатиме мій Відвідувач:
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
}
Тож це моя проблема. Я хочу вирішити це негайно, поки моя мова не підтримує багато функціональності, щоб пізніше не виникнути більшої проблеми.
Я не публікував це в StackOverflow, тому що я не хочу, щоб ви надавали імплементацію. Я хочу лише, щоб ти поділився ідеями та концепціями, які я, можливо, пропустив, і як я повинен до цього підходити.