void Base_Entry::BeforeFirstForm(Grammar& gram) { if (is_quantor(GetClass())) return; const GramClass& cl = gram.classes()[GetClass()]; const int na = cl.attrs().size(); for (int i = 0; i < na; i++) { const GramCoordAdr iglob = cl.attrs()[i]; const GramClass &cls = gram.classes()[GetClass()]; if (GetAttrState(iglob) == UNKNOWN) { // Для атрибута задано значение по умолчанию? lem::zbool has_def; for (lem::Container::size_type j = 0; j < cls.attr_defaults.size(); ++j) { if (cls.attr_defaults[j].first == iglob) { if (cls.attr_defaults[j].second != UNKNOWN) { int ia = attr.FindOnce(iglob); if (ia != UNKNOWN) attr.Remove(ia); attr.push_back(GramCoordPair(iglob, cls.attr_defaults[j].second)); } has_def = true; break; } } if (!has_def) { // Если это координата с двумя неявно объявленными // состояниями, то следует установить состояние // атрибута как FALSE. if (gram.coords()[iglob.GetIndex()].states().empty()) attr.push_back(GramCoordPair(iglob, false)); } } } return; }
void SG_EntryForm::SaveTxt( OFormatter& txtfile, Grammar &gram, const SG_Entry &entry ) const { const GramClass &c = gram.classes()[ entry.GetClass() ]; txtfile.printf( " " ); for( Container::size_type i=0; i<coords().size(); i++ ) { const GramCoordPair cp = coords()[i]; if( find( c.attrs(), cp.GetCoord() )!=UNKNOWN ) continue; const GramCoord& c = gram.coords()[cp.GetCoord().GetIndex()]; const UCString& dim_name = c.GetName()[cp.GetCoord().GetVar()]; if( !c.states().empty() ) { const UCString &state_name = c.GetStateName(cp.GetState()); if( c.IsDefState(cp.GetState()) && c.IsHeadState(cp.GetState() ) ) txtfile.printf( "%us%us%us%us%us ", dim_name.c_str(), sol_get_token(B_COLON).c_str(), sol_get_token(B_OROUNDPAREN).c_str(), state_name.c_str(), sol_get_token(B_CROUNDPAREN).c_str() ); else txtfile.printf( "%us%us%us ", dim_name.c_str(), sol_get_token(B_COLON).c_str(), state_name.c_str() ); } else { UCString prefix; if(!cp.GetState()) prefix=sol_get_token(B_NEGATIVE); txtfile.printf( "%us%us ", prefix.c_str(), dim_name.c_str() ); } } txtfile.printf( " %us %us %us\n", sol_get_token(B_OFIGPAREN).c_str(), content->c_str(), sol_get_token(B_CFIGPAREN).c_str() ); return; }
/********************************************************************* Все атрибуты должны быть определены! Метод вызывается после чтения тела описания Статьи. **********************************************************************/ void Base_Entry::CheckAttr(Macro_Parser& txtfile, Grammar& gram) { if (is_quantor(GetClass())) return; const GramClass& cl = gram.classes()[GetClass()]; const int na = CastSizeToInt(cl.attrs().size()); for (int i = 0; i < na; i++) { const GramCoordAdr iglob = cl.attrs()[i]; const GramClass &cls = gram.classes()[GetClass()]; if (GetAttrState(iglob) == UNKNOWN) { lem::zbool def_unk; for (lem::Container::size_type j = 0; j < cl.attr_defaults.size(); ++j) { if (cl.attr_defaults[j].first == iglob && cl.attr_defaults[j].second == UNKNOWN) { def_unk = true; break; } } if (!def_unk) { // Состояние аттрибута не определено! Print_Error(txtfile); gram.GetIO().merr().printf( "Not defined attribute [%us] state\n", gram.coords()[iglob.GetIndex()].GetName()[iglob.GetVar()].c_str() ); throw E_ParserError(); } } } return; }
void SG_DeclensionForm::ReadAdditionalInfo( Grammar &gram, const SG_DeclensionTable &table, Macro_Parser& txtfile ) { // :: flexer рег_выражение for регулярное_выражение while( !txtfile.eof() ) { BethToken t = txtfile.read(); if( t==B_FOR ) { UFString re = strip_quotes( txtfile.read().string() ).c_str(); if( table.GetClass()!=UNKNOWN ) { const SG_Class &cls = (const SG_Class&)gram.classes()[ table.GetClass() ]; const int id_lang = cls.GetLanguage(); if( id_lang!=UNKNOWN ) { const SG_Language &lang = gram.GetDict().GetSynGram().languages()[id_lang]; lang.SubstParadigmPattern(re); } } condition_str = re; condition = boost::wregex( re.c_str(), boost::basic_regex<wchar_t>::icase ); valid_condition = true; } else if( t==B_FLEXER ) { UFString re = strip_quotes( txtfile.read().string() ).c_str(); flexer_flags_str = re; flexer_flags = boost::wregex( re.c_str(), boost::basic_regex<wchar_t>::icase ); valid_flexer_flags = true; } else { txtfile.seekp(t); break; } } 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())