diff --git a/SyntaxTree/tree/BaseChangeVisitor.cs b/SyntaxTree/tree/BaseChangeVisitor.cs new file mode 100644 index 000000000..dbaee1eb9 --- /dev/null +++ b/SyntaxTree/tree/BaseChangeVisitor.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace PascalABCCompiler.SyntaxTree +{ + public class BaseChangeVisitor : CollectUpperNodesVisitor + { + public override void DefaultVisit(syntax_tree_node n) + { + // frninja 07/12/15 - // SSM - это - идиотский код, приводивший к двойному обходу визитором всех узлов + /*if (!_rootAdded) + { + _rootAdded = true; + ProcessNode(n); + }*/ + + // Элементы списков - с конца в начало чтобы можно было эти элементы изменять по ходу (удалять/вставлять/заменять один несколькими) + var Сount = n.subnodes_count; + var СountWithoutListElements = n.subnodes_without_list_elements_count; + + for (var i = 0; i < СountWithoutListElements; i++) + ProcessNode(n[i]); + + for (var i = Сount - 1; i >= СountWithoutListElements; i--) // в обратном порядке + ProcessNode(n[i]); + } + + public void Replace(syntax_tree_node from, syntax_tree_node to) + { + var upper = UpperNode(); + if (upper == null) + throw new Exception("У корневого элемента нельзя получить UpperNode"); + upper.Replace(from, to); + } + + public T UpperNodeAs(int up = 1) where T : syntax_tree_node + { + var stl = UpperNode(up) as T; + if (stl == null) + throw new Exception("Элемент вложен не в " + typeof(T)); + return stl; + } + + public T UpperTo() where T : syntax_tree_node + { + syntax_tree_node upperNode = null; + + int up = 1; + + do + { + upperNode = UpperNode(up); + ++up; + } + while ((object)upperNode != null && !(upperNode is T)); + + return (object)upperNode != null ? upperNode as T : null; + } + + public bool DeleteInIdentList(ident id) + { + var idl = UpperNodeAs(); + return idl.Remove(id); + } + + public bool DeleteInStatementList(statement st) + { + var stl = UpperNodeAs(); + return stl.Remove(st); + } + + public static IEnumerable SeqStatements(params statement[] seq) + { + var l = new List(); + foreach (var st in seq) + if (st is statement_list) + l.AddRange((st as statement_list).list); + else l.Add(st); + return l; + } + + public void ReplaceStatement(statement from, statement to) + { + var stl = UpperNodeAs(); + stl.ReplaceInList(from, to); + } + + public void ReplaceStatement(statement from, IEnumerable to) + { + var stl = UpperNodeAs(); + stl.ReplaceInList(from, to); + } + } + +} diff --git a/SyntaxTree/tree/CollectUpperNodesVisitor.cs b/SyntaxTree/tree/CollectUpperNodesVisitor.cs new file mode 100644 index 000000000..b78f2772f --- /dev/null +++ b/SyntaxTree/tree/CollectUpperNodesVisitor.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using PascalABCCompiler; +using PascalABCCompiler.SyntaxTree; + +namespace PascalABCCompiler.SyntaxTree +{ + public class CollectUpperNodesVisitor : BaseEnterExitVisitor + { + protected List listNodes = new List(); + + public syntax_tree_node CurrentNode + { + get + { + return listNodes[listNodes.Count - 1]; + } + } + + public syntax_tree_node UpperNode(int up = 1) + { + if (listNodes.Count - 1 - up < 0) + return null; + return listNodes[listNodes.Count - 1 - up]; + } + + public override void Enter(syntax_tree_node st) + { + listNodes.Add(st); + } + public override void Exit(syntax_tree_node st) + { + listNodes.RemoveAt(listNodes.Count - 1); + } + } + +} diff --git a/SyntaxTree/tree/FillParentNodeVisitor.cs b/SyntaxTree/tree/FillParentNodeVisitor.cs new file mode 100644 index 000000000..2a1682bd0 --- /dev/null +++ b/SyntaxTree/tree/FillParentNodeVisitor.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace PascalABCCompiler.SyntaxTree +{ + public class FillParentNodeVisitor: CollectUpperNodesVisitor + { + public static FillParentNodeVisitor New + { + get + { + return new FillParentNodeVisitor(); + } + } + public override void Enter(syntax_tree_node st) + { + base.Enter(st); + st.Parent = UpperNode(); + } + } +}