Tôi đang trong quá trình tạo ngôn ngữ lập trình của riêng mình, điều mà tôi làm cho mục đích học tập. Tôi đã viết lexer và một trình phân tích cú pháp gốc đệ quy cho một tập hợp con ngôn ngữ của tôi (tôi hiện hỗ trợ các biểu thức toán học, chẳng hạn như + - * /
và dấu ngoặc đơn). Trình phân tích cú pháp trao lại cho tôi một Cây cú pháp trừu tượng, trên đó tôi gọi Evaluate
phương thức để lấy kết quả của biểu thức. Mọi thứ đều hoạt động tốt. Đây là xấp xỉ tình hình hiện tại của tôi (ví dụ về mã trong C #, mặc dù điều này khá nhiều ngôn ngữ không thể biết):
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;
}
}
Tuy nhiên, tôi muốn tách rời thuật toán khỏi các nút cây vì tôi muốn áp dụng Nguyên tắc Mở / Đóng để tôi không phải mở lại mọi lớp nút khi tôi muốn thực hiện tạo mã chẳng hạn. Tôi đọc rằng Mô hình khách truy cập là tốt cho điều đó. Tôi có một sự hiểu biết tốt về cách thức hoạt động của mô hình và sử dụng công văn kép là cách để đi. Nhưng do tính chất đệ quy của cây, tôi không chắc mình nên tiếp cận nó như thế nào. Đây là những gì Khách truy cập của tôi sẽ trông như thế nào:
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
}
Vì vậy, đây là vấn đề của tôi. Tôi muốn giải quyết nó ngay lập tức trong khi ngôn ngữ của tôi không hỗ trợ nhiều chức năng để tránh gặp vấn đề lớn hơn sau này.
Tôi không đăng bài này lên StackOverflow vì tôi không muốn bạn cung cấp triển khai. Tôi chỉ muốn bạn chia sẻ những ý tưởng và khái niệm mà tôi có thể đã bỏ lỡ, và làm thế nào tôi nên tiếp cận điều này.