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

ИСПОЛЬЗУЕТ
        (*  \Глагол\              *)
  оЗнака  ИЗ "..\..\Отделы\Иное\",
  оБуквы  ИЗ "..\..\Отделы\Иное\",
(*
  Знак    ИЗ "..\..\Отделы\Иное\",
  Буква   ИЗ "..\..\Отделы\Иное\",
*)
  Ядро,
  Слово,
  Настрой,
  Ошибка,
  Обмен;

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

                             (* положение знака во входном тексте *)
ВИД
  Положение- = НАБОР 
    строка-,колонка-:ЦЕЛ 
  КОН;
ПЕР
      начСлова+:Положение;    (* начало слова (для указания ошибки) *)
  текПоложение :Положение;    (* положение <текЗн> *)

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

(******************************************************************************)
ЗАДАЧА ЧитатьЗнак;
УКАЗ
  текЗн:=Обмен.ОтдЗнак();
  ЕСЛИ текЗн = 0AX ТО
    УВЕЛИЧИТЬ(текПоложение.строка);
    текПоложение.колонка:=0 
  АЕСЛИ текЗн >= " " ТО
    УВЕЛИЧИТЬ(текПоложение.колонка)
  КОН
КОН ЧитатьЗнак;

(******************************************************************************)
ЗАДАЧА ЧитатьЦепочку():ЦЕЛ;
ПЕР
  п:ЦЕЛ;            (* позиция знака в цепочке *)
  кав:ЗНАК;         (* кавычка ('") в начале (и конце) цепочки *)
  цепь:ЦЕПЬ[10000]; (* промежуточная память для считывания цепочки *)
УКАЗ
  кав:=текЗн;
  п:=0;
  КОЛЬЦО
    ЧитатьЗнак;
    ЕСЛИ текЗн = кав ТО 
      ЧитатьЗнак;
      ВЫХОД
    АЕСЛИ текЗн < " " ТО
      Ошибка.Отметить(Ошибка.НЕВЕРНЫЙ_ЗНАК_В_ЦЕПОЧКЕ)
    АЕСЛИ текЗн = "##" ТО (* '#' *)
      ЧитатьЗнак;
      ЕСЛИ текЗн = "##" ТО (* '#' *)
        целЗнач:=ВЦЕЛ(текЗн)
      ИНАЧЕ
        целЗнач:=ЗнакВЦел(текЗн,ВКЛ);
        ЧитатьЗнак;
        целЗнач:=целЗнач*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 <= 2 ТО
          ПОКА 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") ИЛИ (знЭксп = "D") ТО
(*
    ЕСЛИ знЭксп = "E" ТО
*)
      слово:=Слово.вещпост;
      ЕСЛИ (1-Настрой.МаксЭксп < эксп) И (эксп <= Настрой.МаксЭксп) ТО
        ЕСЛИ эксп < 0 ТО
          вещЗнач:=УЗК(мант/ДесятьВ(-эксп))
        ИНАЧЕ
          вещЗнач:=УЗК(мант*ДесятьВ(эксп))
        КОН
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.БОЛЬШОЕ_ЧИСЛО)
      КОН
(*
    ИНАЧЕ
      слово:=Слово.швещпост;
      ЕСЛИ (1-Настрой.МаксШирЭксп < эксп) И (эксп <= Настрой.МаксШирЭксп) ТО
        ЕСЛИ эксп < 0 ТО
          вещЗнач:=мант/ДесятьВ(-эксп)
        ИНАЧЕ
          вещЗнач:=мант*ДесятьВ(эксп)
        КОН
      ИНАЧЕ
        Ошибка.Отметить(Ошибка.БОЛЬШОЕ_ЧИСЛО)
      КОН
*)
    КОН
  КОН;
  ВОЗВРАТ слово
КОН ЧитЧисло;

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

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

(******************************************************************************)
ЗАДАЧА Открыть-;
УКАЗ
  текЗн:=" ";
  текПоложение.строка:=1;
  текПоложение.колонка:=1;
  начСлова:=текПоложение;
  Обмен.ОтдОткрыть()
КОН Открыть;

(******************************************************************************)
ЗАДАЧА Закрыть-;
УКАЗ
  Обмен.ОтдЗакрыть
КОН Закрыть;

КОН Разбор.
