(*~\Глагол\ПриложенияLink\ПГ\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*)
(**)                              ОТДЕЛ РС;
(*============================================================================*)
(* НАЗНАЧЕНИЕ: Разбор Слов языка                                              *)
(*============================================================================*)

ИСПОЛЬЗУЕТ
        (*  \Глагол\              *)
 оБуквы   ИЗ "..\..\Отделы\Иное\",
 оЗнака   ИЗ "..\..\Отделы\Иное\",

  НП,ОО,ФО,СС;

            (*--- значения, сохраняемые в задаче ЧитатьСлово() ---*)
ПЕР
  имя-:НП.Имя;
  цепь-:ДОСТУП К ЦЕПЬ;
  целзнач-:ШИРЦЕЛ;
  вещзнач-:ШИРВЕЩ;

ПЕР
  текзн:ЗНАК;
  текПоз:ОО.нТекстПоз;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ЗнакВЦел(зн:ЗНАК; шестн:КЛЮЧ):ЦЕЛ;
УКАЗ 
  ЕСЛИ оЗнака.Цифра(зн) ТО
    ВОЗВРАТ ВЦЕЛ(зн)-ВЦЕЛ("0")
  АЕСЛИ шестн И ("A" <= зн) И (зн <= "F") ТО
    ВОЗВРАТ ВЦЕЛ(зн)-ВЦЕЛ("A")+10
  ИНАЧЕ
    ОО.Ошибка(ОО.НЕВЕРНЫЙ_ЗНАК_В_ЧИСЛЕ)
  КОН
КОН ЗнакВЦел;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ЧитЗн;
УКАЗ
  ЕСЛИ ФО.ОтдКонец() ТО
    текзн:=0X
  ИНАЧЕ
    ФО.ОтдЗнак(текзн);
    ЕСЛИ текзн=0AX ТО
      УВЕЛИЧИТЬ(текПоз.строка);
      текПоз.колонка:=0
    ИНАЧЕ
      УВЕЛИЧИТЬ(текПоз.колонка)
    КОН
  КОН
