/******************************************************************** Загрузка описания Статьи из текстового файла *********************************************************************/ void Form_Table::LoadTxt( Macro_Parser &txtfile, Grammar& gram, bool IsRealized ) { is_realized = IsRealized; iclass = UNKNOWN; LoadName(txtfile, gram.GetDict()); if (iclass == UNKNOWN) // если в LoadName еще не прочитали информацию о принадлежности к грамматическому классу... { const BethToken class_name = txtfile.read(); if ((iclass = gram.FindClass(class_name.string())) == UNKNOWN) { // Не найден класс, заявленный для статьи Print_Error(class_name, txtfile); gram.GetIO().merr().printf( "The class [%us] is not previously declared in grammar\n" , class_name.c_str() ); throw E_ParserError(); } } LoadBody(txtfile, gram); Loaded(gram.GetDict()); return; }
/**************************************************************************** Загружаем из текстового файла множество символьных строк. Если слово только одно, то оно может идти непосредственно. Если необходимо определить несколько слов, то они заключаются в фигурные скобочки. Форматы: 1. лексема 2. { лексема лексема ... лексема } Второй формат охватывает также и первый, если в фигурных скобочках указать только одну лексему. Способ хранения в обоих случаях одинаков! *****************************************************************************/ void UCStringSet::LoadTxt( const Sol_IO &io, Macro_Parser &txtfile ) { BethToken t = txtfile.read(); if( t.GetToken()!=B_OFIGPAREN ) { // Первый формат. push_back(t.c_str()); } else { // Второй формат. while( !txtfile.eof() ) { if( txtfile.eof() ) { Print_Error(t,txtfile); io.merr().printf( "End of file has been reached before " "set of lexems completely loaded\n" ); LEM_STOPIT; } t = txtfile.read(); if( t.GetToken()==B_CFIGPAREN ) break; push_back(t.string()); weight.push_back(1); } } return; }
/************************************************************************* ЗАГРУЗКА ОПИСАНИЯ ИЗ ТЕКСТОВОГО ФАЙЛА 1. Общий формат: 1.1 Заголовок enum имя, синоним1, синоним2, ... Кроме основного имени можно устанавливать альтернативные имена координаты (синонимы). Это необходимо для работы с некоторыми просторечными конструкциями (типа слова 'ЕГОННЫЙ'). Имя координаты должно начинаться с буквы или символа '_'. 1.2 Список состояний (два взаимоисключающих случая): ... = имя_источника - таким способом координата [имя] получает тот же список состояний, что и заявленые для [имя_источник]. ... { сост1 сост2 ... состN } - в фигурных скобочках перечисляются имена состояний. 2. Один из особых случаев - координаты с двумя состояниями, представимыми по смыслу как TRUE и FALSE. Формат описани их несколько иной. Объявление имеет такой формат: : enum имя_координаты : То есть имена состояний явно не объявляются. Внутреннее описание также не загружается подставными именами состояний, но при операциях с координатами появление координаты с нулевым количеством состояний отлавливается и особо учитывается. **************************************************************************/ void GramCoord::LoadTxt( Macro_Parser &txtfile, const Grammar& gram, bool IsRealized ) { is_realized = IsRealized; BethToken coord_name = txtfile.read(); sol_check_coord_name(gram.GetDict(), txtfile, coord_name); name.push_back(coord_name.c_str()); const bool Me = gram.GetDict().GetDebugLevel_ir() >= 3; if (Me) { // Эхо-сообщение: начали трансляцию координаты. gram.GetIO().mecho().printf( "%us [%vfE%us%vn]->", sol_get_token(B_COORDINATE).c_str(), name.get(0).c_str() ); } BSourceState back = txtfile.tellp(); bool cname_loaded = false; if (txtfile.read().GetToken() == B_AS) { c_name = txtfile.read(); back = txtfile.tellp(); cname_loaded = true; } else txtfile.seekp(back); // Цикл загрузки компонентов описания координаты. bool loading = true; while (loading) { const BethToken t1 = txtfile.read(); switch (t1.GetToken()) { case B_EQUAL: { // Встретили спецификацию '='. Так что пересылаем себе состояния // другой координаты, имя которой идёт следом. const BethToken another = txtfile.read(); const GramCoordAdr ianother = gram.FindCoord(another.string()); if (ianother.GetIndex() == UNKNOWN) { Print_Error(another, txtfile); MemFormatter f; f.printf( "The coordinate [%us] is not previously " "declared in grammar\n" , another.c_str() ); throw E_Solarix(f.string().c_str()); } state = gram.coords()[ianother.GetIndex()].state; // Пересылаем себе состояния #if defined SOL_COMPILER // Очищаем C-имена состояний for (lem::Container::size_type i = 0; i < state.size(); ++i) { state[i].Clear_API_Names(); } #endif loading = false; // Больше считывать нечего break; } case B_COMMA: { // Через запятую идут синонимы имени координаты. const BethToken t2 = txtfile.read(); sol_check_s_name(gram.GetDict(), txtfile, t2, true); if (name.Find(t2.c_str()) != UNKNOWN) { Print_Error(t2, txtfile); MemFormatter f; f.printf("Duplication of the name in coordinate [%us] declaration\n", t2.c_str()); throw E_Solarix(f.string().c_str()); } name.push_back(t2.c_str()); break; } case B_OFIGPAREN: { // В фигурных скобочках перечислены возможные состояния координаты. while (!txtfile.eof()) { const BSourceState back2 = txtfile.tellp(); // Если это '}', то список атрибутов завершен. if (txtfile.read().GetToken() == B_CFIGPAREN) break; txtfile.seekp(back2); GramCoordState dummy; dummy.LoadTxt(gram.GetIO(), txtfile); // Нет повторных объявлений состояний? for (lem::Container::size_type i = 0; i < dummy.size(); i++) { // Проверим, чтобы в загруженной подгруппе не было двух // одинаковых имен. for (lem::Container::size_type j = 0; j < dummy.size(); j++) { if (i != j) if (dummy[i] == dummy[j]) { Print_Error(txtfile); MemFormatter f; f.printf("Two equal names in a coordinate [%us] state subgroup\n", name.string().c_str()); throw E_Solarix(f.string().c_str()); } } const UCString& look_for = dummy.get(i); if (FindState(look_for) != UNKNOWN) { Print_Error(txtfile); MemFormatter f; f.printf("Two states of coordinate [%us] have got the same name\n", name.string().c_str()); throw E_Solarix(f.string().c_str()); } } state.push_back(dummy); if (Me) gram.GetIO().mecho().printf('.'); } loading = false; break; } default: { if (states().size()) { Print_Error(t1, txtfile); MemFormatter f; f.printf( "Definition of the coordinate [%us] is not" " identical to previous one.\n" , name.string().c_str() ); throw E_Solarix(f.string().c_str()); } // Если это не открывающая фигурная скобочка, то имеем координату // с двумя состояниями TRUE и FALSE (бистабильную координату). txtfile.seekp(back); // На этом считывание описания заканчиваем. loading = false; break; } } // end of switch } // end of while if (Me) { // Эхо-сообщение: закончили трансляцию координаты. gram.GetIO().mecho().printf("%vfAOK%vn\n"); } return; }
void Word_Form::LoadPreciser( CompilationContext &context, Macro_Parser& txtfile, SynGram& gram, int iclass ) { // Тапереча в {} могет быть идти список уточняющих координат. // // Каждая уточняющая координата должна следовать такому формату: // // [~]имя_координаты:имя_состояния // // Причем, только если вместо имени статьи указан квантор всеобщности, // то разрешается задавать АТРИБУТЫ как координаты. // // Особо обрабатываются координаты с неявно объявленными состояниями // TRUE/FALSE. Следует учесть, что само упоминание имени такой координаты // равносильно упоминанию также и имени состояния TRUE, а для объявлени // состояния FALSE необходимо использовать конструкцию с оператором // отрицания НЕ. while(!txtfile.eof()) { // Считываем имя координаты. BethToken coord_name = txtfile.read(); // Может, список закончился, то есть встретилась '{' ? if( coord_name.GetToken()==B_CFIGPAREN ) break; // В двойных апострофах может идти имя формы, которую надо использовать вместо // имени словарной статьи. if( lem::in_quotes(coord_name.string()) ) { Lexem *mname = new Lexem( strip_quotes(coord_name) ); gram.GetDict().GetLexAuto().TranslateLexem(*mname,false); mname->Translate( gram.GetDict().GetGraphGram(), 2 ); name = RC_Lexem( mname ); } else { bool AFFIRM=true; if( coord_name.GetToken()==B_NEGATIVE ) { // Оператор отрицания перед определением координаты! AFFIRM=false; coord_name = txtfile.read(); } const GramCoordAdr iglob_coord = gram.FindCoord(coord_name.string()); // Попытаемся найти координату среди списка атрибутов и тэгов. int iloc_coord = gram.classes()[iclass].attrs().find(iglob_coord); // Нашли? if( iloc_coord!=UNKNOWN ) { // Да! Примем к сведению, что если для опорной точки задано // имя словарной статьи, то мы не имеем право по логике вещей // определять также и атрибуты, так как само определение словарной // статьи определяет необходимые атрибуты. if( entry_key!=ANY_STATE ) { lem::Iridium::Print_Error(coord_name,txtfile); gram.GetIO().merr().printf( "The attribute can not be declared here, because entry is already declared\n" ); throw E_ParserError(); } } else { // Попробуем найти координату среди списка измерений. iloc_coord = gram.classes()[iclass].dims().find(iglob_coord); if( iloc_coord==UNKNOWN ) iloc_coord = gram.classes()[iclass].tags().find(iglob_coord); // Нашли? if( iloc_coord==UNKNOWN && iclass!=SOL_EQUIL_INDEX ) { // Нет. Таким образом, имя координаты не определяет // ни тэг, ни измерение. Генерируем сообщение // об ошибке. lem::Iridium::Print_Error(coord_name,txtfile); gram.GetIO().merr() .printf( "Coordinate [%us] is neither tag" " nor dimention for the class [%us]\n" , coord_name.string().c_str() , gram.classes()[ iclass ].GetName().c_str() ); throw E_ParserError(); } } /*------------------------------------------------------------------------- Теперь считываем определение состояния. В некоторых случаях допускается такой формат записи: имя_координаты:=индекс Обычно так указываются те состояния, которые имеет данная координата у заданной индексом опорной точки контекста. Внутреннее описание в этом случае отличается от обычного лишь тем, что состояние имеет знак минус и хранит на самом деле числовое значение индекса минус единица, так что состояние -1 означает опорную точку 0, и так далее. Это сделано, чтобы корректно отличать случай состояния с нулевым индексом. -------------------------------------------------------------------------*/ int istate; const BSourceState back = txtfile.tellp(); if( txtfile.read().GetToken()==B_COLON && txtfile.read().GetToken()==B_EQUAL ) istate = -txtfile.read_int()-1; // Да, это формат ИМЯ_КООРД:=ИНДЕКС else { txtfile.seekp(back); // Является ли она бистабильной? if( gram.coords()[iglob_coord.GetIndex()].states().empty() ) { // Да - считывать имя состояния не надо. istate=AFFIRM; } else { // Индекс состояния у найденной координаты. txtfile.read_it(B_COLON); const BethToken state_name = txtfile.read(); istate = gram.coords()[iglob_coord.GetIndex()].FindState(state_name.string()); if( istate==UNKNOWN ) { lem::Iridium::Print_Error(state_name,txtfile); gram.GetIO().merr().printf( "State [%us] is not declared for coordinate [%us]\n" , state_name.c_str(), coord_name.c_str() ); throw E_ParserError(); } } } pair.push_back(GramCoordEx(iglob_coord,istate,AFFIRM)); } } // конец цикла считывания уточненных координат return; }
/************************************************************************* Загрузка дескриптора ребра из текстового файла. Распознаются форматы: 1. <имя_коорд:имя_связки> Расширенный формат, явно задано имя координаты имя_коорд, одно из состояний которой имя_связки признается за имя связки. Угловые скобки обязательны. Частные случаи этого формата: 1.1 <имя_коорд:*> То есть имя связки (состояния координаты имя_коорд) задается квантором производьности, и в дальнейших проверках игнорируется. 1.2 <имя_коорд:?> Имя связки задано как квантор UNKNOWN. 2. <имя_связки> Сокращенный формат, имя связки должно быть объявлено как имя состояния координаты с предопределенным именем net. 3. <*> Связка задана как квантор всеобщности, так что в операциях сравнения она будет подходить для любой другой связки. 4. <?> Особое задание связки - через квантор UNKNOWN. ***************************************************************************/ bool Tree_Link::LoadTxt(Macro_Parser &txtfile, const SynGram &gram) { const BSourceState back = txtfile.tellp(); BethToken coord_name = txtfile.read(); if (coord_name.GetToken() == B_OTRIPAREN) { coord_name = txtfile.read(); switch (coord_name.GetToken()) { case ANY_STATE: icoord = ANY_STATE; break; case UNKNOWN_STATE: icoord = UNKNOWN_STATE; break; default: { const BethToken t = txtfile.read(); if (t.GetToken() == B_COLON) { // Полный, расширенный формат с указанием имени координаты. if ((icoord = gram.FindCoord(coord_name.string()).GetIndex()) == UNKNOWN) { lem::Iridium::Print_Error(coord_name, txtfile); gram.GetIO().merr().printf( "The coordinate [%us] is not previously declared in grammar\n" , coord_name.c_str() ); throw E_ParserError(); } } else { icoord = I_NET; txtfile.seekp(coord_name); } const BethToken state_name = txtfile.read(); switch (state_name.GetToken()) { case B_ANY: istate = ANY_STATE; break; case B_UNKNOWN: istate = UNKNOWN_STATE; break; default: if ((istate = gram.coords()[icoord].FindState(state_name.string())) == UNKNOWN) { lem::Iridium::Print_Error(state_name, txtfile); gram.GetIO().merr().printf( "State [%us] is not declared for coordinate [%us]\n" , state_name.c_str(), gram.coords()[icoord].GetName().string().c_str() ); throw E_ParserError(); } break; } break; } } txtfile.read_it(B_CTRIPAREN); return true; } else { txtfile.seekp(back); icoord = UNKNOWN; istate = UNKNOWN; return false; } return false; }