(*~\Глагол\ПриложенияLink\МПГ2008 (комп., но не раб.)\~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                                            ОТДЕЛ Выражения;
(*============================================================================* 
 * НАЗНАЧЕНИЕ: разбор выражений языка
 *============================================================================*)

ИСПОЛЬЗУЕТ 
  ОБХОД,
        (*  \Глагол\              *)
 оЦепи    ИЗ "..\..\Отделы\Иное\",
  Пустой  ИЗ "..\..\Отделы\Иное\",  
ЧэргаСлеД ИЗ "..\..\Отделы\Иное\",

  Настрой,
  Данные,
  Обмен,
  Код,
  Узел,
  Рег,
  ВКод,
  Слово,
  Разбор,
  Ошибка;

                       (*--- выходы из цикла КОЛЬЦО ---*)
ПОСТ
  кУровней=32; (* м.б. вложений *)

ПЕР 
  кУровень:ЦЕЛ; (* текущий уровень вложений *)
  кВыходы:РЯД кУровней ИЗ ЦЕЛ; (* метки выхода для каждого уровня *)
  кДопПер:РЯД кУровней ИЗ ЦЕЛ; (* доп. переменных для указаний ОТ ДО и ВЫБРАТЬ *)


                   (*--- неопределенные (опережающие вид) доступы ---*)
ВИД
(*НеопрДоступ = ДОСТУП К НАБОР(Пустой.Вид)*)
  ДкНеопрВиду = ДОСТУП К (*нНеопрВид;
                           нНеопрВид =*) НАБОР(ЧэргаСлеД.нПустой)
    вид:Данные.ДкВидуВид;                                    (* доступ к виду *)
    имя:Настрой.Имя                                (* неопределенное имя вида *)
                                         КОН;

(*---
                    набор-список доступов к неопределённым видам данных
  ---*)
ПЕР
  неопрВиды   :ЧэргаСлеД.нСписок;
(*неопрДоступы:ЧэргаСлеД.нСписок;*) (* очередь
                                     из неопределённых доступов - ДкНеопрВиду *)

                             (*--- тексторез ---*)
ПОСТ
  трУровней=32; (* м.б. вложений *)  
                                    (* состояния: *)
  трДоВкл=0; трВкл=1; трОткл=-1;

ПЕР
  трРаботает:КЛЮЧ;
  трУровень:ЦЕЛ;
  трСостояние:РЯД трУровней ИЗ ЦЕЛ;

                             (*--- разное ---*)
ПЕР 
  слово:ЦЕЛ;                      (* прочитанное слово из входного текста *)
  оЦепьРазрешена:ЦЕЛ;             (* объявление разрешёно только при >= 0 *)
  зУровень:ЦЕЛ;                   (* уровень вложения задач, 0 - отдел    *)
  срдМесто:Пустой.ДкЦепи;         (* местоположение файла "СРЕДА.отд"     *)
  размерПриёмников:ЦЕЛ;           (* размер приёмников у обрабатываемой задачи *)


                   (*--- вид-доступ к телу звена в списке испИмена ---*)
ВИД
(*  ИспИмя- = ДОСТУП К               НАБОР(Набор.Вид)   *)
  ДкИспИмя- = ДОСТУП К (*нИспИмя;
                         нИспИмя =*) НАБОР(ЧэргаСлеД.нПустой)
         имя-:Настрой.Имя;
        путь-: Пустой.ДкЦепи;
    начСлова-: Разбор.Положение
                                     КОН; (* для разбора взаимосвязей отделов *)


(*-оооооооооооооо- опережающие определения/заготовки задач -ооооооооооооооооо-*)

ЗАДАЧА^ Заголовок(видОтвета+:Данные.ДкВидуВид):ЦЕЛ;
ЗАДАЧА^ ВидСлова(вид+:Данные.ДкВидуВид);
ЗАДАЧА^ Выражение(уа+:Узел.нВид);
ЗАДАЧА^ Объявления(задача:Данные.ДкВидуПонятие; конИмя-:Настрой.Имя);
ЗАДАЧА^ Тексторез;


(*----------------------------------------------------------------------------*)
ЗАДАЧА ЧитатьСлово;
УКАЗ
  слово:=Разбор.Слова();
  ПОКА (слово = Слово.мумн) И НЕ трРаботает ВЫП
    трРаботает:=ВКЛ;
    Тексторез;
    трРаботает:=ОТКЛ
  КОН
КОН ЧитатьСлово;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ПропуститьСлово(с:ЦЕЛ);
УКАЗ
  ЕСЛИ слово = с ТО ЧитатьСлово ИНАЧЕ Ошибка.Отметить(с) КОН
КОН ПропуститьСлово;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ТекущееСлово(с:ЦЕЛ);
УКАЗ
  ЕСЛИ слово # с ТО Ошибка.Отметить(с) КОН
КОН ТекущееСлово;

(*----------------------------------------------------------------------------*)
ЗАДАЧА БудетСлово(с:ЦЕЛ);
УКАЗ
  ЧитатьСлово;
  ЕСЛИ слово # с ТО Ошибка.Отметить(с) КОН
КОН БудетСлово;

(*----------------------------------------------------------------------------*)
ЗАДАЧА СледующееСлово():ЦЕЛ;
УКАЗ
  ЧитатьСлово;
  ВОЗВРАТ слово
КОН СледующееСлово;

(*----------------------------------------------------------------------------*)
ЗАДАЧА НайтиПонятие():Данные.ДкВидуПонятие;
(*
 * Цель:  найти понятие в текущей области видимости, учитывая приставки отделов
 * До:    слово = Слово.название
 * Возвр: найденное понятие
 *)
ПЕР
  понД:Данные.ДкВидуПонятие;
УКАЗ
         понД:=Данные.ИскатьПонятие(Разбор.имя);
  ЕСЛИ
         понД = ПУСТО
  ТО
    Ошибка.ОтметитьИмя(Ошибка.НЕ_ОБЪЯВЛЕНО,Разбор.имя)
  АЕСЛИ
        (понД.родп В {Данные.пПер,Данные.пСсылка})  (* приёмник *)
      И                                          
        НЕ (Данные.прОбщаяПер В понД.признаки)      (* или переменная задачи *)
      И                                           
        (понД.обл # Данные.текОбласть)              (* из другой области, т.е. не из текущей *)
  ТО
    Ошибка.ОтметитьИмя(Ошибка.ПЕР_ИЗ_ДРУГОЙ_ОБЛАСТИ,Разбор.имя)
  КОН;
  ЕСЛИ понД.родп = Данные.пОтдел ТО
    БудетСлово(Слово.точка);
    БудетСлово(Слово.название);

    ЕСЛИ Данные.прТекущийОтд В понД.признаки ТО (* в своём отделе по своему *)
            понД:=Данные.ИскатьВСписке(понД.первпон,Разбор.имя);
      ЕСЛИ  понД = ПУСТО ТО
        Ошибка.ОтметитьИмя(Ошибка.НЕ_ОБЪЯВЛЕНО,Разбор.имя)
      КОН
    ИНАЧЕ
            понД:=Данные.ИскатьВСписке(понД.первпон,Разбор.имя);
      ЕСЛИ (понД = ПУСТО)
          ИЛИ (* или скрытый вид *)
           (понД.родп = Данные.пВид)
          И
           НЕ (Данные.прОбщедоступное В понД.признаки)
      ТО
        Ошибка.ОтметитьИмя(Ошибка.НЕ_ОБЪЯВЛЕНО,Разбор.имя)
      КОН
    КОН
  КОН;
  ЕСЛИ понД.родп = Данные.пОтдел ТО
    Ошибка.Отметить(Ошибка.НЕОЖИДАННЫЙ_ОТДЕЛ)
  КОН;
  ЧитатьСлово;
  ВОЗВРАТ понД
КОН НайтиПонятие;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Признаки():МНОЖ;
(*
 * Цель:  прочитать признаки доступности понятия
 * Прим:  не используется для приёмников и отделов
 *)
ПЕР
    признак:МНОЖ;
УКАЗ
  ЧитатьСлово;
  ЕСЛИ слово = Слово.плюс ТО
    признак:={Данные.прОбщедоступное};
    ЧитатьСлово
  АЕСЛИ слово = Слово.минус ТО
    признак:={Данные.прОбщедоступное,Данные.прТолькоЧт};
    ЧитатьСлово
  ИНАЧЕ
    признак:={}
  КОН;
  ВОЗВРАТ признак
КОН Признаки;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ПостВыражение(у+:Узел.нВид);
УКАЗ
  Выражение(у);
  ЕСЛИ у.роду = Узел.уКодУсл ТО
    Узел.СнятьКУ(у)
  КОН;
  ЕСЛИ у.роду # Узел.уПост ТО
    Ошибка.Отметить(Ошибка.ЭТО_НЕ_ПОСТОЯННАЯ)
  КОН
КОН ПостВыражение;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ВидНабор(вид+:Данные.ДкВидуВид);
ПЕР
  смещение:ЦЕЛ;                 (* смещение адреса свойства от начала набора *)
  размер:ЦЕЛ;                   (* размер данных набора *)
  видоб:Данные.ДкВидуВид;       (* общий вид для объединения *)
   овид:Данные.ДкВидуВид;       (* опорный вид набора и свойства *)
   понД,
   перв:Данные.ДкВидуПонятие;   (* свойство и первое свойство объединения *)
УКАЗ
  смещение:=0;
  вид:=Данные.СоздатьВид(Данные.вНабор);
  ЕСЛИ слово = Слово.лкругл ТО (* есть опорный вид *)
    БудетСлово(Слово.название);
    понД:=НайтиПонятие();
    ЕСЛИ понД.родп # Данные.пВид ТО
      Ошибка.Отметить(Ошибка.ЭТО_НЕ_ВИД)
    АЕСЛИ вид.родв # Данные.вНабор ТО
      Ошибка.Отметить(Ошибка.ЭТО_НЕ_НАБОР)
    АЕСЛИ понД.вид = Данные.нетвид ТО
      Ошибка.Отметить(Ошибка.ПЕРЕКРЁСТНЫЙ_ВИД)
    КОН;
    овид:=понД.вид;
    вид.овид:=овид;
    смещение:=овид.размер;
    ПропуститьСлово(Слово.пркругл)
  КОН;
                                                           (* свойства набора *)
  Данные.ОткрытьОбласть("НАБОР");
  КОЛЬЦО
    ЕСЛИ слово = Слово.название ТО
                                         (* объединение свойств с общим видом *)
      перв:=ПУСТО;
      КОЛЬЦО
        ТекущееСлово(Слово.название);
        ЕСЛИ вид.овид # Данные.неопрвид ТО

               понД:=Данные.ИскатьСвойство(вид,Разбор.имя);
          ЕСЛИ понД # ПУСТО ТО
            Ошибка.ОтметитьИмя(Ошибка.ПЕРЕОПРЕДЕЛЕНИЕ,Разбор.имя)
          КОН
        КОН;
               понД:=Данные.Вставить(Разбор.имя);
               понД.родп:=Данные.пСвойство;
               понД.признаки:=Признаки();
        ЕСЛИ
             (зУровень > 0)
            И
             (Данные.прОбщедоступное В понД.признаки)
        ТО
          Ошибка.Отметить(Ошибка.НЕВЕРНАЯ_ОТМЕТКА)
        КОН;

        ЕСЛИ перв = ПУСТО ТО 
          перв:=понД 
        КОН;
        ЕСЛИ слово # Слово.запятая ТО ВЫХОД КОН;

        ЧитатьСлово
      КОН;
      ПропуститьСлово(Слово.двоеточие);
      ВидСлова(видоб);
      размер:=видоб.размер;
                                              (* выравнивание адреса свойства *)
      овид:=видоб;
      ПОКА овид.родв = Данные.вРяд ВЫП
        овид:=овид.овид
      КОН;
      ЕСЛИ овид.размер >= 4 ТО
        УВЕЛИЧИТЬ(смещение,(-смещение) ОСТАТОК 4)
      АЕСЛИ овид.размер = 2 ТО
        УВЕЛИЧИТЬ(смещение,смещение ОСТАТОК 2)
      КОН;
      (* выставляем вид и адрес у объединения свойств *)
           понД:=перв;
      ПОКА понД # ПУСТО ВЫП
           понД.вид:=видоб;
           понД.адр:=смещение;
        УВЕЛИЧИТЬ(смещение,размер);
           понД:=понД.слеД
      КОН
    КОН;
    ЕСЛИ слово # Слово.точкасзап ТО ВЫХОД КОН;

    ЧитатьСлово
  КОН;
  УВЕЛИЧИТЬ(смещение,(-смещение) ОСТАТОК 4);
  вид.размер:=смещение;
  вид.первпон:=Данные.текОбласть.первпон;
  Данные.ЗакрытьОбласть;
  ПропуститьСлово(Слово.кон)
КОН ВидНабор;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ВидРяд(вид+:Данные.ДкВидуВид);
ПЕР
  у:Узел.нВид;
УКАЗ
  вид:=Данные.СоздатьВид(Данные.вРяд);

  ПостВыражение(у);

  ЕСЛИ НЕ (у.вид.родв В {Данные.вЦел16..Данные.вЦел32}) ТО
    Ошибка.Отметить(Ошибка.ПОСТОЯННАЯ_НЕ_ЦЕЛАЯ)
  АЕСЛИ у.a <= 0 ТО
    Ошибка.Отметить(Ошибка.НЕВЕРНАЯ_ПОСТОЯННАЯ)
  КОН;
  ЕСЛИ слово = Слово.из ТО
    ЧитатьСлово;
    ВидСлова(вид.овид)
  АЕСЛИ слово = Слово.запятая ТО
    ЧитатьСлово;
    ВидРяд(вид.овид)
  ИНАЧЕ
    Ошибка.Отметить(Слово.из)
  КОН;
  вид.размер:=у.a*вид.овид.размер
КОН ВидРяд;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ВидБегунок(вид+:Данные.ДкВидуВид);
ПЕР
  у:Узел.нВид;
УКАЗ
  вид:=Данные.СоздатьВид(Данные.вБегунок);
  вид.размер:=Настрой.рБегунок;
  ЕСЛИ слово # Слово.по ТО

    ПостВыражение(у);

    ЕСЛИ НЕ (у.вид.родв В {Данные.вЦел16..Данные.вЦел32}) ТО
      Ошибка.Отметить(Ошибка.ПОСТОЯННАЯ_НЕ_ЦЕЛАЯ)
    КОН;
    вид.шаг:=у.a
  ИНАЧЕ
    вид.шаг:=1
  КОН;
  ПропуститьСлово(Слово.по);
  ВидСлова(вид.овид)
КОН ВидБегунок;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ВидЗадача(вид+:Данные.ДкВидуВид);
ПЕР
  рПриёмников:ЦЕЛ;
УКАЗ
  вид:=Данные.СоздатьВид(Данные.вЗадача);
  ЕСЛИ слово = Слово.лкругл ТО

    ЧитатьСлово;

    Данные.ОткрытьОбласть("ЗАДАЧА");
    рПриёмников:=Заголовок(вид.овид);
    вид.первпон:=Данные.текОбласть.первпон;
    Данные.текОбласть.видотв:=вид.овид;
    Данные.ЗакрытьОбласть
  ИНАЧЕ
    вид.овид:=Данные.нетвид;
    вид.первпон:=ПУСТО
  КОН
КОН ВидЗадача;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ВидДоступ(вид+:Данные.ДкВидуВид);
ПЕР
       понД:Данные.ДкВидуПонятие; (* именной вид *)
  неопрВидД:ДкНеопрВиду;
УКАЗ
                 вид:=Данные.СоздатьВид(Данные.вДоступ);

  ПропуститьСлово(Слово.к);

  ЕСЛИ
          слово = Слово.название
  ТО
         понД:=Данные.ИскатьПонятие(Разбор.имя);
    ЕСЛИ
         понД = ПУСТО
    ТО                                   (* точно нет такого название *)
      вид.овид:=Данные.неопрвид;

      СОЗДАТЬ(неопрВидД);
              неопрВидД.имя:=Разбор.имя;
              неопрВидД.вид:=вид;
  
    ЧэргаСлеД.ДобавитьНовЗвеноВконСписка(неопрВиды,неопрВидД);

      ЧитатьСлово
    ИНАЧЕ                                (* может это название отдела *)
           понД:=НайтиПонятие();
      ЕСЛИ понД.родп # Данные.пВид ТО
        Ошибка.Отметить(Ошибка.ЭТО_НЕ_ВИД)
      АЕСЛИ НЕ (понД.вид.родв В {Данные.вНабор,Данные.вРяд}) ТО
        Ошибка.Отметить(Ошибка.ДОСТУП_ЗАПРЕЩЕН)
      КОН;
      вид.овид:=понД.вид
    КОН
  ИНАЧЕ
    ВидСлова(вид.овид);
    ЕСЛИ НЕ (вид.овид.родв В {Данные.вНабор,Данные.вРяд}) ТО
      Ошибка.Отметить(Ошибка.ДОСТУП_ЗАПРЕЩЕН)
    КОН
  КОН
КОН ВидДоступ;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ВидЦепь(вид+:Данные.ДкВидуВид);
ПЕР
  у:Узел.нВид;
УКАЗ
  вид:=Данные.СоздатьВидЦепь(0);
  ЕСЛИ слово = Слово.лквадр ТО

    ЧитатьСлово();

    ПостВыражение(у);
    ЕСЛИ НЕ (у.вид.родв В {Данные.вЦел16..Данные.вЦел32}) ТО
      Ошибка.Отметить(Ошибка.ПОСТОЯННАЯ_НЕ_ЦЕЛАЯ)
    АЕСЛИ у.a <= 0 ТО
      Ошибка.Отметить(Ошибка.НЕВЕРНАЯ_ПОСТОЯННАЯ)
    КОН;
    вид.размер:=у.a;
    ПропуститьСлово(Слово.прквадр)
  АЕСЛИ оЦепьРазрешена < -1 ТО
    Ошибка.Отметить(Ошибка.ОЦЕПЬ_НЕДОПУСТИМА)
  КОН
КОН ВидЦепь;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ВидСлова(вид+:Данные.ДкВидуВид);
ПЕР
  понД:Данные.ДкВидуПонятие;
УКАЗ
  УМЕНЬШИТЬ(оЦепьРазрешена);
  ВЫБРАТЬ слово ИЗ
  | Слово.название: (* имя другого вида *)
            понД:=НайтиПонятие();
      ЕСЛИ  понД.родп # Данные.пВид ТО
        Ошибка.Отметить(Ошибка.ЭТО_НЕ_ВИД)
      АЕСЛИ понД.вид = Данные.нетвид ТО
        Ошибка.Отметить(Ошибка.НЕ_ОБЪЯВЛЕНО)
      АЕСЛИ понД.вид = Данные.оячейкивид ТО
        ЕСЛИ оЦепьРазрешена < -1 ТО
          Ошибка.Отметить(Ошибка.ОЦЕПЬ_НЕДОПУСТИМА)
        КОН
      КОН;
      вид:=понД.вид
  | Слово.ряд:    ЧитатьСлово; ВидРяд(вид)
  | Слово.цепь:   ЧитатьСлово; ВидЦепь(вид)
  | Слово.набор:  ЧитатьСлово; ВидНабор(вид)
  | Слово.доступ: ЧитатьСлово; ВидДоступ(вид)
  | Слово.задача: ЧитатьСлово; ВидЗадача(вид)
  | Слово.бегунок:ЧитатьСлово; ВидБегунок(вид)
  ИНАЧЕ
    Ошибка.Отметить(Ошибка.НЕВЕРНОЕ_НАЧАЛО_ВИДА)
  КОН;
  УВЕЛИЧИТЬ(оЦепьРазрешена)
КОН ВидСлова;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Заголовок(видОтвета+:Данные.ДкВидуВид):ЦЕЛ;
(*
 * Цель:  приёмники в объявлении задачи
 * После: <видОтвета>                 - вид ответа задачи
 *        <Данные.текОбласть.первпон> - список приёмников у которых:
 *        <.адр>                      - смещение приёмника от FP
 * Возвр: общий размер всех приёмников
 *)
ПЕР
  рПриёмников:ЦЕЛ;               (* общий размер всех прёмников            *)
  ответ:Данные.ДкВидуПонятие;    (* для вида ответа                        *)
  видоб:Данные.ДкВидуВид;        (* общий вид для объединения              *)
   понД,
   перв:Данные.ДкВидуПонятие;    (* приёмник и первый приёмник объединения *)
 (*
      пример расположения в памяти 2-х приёмников (рПриёмников = 8):
------------------------------------------------------------------
память   | FP'  LR   пр2   пр1
         |----------------------
адр до   |             8     4
адр после| (0)  (4)    8    12 *)

(* пример со 2-м приёмником оЦепь (рПриёмников = 12):
память   | FP'  LR   пр2    р2   пр1  
         |----------------------------
адр до   |            12    (8)    4 
адр после| (0)  (4)    8   (12)   16
  *)
УКАЗ
  рПриёмников:=0;
  ЕСЛИ слово = Слово.название ТО
    КОЛЬЦО
      перв:=ПУСТО;
      КОЛЬЦО
        ТекущееСлово(Слово.название);
        понД:=Данные.Вставить(Разбор.имя);
        ЧитатьСлово;
        ЕСЛИ (слово = Слово.плюс) ИЛИ (слово = Слово.минус) ТО
            понД.родп:=Данные.пСсылка;
          ЕСЛИ слово = Слово.минус ТО
            понД.признаки:={Данные.прТолькоЧт}
          КОН;
          ЧитатьСлово
        ИНАЧЕ
            понД.родп:=Данные.пПер
        КОН;
        ЕСЛИ перв = ПУСТО ТО 
          перв:=понД 
        КОН;
        ЕСЛИ слово # Слово.запятая ТО ВЫХОД КОН;

        ЧитатьСлово
      КОН;
      ПропуститьСлово(Слово.двоеточие);
      ВидСлова(видоб);

      (* привязываем вид и адр к приёмникам объединения *)

           понД:=перв;
      ПОКА понД # ПУСТО ВЫП
        (* неизменяемые приёмники простых видов будут приёмниками значений *)
        ЕСЛИ
             (НЕ (видоб.родв В {Данные.вРяд,Данные.вЦепь,Данные.вЯчейки,Данные.вНабор}))
            И
             (понД.родп = Данные.пСсылка)
            И
             (Данные.прТолькоЧт В понД.признаки)
        ТО
          понД.родп:=Данные.пПер
        КОН;

        (* приёмник значений не может иметь сложный вид *)

        ЕСЛИ
             (видоб.родв В {Данные.вРяд,Данные.вЦепь,Данные.вНабор})
            И
             (понД.родп = Данные.пПер)
        ТО
          Ошибка.Отметить(Ошибка.ПРИЁМНИК_СОСТ_ВИДА)
        КОН;
        понД.вид:=видоб;
                             (* кажый приёмник сейчас занимает 4 ячейки стека *)
        УВЕЛИЧИТЬ(рПриёмников,4);
                                   (* размер для оЦепь *)
        ЕСЛИ
             (видоб.родв = Данные.вЦепь)
            И
             (видоб.размер = 0)
        ТО                                    (* оЦепь *)
          УВЕЛИЧИТЬ(рПриёмников,4)
        КОН;
                             (* заготовка для смещения *)
        понД.адр:=рПриёмников;
        понД:=понД.слеД
      КОН;
      ЕСЛИ слово # Слово.точкасзап ТО ВЫХОД КОН;

      ЧитатьСлово
    КОН
  КОН;
  ПропуститьСлово(Слово.пркругл);
                                             (* вид ответа *)
  ЕСЛИ слово = Слово.двоеточие ТО
    БудетСлово(Слово.название);
    ответ:=НайтиПонятие();
    ЕСЛИ ответ.родп # Данные.пВид ТО
      Ошибка.Отметить(Ошибка.ЭТО_НЕ_ВИД)
    АЕСЛИ ответ.вид.родв >= Данные.вРяд ТО
      Ошибка.Отметить(Ошибка.СЛОЖНЫЙ_ОТВЕТ)
    КОН;
    видОтвета:=ответ.вид
  ИНАЧЕ
    видОтвета:=Данные.нетвид
  КОН;
                                            (* смещения всех приёмников от FP *)
       понД:=Данные.текОбласть.первпон;
  ПОКА
       понД # ПУСТО
  ВЫП
       понД.адр:=8+рПриёмников-понД.адр;          (* 8 это место для FP' и LR *)
       понД:=понД.слеД
  КОН;
  ВОЗВРАТ рПриёмников
КОН Заголовок;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Переключатель(уа+:Узел.нВид);
ПЕР
  понД:Данные.ДкВидуПонятие; 
    уб:Узел.нВид;
УКАЗ
  КОЛЬЦО
    ЕСЛИ слово = Слово.лквадр ТО
      ЧитатьСлово;
      КОЛЬЦО
        ЕСЛИ уа.роду В {Узел.уПост,Узел.уВид..Узел.уВстрЗадача} ТО
          Ошибка.Отметить(Ошибка.ЭТО_НЕ_ПЕРЕМЕННАЯ);
        КОН;
        ЕСЛИ (уа.вид # ПУСТО) И (уа.вид.родв = Данные.вДоступ) ТО
          Узел.Ссылка(уа)
        КОН;
        Выражение(уб);
        Узел.АдрПерРяда(уа,уб);
        ЕСЛИ слово # Слово.запятая ТО ВЫХОД КОН;
        ЧитатьСлово
      КОН;
      ПропуститьСлово(Слово.прквадр)
    АЕСЛИ слово = Слово.точка ТО
      БудетСлово(Слово.название);
      ЕСЛИ уа.вид = ПУСТО ТО
        Ошибка.Отметить(Ошибка.ЭТО_НЕ_ВИД)
      КОН;
      ЕСЛИ уа.вид.родв = Данные.вДоступ ТО
        Узел.Ссылка(уа)
      КОН;
      ЕСЛИ уа.вид.родв # Данные.вНабор ТО
        Ошибка.Отметить(Ошибка.ЭТО_НЕ_НАБОР)
      КОН;
      понД:=Данные.ИскатьСвойство(уа.вид,Разбор.имя);
      ЕСЛИ понД = ПУСТО ТО
        Ошибка.Отметить(Ошибка.НЕТ_СВОЙСТВА)
      КОН;
      Узел.Свойство(уа,понД); 
      ЧитатьСлово
    АЕСЛИ слово = Слово.стрелка ТО
      ЧитатьСлово;
      Узел.Ссылка(уа)
    АЕСЛИ
          (слово = Слово.лкругл)
        И
          (НЕ (уа.роду В {Узел.уВид,Узел.уПост,Узел.уЗадача,Узел.уВстрЗадача}))
        И
          (уа.вид.родв # Данные.вЗадача)
    ТО                                                  (* охрана вида *)
      БудетСлово(Слово.название);

           понД:=НайтиПонятие();
      ЕСЛИ
           понД.родп # Данные.пВид
      ТО
        Ошибка.Отметить(Ошибка.ЭТО_НЕ_ВИД)
      КОН;
      ЕСЛИ уа.вид.родв = Данные.вДоступ ТО
        ЕСЛИ уа.вид.овид.родв # Данные.вНабор ТО
          Ошибка.Отметить(Ошибка.ЭТО_НЕ_РАСШИРЕНИЕ)
        АЕСЛИ понД.вид.родв # Данные.вДоступ ТО
          Ошибка.Отметить(Ошибка.ОХРАНА_НЕ_У_ДОСТУПА)
        КОН;
        ВКод.РасширенОт(понД.вид.овид,уа.вид.овид)
      АЕСЛИ (уа.вид.родв = Данные.вНабор) И (уа.понД.родп = Данные.пСсылка)
          И (понД.вид.родв = Данные.вНабор) ТО
        ВКод.РасширенОт(понД.вид,уа.вид)
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.ОХРАНА_НЕВОЗМОЖНА)
      КОН;
      уа.вид:=понД.вид;
      ПропуститьСлово(Слово.пркругл)
    ИНАЧЕ
      ВЫХОД
    КОН
  КОН
КОН Переключатель;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Источники(приёмник:Данные.ДкВидуПонятие);
                                          (* вычисление и передача источников *)
ПЕР
  источник:Узел.нВид; 
УКАЗ
  ЕСЛИ слово # Слово.пркругл ТО
    КОЛЬЦО
      ЕСЛИ НЕ Данные.ЭтоПриёмник(приёмник) ТО
        Ошибка.Отметить(Ошибка.МНОГО_ИСТОЧНИКОВ)
      КОН;
      Выражение(источник);
      ВКод.Передать(источник,приёмник);
      Узел.Освободить(источник); 
      приёмник:=приёмник.слеД;
      ЕСЛИ слово # Слово.запятая ТО ВЫХОД КОН;

      ЧитатьСлово
    КОН
  КОН;
  ПропуститьСлово(Слово.пркругл);
  ЕСЛИ Данные.ЭтоПриёмник(приёмник) ТО
    Ошибка.Отметить(Ошибка.МАЛО_ИСТОЧНИКОВ)
  КОН
КОН Источники;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ВызовВстрЗадачи(у0+:Узел.нВид);
ПЕР
  у1,у2:Узел.нВид;
  задача,приёмников:ЦЕЛ;
УКАЗ
  задача:=у0.понД.адр;
  приёмников:=0;
  ПропуститьСлово(Слово.лкругл);
  КОЛЬЦО
    ВЫБРАТЬ приёмников ИЗ
    | 0: Выражение(у0); Узел.ВстрПриёмник0(задача,у0)
    | 1: Выражение(у1); Узел.ВстрПриёмник1(задача,у0,у1)
    | 2: Выражение(у2); Узел.ВстрПриёмник2(задача,у0,у1,у2)
    ИНАЧЕ
      Ошибка.Отметить(Ошибка.МНОГО_ИСТОЧНИКОВ)
    КОН;
    УВЕЛИЧИТЬ(приёмников);
    ЕСЛИ слово # Слово.запятая ТО ВЫХОД КОН;
    ЧитатьСлово
  КОН;
  Узел.ВстрПриёмникN(задача,приёмников,у0,у1,у2);
  ПропуститьСлово(Слово.пркругл)
КОН ВызовВстрЗадачи;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Элемент(у+:Узел.нВид);
ПЕР
  у1,у2:Узел.нВид;
УКАЗ
  Выражение(у1);
  ЕСЛИ слово = Слово.дветочки ТО
    ЧитатьСлово;
    Выражение(у2);
    Узел.ВнестиНеск(у,у1,у2)
  ИНАЧЕ
    Узел.Внести1(у,у1)
  КОН 
КОН Элемент;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Множество(x+:Узел.нВид);
ПЕР
  y:Узел.нВид;
УКАЗ
  x.вид:=Данные.множвид; 
  y.вид:=Данные.множвид;
  ЕСЛИ слово # Слово.прфигурн ТО
    Элемент(x);
    ПОКА слово = Слово.запятая ВЫП
      ЧитатьСлово;
      Элемент(y);
      Узел.Действие(Слово.плюс,x,y)
    КОН
  ИНАЧЕ (* {} *)
    x.роду:=Узел.уПост;
    x.a:=0
  КОН;
  ПропуститьСлово(Слово.прфигурн)
КОН Множество;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Множитель(у+:Узел.нВид);
ПЕР
  сохрРеги:МНОЖ;
       понД:Данные.ДкВидуПонятие;
УКАЗ
  ВЫБРАТЬ слово ИЗ
  | Слово.название:
      Узел.Создать(НайтиПонятие(),у);
      Переключатель(у);
      ЕСЛИ у.роду = Узел.уВстрЗадача ТО
        ВызовВстрЗадачи(у)
      АЕСЛИ слово = Слово.лкругл ТО
        ЧитатьСлово;
        сохрРеги:=ВКод.СохранитьРеги();
        ЕСЛИ у.роду = Узел.уЗадача ТО
          Источники(у.понД.первпон);
        АЕСЛИ (у.вид # ПУСТО) И (у.вид.родв = Данные.вЗадача) ТО
          Источники(у.вид.первпон);
        ИНАЧЕ
          Ошибка.Отметить(Ошибка.ЭТО_НЕ_ЗАДАЧА)
        КОН;
        ВКод.Вызов(у);
        ВКод.ПолучитьОтвет(сохрРеги,у)
      КОН
  | Слово.знак:
      у.роду:=Узел.уПост;
      у.a:=Разбор.целЗнач;
      у.вид:=Данные.знаквид;
      ЧитатьСлово
  | Слово.целпост:
      у.роду:=Узел.уПост;
      у.a:=Разбор.целЗнач;
      Узел.ОпредЦелВид(у);
      ЧитатьСлово
  | Слово.цепьпост:
      понД:=Данные.СоздатьПостЦепь(Разбор.цепьЗнач);
      Узел.Создать(понД,у);
      ЧитатьСлово
  | Слово.пусто:
      у.роду:=Узел.уПост;
      у.вид:=Данные.пустовид;
      у.a:=0;
      ЧитатьСлово
  | Слово.лкругл:
      ЧитатьСлово;
      Выражение(у);
      ПропуститьСлово(Слово.пркругл)
  | Слово.лфигурн:
      ЧитатьСлово;
      Множество(у)
  | Слово.не:
      ЧитатьСлово;
      Множитель(у);
      Узел.Действие1(Слово.не,у)
  ИНАЧЕ
    Ошибка.Отметить(Ошибка.НЕВЕРНОЕ_НАЧАЛО_МНОЖИТЕЛЯ)
  КОН
КОН Множитель;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Слагаемое(уа+:Узел.нВид);
ПЕР
  уб:Узел.нВид; 
  действие:ЦЕЛ;
УКАЗ
  Множитель(уа);
  ПОКА (Слово.умножить <= слово) И (слово <= Слово.и) ВЫП
    действие:=слово;
    ЕСЛИ действие = Слово.и ТО
      Узел.Действие1(Слово.и,уа)
    КОН;
    ЧитатьСлово;
    Множитель(уб);
    Узел.Действие(действие,уа,уб)
  КОН
КОН Слагаемое;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ПростоеВыражение(уа+:Узел.нВид);
ПЕР
  уб:Узел.нВид;
  действие:ЦЕЛ;
УКАЗ
  ЕСЛИ (слово = Слово.минус) ИЛИ (слово = Слово.плюс) ТО
    действие:=слово;
    ЧитатьСлово;
    Слагаемое(уа);
    Узел.Действие1(действие,уа)
  ИНАЧЕ
    Слагаемое(уа)
  КОН;
  ПОКА (Слово.плюс <= слово) И (слово <= Слово.или) ВЫП
    действие:=слово;
    ЕСЛИ действие = Слово.или ТО
      Узел.Действие1(Слово.или,уа)
    КОН;
    ЧитатьСлово;
    Слагаемое(уб);
    Узел.Действие(действие,уа,уб)
  КОН
КОН ПростоеВыражение;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Выражение(уа+:Узел.нВид);
ПЕР
  уб:Узел.нВид;
  действие:ЦЕЛ;
УКАЗ
  ПростоеВыражение(уа);
  ЕСЛИ (Слово.равно <= слово) И (слово <= Слово.бравно) ТО
    действие:=слово;
    ЕСЛИ уа.вид.родв = Данные.вКлюч ТО
      Узел.Действие1(действие,уа)
    КОН;
    ЧитатьСлово;
    ПростоеВыражение(уб);
    Узел.Действие(действие,уа,уб)
  АЕСЛИ слово = Слово.в ТО
    ЧитатьСлово;
    ПростоеВыражение(уб);
    Узел.ВМнож(уа,уб)
  КОН
КОН Выражение;

(*----------------------------------------------------------------------------*)
ЗАДАЧА ОбъявлениеЗадачи;
ПЕР
      понД,
     зпонД:Данные.ДкВидуПонятие;
       имя:Настрой.Имя;
  признаки:МНОЖ;
  объявлениеЗаготовки:КЛЮЧ;
  былРазмерПриёмников,
          рПриёмников:ЦЕЛ;
УКАЗ
          рПриёмников:=0;
   понД:=ПУСТО;
  зпонД:=ПУСТО;
  объявлениеЗаготовки:=ОТКЛ;
  ЕСЛИ слово = Слово.стрелка ТО
    ЧитатьСлово;
    объявлениеЗаготовки:=ВКЛ
  КОН;
  ТекущееСлово(Слово.название);
  имя:=Разбор.имя;
  признаки:=Признаки();
  ЕСЛИ Данные.прОбщедоступное В признаки ТО
    ЕСЛИ (зУровень > 0) ИЛИ НЕ (Данные.прТолькоЧт В признаки) ТО
      Ошибка.Отметить(Ошибка.НЕВЕРНАЯ_ОТМЕТКА)
    КОН
  КОН;
        зпонД:=Данные.ИскатьПонятие(имя);
  ЕСЛИ
       (зпонД # ПУСТО) И (зпонД.обл # Данные.текОбласть)
  ТО
        зпонД:=ПУСТО
  КОН;
  ЕСЛИ 
        зпонД # ПУСТО
  ТО
    ЕСЛИ
         (зпонД.родп # Данные.пЗадача)
        ИЛИ
         (Данные.прОпрЗадача В зпонД.признаки)
    ТО
      Ошибка.ОтметитьИмя(Ошибка.ПЕРЕОПРЕДЕЛЕНИЕ,зпонД.имя)
    АЕСЛИ зпонД.признаки # признаки ТО
      Ошибка.Отметить(Ошибка.МЕТКА_НЕ_СОВПАДАЕТ)
    КОН;
    понД:=Данные.СоздатьПонятие()
  ИНАЧЕ
    понД:=Данные.Вставить(имя)
  КОН;
  понД.родп:=Данные.пЗадача;
  понД.вид:=Данные.нетвид;
  понД.признаки:=признаки;
  Данные.ОткрытьОбласть(имя);

  ЕСЛИ слово = Слово.лкругл ТО (* есть приёмники *)
    ЧитатьСлово;
    рПриёмников:=Заголовок(понД.вид)
  КОН;
  понД.первпон:=Данные.текОбласть.первпон;
  Данные.текОбласть.видотв:=понД.вид;

  ЕСЛИ зпонД # ПУСТО ТО
    (* проверяем соответствие приёмников заготовки *)
    ВКод.СравнитьПриёмники(понД.первпон,зпонД.первпон);
    ЕСЛИ понД.вид # зпонД.вид ТО
      Ошибка.Отметить(Ошибка.НЕВЕРНАЯ_ЗАГОТОВКА)
    КОН;
    понД:=зпонД
  КОН;

  ПропуститьСлово(Слово.точкасзап);

  ЕСЛИ НЕ объявлениеЗаготовки ТО
    понД.признаки:=понД.признаки+{Данные.прОпрЗадача};
    ЕСЛИ слово = Слово.код ТО                           (* задача вставка *)
      Код.ПоставитьИмя(понД);
      Обмен.НачалоВставки;
      ПОВТОРЯТЬ ДО СледующееСлово() = Слово.кон;
      Обмен.КонецВставки;
      БудетСлово(Слово.название);
      ЕСЛИ Разбор.имя # имя ТО
        Ошибка.Отметить(Ошибка.НЕСОВПАДЕНИЕ_ИМЕНИ)
      КОН;
      ЧитатьСлово;
      ПропуститьСлово(Слово.точкасзап)
    ИНАЧЕ
      былРазмерПриёмников:=размерПриёмников;
      размерПриёмников:=рПриёмников; 
      УВЕЛИЧИТЬ(зУровень);
      Объявления(понД,имя);
      УМЕНЬШИТЬ(зУровень);
      размерПриёмников:=былРазмерПриёмников
    КОН
  КОН;
  Данные.ЗакрытьОбласть
КОН ОбъявлениеЗадачи;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Указания;
ПЕР
  естьДопПер:КЛЮЧ;
  приёмники:Данные.ДкВидуПонятие;
  уа,
  уб,
  ув,
  уг:Узел.нВид;

  мИначе,
  мКон,
  мПока,
  мКольцо,
  мПовторять:ЦЕЛ;  (* метки *)
УКАЗ
  КОЛЬЦО
    ВЫБРАТЬ слово ИЗ
    | Слово.название:
        Узел.Создать(НайтиПонятие(),уа);
        Переключатель(уа);
        ЕСЛИ слово = Слово.присвоить ТО
          ЧитатьСлово;
          ЕСЛИ (уа.вид.родв = Данные.вЦепь) И (уа.вид.размер = 0) ТО (* оЦепь *)
            Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
          КОН;
          Выражение(уб);
          ВКод.Присвоить(уа,уб)
        АЕСЛИ уа.роду = Узел.уВстрЗадача ТО
          ВызовВстрЗадачи(уа);
          ЕСЛИ уа.вид.родв # Данные.вНет ТО
            Ошибка.Отметить(Ошибка.ОТВЕТ_НЕ_ИСПОЛЬЗОВАН)
          КОН
        ИНАЧЕ
          ЕСЛИ уа.роду = Узел.уЗадача ТО
            приёмники:=уа.понД.первпон
          АЕСЛИ (уа.вид # ПУСТО) И (уа.вид.родв = Данные.вЗадача) ТО
            приёмники:=уа.вид.первпон
          ИНАЧЕ
            Ошибка.Отметить(Ошибка.ЭТО_НЕ_ЗАДАЧА)
          КОН;
          ЕСЛИ слово = Слово.лкругл ТО
            ЧитатьСлово;
            Источники(приёмники)
          АЕСЛИ Данные.ЭтоПриёмник(приёмники) ТО
            Ошибка.Отметить(Ошибка.МАЛО_ИСТОЧНИКОВ)
          КОН;
          ВКод.Вызов(уа);
          ЕСЛИ уа.вид.родв # Данные.вНет ТО
            Ошибка.Отметить(Ошибка.ОТВЕТ_НЕ_ИСПОЛЬЗОВАН)
          КОН
        КОН
    | Слово.если:
        ЧитатьСлово;
        Выражение(уа);
        мИначе:=Узел.ПереходПоОтклНа(уа);
        (* ВКЛ - сюда *)
        Рег.БудутЗаняты({});
        ПропуститьСлово(Слово.то);
        Указания;
        мКон:=Код.ПолучитьМетку(); (* конец у ЕСЛИ *)
        ПОКА слово = Слово.аесли ВЫП
          ЧитатьСлово;
          Код.ПереходНа(мКон); (* конец пред. указаний *)
          Код.СбросПост;
Код.ПоставитьМетку(мИначе);
          Выражение(уа);
          мИначе:=Узел.ПереходПоОтклНа(уа);
          (* ВКЛ - сюда *)
          Рег.БудутЗаняты({});
          ПропуститьСлово(Слово.то);
          Указания
        КОН;
        ЕСЛИ слово = Слово.иначе ТО
          ЧитатьСлово;
          Код.ПереходНа(мКон); (* конец пред. указаний *)
          Код.СбросПост;
Код.ПоставитьМетку(мИначе);
          Указания
        ИНАЧЕ
Код.ПоставитьМетку(мИначе)
        КОН;
Код.ПоставитьМетку(мКон);
        ПропуститьСлово(Слово.кон)
    | Слово.пока:
        ЧитатьСлово;
        мПока:=Код.ПолучитьМетку();
Код.ПоставитьМетку(мПока);
        Выражение(уа);
        мКон:=Узел.ПереходПоОтклНа(уа);
        (* ВКЛ - сюда *)
        Рег.БудутЗаняты({});
        ПропуститьСлово(Слово.вып);
        Указания;
        Код.ПереходНа(мПока);
Код.ПоставитьМетку(мКон);
        ПропуститьСлово(Слово.кон)
    | Слово.повторять:
        ЧитатьСлово;
        мПовторять:=Код.ПолучитьМетку();
Код.ПоставитьМетку(мПовторять);
        Указания;
        ПропуститьСлово(Слово.до);
        Выражение(уа);
        Узел.ПовторятьДо(уа,мПовторять)
    | Слово.от:
        ЧитатьСлово;
        ТекущееСлово(Слово.название);
        Узел.Создать(НайтиПонятие(),уа);
        Переключатель(уа);
        ЕСЛИ уа.роду В {Узел.уПост,Узел.уВид..Узел.уВстрЗадача} ТО
          Ошибка.Отметить(Ошибка.ЭТО_НЕ_ПЕРЕМЕННАЯ)
        АЕСЛИ НЕ (уа.вид.родв В {Данные.вЦел16,Данные.вЦел32}) ТО
          Ошибка.Отметить(Ошибка.УПР_НЕ_ЦЕЛАЯ)
        АЕСЛИ уа.толькочт ТО
          Ошибка.Отметить(Ошибка.ПЕР_ДЛЯ_ЧТЕНИЯ)
        КОН;
        уг:=уа;
        ПропуститьСлово(Слово.присвоить); 
        Выражение(уб);
        ВКод.Присвоить(уа,уб); 
        ПропуститьСлово(Слово.до); 
        Выражение(уб);
        ЕСЛИ НЕ  (уа.вид.родв В {Данные.вЦел16,Данные.вЦел32})
             ИЛИ (уб.вид.родв > уа.вид.родв) ТО
          Ошибка.Отметить(Ошибка.НЕСОВМЕСТИМОЕ_ПРИСВАИВАНИЕ)
        КОН;
        ЕСЛИ уб.роду # Узел.уПост ТО (* нужна дополнительная переменная *)
          ВКод.ВДопПер(уб);
          УВЕЛИЧИТЬ(кДопПер[кУровень]);
          естьДопПер:=ВКЛ
        ИНАЧЕ
          естьДопПер:=ОТКЛ
        КОН;
        ЕСЛИ слово = Слово.по ТО
          ЧитатьСлово;
          ПостВыражение(ув);
          ЕСЛИ НЕ (ув.вид.родв В {Данные.вЦел16,Данные.вЦел32}) ИЛИ (ув.a = 0) ТО
            Ошибка.Отметить(Ошибка.НЕВЕРНАЯ_ПОСТОЯННАЯ)
          КОН
        ИНАЧЕ
          Узел.СоздатьЦелПост(ув,1)
        КОН;
        ув.вид:=уа.вид;
        мПока:=Код.ПолучитьМетку();
Код.ПоставитьМетку(мПока);
        уа:=уг;
        ЕСЛИ ув.a > 0 ТО
          Узел.Действие(Слово.мравно,уа,уб)
        АЕСЛИ ув.a < 0 ТО
          Узел.Действие(Слово.бравно,уа,уб)
        КОН;
        мКон:=Узел.ПереходПоОтклНа(уа);
        (* ВКЛ - сюда *)
        ПропуститьСлово(Слово.вып);
        Указания;
        ПропуститьСлово(Слово.кон);
        уа:=уг;
        Узел.Увеличить(уа,ув);
        Код.ПереходНа(мПока);
Код.ПоставитьМетку(мКон);
        ЕСЛИ естьДопПер ТО
          ВКод.УбратьДопПер(1);
          УМЕНЬШИТЬ(кДопПер[кУровень])
        КОН
    | Слово.кольцо:
        ЧитатьСлово;
        УВЕЛИЧИТЬ(кУровень);
        ЕСЛИ кУровень >= кУровней ТО
          Ошибка.Отметить(Ошибка.МНОГО_ВЛОЖЕНИЙ_КОЛЬЦО)
        КОН;
        мКольцо:=Код.ПолучитьМетку();
Код.ПоставитьМетку(мКольцо);
        кВыходы[кУровень]:=Код.ПолучитьМетку();
        кДопПер[кУровень]:=0;
        Указания;
        ПропуститьСлово(Слово.кон);
        Код.ПереходНа(мКольцо);
Код.ПоставитьМетку(кВыходы[кУровень]);
        УМЕНЬШИТЬ(кУровень)
    | Слово.выход:
        ЧитатьСлово;
        ЕСЛИ кУровень = 0 ТО
          Ошибка.Отметить(Ошибка.ВЫХОД_ВНЕ_КОЛЬЦА)
        КОН;
        ВКод.УбратьДопПер(кДопПер[кУровень]);
        Код.ПереходНа(кВыходы[кУровень])
    | Слово.возврат:
        ЧитатьСлово;
        ЕСЛИ слово < Слово.точкасзап ТО
          Выражение(уа);
          ВКод.Ответ(уа,Данные.текОбласть.видотв)
        АЕСЛИ Данные.текОбласть.видотв.родв # Данные.вНет ТО
          Ошибка.Отметить(Ошибка.ПРИСВАИВАНИЕ_ОТВЕТУ)
        КОН;
        ВКод.Возврат(размерПриёмников)
    ИНАЧЕ
    КОН;
    Рег.БудутЗаняты({});
    ЕСЛИ (слово >= Слово.черта) И (слово <= Слово.до) ТО ВЫХОД КОН;
    ПропуститьСлово(Слово.точкасзап)
  КОН
КОН Указания;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Объявления(  задача:Данные.ДкВидуПонятие;
                   конИмя-:Настрой.Имя
                 );
ПЕР
    вид,
    видоб:Данные.ДкВидуВид;
     понД,
     перв:Данные.ДкВидуПонятие;
        у:Узел.нВид;
   размер:ЦЕЛ;
      имя:Настрой.Имя;
   признаки:МНОЖ;
   неопрВидД:ДкНеопрВиду;
   звеноД:ЧэргаСлеД.ДкЗвену_телоД;
  рДанных:ЦЕЛ; 
УКАЗ
  рДанных:=0;

  ЧэргаСлеД.ОчиститьСписок(неопрВиды);
  КОЛЬЦО
    ВЫБРАТЬ слово ИЗ
    | Слово.пост:
        ПОКА СледующееСлово() = Слово.название ВЫП
          имя:=Разбор.имя;
          признаки:=Признаки();
          ЕСЛИ Данные.прОбщедоступное В признаки ТО
            ЕСЛИ (зУровень > 0) ИЛИ НЕ (Данные.прТолькоЧт В признаки) ТО
              Ошибка.Отметить(Ошибка.НЕВЕРНАЯ_ОТМЕТКА)
            КОН
          КОН;
          ПропуститьСлово(Слово.равно);
          ПостВыражение(у);
          понД:=Данные.Вставить(имя);
          понД.родп:=Данные.пПост;
          понД.признаки:=признаки;
          понД.вид:=у.вид;
          понД.адр:=у.a;
          ЕСЛИ
               у.понД # ПУСТО
          ТО                         (* т.к. узел пропадает, сохраним цепочку *)
            понД.цепьД:=у.понД.цепьД
          КОН;
          ТекущееСлово(Слово.точкасзап)
        КОН
    | Слово.вид:
        ПОКА СледующееСлово() = Слово.название ВЫП
          понД:=Данные.Вставить(Разбор.имя);
          понД.родп:=Данные.пВид;
          понД.вид:=Данные.нетвид;
          признаки:=Признаки();
          ЕСЛИ Данные.прОбщедоступное В признаки ТО
            ЕСЛИ (зУровень > 0) ИЛИ НЕ (Данные.прТолькоЧт В признаки) ТО
              Ошибка.Отметить(Ошибка.НЕВЕРНАЯ_ОТМЕТКА)
            КОН
          КОН;
          понД.признаки:=признаки;
          ПропуститьСлово(Слово.равно);
          ВидСлова(вид);
          понД.вид:=вид;
          ЕСЛИ
               вид.понвида = ПУСТО
          ТО
               вид.понвида:=понД
          КОН;
          ЕСЛИ вид.родв В {Данные.вНабор,Данные.вРяд} ТО

            (* доопределяем неопределённые ранее доступы *)
(*
   Обход списка с 1-го звена до N-го, т.е. пока звеноД.слеД # ПУСТО
 *)
                         звеноД:=ЧэргаСлеД.Дк1муЗвену(неопрВиды);
            ПОКА
                         звеноД # ПУСТО
            ВЫП
              неопрВидД:=звеноД.телоД(ДкНеопрВиду);
              ЕСЛИ
                   неопрВидД.имя = понД.имя
              ТО
                   неопрВидД.вид.овид:=вид
              КОН;
                         звеноД:=звеноД.слеД
            КОН
          КОН;
          ТекущееСлово(Слово.точкасзап)
        КОН
    | Слово.пер:
        ПОКА СледующееСлово() = Слово.название ВЫП
          перв:=ПУСТО;
          КОЛЬЦО
            ТекущееСлово(Слово.название);
            понД:=Данные.Вставить(Разбор.имя);
            понД.признаки:=Признаки();
            ЕСЛИ (зУровень > 0) И (Данные.прОбщедоступное В понД.признаки) ТО
              Ошибка.Отметить(Ошибка.НЕВЕРНАЯ_ОТМЕТКА)
            КОН;
            понД.родп:=Данные.пПер;
            понД.вид:=Данные.неопрвид;
            ЕСЛИ перв = ПУСТО ТО 
              перв:=понД 
            КОН;
            ЕСЛИ слово # Слово.запятая ТО ВЫХОД КОН;
            ЧитатьСлово
          КОН;
          ПропуститьСлово(Слово.двоеточие);
          ВидСлова(видоб);
          понД:=перв;
          ПОКА понД # ПУСТО ВЫП
            понД.вид:=видоб;
            размер:=видоб.размер;
            ЕСЛИ размер = 0 ТО
              Ошибка.Отметить(Ошибка.ОЦЕПЬ_НЕДОПУСТИМА)
            КОН;
            ЕСЛИ зУровень = 0 ТО
              понД.признаки:=понД.признаки+{Данные.прОбщаяПер,Данные.прТекущийОтд};
              Код.ПоставитьПер(понД)
            ИНАЧЕ
              (* выравнивание *)
              УВЕЛИЧИТЬ(рДанных,размер);
              ЕСЛИ размер = 2 ТО
                УВЕЛИЧИТЬ(рДанных,рДанных ОСТАТОК 2)
              АЕСЛИ размер >= 4 ТО
                УВЕЛИЧИТЬ(размер,(-размер) ОСТАТОК 4);
                УВЕЛИЧИТЬ(рДанных,(-рДанных) ОСТАТОК 4)
              КОН;
              понД.адр:=-рДанных
            КОН;
            понД:=понД.слеД
          КОН;
          ТекущееСлово(Слово.точкасзап)
        КОН
    ИНАЧЕ
      ВЫХОД
    КОН 
  КОН;
  ЕСЛИ зУровень > 0 ТО
    УВЕЛИЧИТЬ(рДанных,(-рДанных) ОСТАТОК 4)
  КОН;
                           (* проверяем нет ли больше неопределённых доступов *)
(*
   Обход списка с 1-го звена до N-го, т.е. пока звеноД.слеД # ПУСТО
 *)
               звеноД:=ЧэргаСлеД.Дк1муЗвену(неопрВиды);
  ПОКА
               звеноД # ПУСТО
  ВЫП
    неопрВидД:=звеноД.телоД(ДкНеопрВиду);

    ЕСЛИ
         неопрВидД.вид.овид = Данные.неопрвид
    ТО
      Ошибка.ОтметитьИмя(Ошибка.НЕСУЩЕСТВУЮЩИЙ_ВИД,неопрВидД.имя)
    КОН;
               звеноД:=звеноД.слеД
  КОН;

  ЧэргаСлеД.ОчиститьСписок(неопрВиды);
                                              (* начало кода отдела *)
  ЕСЛИ зУровень = 0 ТО
    Код.Начало
  КОН;

  (* свои задачи *)
  ПОКА слово = Слово.задача ВЫП
    ЧитатьСлово;
    ОбъявлениеЗадачи
  КОН;
  (* начало кода задачи *)
  Код.ПоставитьИмя(задача);
  ВКод.Вход(рДанных);
  ЕСЛИ (зУровень = 0) И (Настрой.отдВид = Настрой.приложение) ТО
    Код.ЗапускПриложения
  КОН;
  ЕСЛИ слово = Слово.указ ТО
    ЧитатьСлово;
    Указания
  АЕСЛИ слово # Слово.кон ТО
    Ошибка.Отметить(Ошибка.ОЖИДАЕТСЯ_ЗАДАЧА_УКАЗ_КОН)
  КОН;
  (* конец кода задачи *)

  ЕСЛИ (зУровень = 0) И (Настрой.отдВид = Настрой.приложение) ТО
    Код.ОстановПриложения
  КОН;
  ВКод.Возврат(размерПриёмников);
  Код.СбросПост;
  ПропуститьСлово(Слово.кон);
  ТекущееСлово(Слово.название);
  ЕСЛИ Разбор.имя # конИмя ТО
    Ошибка.Отметить(Ошибка.НЕСОВПАДЕНИЕ_ИМЕНИ)
  КОН;
  ЕСЛИ зУровень = 0 ТО
    БудетСлово(Слово.точка)
  ИНАЧЕ
    БудетСлово(Слово.точкасзап);
    ЧитатьСлово
  КОН
КОН Объявления;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Отдел-(      отдИмя-:Настрой.Имя;
                  испИмена+:ЧэргаСлеД.нСписок;
               толькоСписок:КЛЮЧ
            );
ПЕР
  испИмя:ДкИспИмя;
  звеноД:ЧэргаСлеД.ДкЗвену_телоД;
    понД:Данные.ДкВидуПонятие;
     имя:Настрой.Имя;
  отдВид:ЦЕЛ;
   пусто:Пустой.ДкЦепи;
УКАЗ
                                (* переменные отдела *)
  зУровень:=0;
  размерПриёмников:=0;
  кУровень:=0;
  трРаботает:=ОТКЛ;
  трУровень:=0;
  оЦепьРазрешена:=0;
  трСостояние[0]:=трВкл;
                                      (* свои переменные *)
  СОЗДАТЬ(пусто,"");
  ЧэргаСлеД.ОчиститьСписок(испИмена);
                                      (* начинаем разбор *)
  Разбор.Открыть;
  БудетСлово(Слово.отдел);
  БудетСлово(Слово.название);

  ЕСЛИ отдИмя # Разбор.имя ТО 
    Ошибка.ОтметитьИмя(Ошибка.ОТДЕЛ_ОТЛИЧАЕТСЯ_ОТ_ФАЙЛА,Разбор.имя)
  КОН;
  ЧитатьСлово;
  ЕСЛИ слово = Слово.плюс ТО
    отдВид:=Настрой.приложение;
    СОЗДАТЬ(испИмя);
    испИмя.имя:="СРЕДА";
    испИмя.начСлова:=Разбор.начСлова;
    испИмя.путь:=срдМесто;

    ЧэргаСлеД.ДобавитьНовЗвеноВконСписка(испИмена,испИмя);

    ЧитатьСлово
  АЕСЛИ слово = Слово.минус ТО
    отдВид:=Настрой.описание;
    ЧитатьСлово
  ИНАЧЕ
    отдВид:=Настрой.отдел
  КОН;
  ПропуститьСлово(Слово.точкасзап);
  ЕСЛИ слово = Слово.использует ТО
    ПОВТОРЯТЬ
      БудетСлово(Слово.название);
      СОЗДАТЬ(испИмя);
      испИмя.имя:=Разбор.имя;
      испИмя.начСлова:=Разбор.начСлова;
      испИмя.путь:=пусто;
      ЧитатьСлово;
      ЕСЛИ испИмя.имя = "СРЕДА" ТО
        испИмя.путь:=срдМесто
      АЕСЛИ слово = Слово.из ТО
        БудетСлово(Слово.цепьпост);
        испИмя.путь:=Разбор.цепьЗнач;
        ЧитатьСлово
      КОН;
      ЕСЛИ
           НЕ ((испИмя.имя = "СРЕДА")
          И
           (отдВид = Настрой.приложение))
      ТО
        ЧэргаСлеД.ДобавитьНовЗвеноВконСписка(испИмена,испИмя)
      КОН
    ДО слово # Слово.запятая;
    ПропуститьСлово(Слово.точкасзап)
  КОН;
  ЕСЛИ толькоСписок ТО
    Разбор.Закрыть;
    ВОЗВРАТ
  КОН;
                                                  (* готовим зависимые отделы *)
  Настрой.УстОтдел(отдИмя,отдВид);
  Данные.УстОтдел(отдИмя);
  Данные.ОткрытьОбласть(отдИмя);
                                             (* считываем используемые отделы *)
(*
   Обход списка с 1-го звена до N-го, т.е. пока звеноД.слеД # ПУСТО
 *)
            звеноД:=ЧэргаСлеД.Дк1муЗвену(испИмена);
  ПОКА
            звеноД # ПУСТО
  ВЫП
    испИмя:=звеноД.телоД(ДкИспИмя);

    Данные.Использовать(испИмя.имя,испИмя.путь^);

            звеноД:=звеноД.слеД
  КОН;
                                                  (* отдел *)
  понД:=Данные.Вставить(отдИмя);
  понД.родп:=Данные.пОтдел;
  понД.признаки:={Данные.прТекущийОтд};
  понД.вид:=Данные.нетвид;
  понД.первпон:=Данные.текОбласть.первпон;
                                        (* главная задача отдела и приложения *)
  ЕСЛИ отдВид = Настрой.приложение ТО
    имя:="Nachalo"
  ИНАЧЕ
    имя:=отдИмя;
    оЦепи.ДобавитьВКонецЗнак(имя,"!");
  КОН;
  понД:=Данные.Вставить(имя);
  понД.родп:=Данные.пЗадача;
  понД.признаки:={Данные.прОбщедоступное};
  понД.вид:=Данные.нетвид;
  ЕСЛИ
       отдВид = Настрой.приложение
  ТО
    понД.обл:=ПУСТО
  КОН;
                                                     (* начало выработки кода *)
  Код.Открыть((отдИмя # "СРЕДА") И (отдВид # Настрой.приложение));
  Объявления(понД,отдИмя);
  Код.Закрыть;

  ЕСЛИ Настрой.отдВид # Настрой.приложение ТО
    Данные.Сохранить
  КОН;
  Данные.ЗакрытьОбласть;

  ЕСЛИ трУровень > 0 ТО
    Ошибка.Отметить(Ошибка.ТЕКСТОРЕЗ_НЕ_ОКОНЧЕН)
  КОН;
  Разбор.Закрыть
КОН Отдел;

(*----------------------------------------------------------------------------*)
ЗАДАЧА Тексторез;
ПЕР
  состояние:ЦЕЛ;
  трСлово:ЦЕЛ;
  условие:КЛЮЧ;
  у:Узел.нВид;
УКАЗ
  ЧитатьСлово;
  трСлово:=слово;
  ЧитатьСлово;
  ЕСЛИ (трСлово = Слово.если) ИЛИ (трСлово = Слово.аесли) ТО
    ПостВыражение(у);

    ЕСЛИ у.вид.родв # Данные.вКлюч ТО
      Ошибка.Отметить(Ошибка.ОЖИДАЕТСЯ_КЛЮЧ)
    КОН;
    ПропуститьСлово(Слово.то);
    условие:=у.a = 1
  КОН;

  ПропуститьСлово(Слово.умнб);
  состояние:=трСостояние[трУровень];

  ВЫБРАТЬ трСлово ИЗ
  | Слово.если:
      УВЕЛИЧИТЬ(трУровень);
      ЕСЛИ трУровень = трУровней ТО 
        Ошибка.Отметить(Ошибка.МНОГО_УРОВНЕЙ_ТЕКСТОРЕЗА) 
      КОН; 
      ЕСЛИ состояние = трВкл ТО
        ЕСЛИ условие ТО
          трСостояние[трУровень]:=трВкл
        ИНАЧЕ
          трСостояние[трУровень]:=трДоВкл
        КОН
      ИНАЧЕ
        трСостояние[трУровень]:=трОткл
      КОН
  | Слово.аесли:
      ЕСЛИ (состояние = трДоВкл) И условие ТО
        трСостояние[трУровень]:=трВкл
      АЕСЛИ состояние = трВкл ТО
        трСостояние[трУровень]:=трОткл
      КОН
  | Слово.иначе:
      ЕСЛИ состояние = трДоВкл ТО
        трСостояние[трУровень]:=трВкл
      АЕСЛИ состояние = трВкл ТО
        трСостояние[трУровень]:=трОткл
      КОН
  | Слово.кон:
      ЕСЛИ трУровень = 0 ТО 
        Ошибка.Отметить(Ошибка.ЛИШНИЙ_КОН_У_ТЕКСТОРЕЗА) 
      КОН; 
      УМЕНЬШИТЬ(трУровень)
  ИНАЧЕ     
    Ошибка.Отметить(Ошибка.ТЕКСТОРЕЗ_НЕ_ПОНИМАЕТ) 
  КОН; 
  ЕСЛИ трСостояние[трУровень] # трВкл ТО
    ПОКА слово # Слово.мумн ВЫП ЧитатьСлово КОН
  КОН
КОН Тексторез;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА Подготовить-(срдМесто-:ЦЕПЬ);
(*
 * Цель:  выставляет местоположение файла "СРЕДА.отд"
 * До:    <СрдМесто>  - местоположение файла "СРЕДА.отд"
 * После: <срдМесто^> - местоположение файла "СРЕДА.отд"
 * Прим:  вызывается только один раз до разбора всех файлов
 *)
УКАЗ
  СОЗДАТЬ(Выражения.срдМесто,срдМесто)
КОН Подготовить;

КОН Выражения.
