void LA_PhoneticCondictor::LoadTxt( Macro_Parser &txtfile, GraphGram &gram )
{
 txtfile.read_it(B_CONTEXT);
 const BethToken t = txtfile.read();

 context = t.string();

 context.strip_quotes();

 // Каждый символ из строки должен быть известен как буква - то есть
 // быть определен через Алфавит. Допускается также специальный
 // кванторный символ '*'.
 //
 // В двух случаях допускается применение символа $ - для требования на
 // размещение символов: "$aaa" - приставка, "aaa$" - аффикс.

 if( context.front()==L'$' )
  {
   loc = PREFIX;
   context.Remove(0);
  }
 else if( context.back()==L'$' )
  {
   loc = AFFIX;
   context.Remove( context.length()-1 );
  }
 else
  loc = UNLOCATED; 


 const int cl=context.length();
 for( int i=0; i<cl; i++ )
  {
   const wchar_t ch = context[i];

   if( ch==L'*' )
    continue;

   const Word_Coord wc = gram.FindSymbol(ch);
   if( wc.GetEntry()==UNKNOWN )
    {
     lem::Iridium::Print_Error( t, txtfile );
     gram.GetIO().merr().printf(
                            "Condictor [%us] contains unknown symbol (neither "
                            "char nor quantor '*')\n"
                            , context.c_str()
                           );
     throw E_ParserError();
    }

   context.set( i, gram.entries()[wc.GetEntry()].GetName() );
  }

 return;
}
Example #2
0
SyllabContext::SyllabContext(GraphGram &alphabet, const lem::UCString &word, int id_language)
{
    LEM_CHECKIT_Z(id_language != UNKNOWN);

    const SG_Language &lang = alphabet.GetDict().GetSynGram().languages()[id_language];
    const lem::MCollect<int> & id_alphabets = lang.GetAlphabets();

    points.push_back(new SyllabContextLeftBoundary());

    // Разбираем исходное слово по символам, каждый символ ищем в алфавите и создаем по результатам одну точку контекста 
    lem::WideStringUcs4 ucs4(word.c_str());
    lem::uint32_t c;
    while ((c = ucs4.Fetch()) != 0)
    {
        const Word_Coord wc = alphabet.entries().FindSymbol(c, id_alphabets);
        if (wc.IsUnknown())
        {
            SyllabContextUnknownSymbol *point = new SyllabContextUnknownSymbol(c);
            points.push_back(point);
        }
        else
        {
            const GG_Entry &e = alphabet.entries()[wc.GetEntry()];
            const int id_class = e.GetClass();

            const GG_EntryForm & f = e.forms()[wc.GetForm()];
            lem::MCollect<GramCoordPair> coords = f.dims();
            for (lem::Container::size_type k = 0; k < e.attrs().size(); ++k)
                coords.push_back(e.attrs()[k]);

            SyllabContextSymbol *point = new SyllabContextSymbol(c, e.GetName(), wc.GetEntry(), id_class, coords);
            points.push_back(point);
        }
    }

    points.push_back(new SyllabContextRightBoundary());

    return;
}
Example #3
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;
}
Example #4
0
/*************************************************************************
 Для каждого символа слова word находим соответствующую статью и форму
 в Алфавите Графической Грамматике. Результатом работы процедуры является
 структура с подробной информацией о графической структуре слова. Именно
 эта процедура преобразует некое слово в настоящую лексему (она
 возвращается как Lexem).

 Если поле substitute_entries=false, то вместо имен буквостатей будут
 использованы имена буквоформ.

 23.12.2008: UNSAFE из-за того, что длина результата может быть больше
             длины исходной строки!
**************************************************************************/
void LexicalAutomat::ToLexemX(
                              const wchar_t *word,
                              bool substitute_entries,
                              Lexem &res,
                              int LanguageID
                             )
{
 WideStringUcs4 cenum(word);
 lem::uint32_t c;
 lem::uint32_t prev_c=0;

 lem::Ucs4ToUCString yield;

 while( (c=cenum.Fetch())!=0 )
  {
   if( c==L'$' )
    {
     yield.Add(c);

     lem::uint32_t c2 = cenum.Fetch();
     if( c2!=0 )
      {
       // Символ $ используется для escape-последовательностей
       yield.Add(c2);
      }

     continue;
    }

   if( c==L' ' )
    {
     // Оставляем всегда единственный пробел (точнее - символ разделения лексем
     // в мультилексеме).
     if( prev_c!=Lexem::DelimiterChar )
      {
       yield.Add(Lexem::DelimiterChar);
       prev_c = c;
      }

     continue;
    }

   if( c==L'-' || c==L',' || c==L'\'' )
    {
     if( prev_c!=Lexem::DelimiterChar && prev_c!=0 )
      yield.Add(Lexem::DelimiterChar);

     yield.Add(c);

     if( cenum.Fetch()!=0 )
      {
       yield.Add( Lexem::DelimiterChar );
       cenum.Back();
      }

     prev_c = Lexem::DelimiterChar;

     continue;
    }

   Word_Coord wc;
   if( LanguageID==ANY_STATE ) 
    {
     wc = GG->FindSymbol(c);
    }
   else if( LanguageID==UNKNOWN )
    {
     wc = GG->FindSymbol(c,GetDefaultAlphabets());
    }
   else
    {
     const Solarix::SG_Language &lang = GetDict().GetSynGram().languages()[LanguageID];
     const lem::MCollect<int> &id_alphabets = lang.GetAlphabets();
     wc = GG->FindSymbol(c,id_alphabets);
    }

   if( wc.GetEntry()==UNKNOWN )
    {
     // Символ не найден в графической грамматике.
     yield.Add(c);
    }
   else
    {
     const GG_Entry &entry = GG->entries()[ wc.GetEntry() ];

     if(
        !substitute_entries ||
        wc.GetForm()==UNKNOWN ||
        wc.GetForm()==ANY_STATE
       )
      yield.Add( entry.GetForm(wc.GetForm()).GetName() );
     else
      yield.Add( entry.GetName() );
    }

   prev_c = c;
  }

 res = yield.ToString();

 return;
}
Example #5
0
void LexicalAutomat::TranslateLexem(
                                    lem::UFString &str,
                                    bool substitute_entries,
                                    int LanguageID
                                   )
{
 WideStringUcs4 cenum(str.c_str());
 lem::uint32_t c;
 lem::uint32_t prev_c=0;

 lem::Ucs4ToUFString yield;

 while( (c=cenum.Fetch())!=0 )
  {
   if( c==L' ' )
    {
     // Оставляем всегда единственный пробел (точнее - символ разделения лексем
     // в мультилексеме).
     if( prev_c!=Lexem::DelimiterChar )
      {
       yield.Add(Lexem::DelimiterChar);
       prev_c = c;
      }

     continue;
    }

   if( c==L'-' || c==L',' || c==L'\'' )
    {
     if( prev_c!=Lexem::DelimiterChar && prev_c!=0 )
      yield.Add(Lexem::DelimiterChar);

     yield.Add(c);

     if( cenum.Fetch()!=0 )
      {
       yield.Add( Lexem::DelimiterChar );
       cenum.Back();
      }

     prev_c = Lexem::DelimiterChar;

     continue;
    }

   Word_Coord wc;
   if( LanguageID==ANY_STATE ) 
    wc = GG->FindSymbol(c);
   else if( LanguageID==UNKNOWN )
    wc = GG->FindSymbol(c,GetDefaultAlphabets());
   else
    wc = GG->FindSymbol(c,LanguageID);

   if( wc.GetEntry()==UNKNOWN )
    {
     // Символ не найден в графической грамматике.
     yield.Add(c);
    }
   else
    {
     const GG_Entry &entry = GG->entries()[ wc.GetEntry() ];

     if(
        !substitute_entries ||
        wc.GetForm()==UNKNOWN ||
        wc.GetForm()==ANY_STATE
       )
      yield.Add( entry.GetForm(wc.GetForm()).GetName() );
     else
      yield.Add( entry.GetName() );
    }

   prev_c = c;
  }

 str = yield.ToString();

 return;
}