// Синтаксис реализации таблицы склонения может быть более сложным, // чем для обычных таблиц форм: // // declension auto : NOUN for "(.+)S" // { ^^^^^^^^^^^ // : // // // Курсор считывания стоит на первой после имени класса (NOUN в примере) // лексеме. void SG_DeclensionTable::LoadBody( Macro_Parser &txtfile, Grammar& gram ) { if( txtfile.probe(B_FOR) ) { condition.LoadTxt( txtfile, GetClass(), (SynGram&)gram ); } Form_Table::LoadBody( txtfile, gram ); return; }
/************************************************************************** ЗАГРУЗКА ОДНОЙ АТРИБУТНОЙ КООРДИНАТНОЙ ПАРЫ из текстового файла Общий формат: коорд_имя : состояние Особое внимание следует уделять автоматическому созданию AND-атрибутов для многоохватных состояний. Если такое создание нежелательно, то следует заключить имя состояния, входящего в группу многоохватных, в круглые скобочки: коор_имя : ( состояние ) ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ: true - действительно, загружен атрибут или тэг. false - это не определение состояния атрибута или тэга. ****************************************************************************/ bool Form_Table::LoadAttribute( Macro_Parser &txtfile, Grammar& gram ) { const BSourceState back = txtfile.tellp(); bool negative_state = txtfile.probe(B_NEGATIVE); // считываем префикс в ~ПРИЧАСТИЕ BethToken coord_name = txtfile.read(); // Индекс координаты в списке грамматики. const GramCoordAdr iglob = gram.FindCoord(coord_name.string()); // Найдем атрибут в списке грамматического класса. const int iattr = gram.classes()[iclass].attrs().FindTwice(iglob); if (iattr == UNKNOWN) { const int itag = gram.classes()[iclass].tags().FindTwice(iglob); if (itag == UNKNOWN) { txtfile.seekp(back); return false; } } // Если координата имеет два неявно объявленных состояния // TRUE/FALSE, то состояние явно в данной секции не должно быть // указано. if (!gram.coords()[iglob.GetIndex()].IsBistable()) { // Несколько состояний у координаты. if (negative_state) { Print_Error(back, txtfile); gram.GetIO().merr().printf("~ is appliable to bistable coordinates only, whereas [%us] is not bistable\n", coord_name.c_str()); throw E_ParserError(); } txtfile.read_it(B_COLON); // Учтем, что может встретиться AND-атрибут. Такая координата // одновременно может иметь несколько состояний. IntCollect statei; IntCollect doload; FOREVER { if (txtfile.eof()) { Print_Error(txtfile); gram.GetIO().merr().printf("End of file has been reached before list of attribute states in entry completely loaded\n"); throw E_ParserError(); } // Теперь считаем состояние(-я) для заявленного атрибута. const BSourceState back = txtfile.tellp(); BethToken state_name = txtfile.read(); bool letautoload = true; if (state_name.GetToken() == B_ANY) { if (StoreQuantors()) { attr.push_back(GramCoordPair(iglob,ANY_STATE)); break; } else if (statei.empty()) { // Вместо имен состояний для AND-координаты указан квантор *. // Инициализируем координату ВСЕМИ состояниями, заявленными // для координаты. const int ns = gram.coords()[iglob.GetIndex()].GetTotalStates(); for (int i = 0; i < ns; i++) attr.push_back(GramCoordPair(iglob,i)); // Продолжать дальше считывание не имеет смысла. break; } } if (!statei.empty()) { // Если это запятая, то список AND-состояний продолжается. // в противном случае прерываем загрузку состояний. if (state_name.GetToken() != B_COMMA) { txtfile.seekp(back); break; } else state_name = txtfile.read(); } // Если имя атрибута заключено в круглые скобочки, то // для координатной пары запрещено автоматическое создание. if (state_name.GetToken() == B_OROUNDPAREN) { state_name = txtfile.read(); txtfile.read_it(B_CROUNDPAREN); letautoload = false; } // Ищем индекс состояния в координате const int istate = gram.coords()[iglob.GetIndex()].FindState(state_name.string()); if (istate == UNKNOWN) { 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(); } // Добавляем глобальный индекс атрибута и индекс его состояния // к нашим спискам. statei.push_back(istate); doload.push_back(letautoload); } // Состояния, которые объявлены для атрибута, превратим // в список координатных пар и добавим к своему списку // атрибутов статьи. lem::Container::size_type ils; for (ils = 0; ils < statei.size(); ils++) attr.push_back(GramCoordPair(iglob, statei[ils])); // Автоматически подключим те состояния, которые не запрещены // для этого пользователем, не объявлены и входят в подгруппу. const GramCoord& c = gram.coords()[iglob.GetIndex()]; IntCollect attaches; // Автоматически созданные и присоединяемые состояния for (ils = 0; ils < statei.size(); ils++) if (doload[ils]) { int ibase = statei[ils]; // Входит ли состояние в группу многоохватных как главное? if (c.IsHeadState(ibase)) { // Да, входит. // Получаем список состояний, входящих в группу. const IntCollect to_attach = c.GetSubgroupIndeces(c.GetSubgroup(ibase)); for (Container::size_type ia = 1; ia < to_attach.size(); ia++) { const int state_attach = to_attach.get(ia); // Очередное состояние из группы многоохватных // Посмотрим, можно ли присоединять состояние // iglob:state_attach. // // Противопоказания могут быть следующие. // // 1. Состояние уже присутствует в списке statei. // 2. Состояние уже автоматически создано и // добавлено в список attaches. // // 3. Координатная пара уже загружена в списки // статьи. bool already_loaded = false; if (attr.FindOnce(GramCoordPair(iglob, state_attach)) != UNKNOWN) already_loaded = true; if ( !already_loaded && find(statei, state_attach) == UNKNOWN && find(attaches, state_attach) == UNKNOWN ) attaches.push_back(state_attach); // К списку присоединяемых } } } if (!attaches.empty()) // Есть присоединяемые? { // Необходимо предупредить пользователя об автоматически // присоединяемых состояниях. lem::LogFile::logfile->printf("\nCoordinate pairs were autocreated for a form table:"); PrintName(*lem::LogFile::logfile); lem::LogFile::logfile->printf(" ->"); for (Container::size_type ils = 0; ils < attaches.size(); ils++) { if (ils) lem::LogFile::logfile->printf(","); lem::LogFile::logfile->printf( " %us%us%us ", c.GetName().string().c_str(), sol_get_token(B_COLON).c_str(), c.GetStateName(attaches[ils]).c_str() ); attr.push_back(GramCoordPair(iglob, attaches[ils])); } lem::LogFile::logfile->eol(); } } else { // Добавляем глобальный индекс атрибута и индекс его состояния // к нашим спискам, учитывая, что сам факт появления атрибута // с неявными состояниями TRUE/FALSE означает его состояние TRUE. // Если был префикс ~, то состояние присваиваем FALSE. // Есть один особый случай, когда для бистабильной координаты задается // состояние - для грамматических кванторов. В этом случае имя состояния // обязательно квантор * if (StoreQuantors())
SG_calibrator::SG_calibrator(const lem::UCString & keyword, const SynGram &sg, const Sol_IO &io, Macro_Parser &txtfile) { if (keyword.eqi(L"wordentry_freq")) freq_type = WordEntryFreq; else if (keyword.eqi(L"wordform_score")) freq_type = WordFormScore; else if (keyword.eqi(L"wordforms_score")) freq_type = WordFormsScore; id_class = UNKNOWN; freq = 0; word = txtfile.read().string(); word.strip(L'"'); // если далее идет открывающая фигурная скобка, то значит конкретизируется словоформа (или несколько // словоформ). if (txtfile.probe(B_OFIGPAREN)) { while (!txtfile.eof()) { if (txtfile.pick().GetToken() == B_CFIGPAREN) { txtfile.read(); break; } // для обычных: координата:состояние // для бистабильных: координата lem::Iridium::BethToken coord_name = txtfile.read(); if (id_class == UNKNOWN) { const int id_class0 = sg.FindClass(coord_name); if (id_class0 != UNKNOWN) { id_class = id_class0; continue; } } bool AFFIRM = true; if (coord_name.GetToken() == B_NEGATIVE) { // Оператор отрицания перед определением координаты! AFFIRM = false; coord_name = txtfile.read(); } const GramCoordAdr iglob_coord = sg.FindCoord(coord_name.string()); if (!iglob_coord.IsDefined()) { sg.GetIO().merr().printf("Unknown coordinate %us\n", coord_name.c_str()); lem::Iridium::Print_Error(coord_name, txtfile); throw lem::E_BaseException(); } if (sg.coords()[iglob_coord.GetIndex()].IsBistable()) { // Имя состояния не может быть указано. coords.push_back(GramCoordPair(iglob_coord, AFFIRM)); } else { // После двоеточия должно идти имя состояния для координаты. txtfile.read_it(B_COLON); // Имя состояния. BethToken state_name = txtfile.read(); // Получим индекс состояния для определенной координаты. const int istate = sg.coords()[iglob_coord.GetIndex()] .FindState(state_name.string()); if (istate == UNKNOWN) { // Нет такого состояния для этого измерения. lem::Iridium::Print_Error(state_name, txtfile); sg.GetIO().merr().printf( "State [%vfE%us%vn] is not declared for coordinate [%vfE%us%vn]\n" , state_name.c_str(), coord_name.c_str() ); throw E_ParserError(); } coords.push_back(GramCoordEx(iglob_coord, istate, AFFIRM)); } } } txtfile.read_it(B_EQUAL); if (txtfile.probe(B_SUB)) freq = -txtfile.read_int(); else freq = txtfile.read_int(); return; }