pascalabcnet/SyntaxTree/tree/WalkingVisitorNew.cs

77 lines
3.1 KiB
C#
Raw Permalink Normal View History

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)
{
2017-01-10 08:49:49 +03:00
// 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)
{
2017-02-04 20:02:07 +03:00
to.Parent = from.Parent;
if (from.Parent == null)
throw new Exception("У корневого элемента нельзя получить Parent");
from.Parent.ReplaceDescendant(from, to);
}
2017-01-10 08:49:49 +03:00
public void ReplaceStatementUsingParent(statement from, IEnumerable<statement> to, Desc d = Desc.DirectDescendants)
{
2018-10-02 17:53:43 +03:00
var fp = from.Parent; // SSM 02.10.18 - запомним, т.к. from.Parent может быть одним из x.Parent
2018-11-12 06:44:51 +03:00
//foreach (var x in to) // Это и так делается по обоим веткам!
// x.Parent = fp;
2018-10-02 17:53:43 +03:00
var sl = fp as statement_list;
2017-01-10 08:49:49 +03:00
if (sl != null)
{
sl.ReplaceInList(from, to);
}
else
{
var l = new statement_list();
l.AddMany(to);
l.source_context = from.source_context;
2018-10-02 17:53:43 +03:00
fp.ReplaceDescendant(from, l, d);
2018-11-12 06:44:51 +03:00
l.Parent = fp; // на всякий случай
2017-01-10 08:49:49 +03:00
}
}
}
}