// Проверяем, что в теле паттерна на самом деле экспортированы все координаты и именованные узлы, которые объявлены // в секции export. В случае неуспеха проверки возвращается false. bool SynPatternCompilation::PatternHasBeenCompiled( SynGram &sg ) const { bool ok=true; for( lem::Container::size_type i=0; i<export_coords.size(); ++i ) if( actually_exported_coords.find( export_coords[i] )==UNKNOWN && null_export_coords.find(export_coords[i])==UNKNOWN ) { sg.GetIO().merr().printf( "Coordinate [%us] is declared as exportable but was not actually exported\n" , sg.coords()[export_coords[i]].GetName().string().c_str() ); ok=false; } for( lem::Container::size_type i=0; i<export_nodes.size(); ++i ) { lem::UCString uname = lem::to_upper(export_nodes[i]); if( actually_exported_nodes.find( uname )==UNKNOWN && null_export_nodes.find(uname)==UNKNOWN ) { sg.GetIO().merr().printf( "Node [%us] is declared as exportable but was not actually exported\n", export_nodes[i].c_str() ); ok=false; } } return ok; }
void SG_NetLink::SaveTagsTxt( OFormatter &txtfile, SynGram &gram ) const { if( tags!=0 ) { txtfile.printf( " tags { " ); SG_TagsList tags_ptr = gram.Get_Net().tag_sets->operator [](tags); for( lem::Container::size_type i=0; i<tags_ptr->size(); ++i ) { const int itag = (*tags_ptr)[i].first; const int ival = (*tags_ptr)[i].second; const ThesaurusTag &tag = gram.Get_Net().GetTagDefs()[itag]; txtfile.printf( " \"%us\"", tag.GetName().c_str() ); if( ival!=UNKNOWN ) { const lem::UCString &val = tag[ival]; txtfile.printf( "=\"%us\"", val.c_str() ); } txtfile.printf( " }" ); } } return; }
void SG_CoordContext::SaveTxt( OFormatter &txt, SynGram &sg ) const { const UCString &class_name = sg.classes()[iclass].GetName(); txt.printf( " %us:\"???\" { " , class_name.c_str() ); for( Container::size_type k=0; k<coords.size(); k++ ) { const int icoord = coords[k].GetCoord().GetIndex(); const int istate = coords[k].GetState(); const UCString &coord_name = sg.coords()[ icoord ].GetName().front(); if( !sg.coords()[icoord].states().size() ) { if( istate!=0 ) txt.printf( " %us", coord_name.c_str() ); else txt.printf( " ~%us", coord_name.c_str() ); } else { const UCString &state_name = sg.coords()[ icoord ].GetStateName( istate ); txt.printf( " %us:%us", coord_name.c_str(), state_name.c_str() ); } } txt.printf( " }" ); return; }
void SG_EntryForm::Reattach_To_Refs( SynGram &sg ) { // Название формы. content = sg.GetEntries().ReattachLexeme(content); // Координаты dim = sg.GetEntries().ReattachCoordPairs(dim); return; }
void Tree_Node::PrintXML(OFormatter &xml, SynGram &gram) const { xml.printf("<node>"); xml.printf("<wordform>"); if (!node.IsNull()) node->PrintXML(xml, gram); xml.printf("</wordform>"); if (!child.Empty()) { xml.printf("<leaves count=\"%d\">", CastSizeToInt(child.size())); for (Container::size_type i = 0; i < child.size(); i++) { int link_type_id = child[i].GetLink().GetState(); lem::UCString link_name = link_type_id == UNKNOWN ? L"" : gram.GetLink(link_type_id); xml.printf("<leaf n=\"%d\" arc_type=\"%d\" arc_name=\"%us\">\n", CastSizeToInt(i), link_type_id, link_name.c_str()); child[i].PrintXML(xml, gram); xml.printf("</leaf>\n"); } xml.printf("</leaves>"); } if (!dims.empty()) { xml.printf("<dims count=\"%d\">", CastSizeToInt(dims.size())); for (lem::Container::size_type i = 0; i < dims.size(); ++i) { const TreeDimension &d = *dims[i]; xml.printf("<dim n=\"%d\" name=\"%us\">\n", CastSizeToInt(i), d.GetName().c_str()); d.PrintXML(xml, gram.GetDict()); xml.printf("</dim>\n"); } xml.printf("</dims>"); } if (!marks.empty()) { xml.printf("<marks count=\"%d\">", CastSizeToInt(marks.size())); for (lem::Container::size_type i = 0; i < marks.size(); ++i) { xml.printf("<mark n=\"%d\">\n", CastSizeToInt(i)); marks[i]->PrintXML(xml, gram.GetDict()); xml.printf("</mark>\n"); } xml.printf("</marks>"); } xml.printf("</node>"); return; }
void Solarix::PrintTags( SG_TagsList tags, lem::UFString &str, SynGram &sg ) { str.clear(); if( tags!=NULL ) { for( lem::Container::size_type i=0; i<tags->size(); ++i ) { const int itag = (*tags)[i].first; const int ival = (*tags)[i].second; const ThesaurusTag &tag = sg.Get_Net().GetTagDefs()[itag]; if( !str.empty() ) str += L' '; str += tag.GetName().c_str(); if( ival!=UNKNOWN ) { const lem::UCString &val = tag[ival]; str += L'='; str += val.c_str(); } } } return; }
Predef_Word_Form::Predef_Word_Form( int ientry_key, SynGram &gram ) :Word_Form( RC_Lexem( const_cast<Lexem*>(&gram.GetEntry( ientry_key ).GetName()), null_deleter() ), RC_Lexem( const_cast<Lexem*>(&gram.GetEntry( ientry_key ).GetName()), null_deleter() ), ientry_key, Real1(100) ) {}
void SG_NetLink::PrintTagsTxt( lem::UFString &res, SynGram &gram ) const { if( tags!=0 ) { SG_TagsList tags_ptr = (*gram.Get_Net().tag_sets)[tags]; PrintTags( tags_ptr, res, gram ); } return; }
void BackTraceItem::Print( lem::OFormatter &to, SynGram &sg, bool detailed ) const { if( wf!=NULL ) { Solarix::Word_Form dummy( *wf, false ); wf->Print( to, &sg, detailed ); } if( !export_coords.empty() ) { to.printf( " export_coords:=%vf6(%vn" ); for( lem::Container::size_type i=0; i<export_coords.size(); ++i ) { const int id_coord = export_coords[i].GetCoord().GetIndex(); const int id_state = export_coords[i].GetState(); const GramCoord &c = sg.coords()[id_coord]; if( c.IsBistable() ) { if( id_state==1 ) { to.printf( " %us", c.GetName().string().c_str() ); } else { to.printf( " ~%us", c.GetName().string().c_str() ); } } else { to.printf( " %us:%us", c.GetName().string().c_str(), c.GetStateName(id_state).c_str() ); } } to.printf( " %vf6)%vn" ); } if( !export_nodes.empty() ) { to.printf( " export_nodes:=" ); for( lem::Container::size_type i=0; i<export_nodes.size(); ++i ) { to.printf( " %us=", export_nodes[i].first->c_str() ); export_nodes[i].second->Print( to, &sg, true ); } to.eol(); } return; }
void Tree_Link::SaveTxt(OFormatter &txtfile, const SynGram &gram) const { if (icoord == UNKNOWN || icoord == UNKNOWN_STATE || icoord == ANY_STATE) return; txtfile << sol_get_token(B_OTRIPAREN); switch (icoord) { case ANY_STATE: txtfile << sol_get_token(B_ANY); break; case I_NET: txtfile << gram.coords()[icoord].GetStateName(istate); break; default: { txtfile << gram.coords()[icoord].GetName().front() << sol_get_token(B_COLON); switch (istate) { case ANY_STATE: txtfile << sol_get_token(B_ANY); break; case UNKNOWN_STATE: txtfile << sol_get_token(B_UNKNOWN); break; default: txtfile << gram.coords()[icoord].GetStateName(istate); break; } break; } } txtfile << sol_get_token(B_CTRIPAREN); return; }
void LA_WordProjBuffer::PrintMap( OFormatter &txtfile, SynGram &gram ) const { Report(txtfile,gram.GetDict().GetLexAuto()); txtfile.printf( "There are %d item(s) in word projection cache:\n", list.size() ); for( Container::size_type i=0; i<list.size(); i++ ) { list[i].PrintInfo(txtfile,gram); } txtfile.printf( "The end of word projection cache map.\n" ); return; }
void SynPatternResult::PrintLinks(lem::OFormatter &out, SynGram &sg) const { lem::mout->printf("\nThere are %d edges:\n", CastSizeToInt(linkage_edges.size())); for (lem::Container::size_type k = 0; k < linkage_edges.size(); ++k) { const PatternLinkEdge & edge = linkage_edges[k]; Solarix::Word_Form wf0(*edge.from, false); Solarix::Word_Form wf1(*edge.to, false); lem::UCString link_name; if (edge.link_type == UNKNOWN) link_name = L"((unknown))"; else link_name = sg.coords()[0].GetStateName(edge.link_type); wf0.Print(out, &sg, true); out.printf(" --(%us)--> ", link_name.c_str()); wf1.Print(out, &sg, true); out.eol(); } return; }
// *************************************************************** // Лексическое содержимое словоформы приводим в соответствие с // координатами. // *************************************************************** void Word_Form::Rename_By_States( SynGram &sg, bool apply_versions ) { iversion = seq_iversion++; if( entry_key!=UNKNOWN ) { try { const SG_Entry &E = sg.GetEntry(entry_key); const int iclass = E.GetClass(); const GramClass &C = sg.classes()[ iclass ]; // Имеем список всех координатных пар. Из него надо выделить только // измерения. CP_Array dims; dims.reserve(16); for( Container::size_type ic=0; ic<pair.size(); ic++ ) { if( C.dims().find( pair[ic].GetCoord() ) != UNKNOWN ) dims.push_back( pair[ic] ); } // Собрали в список dims только измерения. // Ищем подходящую по координатам форму. const SG_EntryForm &F = E.FindFormAny(dims); // Перекачаем ее координаты себе. const CP_Array& c = F.coords(); for( Container::size_type i2=0; i2<c.size(); i2++ ) SetState( c[i2], false, false ); #if LEM_DEBUGGING==1 const int npairs2 = CastSizeToInt(pair.size()); #endif // Нашли наиболее подходящую форму - берем ее лексическое содержание. const Lexem &new_name = F.name(); name = RC_Lexem( new Lexem(new_name) ); /* // Просто поменять имя словоформы нельзя, так как мы можем быть результатом // свертки. Надо вычленить из списка name те лексемы, которые относятся к // обновленной форме (грамматическому центру), и заменить их на новое // значение. // Начальная позиция в цепочке лексем int i_from = lem::find( lexem_owner, icenter ); int n = std::count( lexem_owner.begin(), lexem_owner.end(), icenter ); UCStringSet parts; new_name.Split(parts); if( n == parts.size() ) { // Число лексем в имени не поменялось UCStringSet old_parts; name->Split( old_parts ); for( int i=0; i<n; i++ ) old_parts[i_from+i] = parts[i]; name = RC_Lexem( new Lexem(old_parts) ); } else { // Вряд ли возможная ситуация: у найденной формы имя имеет иное // число лексем, чем у прежней формы. //LEM_STOPIT; // throw E_BaseException( L"Internal syntax engine error" ); } */ } catch( const E_SG_NoForm& ) { } } if( apply_versions ) for( lem::Container::size_type i=0; i<alt.size(); ++i ) alt[i]->Rename_By_States( sg, true ); 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; }
void SynPattern::CheckBeforeMerge( const SynPattern &x, SynGram &sg ) const { try { compilation_context->CheckThatVariablesTheSame( * x.compilation_context ); } catch( const E_BaseException &e ) { lem::MemFormatter mem; mem.printf( "Error %us\n", e.what() ); mem.printf( "Two contexts have different variables set:\nFirst: " ); this->Print( mem, sg ); mem.printf( "\nSecond: " ); x.Print( mem, sg ); throw lem::E_BaseException( mem.string() ); } // проверим, что экспортируютс¤ одни и те же координаты lem::MCollect<int> mismatched_coords; for( lem::Container::size_type i=0; i<export_info.export_coords.size(); ++i ) if( x.export_info.export_coords.find( export_info.export_coords[i] )==UNKNOWN ) mismatched_coords.push_back( export_info.export_coords[i] ); for( lem::Container::size_type i=0; i<x.export_info.export_coords.size(); ++i ) if( export_info.export_coords.find( x.export_info.export_coords[i] )==UNKNOWN ) mismatched_coords.push_back( x.export_info.export_coords[i] ); if( !mismatched_coords.empty() ) { lem::MemFormatter mem; mem.printf( "Mismatching coordinates in pattern %us:", name.c_str() ); for( lem::Container::size_type i=0; i<mismatched_coords.size(); ++i ) { const lem::UCString &cname = sg.coords()[ mismatched_coords[i] ].GetName()[0]; mem.printf( " %us", cname.c_str() ); } throw lem::E_BaseException( mem.string() ); } lem::MCollect<lem::UCString> mismatched_nodes; for( lem::Container::size_type i=0; i<export_info.export_nodes.size(); ++i ) if( x.export_info.export_nodes.find( export_info.export_nodes[i] )==UNKNOWN ) mismatched_nodes.push_back( export_info.export_nodes[i] ); for( lem::Container::size_type i=0; i<x.export_info.export_nodes.size(); ++i ) if( export_info.export_nodes.find( x.export_info.export_nodes[i] )==UNKNOWN ) mismatched_nodes.push_back( x.export_info.export_nodes[i] ); if( !mismatched_nodes.empty() ) { lem::MemFormatter mem; mem.printf( "Mismatching nodes in pattern %us:", name.c_str() ); for( lem::Container::size_type i=0; i<mismatched_nodes.size(); ++i ) { mem.printf( " %us", mismatched_nodes[i].c_str() ); } throw lem::E_BaseException( mem.string() ); } return; }
bool BackTraceItem::Check( SynGram &sg, const BackRefCorrel & condition, const Solarix::Word_Form & alt ) const { const int id_coord0 = condition.id_coord0; // состо¤ние этой координаты в alt // должно соответствовать const int id_coord1 = condition.id_coord1; // состо¤нию этой координаты в нашем объекте const CPE_Array & alt_pairs = alt.pairs(); const lem::Container::size_type n1 = alt_pairs.size(); if( condition.affirmative ) { bool alt_has_coord=false, b_has_coord=false; if( use_export ) { for( lem::Container::size_type i=0; i<n1; ++i ) { if( id_coord0 == alt_pairs[i].GetCoord().GetIndex() ) { alt_has_coord=true; const int alt_state = alt_pairs[i].GetState(); if( condition.for_group ) { // проверим через сопоставление групп, например –ќƒ»“≈Ћ№Ќџ… и ѕј–“»“»¬ дл¤ падежа дадут совпадение const GramCoord &c = sg.coords()[ id_coord0 ]; const int alt_state_group = c.GetSubgroup(alt_state); const lem::Container::size_type n2 = this->export_coords.size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->export_coords[j].GetCoord().GetIndex() ) { const int state2_group = c.GetSubgroup(this->export_coords[j].GetState()); b_has_coord = true; if( alt_state_group==state2_group ) { // нашли соответствие подгрупп. return true; } } } } else { // »щем такое состо¤ние... const lem::Container::size_type n2 = this->export_coords.size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->export_coords[j].GetCoord().GetIndex() ) { b_has_coord=true; if( this->export_coords[j].GetState()==alt_state ) { // нашли соответствие. return true; } } } } } } } else { for( lem::Container::size_type i=0; i<n1; ++i ) { if( id_coord0 == alt_pairs[i].GetCoord().GetIndex() ) { alt_has_coord=true; const int alt_state = alt_pairs[i].GetState(); if( condition.for_group ) { const GramCoord &c = sg.coords()[ id_coord0 ]; const int alt_state_group = c.GetSubgroup(alt_state); const lem::Container::size_type n2 = this->wf->pairs().size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->wf->pairs()[j].GetCoord().GetIndex() ) { b_has_coord=true; const int state2_group = c.GetSubgroup(this->wf->pairs()[j].GetState()); if( state2_group==alt_state_group ) { return true; } } } } else { // »щем такое состо¤ние... const lem::Container::size_type n2 = this->wf->pairs().size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->wf->pairs()[j].GetCoord().GetIndex() ) { b_has_coord=true; if( this->wf->pairs()[j].GetState()==alt_state ) { return true; } } } } } } } return !alt_has_coord || !b_has_coord; } else { if( use_export ) { for( lem::Container::size_type i=0; i<n1; ++i ) { if( id_coord0 == alt_pairs[i].GetCoord().GetIndex() ) { const int alt_state = alt_pairs[i].GetState(); if( condition.for_group ) { const GramCoord &c = sg.coords()[ id_coord0 ]; const int alt_state_group = c.GetSubgroup(alt_state); const lem::Container::size_type n2 = export_coords.size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == export_coords[j].GetCoord().GetIndex() ) { const int state2_group = c.GetSubgroup(export_coords[j].GetState()); if( state2_group==alt_state_group ) { return false; } } } } else { // »щем такое состо¤ние... const lem::Container::size_type n2 = export_coords.size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == export_coords[j].GetCoord().GetIndex() ) { if( export_coords[j].GetState()==alt_state ) { return false; } } } } } } } else { for( lem::Container::size_type i=0; i<n1; ++i ) { if( id_coord0 == alt_pairs[i].GetCoord().GetIndex() ) { const int alt_state = alt_pairs[i].GetState(); if( condition.for_group ) { const GramCoord &c = sg.coords()[ id_coord0 ]; const int alt_state_group = c.GetSubgroup(alt_state); const lem::Container::size_type n2 = this->wf->pairs().size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->wf->pairs()[j].GetCoord().GetIndex() ) { const int state2_group = c.GetSubgroup(this->wf->pairs()[j].GetCoord().GetIndex()); if( state2_group==alt_state_group ) { return false; } } } } else { // »щем такое состо¤ние... const lem::Container::size_type n2 = this->wf->pairs().size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->wf->pairs()[j].GetCoord().GetIndex() ) { if( this->wf->pairs()[j].GetState()==alt_state ) { return false; } } } } } } } return true; } return false; }
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; }
/****************************************************************** Считывание описание узла BETH-дерева из текстового файла Словаря. *******************************************************************/ void Word_Form::LoadTxt( CompilationContext &context, Macro_Parser &txtfile, SynGram &gram ) { val=Real1(100); score=0; iversion = seq_iversion++; // Сначала считываем определение класса и имя словарной статьи. const BethToken class_name = txtfile.read(); entry_key=UNKNOWN_STATE; int iclass; // Если считанная лексема заключена в апострофы, то имеем дело // с сокращенным форматом: ?:строка. Этот формат применяется дл // описания лексемы, принадлежность которой к какому-либо классу // не очевидна или не важна, а важно лексическое представление. if( in_apostrophes(class_name.string()) ) { name = RC_Lexem( new Lexem(strip_quotes(class_name.string())) ); return; } if( class_name.string()==SOL_UNKNOWN_ENTRY_NAME ) { // Только одна статья принадлежит особому классу UNKNOWN! // Эта статья может быть описана только как "?:?" if( txtfile.read().string()==sol_get_token(B_COLON) && txtfile.read().string()==sol_get_token(B_UNKNOWN) ) { const Word_Coord iuu = gram.FindEntryForm( class_name.string() ); const SG_Entry& euu = gram.GetEntry(iuu.GetEntry()); iclass=UNKNOWN_STATE; entry_key = euu.GetKey(); return; } } // Пытаемся найти имя синтаксического класса в списке // уже загруженных в Словаре для синтаксической грамматики. if( (iclass=gram.FindClass(class_name.string()))==UNKNOWN ) { // Класс не определен. // // Предполагаем, что задано лексическое содержимое некоторой // словоформы. Если такая словоформа лексически уникальна, // то мы сами можем восстановить пару класс:статья. В случае // множественности вариантов тяжесть ответственности ложитс // на пользователя. Word_Coord ie = gram.FindEntryForm( class_name.string() ); if( ie.GetEntry()==UNKNOWN ) { // Выводим сообщение о неверном имени синтаксического класса или // ненайденной словоформе. lem::Iridium::Print_Error(class_name,txtfile); gram.GetIO().merr().printf("Neither a class previously declared in grammar, nor an entry form\n"); throw E_ParserError(); } if( ie.GetEntry()!=UNKNOWN ) { // Словоформа найдена! const SG_Entry& ef = gram.GetEntry(ie.GetEntry()); entry_key = ef.GetKey(); // Вероятно, следует также переслать координатные пары. const SG_EntryForm& eef = ef.forms()[ ie.GetForm() ]; const CP_Array& dims = eef.coords(); for( Container::size_type ii=0; ii<dims.size(); ii++ ) { // Здесь немного наворочено - прямо использовать конструктор без // копирования в промежуточные поля нельзя из-за ошибки в // кодогенераторе Symantec C++ (появляется General Protection Fault). const GramCoordAdr ca = dims[ii].GetCoord(); const int cs = dims[ii].GetState(); pair.push_back( GramCoordEx( ca, cs, true ) ); } // И наконец, пересылаем полное имя (лексическое содержимое) статьи. // icenter=0; // e_list.push_back( entry_key ); name = RC_Lexem( const_cast<Lexem*>(&ef.GetName()), null_deleter() ); } return; } const BSourceState back=txtfile.tellp(); const BethToken t = txtfile.read(); bool read_ofigparen=true; if( t.GetToken()==B_COLON ) { // Считываем имя статьи, которое может в общем случае состоять // из нескольких лексем. Признаком окончания имени служит // открывающая фигурная скобка '{'. Lexem *mname = new Lexem( sol_read_multyname( gram.GetIO(), txtfile,B_OFIGPAREN) ); // Преобразуем в мультилексему так, чтобы правильно распознавались // объявления имен типа "ЕЩ^Ё". gram.GetDict().GetLexAuto().TranslateLexem(*mname,false); mname->Translate( gram.GetDict().GetGraphGram(), 2 ); //(*name) = mname; name = RC_Lexem( mname ); // lexem_owner.resize(1); // lexem_owner.Nullify(); read_ofigparen=false; // Пытаемся найти статью. if( *mname != sol_get_token(B_ANY) ) { // Считан НЕ квантор всеобщности, так что это должно быть имя статьи. // Попытаемся найти статью среди уже загруженных, причем ищем с // критерием принадлежности определенному синтаксическому классу. const int ientry=gram.FindEntry2(*mname,iclass); // Нашли ? if( ientry==UNKNOWN ) { // Нет! Выводим сообщение об неверном имени словарной статьи. lem::Iridium::Print_Error(txtfile); gram.GetIO().merr().printf( "The entry [%us:%us] is not previously declared in grammar\n" , gram.classes()[iclass].GetName().c_str() , mname->ToString().c_str() ); throw E_ParserError(); } // Запомним КЛЮЧ словарной статьи. entry_key=gram.GetEntry(ientry).GetKey(); } else entry_key=ANY_STATE; } else { txtfile.seekp(back); entry_key=ANY_STATE; } bool load_precise=true; if( read_ofigparen ) { const BSourceState back = txtfile.tellp(); if( txtfile.read().GetToken()!=B_OFIGPAREN ) { // Секции уточнения координат нет. txtfile.seekp(back); load_precise = false; } } if(load_precise) LoadPreciser(context,txtfile,gram,iclass); return; }
void Tree_Node::Print(OFormatter &txtfile, SynGram &gram, int offset, bool detailed) const { int Offset = offset; if (offset > 0) txtfile.printf("%H ", offset); ilink.Print(txtfile, gram); if (node.IsNull()) txtfile.printf("%vfC(null)%vn"); else node->Print(txtfile, &gram, detailed); if (!child.Empty()) { if (detailed) { txtfile.printf('.'); if (child.size() != 1) txtfile.printf('{'); } if (Offset != -1) { txtfile.eol(); Offset++; } for (Container::size_type i = 0; i < child.size(); i++) { if (Offset == -1 && i) txtfile.printf(' '); if (Offset != -1) txtfile.printf("%H ", Offset); child[i].Print(txtfile, gram, Offset, detailed); } if (detailed) { if (offset != -1) txtfile.printf("%H ", Offset - 1); if (child.size() != 1) txtfile.printf('}'); } } if (!dims.empty()) { for (lem::Container::size_type i = 0; i < dims.size(); ++i) { const TreeDimension &d = *dims[i]; txtfile.printf(' '); d.Print(gram.GetDict(), txtfile, detailed); } } if (detailed && !marks.empty()) { txtfile.printf(" %vf6marks={%vn"); for (lem::Container::size_type i = 0; i < marks.size(); ++i) { txtfile.printf(' '); marks[i]->Print(gram.GetDict(), txtfile); } txtfile.printf(" %vf6}%vn"); } if (Offset != -1) txtfile.eol(); return; }
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; }
void SG_ComplexLink::LoadPoint( Macro_Parser &txtfile, SynGram &gram, lem::UFString &entry ) { BethToken t = txtfile.read(); if( t.GetToken()==B_ENTRY ) { // Особый формат entry Класс:Статья { уточнение } // преобразуется в ключ статьи и возвращается в виде #ключ UCString class0 = txtfile.read().string(); const int ic0 = class0==L"?" ? ANY_STATE : gram.FindClass(class0); if( ic0==UNKNOWN ) { Print_Error( txtfile ); gram.GetIO().merr().printf( "Unknown class %us\n", class0.c_str() ); throw E_BaseException(); } txtfile.read_it( B_COLON ); UCString entry0 = sol_read_multyname( gram.GetIO(), txtfile, B_OFIGPAREN ); entry0.strip(L'"'); entry0.trim(); // Может быть задана дополнительная фильтрующая координата Solarix::CP_Array coords0; coords0.LoadTxt( txtfile, gram ); if( gram.IsOmonym(ic0,lem::to_upper(entry0)) && coords0.empty() ) { Print_Error( txtfile ); gram.GetIO().merr().printf( "Omonym %us:%us requires the coordinate array\n", class0.c_str(), entry0.c_str() ); throw E_BaseException(); } const int ie0 = coords0.empty() ? gram.FindEntry(entry0,ic0,false) : gram.FindEntryOmonym(entry0,ic0,coords0); if( ie0==UNKNOWN ) { Print_Error( txtfile ); gram.GetIO().merr().printf( "Unknown entry %us:%us\n", class0.c_str(), entry0.c_str() ); throw E_BaseException(); } const int ekey = gram.GetEntry(ie0).GetKey(); entry = lem::format_str( L"#%d", ekey ); return; } bool figparen = t.GetToken()==B_OFIGPAREN; if( !figparen ) txtfile.seekp(t); entry.reserve(128); if( t.string()==L'@' ) { entry = L'@'; t = txtfile.read(); } while( !txtfile.eof() ) { BethToken t = txtfile.read(); if( figparen && t.GetToken()==B_CFIGPAREN ) break; if( !entry.empty() ) entry.Add_Dirty(L' '); UFString ts( t.GetFullStr() ); ts.strip(L'"'); entry.Add_Dirty( ts ); if( !figparen ) break; } entry.calc_hash(); if( entry.front()==L'@' ) { // Спецсимвол @ заставляет запомнить строку в виде "как есть" entry.remove(0); entry.trim(); } else { entry.strip(L'"'); gram.GetDict().GetLexAuto().TranslateLexem(entry,true); } return; }
CasingCoder::CasingCoder( SynGram &sg ) : SG(sg) { default_xlat = new XLAT(); default_xlat->use_unicode = true; GraphGram &gg = sg.GetDict().GetGraphGram(); LexicalAutomat &la = sg.GetDict().GetLexAuto(); Lower=UNKNOWN; FirstCapitalized=UNKNOWN; Upper=UNKNOWN; EachLexemCapitalized=UNKNOWN; UnknownEntries_ekey=UNKNOWN; icoord_casing = sg.FindCoord( L"CharCasing" ).GetIndex(); if( icoord_casing!=UNKNOWN ) { const Solarix::GramCoord &c = sg.coords()[icoord_casing]; Lower = c.FindState( L"Lower" ); FirstCapitalized = c.FindState(L"FirstCapitalized"); Upper = c.FindState(L"Upper"); EachLexemCapitalized = c.FindState(L"EachLexemCapitalized"); UnknownEntries_ekey = la.GetUnknownEntryKey(); // ------ //lem::FString msg = lem::format_str( "icoord_casing=%d Lower=%d FirstCapitalized=%d Upper=%d", icoord_casing, Lower, FirstCapitalized, Upper ); //MessageBox( NULL, msg.c_str(), "DEBUG-2", MB_OK ); // ------ } // Определим языки вывода по-умолчанию sg.GetLanguageUsage().GetOutputLanguages(default_xlat->id_langs); // Для каждого языка смотрим имена таблиц для перевода в верхний и нижний регистры. for( lem::Container::size_type i=0; i<default_xlat->id_langs.size(); ++i ) { const int id_lang = default_xlat->id_langs[i]; const SG_Language &lang = sg.languages()[id_lang]; const int iparam_l = lang.FindParam( L"LowerCase", 0 ); if( iparam_l!=UNKNOWN ) { const lem::UFString &xlat_name = lang.params[iparam_l]->values.front(); const GG_CharOperation *xlat = gg.GetCharOperations()[xlat_name.c_str()]; default_xlat->lower_xlat.push_back(xlat); } const int iparam_u = lang.FindParam( L"UpperCase", 0 ); if( iparam_u!=UNKNOWN ) { const lem::UFString &xlat_name = lang.params[iparam_u]->GetValue(); const GG_CharOperation *xlat = gg.GetCharOperations()[xlat_name.c_str()]; default_xlat->upper_xlat.push_back(xlat); } } if( !default_xlat->upper_xlat.empty() && !default_xlat->lower_xlat.empty() ) default_xlat->use_unicode = false; for( lem::Container::size_type i=0; i<default_xlat->id_langs.size(); ++i ) lang2xlat.insert( std::make_pair( default_xlat->id_langs[i], default_xlat ) ); return; }
void Tree_Link::Print(OFormatter &txtfile, const SynGram &gram) const { if (icoord == UNKNOWN_STATE || icoord == UNKNOWN || istate == UNKNOWN || istate == ANY_STATE || istate == UNKNOWN_STATE) return; txtfile.printf("%vfC%us", sol_get_token(B_OTRIPAREN).c_str()); switch (icoord) { // case UNKNOWN: // case UNKNOWN_STATE: // txtfile.printf( "%us", sol_get_token(B_UNKNOWN).c_str() ); // break; case ANY_STATE: txtfile.printf("%us", sol_get_token(B_ANY).c_str()); break; case I_NET: txtfile.printf( "%vf2%us", gram.coords()[icoord].GetStateName(istate).c_str() ); break; default: txtfile.printf( "%vf2%us%vfC%us", gram.coords()[icoord].GetName().string().c_str(), sol_get_token(B_COLON).c_str() ); switch (istate) { case ANY_STATE: txtfile.printf( "%vf2%us", sol_get_token(B_ANY).c_str() ); break; case UNKNOWN_STATE: txtfile.printf( "%vf2%us", sol_get_token(B_UNKNOWN).c_str() ); break; default: txtfile.printf( "%vf2%us", gram.coords()[icoord].GetStateName(istate).c_str() ); break; } break; } txtfile.printf("%vfC%us%vn", sol_get_token(B_CTRIPAREN).c_str()); return; }
bool BackTraceItem::Check( SynGram &sg, const BackRefCorrel & condition, const std::multimap<int,int> & alt_coords ) const { const int id_coord0 = condition.id_coord0; // состо¤ние этой координаты в alt_coords // должно соответствовать const int id_coord1 = condition.id_coord1; // состо¤нию этой координаты в нашем объекте typedef std::multimap<int,int>::const_iterator II4; if( condition.affirmative ) { bool alt_has_coord=false, b_has_coord=false; if( use_export ) { std::pair<II4,II4> p4 = alt_coords.equal_range(id_coord0); if( condition.for_group ) { const GramCoord &co = sg.coords()[ id_coord0 ]; for( II4 it4=p4.first; it4!=p4.second; ++it4 ) { alt_has_coord=true; const int alt_state = it4->second; const int alt_state_group = co.GetSubgroup(alt_state); // »щем такое состо¤ние... const lem::Container::size_type n2 = this->export_coords.size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->export_coords[j].GetCoord().GetIndex() ) { b_has_coord=true; const int export_state_group = co.GetSubgroup( this->export_coords[j].GetState() ); if( export_state_group==alt_state_group ) { // нашли соответствие. return true; } } } } } else { for( II4 it4=p4.first; it4!=p4.second; ++it4 ) { alt_has_coord=true; const int alt_state = it4->second; // »щем такое состо¤ние... const lem::Container::size_type n2 = this->export_coords.size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->export_coords[j].GetCoord().GetIndex() ) { b_has_coord=true; if( this->export_coords[j].GetState()==alt_state ) { // нашли соответствие. return true; } } } } } } else { std::pair<II4,II4> p4 = alt_coords.equal_range(id_coord0); if( condition.for_group ) { const GramCoord &co = sg.coords()[ id_coord0 ]; for( II4 it4=p4.first; it4!=p4.second; ++it4 ) { alt_has_coord=true; const int alt_state = it4->second; const int alt_state_group = co.GetSubgroup( alt_state ); // »щем такое состо¤ние... const lem::Container::size_type n2 = this->wf->pairs().size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->wf->pairs()[j].GetCoord().GetIndex() ) { b_has_coord=true; const int state2 = this->wf->pairs()[j].GetState(); const int state2_grp = co.GetSubgroup(state2); if( state2_grp==alt_state_group ) { return true; } } } } } else { for( II4 it4=p4.first; it4!=p4.second; ++it4 ) { alt_has_coord=true; const int alt_state = it4->second; // »щем такое состо¤ние... const lem::Container::size_type n2 = this->wf->pairs().size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->wf->pairs()[j].GetCoord().GetIndex() ) { b_has_coord=true; if( this->wf->pairs()[j].GetState()==alt_state ) { return true; } } } } } } return !alt_has_coord || !b_has_coord; } else { if( use_export ) { std::pair<II4,II4> p4 = alt_coords.equal_range(id_coord0); if( condition.for_group ) { const GramCoord &c = sg.coords()[ id_coord0 ]; for( II4 it4=p4.first; it4!=p4.second; ++it4 ) { const int alt_state = it4->second; const int alt_state_group = c.GetSubgroup(alt_state); const lem::Container::size_type n2 = this->export_coords.size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->export_coords[j].GetCoord().GetIndex() ) { const int state2 = this->export_coords[j].GetState(); const int state2_grp = c.GetSubgroup(state2); if( state2_grp==alt_state_group ) { // нашли соответствие. return false; } } } } } else { for( II4 it4=p4.first; it4!=p4.second; ++it4 ) { const int alt_state = it4->second; // »щем такое состо¤ние... const lem::Container::size_type n2 = this->export_coords.size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->export_coords[j].GetCoord().GetIndex() ) { if( this->export_coords[j].GetState()==alt_state ) { // нашли соответствие. return false; } } } } } } else { std::pair<II4,II4> p4 = alt_coords.equal_range(id_coord0); if( condition.for_group ) { const GramCoord &c = sg.coords()[ id_coord0 ]; for( II4 it4=p4.first; it4!=p4.second; ++it4 ) { const int alt_state = it4->second; const int alt_state_group = c.GetSubgroup(alt_state); const lem::Container::size_type n2 = this->wf->pairs().size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->wf->pairs()[j].GetCoord().GetIndex() ) { const int state2_grp = c.GetSubgroup(this->wf->pairs()[j].GetState()); if( state2_grp==alt_state_group ) { return false; } } } } } else { for( II4 it4=p4.first; it4!=p4.second; ++it4 ) { const int alt_state = it4->second; // »щем такое состо¤ние... const lem::Container::size_type n2 = this->wf->pairs().size(); for( lem::Container::size_type j=0; j<n2; ++j ) { if( id_coord1 == this->wf->pairs()[j].GetCoord().GetIndex() ) { if( this->wf->pairs()[j].GetState()==alt_state ) { return false; } } } } } } return true; } return false; }