コード例 #1
0
ファイル: base_entry.cpp プロジェクト: Koziev/GrammarEngine
/********************************************************************
 Читаем из текстового файла секции расширенного описания статьи.
 Под расширенным описанием подразумевается список координат-атрибутов,
 формы, грамматическая сеть и специфические для производных классов
 поля.
*********************************************************************/
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;
}
コード例 #2
0
ファイル: form_table.cpp プロジェクト: Koziev/GrammarEngine
/********************************************************************
  Загрузка описания Статьи из текстового файла
*********************************************************************/
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;
}
コード例 #3
0
ファイル: form_table.cpp プロジェクト: Koziev/GrammarEngine
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;
}
コード例 #4
0
ファイル: base_entry.cpp プロジェクト: Koziev/GrammarEngine
/*********************************************************************
 Все атрибуты должны быть определены! Метод вызывается после чтения
 тела описания Статьи.
**********************************************************************/
void Base_Entry::CheckAttr(Macro_Parser& txtfile, Grammar& gram)
{
    if (is_quantor(GetClass()))
        return;

    const GramClass& cl = gram.classes()[GetClass()];
    const int na = CastSizeToInt(cl.attrs().size());

    for (int i = 0; i < na; i++)
    {
        const GramCoordAdr iglob = cl.attrs()[i];

        const GramClass &cls = gram.classes()[GetClass()];

        if (GetAttrState(iglob) == UNKNOWN)
        {
            lem::zbool def_unk;
            for (lem::Container::size_type j = 0; j < cl.attr_defaults.size(); ++j)
            {
                if (cl.attr_defaults[j].first == iglob && cl.attr_defaults[j].second == UNKNOWN)
                {
                    def_unk = true;
                    break;
                }
            }

            if (!def_unk)
            {
                // Состояние аттрибута не определено!
                Print_Error(txtfile);
                gram.GetIO().merr().printf(
                    "Not defined attribute [%us] state\n",
                    gram.coords()[iglob.GetIndex()].GetName()[iglob.GetVar()].c_str()
                );
                throw E_ParserError();
            }
        }
    }

    return;
}
コード例 #5
0
ファイル: base_entry.cpp プロジェクト: Koziev/GrammarEngine
/**********************************************************
 Загрузка тела описания статьи из текстового файла Словаря.
 Само тело состоит из нескольких факультативных частей.
***********************************************************/
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;
}
コード例 #6
0
ファイル: form_table.cpp プロジェクト: Koziev/GrammarEngine
/**************************************************************************
     ЗАГРУЗКА ОДНОЙ АТРИБУТНОЙ КООРДИНАТНОЙ ПАРЫ
             из текстового файла

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

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

 Особое внимание следует уделять автоматическому созданию 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())
コード例 #7
0
ファイル: coordinate.cpp プロジェクト: Koziev/GrammarEngine
/*************************************************************************

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

  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;
}