57 lines
2.1 KiB
C#
57 lines
2.1 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
|
||
|
||
namespace PascalABCCompiler.SyntaxTree
|
||
{
|
||
|
||
//Два варианта использования визитора:
|
||
//1. Создать экземпляр этого класса, привязать к OnEnter и OnLeave обработчики посещений узла
|
||
//и запустить обход. Визитор обойдет дерево и для каждого узла вызовет эти обработчики.
|
||
//
|
||
//2. Унаследовать от этого класса свой класс, в котором переорпеделить обработку нужных узлов.
|
||
//Не забывать при этом о вызове visit'ов для подузлов (или base.visit), если это нужно.
|
||
|
||
public delegate void VisitorDelegateNew(syntax_tree_node node);
|
||
|
||
public class WalkingVisitorNew : AbstractVisitor
|
||
{
|
||
|
||
protected VisitorDelegateNew OnEnter;
|
||
protected VisitorDelegateNew OnLeave;
|
||
|
||
protected bool visitNode = true; // в OnEnter можно сделать false
|
||
|
||
public virtual void ProcessNode(syntax_tree_node Node)
|
||
{
|
||
if (Node != null)
|
||
{
|
||
if (OnEnter != null)
|
||
OnEnter(Node);
|
||
|
||
if (visitNode)
|
||
Node.visit(this);
|
||
else visitNode = true;
|
||
|
||
if (OnLeave != null)
|
||
OnLeave(Node);
|
||
}
|
||
}
|
||
|
||
public override void DefaultVisit(syntax_tree_node n)
|
||
{
|
||
var count = n.subnodes_count;
|
||
for (var i = 0; i < count; i++)
|
||
ProcessNode(n[i]);
|
||
}
|
||
|
||
// Можно перенести сюда поскольку замена 1 на 1 позволяет пользоваться текущим DefaultVisit
|
||
public void ReplaceByVisitor(syntax_tree_node from, syntax_tree_node to)
|
||
{
|
||
if (from.Parent == null)
|
||
throw new Exception("У корневого элемента нельзя получить Parent");
|
||
from.Parent.ReplaceDescendant(from, to);
|
||
}
|
||
}
|
||
|
||
} |