Example #1
0
/********************************************************************
 Читаем из текстового файла секции расширенного описания статьи.
 Под расширенным описанием подразумевается список координат-атрибутов,
 формы, грамматическая сеть и специфические для производных классов
 поля.
*********************************************************************/
void Base_Entry::LoadTxtEx(
    Macro_Parser& txtfile,
    Grammar& gram
)
{
    // *** Считываем описание статьи ***
    bool looping = true;
    BethToken token;
    CP_Array common;

    while (looping)
    {
        if (txtfile.eof())
        {
            Print_Error(txtfile);
            gram.GetIO().merr().printf("End of file has been reached before entry body completely loaded\n");
            throw E_ParserError();
        }

        const BSourceState back = txtfile.tellp();
        token = txtfile.read();

        if (token.GetToken() == B_CFIGPAREN)
        {
            // Описание статьи закончено
            looping = false;
            break;
        }

        if (token.GetToken() == B_OTRIPAREN)
        {
            txtfile.seekp(token.GetBegin());
            SkipNetSection(txtfile, gram);
            continue;
        }

        if (ProcessSection(txtfile, gram, token))
            continue;

        txtfile.seekp(back);

        if (LoadAttribute(txtfile, gram))
            continue;

        // Загружаем словоформу.
        LoadForm(
            txtfile,
            gram,
            common,
            GramCoordAdr(UNKNOWN, UNKNOWN),
            UNKNOWN,
            GramCoordAdr(UNKNOWN, UNKNOWN),
            UNKNOWN,
            UNKNOWN
        );

    } // конец цикла считывания описания статьи

    return;
}
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 #3
0
void Form_Table::LoadBody(Macro_Parser &txtfile, Grammar& gram)
{
    txtfile.read_it(B_OFIGPAREN);

    // *** Считываем описание Таблицы ***
    BethToken token;
    CP_Array common;

    FOREVER
    {
     if (txtfile.eof())
      {
       Print_Error(txtfile);
       gram.GetIO().merr().printf("End of file has been reached before entry body completely loaded\n");
       throw E_ParserError();
      }

     const BSourceState back = txtfile.tellp();
     token = txtfile.read();

     if (token.GetToken() == B_CFIGPAREN)
      {
         // Описание Таблицы закончено.
         break;
        }

       if (ProcessSection(txtfile,gram,token))
        continue;

       txtfile.seekp(back);

       if (LoadAttribute(txtfile,gram))
        continue;

       LoadForm(
                txtfile,
                gram,
                common,
                GramCoordAdr(UNKNOWN,UNKNOWN),
                UNKNOWN,
                GramCoordAdr(UNKNOWN,UNKNOWN),
                UNKNOWN,
                UNKNOWN
                ); // Загружаем словоформу.

    } // конец цикла считывания описания статьи

    return;
}
Example #4
0
/********************************************************************
  Загрузка описания Статьи из текстового файла
*********************************************************************/
void Form_Table::LoadTxt(
    Macro_Parser &txtfile,
    Grammar& gram,
    bool IsRealized
)
{
    is_realized = IsRealized;
    iclass = UNKNOWN;

    LoadName(txtfile, gram.GetDict());

    if (iclass == UNKNOWN) // если в LoadName еще не прочитали информацию о принадлежности к грамматическому классу...
    {
        const BethToken class_name = txtfile.read();

        if ((iclass = gram.FindClass(class_name.string())) == UNKNOWN)
        {
            // Не найден класс, заявленный для статьи
            Print_Error(class_name, txtfile);
            gram.GetIO().merr().printf(
                "The class [%us] is not previously declared in grammar\n"
                , class_name.c_str()
            );
            throw E_ParserError();
        }
    }

    LoadBody(txtfile, gram);
    Loaded(gram.GetDict());
    return;
}
Example #5
0
/********************************************************************
 Класс Словаря Dictionary обнаружил в текстовом файле секцию описания
 Автомата и просит нас загрузить ее тело (шапка уже считана им).
 Перед началом первой загрузки Автомата вызывается метод PreLoad, а
 после считывания очередной порции вызывается PostRead.
*********************************************************************/
void Automaton::LoadTxt(
                        Macro_Parser &txtfile,
                        const Binarization_Options &options
                       )
{
 try
  {
   if( !was_loaded )
    PreLoad(txtfile,options);

   was_loaded=true;
   txtfile.read_it(B_OFIGPAREN);
   load(txtfile,options);
   PostRead(txtfile,options);
  }
 catch( E_ParserError &x )
  {
   GetIO().merr().printf(
                         "Syntax error in automaton [%us] section\n%us\n"
                         , GetName().c_str()
                         , x.what()
                        );

   was_loaded = false;
   throw(x);
  }

 return;
}
Example #6
0
/*********************************************************************************
 Загрузка описания связки из текстового файла Словаря. Если realy=false, то
 поиска именованных полей в Грамматике и запоминания индексов производится
 не будет, то есть произойдет фактически пропуск описания связки. Данный прием
 используется при двухпроходном чтении описания статей Синтаксической Грамматики,
 а это необходимо из-за возможных ссылок вперед на неописанные словарные статьи.

 Формат:
        <имя_связки>класс:имя_статьи{}

**********************************************************************************/
void SG_NetLink::LoadTxt(
                         Macro_Parser &txtfile,
                         SynGram &gram,
                         bool realy,
                         int EntryKey0
                        )
{
 entry_key0 = EntryKey0;

 link.LoadTxt(txtfile,gram);

 BSourceState s = txtfile.tellp();
  
 entry_key1 = sol_load_omonym(txtfile,gram,false);

 if( realy && entry_key1==UNKNOWN )
  {
 
   BSourceState s1 = txtfile.tellp();
/*
   // Это не ошибка, но напечатать предупреждение следует: статья,
   // на которую отсылает связка, не найдена.

   // Распечатаем имя ненайденной статьи
//   Print_Error( s, txtfile, true );
   gram.GetIO().merr().printf( "Warning: link to undeclared entry " );
   txtfile.seekp(s);

   while( !txtfile.eof() )
    {
     BethToken t = txtfile.read();
     if( t.GetToken()==B_OFIGPAREN )
      break;

     gram.GetIO().merr().printf( "%us", t.c_str() );
    }

   gram.GetIO().merr().eol();
*/

   // Продолжаем трансляцию
   txtfile.seekp(s1);
  }

 return;
}
Example #7
0
void SG_DeclensionForm::ReadAdditionalInfo( Grammar &gram, const SG_DeclensionTable &table, Macro_Parser& txtfile )
{
 // :: flexer рег_выражение for регулярное_выражение
 
 while( !txtfile.eof() )
  {
   BethToken t = txtfile.read();

   if( t==B_FOR )
    {
     UFString re = strip_quotes( txtfile.read().string() ).c_str();
     if( table.GetClass()!=UNKNOWN )
      {
       const SG_Class &cls = (const SG_Class&)gram.classes()[ table.GetClass() ];

       const int id_lang = cls.GetLanguage();
       if( id_lang!=UNKNOWN )
        {
         const SG_Language &lang = gram.GetDict().GetSynGram().languages()[id_lang];
         lang.SubstParadigmPattern(re);
        }
      }

     condition_str = re;
     condition = boost::wregex( re.c_str(), boost::basic_regex<wchar_t>::icase );
     valid_condition = true;
    }
   else if( t==B_FLEXER )
    {
     UFString re = strip_quotes( txtfile.read().string() ).c_str();

     flexer_flags_str = re; 
     flexer_flags = boost::wregex( re.c_str(), boost::basic_regex<wchar_t>::icase );
     valid_flexer_flags = true;
    }
   else
    {
     txtfile.seekp(t);
     break;
    }
  }

 return;
}
Example #8
0
// Синтаксис реализации таблицы склонения может быть более сложным,
// чем для обычных таблиц форм:
//
// declension auto : NOUN for "(.+)S"
// {                      ^^^^^^^^^^^
//  :    
//
//
// Курсор считывания стоит на первой после имени класса (NOUN в примере)
// лексеме.
void SG_DeclensionTable::LoadBody( Macro_Parser &txtfile, Grammar& gram )
{
 if( txtfile.probe(B_FOR) )
  {
   condition.LoadTxt( txtfile, GetClass(), (SynGram&)gram );
  }

 Form_Table::LoadBody( txtfile, gram );

 return;
}
Example #9
0
/*******************************************************************
 Именем таблицы в данном случае является целое неотрицательное число
 в десятеричной системе счисления.
********************************************************************/
void SG_DeclensionTable::LoadName(
                                  Macro_Parser &txtfile,
                                  Dictionary &dict
                                 )
{
 const BethToken& t = txtfile.read();
 key = ANY_STATE;

 // Формат:
 // paradigma Условное_Имя, Алиас1, ... :
 name = t.string();
 names.push_back(name);

 key = ANY_STATE;

 while( !txtfile.eof() && txtfile.pick().GetToken()==B_COMMA )
  {
   txtfile.read_it(B_COMMA);  
   names.push_back( txtfile.read().string() );
  } 

 txtfile.read_it(B_COLON);

 if( dict.GetDebugLevel_ir()>=3 )
  {
   dict.GetIO().mecho().printf(
                               "%us [%vfE%us%vn]->",
                               sol_get_token(B_PARADIGMA).c_str(),
                               GetName().c_str()
                              );
  }

 return;
}
Example #10
0
/**********************************************************
 Загрузка тела описания статьи из текстового файла Словаря.
 Само тело состоит из нескольких факультативных частей.
***********************************************************/
void Base_Entry::LoadBody(
    Macro_Parser &txtfile,
    Grammar& gram
)
{
    if (is_realized)
    {
        // Если теперь встретится '{', то значит имеем расширенное
        // описание словарной статьи.

        const BSourceState prefig = txtfile.tellp();
        const BethToken isfig = txtfile.read();

#if LEM_DEBUGGING==1
        int nf = CountForms();
#endif

        if (isfig.GetToken() != B_OFIGPAREN)
            txtfile.seekp(prefig);
        else
            LoadTxtEx(txtfile, gram);

        if (CountForms() == 0)
            BeforeFirstForm(gram);

        CheckAttr(txtfile, gram);
    }

#if defined SOL_DETAILED
    if (gram.GetDict().GetDebugLevel_ir() >= 3)
    {
        // Эхо-сообщение: закончили трансляцию статьи.
        gram.GetIO().mecho().printf("Ok\n");
    }
#endif

    return;
}
Example #11
0
/****************************************************************************
 Загружаем из текстового файла множество символьных строк. Если слово
 только одно, то оно может идти непосредственно. Если необходимо определить
 несколько слов, то они заключаются в фигурные скобочки.
 Форматы:
         1. лексема
         2. { лексема лексема ... лексема }

 Второй формат охватывает также и первый, если в фигурных скобочках указать
 только одну лексему. Способ хранения в обоих случаях одинаков!
*****************************************************************************/
void UCStringSet::LoadTxt( const Sol_IO &io, Macro_Parser &txtfile )
{
 BethToken t = txtfile.read();

 if( t.GetToken()!=B_OFIGPAREN )
  {
   // Первый формат.
   push_back(t.c_str());
  }
 else
  {
   // Второй формат.
   while( !txtfile.eof() )
    {
     if( txtfile.eof() )
      {
       Print_Error(t,txtfile);
       io.merr().printf(
                        "End of file has been reached before "
                        "set of lexems completely loaded\n"
                       );
       LEM_STOPIT;
      }

     t = txtfile.read();

     if( t.GetToken()==B_CFIGPAREN )
      break;

     push_back(t.string());
     weight.push_back(1);
    }
  }

 return;
}
Example #12
0
/**************************************************************************
     ЗАГРУЗКА ОДНОЙ АТРИБУТНОЙ КООРДИНАТНОЙ ПАРЫ
             из текстового файла

  Общий формат:

     коорд_имя : состояние

 Особое внимание следует уделять автоматическому созданию AND-атрибутов
 для многоохватных состояний. Если такое создание нежелательно, то
 следует заключить имя состояния, входящего в группу многоохватных, в
 круглые скобочки:

           коор_имя : ( состояние )

 ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ:

  true - действительно, загружен атрибут или тэг.
  false - это не определение состояния атрибута или тэга.
****************************************************************************/
bool Form_Table::LoadAttribute(
    Macro_Parser &txtfile,
    Grammar& gram
)
{
    const BSourceState back = txtfile.tellp();
    bool negative_state = txtfile.probe(B_NEGATIVE); // считываем префикс в ~ПРИЧАСТИЕ

    BethToken coord_name = txtfile.read();

    // Индекс координаты в списке грамматики.
    const GramCoordAdr iglob = gram.FindCoord(coord_name.string());

    // Найдем атрибут в списке грамматического класса.
    const int iattr = gram.classes()[iclass].attrs().FindTwice(iglob);

    if (iattr == UNKNOWN)
    {
        const int itag = gram.classes()[iclass].tags().FindTwice(iglob);

        if (itag == UNKNOWN)
        {
            txtfile.seekp(back);
            return false;
        }
    }

    // Если координата имеет два неявно объявленных состояния
    // TRUE/FALSE, то состояние явно в данной секции не должно быть
    // указано.

    if (!gram.coords()[iglob.GetIndex()].IsBistable())
    {
        // Несколько состояний у координаты.

        if (negative_state)
        {
            Print_Error(back, txtfile);
            gram.GetIO().merr().printf("~ is appliable to bistable coordinates only, whereas [%us] is not bistable\n", coord_name.c_str());
            throw E_ParserError();
        }

        txtfile.read_it(B_COLON);

        // Учтем, что может встретиться AND-атрибут. Такая координата
        // одновременно может иметь несколько состояний.

        IntCollect statei;
        IntCollect doload;

        FOREVER
        {
         if (txtfile.eof())
          {
           Print_Error(txtfile);
           gram.GetIO().merr().printf("End of file has been reached before list of attribute states in entry completely loaded\n");
           throw E_ParserError();
          }

        // Теперь считаем состояние(-я) для заявленного атрибута.
        const BSourceState back = txtfile.tellp();
        BethToken state_name = txtfile.read();

        bool letautoload = true;

        if (state_name.GetToken() == B_ANY)
         {
          if (StoreQuantors())
           {
            attr.push_back(GramCoordPair(iglob,ANY_STATE));
            break;
           }
          else if (statei.empty())
           {
              // Вместо имен состояний для AND-координаты указан квантор *.
              // Инициализируем координату ВСЕМИ состояниями, заявленными
              // для координаты.

              const int ns = gram.coords()[iglob.GetIndex()].GetTotalStates();

              for (int i = 0; i < ns; i++)
               attr.push_back(GramCoordPair(iglob,i));

              // Продолжать дальше считывание не имеет смысла.
              break;
             }
           }

          if (!statei.empty())
           {
              // Если это запятая, то список AND-состояний продолжается.
              // в противном случае прерываем загрузку состояний.

              if (state_name.GetToken() != B_COMMA)
               {
                txtfile.seekp(back);
                break;
               }
              else
               state_name = txtfile.read();
             }

          // Если имя атрибута заключено в круглые скобочки, то
          // для координатной пары запрещено автоматическое создание.
          if (state_name.GetToken() == B_OROUNDPAREN)
           {
            state_name = txtfile.read();
            txtfile.read_it(B_CROUNDPAREN);
            letautoload = false;
           }

          // Ищем индекс состояния в координате
          const int istate = gram.coords()[iglob.GetIndex()].FindState(state_name.string());
          if (istate == UNKNOWN)
           {
            Print_Error(state_name,txtfile);
            gram.GetIO().merr().printf(
                                       "State [%us] is not declared for coordinate [%us]\n"
                                       , state_name.c_str(), coord_name.c_str()
                                      );
            throw E_ParserError();
           }

          // Добавляем глобальный индекс атрибута и индекс его состояния
          // к нашим спискам.
          statei.push_back(istate);
          doload.push_back(letautoload);
        }

            // Состояния, которые объявлены для атрибута, превратим
            // в список координатных пар и добавим к своему списку
            // атрибутов статьи.
        lem::Container::size_type ils;
        for (ils = 0; ils < statei.size(); ils++)
            attr.push_back(GramCoordPair(iglob, statei[ils]));

        // Автоматически подключим те состояния, которые не запрещены
        // для этого пользователем, не объявлены и входят в подгруппу.
        const GramCoord& c = gram.coords()[iglob.GetIndex()];
        IntCollect attaches; // Автоматически созданные и присоединяемые состояния

        for (ils = 0; ils < statei.size(); ils++)
            if (doload[ils])
            {
                int ibase = statei[ils];

                // Входит ли состояние в группу многоохватных как главное?
                if (c.IsHeadState(ibase))
                {
                    // Да, входит.
                    // Получаем список состояний, входящих в группу.
                    const IntCollect to_attach = c.GetSubgroupIndeces(c.GetSubgroup(ibase));

                    for (Container::size_type ia = 1; ia < to_attach.size(); ia++)
                    {
                        const int state_attach = to_attach.get(ia); // Очередное состояние из группы многоохватных

                        // Посмотрим, можно ли присоединять состояние
                        // iglob:state_attach.
                        //
                        // Противопоказания могут быть следующие.
                        //
                        // 1. Состояние уже присутствует в списке statei.
                        // 2. Состояние уже автоматически создано и
                        //    добавлено в список attaches.
                        //
                        // 3. Координатная пара уже загружена в списки
                        //    статьи.

                        bool already_loaded = false;

                        if (attr.FindOnce(GramCoordPair(iglob, state_attach)) != UNKNOWN)
                            already_loaded = true;

                        if (
                            !already_loaded                      &&
                            find(statei, state_attach) == UNKNOWN   &&
                            find(attaches, state_attach) == UNKNOWN
                            )
                            attaches.push_back(state_attach); // К списку присоединяемых
                    }
                }
            }

        if (!attaches.empty()) // Есть присоединяемые?
        {
            // Необходимо предупредить пользователя об автоматически
            // присоединяемых состояниях.
            lem::LogFile::logfile->printf("\nCoordinate pairs were autocreated for a form table:");

            PrintName(*lem::LogFile::logfile);
            lem::LogFile::logfile->printf(" ->");

            for (Container::size_type ils = 0; ils < attaches.size(); ils++)
            {
                if (ils)
                    lem::LogFile::logfile->printf(",");

                lem::LogFile::logfile->printf(
                    " %us%us%us ",
                    c.GetName().string().c_str(),
                    sol_get_token(B_COLON).c_str(),
                    c.GetStateName(attaches[ils]).c_str()
                );
                attr.push_back(GramCoordPair(iglob, attaches[ils]));
            }

            lem::LogFile::logfile->eol();
        }
    }
    else
    {
        // Добавляем глобальный индекс атрибута и индекс его состояния
        // к нашим спискам, учитывая, что сам факт появления атрибута
        // с неявными состояниями TRUE/FALSE означает его состояние TRUE.
        // Если был префикс ~, то состояние присваиваем FALSE.

        // Есть один особый случай, когда для бистабильной координаты задается
        // состояние - для грамматических кванторов. В этом случае имя состояния
        // обязательно квантор *
        if (StoreQuantors())
Example #13
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;
}
Example #14
0
/************************************************************************
 Собственно, загрузка содержимого тела секции Автомата. Дабы позволить
 производным классам автоматов разпознавать и загружать свои собственные
 структуры данных сверх того, что распознает и загружает наш класс,
 вызывается виртуальный метод ProcessLexem.
*************************************************************************/
void Automaton::load(
                     Macro_Parser &txtfile,
                     const Binarization_Options &options
                    )
{
 bool looping=true;
 while( looping )
  {
   if( txtfile.eof() )
    {
     Print_Error(txtfile);
     GetIO().merr().printf(
                           "End of file has been reached before Automaton [%us] section completely loaded\n"
                           , GetName().c_str()
                          );
     throw E_ParserError();
    }

   const BethToken t=txtfile.read();

   if( !ProcessLexem(t,txtfile,options) )
    {
     switch(t.GetToken())
      {
       case B_CRITERION:
        if( param!=NULL )
         param->LoadTxt( GetIO(), txtfile );
        break;

       case B_CFIGPAREN:
        looping=false;
        break;

       default:
        {
         const BSourceState back=txtfile.tellp();

         if( param!=NULL )
          {
           if( txtfile.read().GetToken()==B_EQUAL )
            {
             txtfile.seekp( t.GetBegin() );
             param->LoadTxt(GetIO(),txtfile);
             break;
            }
          }
         else
          {
           LEM_STOPIT;
          }

         txtfile.seekp(back);

         // Нераспознанная лексема.
         GetIO().merr().printf( "\nIncorrect lexem [%us]\n", t.string().c_str() );
         Print_Error(t,txtfile);
         throw E_ParserError();
        }
      }
    }
  }

 return;
}
Example #15
0
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;
}
Example #16
0
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;
}
Example #17
0
void SG_Language::LoadTxt(int Id, Macro_Parser& txt, GraphGram& gram)
{
    // Store the beginning of language specification
    BSourceState beg = txt.tellp();

    id = Id;

    name = txt.read().string();

    const bool Me = gram.GetDict().GetDebugLevel_ir() >= 3;
    if (Me)
    {
        // Эхо-сообщение: начали трансляцию языка.
        gram.GetIO().mecho().printf(
            "%us [%vfE%us%vn]->",
            sol_get_token(B_LANGUAGE).c_str(),
            name.c_str()
        );
    }


    BethToken t = txt.read();
    if (t.GetToken() == B_AS)
    {
        c_name = txt.read().string();
        t = txt.read();
    }

    if (t.GetToken() != B_OFIGPAREN)
    {
        // Пустое объявление языка.
        txt.seekp(t.GetBegin());
    }
    else
    {
        // Load the list of alphabets, allowed for the language. Also do load other
        // language parameters.
        while (!txt.eof())
        {
            BethToken t = txt.read();

            if (t.GetToken() == B_CFIGPAREN)
                break;

            if (t.GetToken() == B_ALPHABET)
            {
                // Add the valid alphabet name for this language

                BethToken abc_name = txt.read();
                int id_abc = gram.Find_Alphabet(abc_name.string());

                if (id_abc == UNKNOWN)
                {
                    lem::Iridium::Print_Error(abc_name, txt);
                    gram.GetIO().merr().printf("Unknown alphabet [%us] used in in language [%us] specification\n", abc_name.string().c_str(), name.c_str());
                    throw E_ParserError();
                }

                alphabet.push_back(id_abc);
                continue;
            }
            else if (t.GetToken() == B_LINK)
            {
                Tree_Link l;
                l.LoadTxt(txt, gram.GetDict().GetSynGram());

                txt.read_it(B_LANGUAGE);
                BethToken lang_name = txt.read();

                int id_lang = gram.GetDict().GetSynGram().Find_Language(lang_name);
                if (id_lang == UNKNOWN)
                {
                    lem::Iridium::Print_Error(lang_name, txt);
                    gram.GetIO().merr().printf("Unknown language [%us] used in in language [%us] specification\n", lang_name.string().c_str(), name.c_str());
                    throw E_ParserError();
                }

                lang_links.push_back(std::make_pair(l, id_lang));
                continue;
            }
            else
            {
                // Синтаксис задания параметра: 
                // 1. скалярный param_name = value
                // 2. векторный param_name = { value1 values2 ... }

                if (txt.pick().GetToken() == B_EQUAL)
                {
                    txt.read_it(B_EQUAL);
                    SG_LanguageParam *param = new SG_LanguageParam;
                    param->name = t;

                    if (txt.pick().GetToken() == B_OFIGPAREN)
                    {
                        txt.read_it(B_OFIGPAREN);

                        while (!txt.eof())
                        {
                            if (txt.pick().GetToken() == B_CFIGPAREN)
                            {
                                txt.read_it(B_CFIGPAREN);
                                break;
                            }

                            UFString v = txt.read().GetFullStr();
                            v.strip(L'"');
                            v.trim();
                            param->values.push_back(v);
                        }
                    }
                    else
                    {
                        param->values.push_back(lem::trim(lem::UFString(txt.read().GetFullStr())));
                    }

                    params.push_back(param);

                    continue;
                }
            }

            lem::Iridium::Print_Error(t, txt);
            gram.GetIO().merr().printf("Invalid token in language [%us] specification\n", name.c_str());
            throw E_ParserError();
        }
    }

    if (Me)
    {
        // Эхо-сообщение: закончили трансляцию.
        gram.GetIO().mecho().printf("%vfAOK%vn\n");
    }

    return;
}
Example #18
0
/*************************************************************************

                 ЗАГРУЗКА ОПИСАНИЯ ИЗ ТЕКСТОВОГО ФАЙЛА

  1. Общий формат:

     1.1 Заголовок

     enum имя, синоним1, синоним2, ...

     Кроме основного имени можно устанавливать альтернативные имена
     координаты (синонимы). Это необходимо для работы с некоторыми
     просторечными конструкциями (типа слова 'ЕГОННЫЙ'). Имя координаты
     должно начинаться с буквы или символа '_'.

     1.2 Список состояний (два взаимоисключающих случая):

     ... = имя_источника

     - таким способом координата [имя] получает тот же список состояний,
       что и заявленые для [имя_источник].

     ... { сост1 сост2 ... состN }

     - в фигурных скобочках перечисляются имена состояний.

  2. Один из особых случаев - координаты с двумя состояниями,
     представимыми по смыслу как TRUE и FALSE. Формат описани
     их несколько иной. Объявление имеет такой формат:

                 :

     enum имя_координаты

                 :


     То есть имена состояний явно не объявляются. Внутреннее описание
     также не загружается подставными именами состояний, но при операциях
     с координатами появление координаты с нулевым количеством состояний
     отлавливается и особо учитывается.
**************************************************************************/
void GramCoord::LoadTxt(
    Macro_Parser &txtfile,
    const Grammar& gram,
    bool IsRealized
)
{
    is_realized = IsRealized;

    BethToken coord_name = txtfile.read();
    sol_check_coord_name(gram.GetDict(), txtfile, coord_name);
    name.push_back(coord_name.c_str());

    const bool Me = gram.GetDict().GetDebugLevel_ir() >= 3;
    if (Me)
    {
        // Эхо-сообщение: начали трансляцию координаты.
        gram.GetIO().mecho().printf(
            "%us [%vfE%us%vn]->",
            sol_get_token(B_COORDINATE).c_str(),
            name.get(0).c_str()
        );
    }


    BSourceState back = txtfile.tellp();

    bool cname_loaded = false;
    if (txtfile.read().GetToken() == B_AS)
    {
        c_name = txtfile.read();
        back = txtfile.tellp();
        cname_loaded = true;
    }
    else
        txtfile.seekp(back);

    // Цикл загрузки компонентов описания координаты.
    bool loading = true;
    while (loading)
    {
        const BethToken t1 = txtfile.read();

        switch (t1.GetToken())
        {
        case B_EQUAL:
        {
            // Встретили спецификацию '='. Так что пересылаем себе состояния
            // другой координаты, имя которой идёт следом.

            const BethToken another = txtfile.read();
            const GramCoordAdr ianother = gram.FindCoord(another.string());

            if (ianother.GetIndex() == UNKNOWN)
            {
                Print_Error(another, txtfile);
                MemFormatter f;
                f.printf(
                    "The coordinate [%us] is not previously "
                    "declared in grammar\n"
                    , another.c_str()
                );
                throw E_Solarix(f.string().c_str());
            }

            state = gram.coords()[ianother.GetIndex()].state; // Пересылаем себе состояния

#if defined SOL_COMPILER  
// Очищаем C-имена состояний
            for (lem::Container::size_type i = 0; i < state.size(); ++i)
            {
                state[i].Clear_API_Names();
            }
#endif

            loading = false; // Больше считывать нечего
            break;
        }

        case B_COMMA:
        {
            // Через запятую идут синонимы имени координаты.
            const BethToken t2 = txtfile.read();
            sol_check_s_name(gram.GetDict(), txtfile, t2, true);
            if (name.Find(t2.c_str()) != UNKNOWN)
            {
                Print_Error(t2, txtfile);
                MemFormatter f;
                f.printf("Duplication of the name in coordinate [%us] declaration\n", t2.c_str());
                throw E_Solarix(f.string().c_str());
            }

            name.push_back(t2.c_str());
            break;
        }

        case B_OFIGPAREN:
        {
            // В фигурных скобочках перечислены возможные состояния координаты.

            while (!txtfile.eof())
            {
                const BSourceState back2 = txtfile.tellp();

                // Если это '}', то список атрибутов завершен.
                if (txtfile.read().GetToken() == B_CFIGPAREN)
                    break;

                txtfile.seekp(back2);
                GramCoordState dummy;
                dummy.LoadTxt(gram.GetIO(), txtfile);

                // Нет повторных объявлений состояний?
                for (lem::Container::size_type i = 0; i < dummy.size(); i++)
                {
                    // Проверим, чтобы в загруженной подгруппе не было двух
                    // одинаковых имен.
                    for (lem::Container::size_type j = 0; j < dummy.size(); j++)
                    {
                        if (i != j)
                            if (dummy[i] == dummy[j])
                            {
                                Print_Error(txtfile);
                                MemFormatter f;
                                f.printf("Two equal names in a coordinate [%us] state subgroup\n", name.string().c_str());
                                throw E_Solarix(f.string().c_str());
                            }
                    }

                    const UCString& look_for = dummy.get(i);
                    if (FindState(look_for) != UNKNOWN)
                    {
                        Print_Error(txtfile);
                        MemFormatter f;
                        f.printf("Two states of coordinate [%us] have got the same name\n", name.string().c_str());
                        throw E_Solarix(f.string().c_str());
                    }
                }

                state.push_back(dummy);

                if (Me)
                    gram.GetIO().mecho().printf('.');
            }

            loading = false;
            break;
        }

        default:
        {
            if (states().size())
            {
                Print_Error(t1, txtfile);
                MemFormatter f;
                f.printf(
                    "Definition of the coordinate [%us] is not"
                    " identical to previous one.\n"
                    , name.string().c_str()
                );
                throw E_Solarix(f.string().c_str());
            }

            // Если это не открывающая фигурная скобочка, то имеем координату
            // с двумя состояниями TRUE и FALSE (бистабильную координату).
            txtfile.seekp(back);

            // На этом считывание описания заканчиваем.
            loading = false;
            break;
        }
        } // end of switch
    } // end of while

    if (Me)
    {
        // Эхо-сообщение: закончили трансляцию координаты.
        gram.GetIO().mecho().printf("%vfAOK%vn\n");
    }

    return;
}
Example #19
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 #20
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;
}