void LemmatizatorStorage_SQLITE::Lemmatize(
                                           const lem::UCString &word,
                                           lem::MCollect<lem::UCString> &lemmas
                                          )
{
 lemmas.clear();

 lem::MemFormatter mem;
 mem.printf( "SELECT L.lemma"
             " FROM lexemes_n X, lemmas L"
             " WHERE X.lexeme='%us' AND L.id=X.id_lemma", to_upper(word).c_str() );

 lem::Ptr<LS_ResultSet> rs(cnx->Select(lem::to_utf8(mem.string())));
 while( rs->Fetch() )
  {
   lemmas.push_back( rs->GetUCString(0) );
  }

 if( lemmas.empty() )
  {
   lemmas.push_back(word);
  }

 return;
}
예제 #2
0
void SynPatternResult::SelectUnique_WithRemoval(lem::MCollect<SynPatternResult*> & results)
{
    lem::MCollect<int> result_hash;
    lem::PtrCollect<SynPatternResult> unique_result;
    for (lem::Container::size_type k = 0; k < results.size(); ++k)
    {
        SynPatternResult * result_k = results[k];
        const int h = result_k->CalcHash();

        bool found = false;
        for (lem::Container::size_type i = 0; i < unique_result.size(); ++i)
        {
            if (result_hash[i] == h)
            {
                if (SynPatternResult::Equals(result_k, unique_result[i]))
                {
                    found = true;
                    break;
                }
            }
        }

        if (!found)
        {
            result_hash.push_back(h);
            unique_result.push_back(result_k);
            results[k] = nullptr;
        }
    }

    results.clear();

    for (lem::Container::size_type i = 0; i < unique_result.size(); ++i)
    {
        results.push_back(unique_result[i]);
        unique_result[i] = nullptr;
    }

    return;
}
예제 #3
0
void Lemmatizator::Lemmatize( const lem::UCString &word, lem::MCollect<lem::UCString> &lemmas )
{
 lem::UCString res(word);
 res.to_upper();

 bool rehash=false;
 for( int i=0; i<res.length(); ++i )
  if( res[i]==0x0401 )
   {
    res.set( i, 0x0415 );
    rehash=true;
   }

 if( rehash )
  res.calc_hash();

 // Определяем, в какой группе искать.
 const int igroup = (unsigned)res.GetHash16() & (L_NHASHGROUP-1);
 const lem::Stream::pos_type pos = group_pos[igroup];

 #if defined LEM_THREADS
 lem::Process::CritSecLocker lock(&cs);
 #endif

 // перемещается на начало группы в файле.
 bin->seekp(pos);

 // перебираем элементы группы в поисках нашей формы.
 const int n = bin->read_int();

 lem::uint8_t x8[3];

 if( char_size==sizeof(wchar_t) )
  {
   lem::UCString form;
   lem::MCollect<int> inorm;

   for( int i=0; i<n; ++i )
    {
     inorm.clear();
     lem::Load_Packed( &form, *bin );

     lem::uint8_t n8 = bin->read_uint8();
     inorm.reserve(n8);
     for( lem::uint8_t i8=0; i8<n8; ++i8 )
      {
       bin->read( x8, 3 );
       const int x32 = (0x00ff0000&(x8[0]<<16)) |
                       (0x0000ff00&(x8[1]<<8))  |
                       (0x000000ff&x8[2]);
       inorm.push_back(x32);
      } 
   
     if( form==res )
      {
       // Нашли!!!
       for( lem::Container::size_type j=0; j<inorm.size(); ++j )
        {
         lemmas.push_back( GetLemma(inorm[j]) );
        }

       return;
      }
    }
  }
 else if( char_size==1 )
  {
   lem::UCString form;
   lem::MCollect<int> inorm;

   for( int i=0; i<n; ++i )
    {
     inorm.clear();
     LoadEncodedString( &form, *bin, 1 );

     lem::uint8_t n8 = bin->read_uint8();
     inorm.reserve(n8);
     for( lem::uint8_t i8=0; i8<n8; ++i8 )
      {
       bin->read( x8, 3 );
       const int x32 = (0x00ff0000&(x8[0]<<16)) |
                       (0x0000ff00&(x8[1]<<8))  |
                       (0x000000ff&x8[2]);
       inorm.push_back(x32);
      } 
   
     if( form==res )
      {
       // Нашли!!!
       for( lem::Container::size_type j=0; j<inorm.size(); ++j )
        {
         lemmas.push_back( GetLemma(inorm[j]) );
        }

       return;
      }
    }
  }
 else
  {
   LEM_STOPIT;
  }

 lemmas.clear();

 // Табличной подстановки не нашлось, проверяем замену суффикса.
 for( lem::Container::size_type i=0; i<suffices.size(); ++i )
  {
   if( res.eq_endi( suffices[i].first ) )
    {
     // Нашли замену суффикса!
     UCString lemma = lem::left( res, res.length()-suffices[i].first.length() );
     lemma += suffices[i].second;
     lemmas.push_back(lemma);
     return;
    }
  }


 // Лемматизация не выполнена, возвращаем исходное слово в качестве леммы.
 lemmas.push_back(res);
 return;
}
예제 #4
0
bool GeneratorLexer::Fetch( const LexerTextPos * current, const TokenExpectation * unused, lem::MCollect<const LexerTextPos*> & next )
{
 if( current==NULL )
  {
   next.push_back( GetBeginToken() );
   return true;
  }

 if( current->IsEnd() )
  {
   return false;
  }

 next.clear();

 // поищем в кэше уже найденные продолжения.
 std::pair<CACHED_EDGES::const_iterator,CACHED_EDGES::const_iterator> p_edges = edges.equal_range(current);
 if( p_edges.first!=p_edges.second )
  {
   for( CACHED_EDGES::const_iterator it=p_edges.first; it!=p_edges.second; ++it )
    {
     next.push_back( it->second );
    }

   return true;
  }

 // Посмотрим, какие токены были перед данным, и какие слова они уже использовали.
 lem::MCollect<int> indeces;
 CollectUsedWords( current, indeces );

/*
#if LEM_DEBUGGING==1
if( current->GetWordform()->GetName()->eqi(L"ловит") )
 {
  lem::mout->printf("!\n");
 }
#endif
*/

 bool token_created=false;
 lem::MCollect<const LexerTextPos*> matched_by_literal_ngrams, matched_by_normalized_ngrams, all_next_tokens;

 lem::Ptr<Ngrams> ngrams;
 lem::UCString prev_lemma;

 if( UseNGrams )
  ngrams = dict->GetNgrams();

 // Теперь неиспользованные ранее слова порождают новые токены.
 for( lem::Container::size_type i=0; i<words.size(); ++i )
  if( indeces.find(i)==UNKNOWN )
   {
    // слово не использовалось.
    typedef INDEX2WORDFORM::const_iterator IT;
    std::pair<IT,IT> p = index2wordform.equal_range( CastSizeToInt(i) );

    for( IT it=p.first; it!=p.second; ++it )
     {
      const Word_Form * wordform = it->second;
      const int word_index = current->IsRealWord() ? current->GetWordIndex()+1 : 0;
      const int start_pos = current->IsRealWord() ? (current->GetStartPosition()+current->GetWordLength()+1) : 0;

      // Нам нужно создать новый вариант этой словоформы.
      Word_Form * wf = new Word_Form( *wordform, true );
      wf->SetOriginPos( word_index );
      wordforms.push_back(wf);

      LexerTextPos * new_token = new LexerTextPos( current, wf, 0, start_pos, wf->GetName()->length(), word_index );
      positions.push_back(new_token);

      all_next_tokens.push_back( new_token );

      token2word.insert( std::make_pair(new_token,CastSizeToInt(i)) );

      token_created = true;

      // Слово сочетается с предыдущим?
      if( UseNGrams && current->IsRealWord() )
       {
        const lem::UCString & prev_word = * current->GetWordform()->GetNormalized();
        const lem::UCString & new_word = * new_token->GetWordform()->GetNormalized();
        
        float w2=0;
        int iw2=0;
        if( ngrams->FindLiteralNGrams( prev_word, new_word, w2, iw2 ) )
         {
          // TODO: использовать частотность подошедшей N-граммы для взвешивания созданных токенов.
          matched_by_literal_ngrams.push_back( new_token );
         }
        else
         {
          if( prev_lemma.empty() )
           {
            const int prev_ekey = current->GetWordform()->GetEntryKey();
            const SG_Entry & prev_e = dict->GetSynGram().GetEntry( prev_ekey );
            prev_lemma = prev_e.GetName();
           }

          const int new_ekey = new_token->GetWordform()->GetEntryKey();
          const SG_Entry & new_e = dict->GetSynGram().GetEntry( new_ekey );
          const lem::UCString & new_lemma = new_e.GetName();

          if( ngrams->FindRawNGrams( prev_lemma, new_lemma, w2, iw2 ) )
           {
            // TODO: использовать частотность подошедшей N-граммы для взвешивания созданных токенов.
            matched_by_normalized_ngrams.push_back( new_token );
           }
         }
       }
     }
   }

 if( !matched_by_literal_ngrams.empty() )
  {
   // найдена по крайней мере одна буквальная 2-грамма, поэтому отбрасываем все неподтвержденные варианты токенов.
   next = matched_by_literal_ngrams;
  }
 else if( !matched_by_normalized_ngrams.empty() )
  {
   next = matched_by_normalized_ngrams;
  }
 else
  {
   next = all_next_tokens;
  }

 for( lem::Container::size_type i=0; i<next.size(); ++i )
  {
   edges.insert( std::make_pair(current, const_cast<LexerTextPos*>( next[i] ) ) );
  }


/*
 #if LEM_DEBUGGING==1
 lem::mout->printf( "%60h-\n" );
 for( lem::Container::size_type i=0; i<next.size(); ++i )
  {
   lem::mout->printf( "FETCHED: %us(%p) -> %us(%p)\n", current->GetWordform()->GetName()->c_str(), current, next[i]->GetWordform()->GetName()->c_str(), next[i] );
  }
 #endif
*/


 if( !token_created )
  {
   // Возвращаем правую границу.
   next.push_back( GetEndToken(current) );
   return true;
  }

 return false;
}