CodeBlanks Logo Icon CodeBlanks

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.

Başlangıç kodu

index.ts
// Node discriminated union türünü tanımla (kind: number, string, add)

// Visitor interface tanımla (visitNumber, visitString, visitAdd)

// traverse fonksiyonunu switch ile yaz

// Visitor uygulaması oluştur ve traverse çağır

Örnek çözüm

index.ts
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);

Beklenen çıktı

add
n:1
s:x

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 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 Doğru cevap
  • Düğümleri silmek

Açıklama: 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.

2 Visitor interface yöntemi

Soru
interface Visitor {
  visitNumber(value: number): void;
  visitString(value: string): void;
  visit____(): void;
}
Cevap
interface Visitor {
  visitNumber(value: number): void;
  visitString(value: string): void;
  visitAdd(): void;
}

Açıklama: Visitor deseni her düğüm türü için ayrı visit yöntemi içerir; visitAdd add düğümü için çağrılır.

3 Visitor tasarımı parçaları

Kavram Anlamı
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

İleri seviye bölümündeki tüm dersler