pascalabcnet/SyntaxVisitors/YieldVisitors/DeleteLocalDefs.cs
Mikhalkovich Stanislav e603b1fd6d Mikhalkovich в Copyright
Заготовка для школьного плагина образцов кода
2019-07-28 23:53:15 +03:00

75 lines
4.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class DeleteLocalDefs : BaseChangeVisitor
{
public List<var_def_statement> LocalDeletedIds = new List<var_def_statement>();
public List<var_def_statement> BlockDeletedIds = new List<var_def_statement>();
public HashSet<string> idsToDelete;
public HashSet<string> deletedIdsToDeleteInLocalScope = new HashSet<string>(); // одно множество и на Local и на Block
public DeleteLocalDefs(HashSet<string> ids) // надо запускать этот визитор начиная с корня подпрограммы
{
idsToDelete = ids;
}
public override void visit(var_statement vs)
{
var idents = vs.var_def.vars.idents;
var IdentsToDeleteInVarDef = idents.FindAll(id => idsToDelete.Contains(id.name)); // найти в операторе все идентификаторы для удаления
if (IdentsToDeleteInVarDef.Count != 0)
{
deletedIdsToDeleteInLocalScope.UnionWith(IdentsToDeleteInVarDef.Select(id => id.name.ToLower())); // добавить те идентификаторы, которые мы удаляем из данного описания
LocalDeletedIds.Add(new var_def_statement(new ident_list(IdentsToDeleteInVarDef), vs.var_def.vars_type, vs.var_def.inital_value)); // добавить описание из удаленных в данном разделе описаний идентификаторов
idents.RemoveAll(id => idsToDelete.Contains(id.name)); // удалить в операторе все идентификаторы для удаления
idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope);
if (idents.Count == 0) // то и весь var_statement надо убить
this.DeleteInStatementList(vs);
}
// Здесь мы не обрабатываем вложенный var_def_statement, поэтому когда мы будем обрабатывать его в другом visit, то это будут переменные до beginа подпрограммы или основной программы
}
public override void visit(var_def_statement vd)
{
var idents = vd.vars.idents;
var IdentsToDeleteInVarDef = idents.FindAll(id => idsToDelete.Contains(id.name.ToLower())); // найти в операторе все идентификаторы для удаления
if (IdentsToDeleteInVarDef.Count != 0)
{
deletedIdsToDeleteInLocalScope.UnionWith(IdentsToDeleteInVarDef.Select(id => id.name.ToLower())); // добавить те идентификаторы, которые мы удаляем из данного описания
BlockDeletedIds.Add(new var_def_statement(new ident_list(IdentsToDeleteInVarDef), vd.vars_type, vd.inital_value)); // добавить описание из удаленных в данном разделе описаний идентификаторов
idents.RemoveAll(id => idsToDelete.Contains(id.name.ToLower())); // удалить в операторе все идентификаторы для удаления
if (idents.Count == 0)
{
// Выше - variable_definitions, еще выше - declarations
var uvdsl = UpperNodeAs<variable_definitions>();
uvdsl.var_definitions.Remove(vd);
if (uvdsl.var_definitions.Count == 0)
{
var d = UpperNodeAs<declarations>(2);
d.defs.Remove(uvdsl);
}
}
}
}
public void AfterProcTraverse()
{
idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope); // исключаем из множества удаляемых идентификаторов те, которые мы нашли и удалили в секции var_statement. Это надо делать не для каждого описания, а в конце подпрограммы после удаления из всех секций var_statement
}
}
}