예제 #1
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;
}
예제 #2
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())
예제 #3
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;
}