publicHashSet<string>deletedIdsToDeleteInLocalScope=newHashSet<string>();// одно множество и на Local и на Block
publicDeleteLocalDefs(HashSet<string>ids)// надо запускать этот визитор начиная с корня подпрограммы
{
idsToDelete=ids;
}
publicoverridevoidvisit(var_statementvs)
{
varidents=vs.var_def.vars.idents;
varIdentsToDeleteInVarDef=idents.FindAll(id=>idsToDelete.Contains(id.name));// найти в операторе все идентификаторы для удаления
if(IdentsToDeleteInVarDef.Count!=0)
{
deletedIdsToDeleteInLocalScope.UnionWith(IdentsToDeleteInVarDef.Select(id=>id.name));// добавить те идентификаторы, которые мы удаляем из данного описания
LocalDeletedIds.Add(newvar_def_statement(newident_list(IdentsToDeleteInVarDef),vs.var_def.vars_type,vs.var_def.inital_value));// добавить описание из удаленных в данном разделе описаний идентификаторов
idents.RemoveAll(id=>idsToDelete.Contains(id.name));// удалить в операторе все идентификаторы для удаления
if(idents.Count==0)// то и весь var_statement надо убить
this.DeleteInStatementList(vs);
}
// Здесь мы не обрабатываем вложенный var_def_statement, поэтому когда мы будем обрабатывать его в другом visit, то это будут переменные до beginа подпрограммы или основной программы
}
publicoverridevoidvisit(var_def_statementvd)
{
varidents=vd.vars.idents;
varIdentsToDeleteInVarDef=idents.FindAll(id=>idsToDelete.Contains(id.name));// найти в операторе все идентификаторы для удаления
if(IdentsToDeleteInVarDef.Count!=0)
{
deletedIdsToDeleteInLocalScope.UnionWith(IdentsToDeleteInVarDef.Select(id=>id.name));// добавить те идентификаторы, которые мы удаляем из данного описания
BlockDeletedIds.Add(newvar_def_statement(newident_list(IdentsToDeleteInVarDef),vd.vars_type,vd.inital_value));// добавить описание из удаленных в данном разделе описаний идентификаторов
idents.RemoveAll(id=>idsToDelete.Contains(id.name));// удалить в операторе все идентификаторы для удаления
if(idents.Count==0)
{
// Выше - variable_definitions, еще выше - declarations
varuvdsl=UpperNodeAs<variable_definitions>();
uvdsl.var_definitions.Remove(vd);
if(uvdsl.var_definitions.Count==0)
{
vard=UpperNodeAs<declarations>(2);
d.defs.Remove(uvdsl);
}
}
}
}
publicvoidAfterProcTraverse()
{
idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope);// исключаем из множества удаляемых идентификаторов те, которые мы нашли и удалили в секции var_statement. Это надо делать не для каждого описания, а в конце подпрограммы после удаления из всех секций var_statement