TypeScript
Visitor tasarımı
AST ziyaretçisini visitor deseniyle yazarsın.
Visitor tasarımı
Visitor deseni, bir veri yapısını dolaşırken her düğüm türü için ayrı işlem yapmayı sağlar. AST ziyaretçisi, her düğüm türüne karşılık bir visit yöntemi içerir; traverse fonksiyonu düğümü alır ve uygun visit yöntemini çağırır.
interface Visitor {
visitNumber(value: number): void;
visitString(value: string): void;
visitAdd(): void;
}
function traverse(n: Node, v: Visitor): void {
switch (n.kind) {
case "number": v.visitNumber(n.value); break;
case "string": v.visitString(n.value); break;
case "add": v.visitAdd(); break;
}
}
Traverse ile dolaşma
traverse fonksiyonu, AST'yi özyinelemeli olarak dolaşır. Her düğüm için ilgili visit yöntemi çağrılır; alt düğümler olan (örneğin add) düğümler için alt düğümler de dolaşılır. Bu, tüm ağacı işlemeyi sağlar.
function traverse(n: Node, v: Visitor): void {
switch (n.kind) {
case "number": v.visitNumber(n.value); break;
case "string": v.visitString(n.value); break;
case "add":
v.visitAdd();
traverse(n.left, v);
traverse(n.right, v);
break;
}
}
Uygulama Visitor ile AST dolaş
Node discriminated union türünü tanımla ("number" (value: number), "string" (value: string), "add" (left: Node, right: Node)). Visitor interface'ini tanımla: visitNumber(value: number): void, visitString(value: string): void, visitAdd(): void yöntemleriyle. traverse(n: Node, v: Visitor): void fonksiyonunu switch ile yaz. Bir Visitor uygulaması oluştur: visitNumber console.log("n:" + value), visitString console.log("s:" + value), visitAdd console.log("add") yapsın. traverse({ kind: "add", left: { kind: "number", value: 1 }, right: { kind: "string", value: "x" } }, visitor) çağrısı yap.
Örnek çözümü göster
type Node =
| { kind: "number"; value: number }
| { kind: "string"; value: string }
| { kind: "add"; left: Node; right: Node };
interface Visitor {
visitNumber(value: number): void;
visitString(value: string): void;
visitAdd(): void;
}
function traverse(n: Node, v: Visitor): void {
switch (n.kind) {
case "number":
v.visitNumber(n.value);
break;
case "string":
v.visitString(n.value);
break;
case "add":
v.visitAdd();
traverse(n.left, v);
traverse(n.right, v);
break;
}
}
const visitor: Visitor = {
visitNumber: (value) => console.log("n:" + value),
visitString: (value) => console.log("s:" + value),
visitAdd: () => console.log("add"),
};
traverse({ kind: "add", left: { kind: "number", value: 1 }, right: { kind: "string", value: "x" } }, visitor);
Kendini test et
-
Visitor deseninin temel amacı nedir?
- Çalışma zamanı hatalarını gizlemek
- Düğüm türlerini birleştirmek
- Her düğüm türü için ayrı işlem yapmayı sağlamak
- Düğümleri silmek
Cevabı göster
Her düğüm türü için ayrı işlem yapmayı sağlamak — Visitor deseni, her düğüm türü için ayrı visit yöntemi tanımlar; traverse fonksiyonu düğüm türüne göre doğru yöntemi çağırır.
-
Visitor interface yöntemi
interface Visitor {
visitNumber(value: number): void;
visitString(value: string): void;
visit____(): void;
}
Cevabı göster
interface Visitor {
visitNumber(value: number): void;
visitString(value: string): void;
visitAdd(): void;
}
-
Visitor tasarımı parçaları
- Visitor interface
- visit yöntemleri
- traverse fonksiyonu
- ağacı dolaşır
- switch (n.kind)
- doğru visit'i çağırır
- özyinelemeli traverse
- alt düğümleri işler
Sıradaki ders: Type guard'lar