// Проверяем, что в теле паттерна на самом деле экспортированы все координаты и именованные узлы, которые объявлены
// в секции 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;
}
Exemple #2
0
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;
}
Exemple #4
0
void SG_EntryForm::Reattach_To_Refs( SynGram &sg )
{
 // Название формы.
 content = sg.GetEntries().ReattachLexeme(content);

 // Координаты
 dim = sg.GetEntries().ReattachCoordPairs(dim);

 return;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
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)
          )
{}
Exemple #8
0
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;
}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #13
0
// ***************************************************************
// Лексическое содержимое словоформы приводим в соответствие с
// координатами.
// ***************************************************************
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;
}
Exemple #14
0
/*************************************************************************

 Загрузка дескриптора ребра из текстового файла. Распознаются форматы:

 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;
}
Exemple #15
0
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;
}
Exemple #16
0
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;
}
Exemple #17
0
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;
}
Exemple #18
0
/******************************************************************
 Считывание описание узла 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;
}
Exemple #19
0
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;
}
Exemple #22
0
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;
}
Exemple #23
0
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;
}
Exemple #24
0
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;
}