Вот как выглядит модуль ЗагрузиПереводыЭлементовКода в русской версии.
Код: Выделить всё
модуль ЗагрузиПереводыЭлементовКода;
использует KernelLog, Strings, Files, Streams, XML, XMLScanner, XMLParser, XMLObjects, ПереводыЭлементовКода;
конст
ИмяФайлаПереводов = "ПереводыЭлементовКода.XML";
Trace* = ложь;
тип
СостояниеДелаРазбора = набор (* передавать по VAR *)
имяФайла : ряд 256 из литера8;
будущиеМодули : ПереводыЭлементовКода.Модуль;
гдея : Streams.Position кн;
перем
hasErrors: булево;
проц РазбериПереводыЭлементовКода(перем сдр : СостояниеДелаРазбора; doc: XML.Document) : булево;
перем
enum: XMLObjects.Enumerator;
p: динамически_типизированный_укль;
у(*узел*): XML.Element;
s: XML.String;
тело
если (doc = НУЛЬ) то возврат ложь кн;
(* First we just count the number of hot keys defined *)
у := doc.GetRoot();
enum := у.GetContents();
цикл_пока enum.HasMoreElements() делай
p := enum.GetNext();
если (p суть XML.Element) то
у := p(XML.Element);
сдр.гдея := у.GetPos();
s := у.GetName();
если ((s # НУЛЬ) и (s^ = "Module")) то
если ~РазбериМодуль(сдр, у) то
возврат ложь кн
иначе
ОшибкаСмысла(сдр, Strings.NewString("Ожидался элемент Module, а попался иной элемент"));
возврат ложь кн
аесли (p суть XML.Comment) то
(* ничего не делаем *)
иначе
ОшибкаСмысла(сдр, Strings.NewString("Ожидался элемент Module, а попался вообще не элемент"));
возврат ложь кн кн;
ПереводыЭлементовКода.модули := сдр.будущиеМодули;
возврат правда кн РазбериПереводыЭлементовКода;
(* ПрочитайОбязательныйСтроковыйАтрибут возвращает успех или неудачу *)
проц ПрочитайОбязательныйСтроковыйАтрибут(перем сдр: СостояниеДелаРазбора; у: XML.Element;
имяАтрибута : ряд из литера8; перем приёмник: Strings.String) : булево;
перем врем: Strings.String;
тело
врем := у.GetAttributeValue(имяАтрибута);
если (врем = НУЛЬ) или (врем^ = "") то
ОшибкаСмысла(сдр, Strings.NewString("атрибтут «") + имяАтрибута + "» должен быть задан непустой строкой");
возврат ложь кн;
приёмник := врем;
возврат правда кн ПрочитайОбязательныйСтроковыйАтрибут;
(* ПрочитайНеобязательныйСтроковыйАтрибут возвращает успех или неудачу *)
проц ПрочитайНеобязательныйСтроковыйАтрибут(перем сдр: СостояниеДелаРазбора; у: XML.Element;
конст имяАтрибута : ряд из литера8; конст умолч: ряд из литера8; перем приёмник: Strings.String) : булево;
перем врем: Strings.String;
тело
врем := у.GetAttributeValue(имяАтрибута);
если (врем = НУЛЬ) или (врем^ = "") то
врем := Strings.NewString(умолч) кн;
приёмник := врем;
возврат правда кн ПрочитайНеобязательныйСтроковыйАтрибут;
проц РазбериЧлены(перем сдр: СостояниеДелаРазбора; хозяин : XML.Element; перем приёмник: ПереводыЭлементовКода.ИменованнаяОбластьВидимости): булево;
перем
обход: XMLObjects.Enumerator;
элт: динамически_типизированный_укль;
у(*узел*): XML.Element;
врем : ПереводыЭлементовКода.ИменованнаяОбластьВидимости;
s: XML.String;
тело
приёмник := НУЛЬ;
обход := хозяин.GetContents();
цикл_пока обход.HasMoreElements() делай
элт := обход.GetNext();
если (элт суть XML.Element) то
у := элт(XML.Element);
сдр.гдея := у.GetPos();
s := у.GetName();
если ((s # НУЛЬ) и (s^ = "Scope")) то
если ~РазбериИменованнуюОбластьВидимости(сдр, у, врем) то
возврат ложь кн;
врем.следующий := приёмник;
приёмник := врем кн кн кн;
возврат правда кн РазбериЧлены;
проц РазбериИменованнуюОбластьВидимости(перем сдр: СостояниеДелаРазбора; у : XML.Element; перем приёмник: ПереводыЭлементовКода.ИменованнаяОбластьВидимости) : булево;
перем
ов: ПереводыЭлементовКода.ИменованнаяОбластьВидимости; russianExists : XML.String;
тело
приёмник := НУЛЬ;
нов(ов);
если ~ПрочитайОбязательныйСтроковыйАтрибут(сдр, у, "en", ов.en) то возврат ложь кн;
если ~ПрочитайНеобязательныйСтроковыйАтрибут(сдр, у, "ru", "", ов.ru) то возврат ложь кн;
если ов.ru^ = "" то ов.ru := ов.en кн;
если ~ПрочитайНеобязательныйСтроковыйАтрибут(сдр, у, "rx", "1", russianExists) то возврат ложь кн;
(* также для справки есть атрибут ee = ExportEd, но он нужен только человеку *)
если russianExists^ = "1" то
ов.russianExists := 1
аесли russianExists^ = "0" то
ов.russianExists := 0
иначе
KernelLog.String("russianExists^ = «");
KernelLog.String(russianExists^);
KernelLog.String("»"); KernelLog.Ln;
ОшибкаСмысла(сдр, Strings.NewString("russianExists должно быть 0 или 1"));
возврат ложь кн;
если ~РазбериЧлены(сдр,у, ов.члены) то
возврат ложь кн;
приёмник := ов;
возврат правда кн РазбериИменованнуюОбластьВидимости;
проц РазбериМодуль(перем сдр: СостояниеДелаРазбора; у : XML.Element) : булево;
перем
м: ПереводыЭлементовКода.Модуль; russianExists : XML.String;
тело
нов(м);
если ~ПрочитайОбязательныйСтроковыйАтрибут(сдр, у, "en", м.en) то возврат ложь кн;
если ~ПрочитайОбязательныйСтроковыйАтрибут(сдр, у, "ru", м.ru) то возврат ложь кн;
если ~ПрочитайНеобязательныйСтроковыйАтрибут(сдр, у, "rx", "1", russianExists) то возврат ложь кн;
если russianExists^ = "1" то
м.russianExists := 1
аесли russianExists^ = "0" то
м.russianExists := 0
иначе
KernelLog.String("rx^ = «");
KernelLog.String(russianExists^);
KernelLog.String("»"); KernelLog.Ln;
ОшибкаСмысла(сдр, Strings.NewString("rx должно быть 0 или 1"));
возврат ложь кн;
если ~(РазбериПопулярныеПсевдонимы(сдр,м,у) и РазбериКонстанты(сдр,м,у)) то
возврат ложь кн;
если ~РазбериЧлены(сдр, у, м.члены) то
возврат ложь кн;
м.следующий := сдр.будущиеМодули;
сдр.будущиеМодули := м; возврат правда кн РазбериМодуль;
проц РазбериПопулярныеПсевдонимы(перем сдр: СостояниеДелаРазбора; м: ПереводыЭлементовКода.Модуль; у : XML.Element):булево;
перем бегунок: XMLObjects.Enumerator; пуб(*подузелбестиповый*) : динамически_типизированный_укль; пу(*подузел*) : XML.Element;
тег : XML.String;
тело
бегунок := у.GetContents();
цикл_пока бегунок.HasMoreElements() делай
пуб := бегунок.GetNext();
если пуб суть XML.Content то
сдр.гдея := пуб(XML.Content).GetPos() кн;
если пуб суть XML.Element то
пу := пуб(XML.Element);
тег := пу.GetName();
если ((тег # НУЛЬ) и (тег^ = "PopularAlias")) то
если ~РазбериПопулярныйПсевдоним(сдр, м, пу) то
возврат ложь кн кн
аесли пуб суть XML.Content то (* пропускаем *)
иначе
ОшибкаСмысла(сдр, Strings.NewString("ожидался элемент, а попалось неведомо что"));
возврат ложь кн кн;
возврат правда кн РазбериПопулярныеПсевдонимы;
проц РазбериПопулярныйПсевдоним(перем сдр: СостояниеДелаРазбора; м: ПереводыЭлементовКода.Модуль; у: XML.Element):булево;
перем пп : ПереводыЭлементовКода.ПопулярныйПсевдоним; en, ru : XML.String; успех : булево;
тело
если ~ПрочитайОбязательныйСтроковыйАтрибут(сдр, у, "en", en) то возврат ложь кн;
если ~ПрочитайОбязательныйСтроковыйАтрибут(сдр, у, "ru", ru) то возврат ложь кн;
успех := ПроверьНовизнуПопулярногоПсевдонима(сдр, м, en, ru);
если успех то
нов(пп);
пп.en := en; пп.ru := ru;
пп.следующий := м.популярныеПсевдонимы;
м.популярныеПсевдонимы := пп кн;
возврат успех кн РазбериПопулярныйПсевдоним;
проц ПроверьНовизнуПопулярногоПсевдонима(перем сдр: СостояниеДелаРазбора; м: ПереводыЭлементовКода.Модуль;
en, ru : XML.String):булево;
перем пп: ПереводыЭлементовКода.ПопулярныйПсевдоним;
тело
пп := м.популярныеПсевдонимы;
цикл_пока пп # НУЛЬ делай
если пп.en^ = en^ то
ОшибкаСмысла(сдр, Strings.NewString("Неуникальное английское имя")); возврат ложь
аесли
пп.ru^ = ru^ то
ОшибкаСмысла(сдр, Strings.NewString("Неуникальное русское имя")); возврат ложь кн;
пп := пп.следующий кн;
возврат правда кн ПроверьНовизнуПопулярногоПсевдонима;
проц РазбериКонстанты(перем сдр: СостояниеДелаРазбора; м: ПереводыЭлементовКода.Модуль; у : XML.Element):булево;
тело возврат правда кн РазбериКонстанты;
(* Ошибка для парсера XML *)
проц ОшибкаДляПарсераXML(pos, line, row: Streams.Position; конст msg: ряд из литера8);
тело
KernelLog.String("ПереводыЭлементовКода: позиция");
KernelLog.Int(pos, 5);
KernelLog.String(", стр ");
KernelLog.Int(line, 5);
KernelLog.String(" кол ");
KernelLog.Int(row, 5);
KernelLog.String(" - ");
KernelLog.String(msg);
KernelLog.Ln();
hasErrors := правда
кн ОшибкаДляПарсераXML;
проц ОшибкаСмысла(перем сдр : СостояниеДелаРазбора; msg: Strings.String);
тело
KernelLog.String("ПереводыЭлементовКода: файл ");
KernelLog.String(сдр.имяФайла);
KernelLog.String(", позиция ");
KernelLog.Int(сдр.гдея, 5);
KernelLog.String(": ");
KernelLog.String(msg^);
KernelLog.Ln();
HALT(45345); (* не можем позволить себе загрузить ЯОС с битым файлом переводов *)
кн ОшибкаСмысла;
проц Read(перем сдр: СостояниеДелаРазбора) : булево;
перем
f: Files.File;
scanner: XMLScanner.Scanner;
parser: XMLParser.Parser;
reader: Files.Reader;
doc: XML.Document;
успех : булево;
тело
hasErrors := ложь;
f := Files.Old(сдр.имяФайла);
если (f # НУЛЬ) то
нов(reader, f, 0);
нов(scanner, reader);
scanner.reportError := ОшибкаДляПарсераXML;
нов(parser, scanner);
parser.reportError := ОшибкаДляПарсераXML;
doc := parser.Parse();
если hasErrors то
ОшибкаСмысла(сдр,Strings.NewString("есть ошибки XML."));
иначе
успех := РазбериПереводыЭлементовКода(сдр, doc);
если успех то (* иначе ошибку должны были вывести раньше *)
ПереводыЭлементовКода.модули := сдр.будущиеМодули;
KernelLog.String("ПереводыЭлементовКода: файл ");
KernelLog.String(сдр.имяФайла);
KernelLog.String(" успешно загружен.");
KernelLog.Ln кн кн
иначе
ОшибкаСмысла(сдр,Strings.NewString("файл не найден.")) кн;
возврат успех кн Read;
проц ИзФайла*;
перем
сдр : СостояниеДелаРазбора;
тело
сдр.имяФайла := ИмяФайлаПереводов;
неважно Read(сдр) кн ИзФайла;
кн ЗагрузиПереводыЭлементовКода.ИзФайла ~