КОН ЧитЗн;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ЧитЦепь():ЦЕЛ;
ПЕР
  п:ЦЕЛ;             (* позиция знака в цепочке *)
  цифра:ЦЕЛ;         (* номер цифры в знаке "#nnnn" *)
  кав:ЗНАК;          (* кавычка ('") в начале (и конце) цепочки *)
  пцепь:ЦЕПЬ[10000]; (* промежуточная память для считывания цепочки *)
УКАЗ
  кав:=текзн;
  п:=0;
  КОЛЬЦО
    ЧитЗн;
    ЕСЛИ текзн = кав ТО 
      ЧитЗн;
      ВЫХОД
    АЕСЛИ текзн < " " ТО
      ОО.Ошибка(ОО.НЕВЕРНЫЙ_ЗНАК_В_ЦЕПОЧКЕ)
    АЕСЛИ текзн = "##" ТО (* '#' *)
      ЧитЗн;
      ЕСЛИ текзн = "##" ТО (* '#' *)
        целзнач:=ВЦЕЛ(текзн)
      ИНАЧЕ
        целзнач:=ЗнакВЦел(текзн,ВКЛ);
        ОТ цифра:=2 ДО 4 ВЫП
          ЧитЗн;
          целзнач:=целзнач*10H+ЗнакВЦел(текзн,ВКЛ)
        КОН;
        текзн:=ВЗНАК(целзнач)
      КОН
    ИНАЧЕ
      целзнач:=ВЦЕЛ(текзн)
    КОН;
    пцепь[п]:=текзн;
    УВЕЛИЧИТЬ(п)
  КОН;
  ЕСЛИ п = 1 ТО
    ВОЗВРАТ СС.знак
  КОН;
  пцепь[п]:=0X;
  УВЕЛИЧИТЬ(п);
  СОЗДАТЬ(цепь,п);
  (* учитываем цепочки с внутренними 0X *)
  ПОКА п > 0 ВЫП
    УМЕНЬШИТЬ(п);
    цепь[п]:=пцепь[п]
  КОН;
  ВОЗВРАТ СС.цепьпост
КОН ЧитЦепь;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ЧитНазв;
ПЕР
  п:ЦЕЛ;
УКАЗ
  п:=0;
  ПОВТОРЯТЬ
    ЕСЛИ
          п=НП.длинаНазвания-1
    ТО
      ОО.Ошибка(ОО.ДЛИННОЕ_НАЗВАНИЕ)
    КОН;
    имя[п]:=текзн;
    УВЕЛИЧИТЬ(п);
    ЧитЗн
  ДО НЕ оЗнака.ВСлове(текзн);
  имя[п]:=0X
КОН ЧитНазв;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ЧитЧисло():ЦЕЛ;
(*   До: ("0" <= текзн) И (текзн <= "9") *)
ПЕР
  i,m,n,d:ЦЕЛ;
  цифры:ЦЕПЬ[64];
  мант:ШИРВЕЩ;
  эксп:ЦЕЛ;
  знЭксп:ЗНАК;
  отриц:КЛЮЧ;
  смв:ЦЕЛ; (* СС.знак, СС.целч, СС.вещч, СС.швещч *)

 (*....................................подЗадача..*)
  ЗАДАЧА ДесятьВ(x:ЦЕЛ):ШИРВЕЩ;
  ПЕР
    ответ,множ:ШИРВЕЩ;
  УКАЗ
    ответ:=1;
    множ:=10;
    ПОКА x > 0 ВЫП
      ЕСЛИ НЕ ЧЕТ(x) ТО ответ:=ответ*множ КОН;
      x:=x ДЕЛИТЬ 2;
      ЕСЛИ x > 0 ТО (* защита <множ> от переполнения *)
        множ:=множ*множ 
      КОН
    КОН;
    ВОЗВРАТ ответ
  КОН ДесятьВ;

УКАЗ
  i:=0; m:=0; n:=0; d:=0;
  КОЛЬЦО (* читаем мантиссу *)
    ЕСЛИ оЗнака.Цифра(текзн) ИЛИ (d = 0) И ("A" <= текзн) И (текзн <= "F") ТО
      ЕСЛИ (m > 0) ИЛИ (текзн # "0") ТО (* предстоящие нули пропускаем *)
        ЕСЛИ n < РАЗМЕР(цифры) ТО
          цифры[n]:=текзн;
          УВЕЛИЧИТЬ(n)
        КОН;
        УВЕЛИЧИТЬ(m)
      КОН;
      ЧитЗн;
      УВЕЛИЧИТЬ(i)
    АЕСЛИ текзн = "." ТО
      ЧитЗн;
      ЕСЛИ текзн = "." ТО (* .. *)
        текзн:=7FX;
        ВЫХОД
      АЕСЛИ d = 0 ТО (* i > 0 *)
        d:=i
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕВЕРНЫЙ_ЗНАК_В_ЧИСЛЕ)
      КОН
    ИНАЧЕ
      ВЫХОД
    КОН
  КОН; (* 0<=n<=m<=i, 0<=d<=i *)
  ЕСЛИ d = 0 ТО (* целое *)
    ЕСЛИ n = m ТО
      целзнач:=0;
      i:=0;
      ЕСЛИ текзн = "X" ТО (* знак *)
        ЧитЗн;
        смв:=СС.знак;
        ЕСЛИ n <= 4 ТО
          ПОКА i < n ВЫП
            целзнач:=целзнач*10H+ЗнакВЦел(цифры[i],ВКЛ);
            УВЕЛИЧИТЬ(i)
          КОН
        ИНАЧЕ
          ОО.Ошибка(ОО.БОЛЬШОЕ_ЧИСЛО)
        КОН
      АЕСЛИ текзн = "H" ТО (* 16-тиричное *)
        ЧитЗн;
        смв:=СС.целпост;
        ЕСЛИ n <= НП.ВсегоЦифр16 ТО
          ЕСЛИ (n = НП.ВсегоЦифр16) И (цифры[0] > "7") ТО
            ОО.Ошибка(ОО.БОЛЬШОЕ_ЧИСЛО);
          КОН;
          ПОКА i < n ВЫП
            целзнач:=целзнач*10H+ЗнакВЦел(цифры[i],ВКЛ);
            УВЕЛИЧИТЬ(i)
          КОН
        ИНАЧЕ
          ОО.Ошибка(ОО.БОЛЬШОЕ_ЧИСЛО)
        КОН
      ИНАЧЕ (* 10-тичное *)
        смв:=СС.целпост;
        ПОКА i < n ВЫП
          d:=ЗнакВЦел(цифры[i],ОТКЛ);
          УВЕЛИЧИТЬ(i);
          ЕСЛИ целзнач <= (МАКС(ШИРЦЕЛ)-d) ДЕЛИТЬ 10 ТО
            целзнач:=целзнач*10+d
          ИНАЧЕ
            ОО.Ошибка(ОО.БОЛЬШОЕ_ЧИСЛО)
          КОН
        КОН
      КОН
    ИНАЧЕ
      ОО.Ошибка(ОО.БОЛЬШОЕ_ЧИСЛО)
    КОН
  ИНАЧЕ (* дробная часть *)
    мант:=0; эксп:=0; знЭксп:="E";
    ПОКА n > 0 ВЫП (* 0<=мант<1 *)
      УМЕНЬШИТЬ(n);
      мант:=(ЗнакВЦел(цифры[n],ОТКЛ)+мант)/10
    КОН;
    ЕСЛИ (текзн = "E") ИЛИ (текзн = "D") ТО
      знЭксп:=текзн;
      ЧитЗн;
      отриц:=ОТКЛ;
      ЕСЛИ текзн = "-" ТО
        отриц:=ВКЛ;
        ЧитЗн
      АЕСЛИ текзн = "+" ТО
        ЧитЗн
      КОН;
      ЕСЛИ оЗнака.Цифра(текзн) ТО
        ПОВТОРЯТЬ
          n:=ЗнакВЦел(текзн,ОТКЛ);
          ЧитЗн;
          ЕСЛИ эксп <= (МАКС(ЦЕЛ)-n) ДЕЛИТЬ 10 ТО
            эксп:=эксп*10+n
          ИНАЧЕ
            ОО.Ошибка(ОО.БОЛЬШОЕ_ЧИСЛО)
          КОН
        ДО НЕ оЗнака.Цифра(текзн);
        ЕСЛИ отриц ТО
          эксп:=-эксп
        КОН
      ИНАЧЕ
        ОО.Ошибка(ОО.НЕВЕРНЫЙ_ЗНАК_В_ЧИСЛЕ)
      КОН
    КОН;
    УМЕНЬШИТЬ(эксп,i-d-m); (* сдвиг десятичной точки *)
    ЕСЛИ знЭксп = "E" ТО
      смв:=СС.вещпост;
      ЕСЛИ (1-НП.МаксЭксп < эксп) И (эксп <= НП.МаксЭксп) ТО
        ЕСЛИ эксп < 0 ТО
          вещзнач:=УЗК(мант/ДесятьВ(-эксп))
        ИНАЧЕ
          вещзнач:=УЗК(мант*ДесятьВ(эксп))
        КОН
      ИНАЧЕ
        ОО.Ошибка(ОО.БОЛЬШОЕ_ЧИСЛО)
      КОН
    ИНАЧЕ
      смв:=СС.швещпост;
      ЕСЛИ (1-НП.МаксШирЭксп < эксп) И (эксп <= НП.МаксШирЭксп) ТО
        ЕСЛИ эксп < 0 ТО
          вещзнач:=мант/ДесятьВ(-эксп)
        ИНАЧЕ
          вещзнач:=мант*ДесятьВ(эксп)
        КОН
      ИНАЧЕ
        ОО.Ошибка(ОО.БОЛЬШОЕ_ЧИСЛО)
      КОН
    КОН
  КОН;
  ВОЗВРАТ смв
КОН ЧитЧисло;

(*-----------------------------------------локальная ЗАДАЧА-------------------*)
ЗАДАЧА ЧитПрим;
УКАЗ
  ЧитЗн;
  ПОВТОРЯТЬ
    КОЛЬЦО
      ПОКА текзн = "(" ВЫП
        ЧитЗн;
        ЕСЛИ текзн = "*" ТО ЧитПрим КОН
      КОН;
      ЕСЛИ текзн = "*" ТО
        ЧитЗн;
        ВЫХОД
      КОН;
      ЕСЛИ текзн = 0X ТО ВЫХОД КОН;
      ЧитЗн
    КОН;
    ЕСЛИ текзн = 0X ТО
      ОО.Ошибка(ОО.НЕЗАКРЫТОЕ_ПРИМЕЧАНИЕ)
    КОН
  ДО текзн = ")";
  ЧитЗн
КОН ЧитПрим;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       ЧитатьСлово-():ЦЕЛ;
ПЕР
  смв:ЦЕЛ;
УКАЗ
  ПОКА текзн <= " " ВЫП (* пропускаем все пробелы *)
    ЕСЛИ текзн = 0X ТО
      ОО.текПоз:=текПоз;
      ОО.Ошибка(ОО.НЕОЖИДАННЫЙ_КОНЕЦ_ФАЙЛА)
    ИНАЧЕ
      ЧитЗн
    КОН
  КОН;
  ОО.текПоз:=текПоз;
  ВЫБРАТЬ текзн ИЗ
    "'",'"':    смв:=ЧитЦепь()
  | "##":ЧитЗн; смв:=СС.неравно
  | "(": ЧитЗн; ЕСЛИ текзн = "*" ТО 
                  ЧитПрим; 
                  смв:=ЧитатьСлово() 
                ИНАЧЕ 
                  смв:=СС.лкругл 
                КОН
  | ")": ЧитЗн; смв:=СС.пркругл
  | "*": ЧитЗн; ЕСЛИ текзн = ">" ТО 
                  ЧитЗн; 
                  смв:=СС.умнб
                ИНАЧЕ
                  смв:=СС.умножить
                КОН
  | "+": ЧитЗн; смв:=СС.плюс
  | ",": ЧитЗн; смв:=СС.запятая
  | "-": ЧитЗн; смв:=СС.минус
  | ".": ЧитЗн; ЕСЛИ текзн = "." ТО 
                  ЧитЗн; 
                  смв:=СС.дветочки 
                ИНАЧЕ 
                  смв:=СС.точка 
                КОН
  | "/": ЧитЗн; смв:=СС.косая
  | "0".."9":     смв:=ЧитЧисло()
  | ":": ЧитЗн; ЕСЛИ текзн = "=" ТО 
                  ЧитЗн; 
                  смв:=СС.присвоить 
                ИНАЧЕ 
                  смв:=СС.двоеточие 
                КОН
  | ";": ЧитЗн; смв:=СС.точкасзап
  | "<": ЧитЗн; ЕСЛИ текзн = "=" ТО 
                  ЧитЗн; 
                  смв:=СС.мравно 
                АЕСЛИ текзн="*" ТО 
                  ЧитЗн; 
                  смв:=СС.мумн
                ИНАЧЕ 
                  смв:=СС.меньше 
                КОН
  | "=": ЧитЗн; смв:=СС.равно
  | ">": ЧитЗн; ЕСЛИ текзн = "=" ТО 
                  ЧитЗн; 
                  смв:=СС.бравно 
                ИНАЧЕ 
                  смв:=СС.больше 
                КОН
  | "[": ЧитЗн; смв:=СС.лквадр
  | "]": ЧитЗн; смв:=СС.прквадр
  | "^": ЧитЗн; смв:=СС.стрелка
  | "{": ЧитЗн; смв:=СС.лфигурн
  | "}": ЧитЗн; смв:=СС.прфигурн
  | "|": ЧитЗн; смв:=СС.черта
  | 7FX: ЧитЗн; смв:=СС.дветочки
  ИНАЧЕ
    ЕСЛИ оБуквы.Известная(текзн)
       ИЛИ
        (текзн = "_")
    ТО
      ЧитНазв;
      смв:=СС.название;
      ВЫБРАТЬ имя[0] ИЗ
        "А": ЕСЛИ  имя = "АЕСЛИ"      ТО смв:=СС.аесли
             КОН         
      | "Б": ЕСЛИ  имя = "БЕГУНОК"    ТО смв:=СС.бегунок
             КОН         
      | "В": ЕСЛИ  имя = "ВЫП"        ТО смв:=СС.вып
             АЕСЛИ имя = "ВИД"        ТО смв:=СС.вид
             АЕСЛИ имя = "ВОЗВРАТ"    ТО смв:=СС.возврат
             АЕСЛИ имя = "ВЫБРАТЬ"    ТО смв:=СС.выбрать
             АЕСЛИ имя = "ВЫХОД"      ТО смв:=СС.выход
             АЕСЛИ имя = "В"          ТО смв:=СС.в
             АЕСЛИ имя = "ВИДА"       ТО смв:=СС.вида
             АЕСЛИ имя = "ВЫЗОВ"      ТО смв:=СС.вызов
             КОН         
      | "Д": ЕСЛИ  имя = "ДОСТУП"     ТО смв:=СС.доступ
             АЕСЛИ имя = "ДЕЛИТЬ"     ТО смв:=СС.делить
             АЕСЛИ имя = "ДЛЯ"        ТО смв:=СС.для
             АЕСЛИ имя = "ДО"         ТО смв:=СС.до
             КОН         
      | "Е": ЕСЛИ  имя = "ЕСЛИ"       ТО смв:=СС.если
             КОН         
      | "З": ЕСЛИ  имя = "ЗАДАЧА"     ТО смв:=СС.задача
             КОН         
      | "И": ЕСЛИ  имя = "ИНАЧЕ"      ТО смв:=СС.иначе
             АЕСЛИ имя = "И"          ТО смв:=СС.и
             АЕСЛИ имя = "ИЛИ"        ТО смв:=СС.или
             АЕСЛИ имя = "ИЗ"         ТО смв:=СС.из
             АЕСЛИ имя = "ИСПОЛЬЗУЕТ" ТО смв:=СС.использует
             КОН         
      | "К": ЕСЛИ  имя = "КОН"        ТО смв:=СС.кон
             АЕСЛИ имя = "К"          ТО смв:=СС.к
             АЕСЛИ имя = "КОЛЬЦО"     ТО смв:=СС.кольцо
             КОН         
      | "Н": ЕСЛИ  имя = "НАБОР"      ТО смв:=СС.набор
             АЕСЛИ имя = "НЕ"         ТО смв:=СС.не
             КОН         
      | "О": ЕСЛИ  имя = "ОТ"         ТО смв:=СС.от
             АЕСЛИ имя = "ОСТАТОК"    ТО смв:=СС.остаток   
             АЕСЛИ имя = "ОТДЕЛ"      ТО смв:=СС.отдел
             КОН         
      | "П": ЕСЛИ  имя = "ПЕР"        ТО смв:=СС.пер
             АЕСЛИ имя = "ПУСТО"      ТО смв:=СС.пусто
             АЕСЛИ имя = "ПОКА"       ТО смв:=СС.пока
             АЕСЛИ имя = "ПОВТОРЯТЬ"  ТО смв:=СС.повторять
             АЕСЛИ имя = "ПО"         ТО смв:=СС.по   
             АЕСЛИ имя = "ПОСТ"       ТО смв:=СС.пост
             КОН         
      | "Р": ЕСЛИ  имя = "РЯД"        ТО смв:=СС.ряд
             КОН         
      | "С": ЕСЛИ  имя = "СЖАТЫЙ"     ТО смв:=СС.сжатый
             КОН         
      | "Т": ЕСЛИ  имя = "ТО"         ТО смв:=СС.то
             КОН         
      | "У": ЕСЛИ  имя = "УКАЗ"       ТО смв:=СС.указ
             КОН         
      | "Ц": ЕСЛИ  имя = "ЦЕПЬ"       ТО смв:=СС.цепь
             КОН         
      | "Я": ЕСЛИ  имя = "ЯВЛЯЕТСЯ"   ТО смв:=СС.является
             КОН
      ИНАЧЕ
      КОН
    ИНАЧЕ
      ЧитЗн;
          смв:=СС.ноль
    КОН
  КОН;
  ВОЗВРАТ смв
КОН ЧитатьСлово;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Подготовить-;
УКАЗ
  текзн:=" ";
  текПоз.строка:=1;
  текПоз.колонка:=1;
  ФО.ОтдОткрыть
КОН Подготовить;

(*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~общедоступная ЗАДАЧА~~~~~~~~~~~~~~~~~~~~~*)
ЗАДАЧА
       Завершить-;
УКАЗ
  ФО.ОтдЗакрыть
КОН Завершить;

КОН РС.
