S. Найти и заменить! (151 балл)

Метаобъектом языка Pascal назовём одно из следующих понятий:
  • программа (program);
  • переменная;
  • константа (const);
  • тип (type);
  • функция или процедура (function, procedure);
  • поле записи (record);
  • элемент пользовательского перечислимого типа (элемент ППТ);
  • метка (label).
Каждый метаобъект имеет своё имя и существует в некоторой области видимости. Областей видимости может быть несколько, и они могут вкладываться друг в друга или не пересекаться. С некоторыми метаобъектами связаны свои области видимости. Например:

 1 Program Example;
 2 type
 3   tparity = (_even, _odd);
 4   tpoint = record
 5     x, y : real;
 6   end;
 7 var
 8   i : tparity;
 9   p : tpoint;
10 function Scope : longint;
11 var
12  i : tparity;
13 begin
14   i := _even;
15   p.x := 10;
16 end;
17 begin
18   i := _even;
19   p.x := 10;
20 end.
Здесь объявлены следующие метаобъекты: программа Example, тип tparity, элементы перечислимого типа c именами _even и _odd, тип tpoint, поле x, поле y, две переменные с именами i, переменная p и процедура Scope.
  • Область видимости метаобъекта Example содержит: tparity, _even, _odd, tpoint, i (глобальное объявление), p, Scope.
  • Область видимости метаобъекта tpoint содержит: x, y.
  • Область видимости метаобъекта p также содержит: x, y.
  • Область видимости метаобъекта Scope содержит: i (локальное объявление).
Идентификатором называется любая последовательность латинских букв, цифр и символов '_' (первый символ - не цифра), кроме тех, которые являются ключевыми словами (reserved words).
Каждый идентификатор в программе связан с некоторым метаобъектом. В данном примере:
  • в строчке 8 идентификатор tparity связан типом, объявленном в строчке 3;
  • в строчке 9 идентификатор tpoint связан типом, объявленном в строчке 4;
  • в строчке 12 идентификатор tparity связан типом, объявленном в строчке 3;
  • в строчке 14 идентификатор i связан с переменной, объявленной в строчке 12, а идентификатор _even - с элементом ППТ, объявленном в строчке 3;
  • в строчке 15 идентификатор p связан с переменной, объявленной в строчке 9, а идентификатор x - с полем записи, объявленном в строчке 5;
  • в строчке 18 идентификатор i связан с переменной, объявленной в строчке 8, а идентификатор _even - с элементом ППТ, объявленном в строчке 3;
  • в строчке 19 идентификатор p связан с переменной, объявленной в строчке 9, а идентификатор x - с полем записи, объявленном в строчке 5.
Назовём программу на языке Pascal правильной, если она успешно обрабатывается компилятором Borland Pascal 7.0 с включённой опцией расширенного синтаксиса (X+).
Вам дана правильная программа, позиция в ней и новый идентификатор. Требуется:
  • определить, что находится в данной позиции;
  • если в ней находится не идентификатор, то выдать диагностическое сообщение об ошибке "Не идентификатор";
  • иначе определить, c каким метаобъектом связан данный идентификатор, заменить имя метаобъекта и все идентификаторы, связанные с ним, на заданный новый идентификатор. Если получившаяся программа не будет правильной или изменится связывание некоторых идентификаторов, то выдать диагностическое сообщение об ошибке "Невозможно заменить".
Гарантируется, что в исходной программе отсутствуют следующие конструкции:
  • комментарии в стиле (* ... *);
  • метки, обозначенные числами;
  • директивы препроцессора;
  • директивы uses, interface, implementaion, asm;
  • использование типа множество;
  • использование объктов;
  • модификатор absolute;
  • ссылка на системный модуль (например, System.writeLn);
  • модификаторы forward, far, near, external, interrupt;
  • тип string с указанием длины;
  • константы типа массив, запись и объект.

Входные данные
Также гарантируется выполнение следующих ограничений:
  • длина всех идентификаторов не превышает 64 символов;
  • размер входного файла не превышает 5KB;
Первая строка имеет вид: открывающая фигурная скобка, строка и столбец (позиция во входном файле), новый идентификатор, закрывающая фигурная скобка.
В следующих строках - программа на языке Pascal.

Выходные данные
Если замену произвести нельзя, то первая строка выходного файла должна содержать слово 'Ошибка', а вторая - диагностическое сообщение об ошибке.
Иначе первая строка должна содержать сообщение '{Успешно}', а в последующих строках должна содержаться программа, в которой произведены все необходимые замены.
Ваша программа будет оцениваться в зависимости от количества пройденных тестов по каждому из следующих пунктов:
  • Диагностика ошибок
  • Замена имён глобальных метаобъектов
  • Замена имён локальных метаобъектов процедур и функций
  • Замена имён полей записей
Примеры входного и выходного файлов
INPUT.PAS OUTPUT.PAS
{2 13 writeLn}
procedure Print;
begin
end;
begin
  writeLn(10);
  print;
end.
  
Ошибка
Невозможно заменить
  
INPUT.PAS OUTPUT.PAS
{2 13 writeLn}
procedure Print;
begin
end;
begin
  print;
end.
  
{Успешно}
procedure writeLn;
begin
end;
begin
  writeLn;
end.
  
INPUT.PAS OUTPUT.PAS
{5 3 new_id}
program Example;
procedure swap(var a, b:integer);
var
  temp : integer;
begin
  temp := a;
  a := b;
  b := temp;
end;
var
  temp, persist : integer;
begin
  temp := -10*21;
  persist := 0;
  swap(temp, persist)
end.
  
{Успешно}
program Example;
procedure swap(var a, b : integer);
var
  new_id : integer;
begin
  new_id := a;
  a := b;
  b := new_id;
end;
var
  temp, persist : integer;
begin
  temp := -10*21;
  persist := 0;
  swap(temp, persist)
end.
  
INPUT.PAS OUTPUT.PAS
{16 7 z}
program big_record;
type
  tPoint = record
    x, y : real;
  end;
  tCircle = record
    r : real;
    p : tPoint
  end;
var
  c, c1 : tCircle;
begin
  c.r := 1.234E-02;
  c.p.x := 0;
  c.p.y := 23.152;
  c1.p.y := 10;
end.
  
{Успешно}
program big_record;
type
  tPoint = record
    x, z : real;
  end;
  tCircle = record
    r : real;
    p : tPoint
  end;
var
  c, c1 : tCircle;
begin
  c.r := 1.234E-02;
  c.p.x := 0;
  c.p.z := 23.152;
  c1.p.z := 10;
end.