75 lines
2.9 KiB
C#
75 lines
2.9 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
|
||
|
||
namespace PascalABCCompiler.SyntaxTree
|
||
{
|
||
|
||
//Два варианта использования визитора:
|
||
//1. Создать экземпляр этого класса, привязать к OnEnter и OnLeave обработчики посещений узла
|
||
//и запустить обход. Визитор обойдет дерево и для каждого узла вызовет эти обработчики.
|
||
//
|
||
//2. Унаследовать от этого класса свой класс, в котором переорпеделить обработку нужных узлов.
|
||
//Не забывать при этом о вызове visit'ов для подузлов (или base.visit), если это нужно.
|
||
|
||
public class WalkingVisitorNew : AbstractVisitor
|
||
{
|
||
|
||
protected Action<syntax_tree_node> OnEnter;
|
||
protected Action<syntax_tree_node> 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)
|
||
{
|
||
// n.subnodes_count может меняться в процессе работы этого алгоритма
|
||
// В частности, в результате ReplaceStatementWithParent
|
||
for (var i = 0; i < n.subnodes_count; i++)
|
||
ProcessNode(n[i]);
|
||
}
|
||
|
||
// Можно перенести сюда поскольку замена 1 на 1 позволяет пользоваться текущим DefaultVisit
|
||
public void ReplaceUsingParent(syntax_tree_node from, syntax_tree_node to)
|
||
{
|
||
to.Parent = from.Parent;
|
||
if (from.Parent == null)
|
||
throw new Exception("У корневого элемента нельзя получить Parent");
|
||
from.Parent.ReplaceDescendant(from, to);
|
||
}
|
||
|
||
public void ReplaceStatementUsingParent(statement from, IEnumerable<statement> to, Desc d = Desc.DirectDescendants)
|
||
{
|
||
foreach (var x in to)
|
||
x.Parent = from.Parent;
|
||
var sl = from.Parent as statement_list;
|
||
if (sl != null)
|
||
{
|
||
sl.ReplaceInList(from, to);
|
||
}
|
||
else
|
||
{
|
||
var l = new statement_list();
|
||
l.AddMany(to);
|
||
l.source_context = from.source_context;
|
||
from.Parent.ReplaceDescendant(from, l, d);
|
||
}
|
||
}
|
||
}
|
||
|
||
} |