예제 #1
0
void Solarix::PrintTags( SG_TagsList tags, lem::UFString &str, SynGram &sg )
{
 str.clear();

 if( tags!=NULL )
  {
   for( lem::Container::size_type i=0; i<tags->size(); ++i )
    {
     const int itag = (*tags)[i].first;
     const int ival = (*tags)[i].second;

     const ThesaurusTag &tag = sg.Get_Net().GetTagDefs()[itag];

     if( !str.empty() ) str += L' ';
     str += tag.GetName().c_str();

     if( ival!=UNKNOWN )
      {
       const lem::UCString &val = tag[ival];
       str += L'=';
       str += val.c_str();
      }
    }
  }

 return;
}
예제 #2
0
bool SentenceBroker::Fetch(lem::UFString &line, int & line_paragraph_id)
{
    line.clear();
    line_paragraph_id = cur_paragraph_id;

    if (eof)
        return false;

    int n_quote = 0; // для учета символов "

    // Пропустим начальные пробелы.
    while (!eof)
    {
        wchar_t c = GetChar();

        if (c == WEOF)
        {
            break;
        }

        if (!lem::is_uspace(c) || IsEndOfSentenceMarker(c))
        {
            UngetChar(c);
            break;
        }
    }


    while (!eof || !chars.empty())
    {
        wchar_t c = GetChar();

        if (c == WEOF)
        {
            eof = true;
            return true;
        }
        else if (c == L' ')
        {
            line += c;
            continue;
        }
        else if (IsEndOfSentenceMarker(c))
        {
            line += c;
            break;
        }

        bool line_ready = false;

        if (
            (line.empty() || IsTokenDelimiter(line.back()) || IsTokenDelimiter(c)) &&
            tokenizer.NotNull() && tokenizer->IsUnbreakableFront(c)
            )
        {
            // Возможно далее идет исключительный случай. Выбираем символы из входного потока в 
            // попытке сконструировать максимально длинное исключение.
            lem::UCString substr;
            substr = c;

            while (!eof)
            {
                wchar_t c2 = GetChar();
                if (c2 == WEOF)
                {
                    // Достигли конца файла. Считали полный исключительный случай?
                    if (tokenizer->IsMatched(substr))
                    {
                        // Да!
                        line += substr.c_str();
                        c = c2;

                        // Считанный токен является разделителем предложений (типа ...)
                        if (sent_delims.find(substr) != UNKNOWN)
                        {
                            line.trim();

                            if (!line.empty() && (n_quote % 2) == 0)
                            {
                                count++;
                                return true;
                            }
                        }
                    }
                    else
                    {
                        // нет - вернем накопленные символы в поток чтения
                        for (int k = substr.length() - 1; k >= 0; --k)
                            UngetChar(substr[k]);

                        c = GetChar();
                    }

                    break;
                }

                substr += c2; // добавили еще один символ.

                // С символов substr начинается хоть одно исключение?
                if (!tokenizer->IsUnbreakableFront(substr) || substr.length() == lem::UCString::max_len)
                {
                    // Нет.
                    // Возможно, предыдущая подстрока является исключительной ситуацией.
                    UCString substr1 = lem::left(substr, substr.length() - 1);
                    if (tokenizer->IsMatched(substr1) && IsTokenDelimiter(substr.back()))
                    {
                        // Да!
                        line += substr1.c_str();

                        // Считанный токен является разделителем предложений (типа ...)
                        if (sent_delims.find(substr1) != UNKNOWN)
                        {
                            if ((n_quote % 2) == 0)
                            {
                                line.trim();

                                if (!line.empty())
                                {
                                    UngetChar(c2);
                                    count++;
                                    return true;
                                }
                            }
                            else
                            {
                                if (c2 == L'"')
                                {
                                    // Ситуация типа Кошка говорит "Мяу!" Собака говорит "Гав!"
                                    bool continuation_found = true;
                                    lem::MCollect<wchar_t> tmp_chars;
                                    while (!eof || !chars.empty())
                                    {
                                        const wchar_t c4 = GetChar();
                                        tmp_chars.push_back(c4);
                                        if (!lem::is_uspace(c4))
                                        {
                                            if (IsUpperChar(c4))
                                            {
                                                continuation_found = false;
                                            }

                                            break;
                                        }
                                    }

                                    for (int k = CastSizeToInt(tmp_chars.size()) - 1; k >= 0; --k)
                                        UngetChar(tmp_chars[k]);

                                    if (!continuation_found)
                                    {
                                        line += c2;
                                        return true;
                                    }
                                }
                            }
                        }

#if defined SOL_CAA
                        // Если считанный токен делит предложения в случае, когда за ним
                        // идет слово с первой заглавной буквой.
                        if (use_lexicon && casing_sent_delim.find(to_lower(substr1)) != UNKNOWN && CharCasingCoord != UNKNOWN && LowerCasingState != UNKNOWN)
                        {
                            Lexem next_token = PickNextToken();
                            if (IsUpperChar(next_token.front()))
                            {
                                la->TranslateLexem(next_token);

                                int ie = UNKNOWN;
                                if (seeker != NULL)
                                {
                                    ie = seeker->Find(next_token, false);
                                }
                                else
                                {
                                    MCollect<Word_Coord> found_list;
                                    la->ProjectWord(next_token, found_list, LanguageID);
                                    if (!found_list.empty())
                                        ie = found_list.front().GetEntry();
                                }

                                if (ie != UNKNOWN)
                                {
                                    const Solarix::SG_Entry &e = sg->GetEntry(ie);

                                    const int casing = e.attrs().FindOnce(Solarix::GramCoordAdr(CharCasingCoord));
                                    if (casing == LowerCasingState || casing == UNKNOWN)
                                    {
                                        UngetChar(c2);
                                        count++;
                                        return true;
                                    }
                                }
                            }
                        }
#endif

                        c = c2;
                    }
                    else
                    {
                        // Возвращаем все загруженные символы обратно в поток.
                        for (int k = substr.length() - 1; k >= 0; --k)
                            UngetChar(substr[k]);

                        c = GetChar();
                    }

                    break;
                }
            }
        }

        if (c == WEOF)
        {
            // закончился исходный текст, принудительно прерываем текущее предложение.
            eof = true;
            return true;
        }

        const bool ItIsSentDelim = sent_delims1.find(c) != UNKNOWN;
        if (ItIsSentDelim)
        {
            if (IsEndOfSentenceMarker(c))
                break;

            // Обычный конец предложения. Для точки надо проверять, если сразу после точки идет цифра
            // или символ в нижнем регистре, то это НЕ конец предложения.
            bool breaker = false;
            bool add_char = true;

            // Если у нас есть незакрытая пара ", то проверим следующий непустой символ.
            if ((n_quote % 2) != 0)
            {
                const wchar_t c2 = GetChar();
                // Если это закрывающая "
                if (c2 == L'"')
                {
                    n_quote++;
                    line += c;
                    line += c2;

                    const wchar_t c4 = GetChar();
                    if (sent_delims1.find(c4) != UNKNOWN)
                    {
                        line += c4;
                        count++;
                        return true;
                    }
                    else
                    {
                        UngetChar(c4);
                    }

                    // если дальше - пробел, и после него идет символ в нижнем регистре, то это не конец предложения.
                    bool continuation_found = true;
                    UFString tmp_chars;
                    while (!eof)
                    {
                        const wchar_t c5 = GetChar();
                        if (c5 == WEOF)
                        {
                            break;
                        }

                        tmp_chars += c5;
                        if (!lem::is_uspace(c5))
                        {
                            // найден не-пробельный символ.
                            if (IsUpperChar(c5))
                            {
                                continuation_found = false;
                            }

                            break;
                        }
                    }

                    // возвращаем все символы обратно
                    for (int i = CastSizeToInt(tmp_chars.size()) - 1; i >= 0; --i)
                        UngetChar(tmp_chars[i]);

                    if (!continuation_found)
                    {
                        // обрываем предложение.
                        line.trim();
                        count++;
                        return true;
                    }
                }
                else
                {
                    // нет - продолжим считывание символов предложения.
                    line += c;
                    line += c2;
                }
            }
            else
            {
#if defined SOL_CAA
                if (tokenizer.NotNull() && seeker.NotNull() && use_lexicon && c == L'.')
                {
                    // надо выделить слово, предшествующее точке. идем влево до разделителя токенов.
                    int icur = line.length() - 1;
                    while (icur >= 0)
                    {
                        if (tokenizer->IsTokenDelimiter(line[icur]))
                            break; // нашли начало последнего слова
                        else
                            icur--; // сдвигаемся влево
                    }

                    Solarix::Lexem last_word;
                    for (int j = icur + 1; j < line.length(); ++j)
                        last_word.Add_Dirty(line[j]);

                    last_word.calc_hash();

                    la->TranslateLexem(last_word);

                    if (seeker->Find(last_word, false) != UNKNOWN)
                    {
                        breaker = true;
                    }
                }
#endif 

                if (!breaker)
                {
                    breaker = true;
                    wchar_t c2 = PeekChar();
                    if (c == L'.')
                    {
                        if (lem::is_udigit(c2))
                        {
                            breaker = false;
                        }
                        else if (IsLowerChar(c2))
                        {
                            breaker = false;
                        }
                        else if (c2 == L',')
                        {
                            breaker = false;
                        }
                        else if (lem::is_uspace(c2))
                        {
                            // Дойдем до первого не-пробельного символа.
                            line += c;

                            add_char = false;
                            while (c != WEOF)
                            {
                                c = GetChar();
                                line += c;
                                if (IsEndOfSentenceMarker(c))
                                    break;

                                c = PeekChar();

                                if (!lem::is_uspace(c))
                                {
                                    if (IsLowerChar(c))
                                    {
                                        breaker = false;
                                    }

                                    break;
                                }
                            }

                            c = L'.';
                        }

                        wchar_t c0 = c;
                        c2 = PeekChar();
                        if (c2 == c0)
                        {
                            line += c;
                            add_char = false;
                            while (c != WEOF && c == c0)
                            {
                                c = GetChar();
                                line += c;
                                c = PeekChar();
                            }
                        }
                    }
                    else if (c == '!' || c == '?')
                    {
                        wchar_t c0 = c;
                        c2 = PeekChar();
                        if (c2 == L'?' || c2 == L'!') // То есть токены типа !!! и !?
                        {
                            line += c;
                            add_char = false;
                            while (c != WEOF && (c == L'!' || c == L'?'))
                            {
                                c = GetChar();
                                line += c;
                                c = PeekChar();
                            }
                        }
                    }
                }

                if (c == WEOF)
                {
                    eof = true;
                    add_char = false;
                }

                if (breaker)
                {
                    line_ready = true;
                }

                if (add_char)
                    line += c;
            }
        }
        else if (line.length() > max_sentence_length && (lem::is_uspace(c) || c == L',' || c == L'-' || c == L';' || c == L':'))
        {
            // Слишком длинные предложения обрываем на безопасных символах.
            line_ready = true;
            line += c;
        }
        else if (c == L'\r' || c == L'\n' || c == L'\t' || c == L'\b')
        {
            // некоторые управляющие символы заменяем пробелами
            line += L' ';
        }
        else
        {
            line += c;

            if (c == L'"')
                n_quote++;
            else if (c == L'(')
            {
                // если предложение начинается с (, то надо смотреть, какой токен будет перед ), и если это терминатор - обрывать предложение.
                if (line.size() == 1)
                {
                    if (ReadCharsUntilClosingParen(line))
                    {
                        line.trim();
                        return true;
                    }
                }
                else
                {
                    ReadCharsUntilClosingParen(line);
                }
            }
        }

        if (line_ready)
        {
            if (line.length() > 0 && IsEndOfParagraphMarker(line.last_char()))
            {
                line.remove(line.length() - 1);
                cur_paragraph_id++;
            }

            line.trim();

            if (!line.empty())
                count++;

            return true;
        }
    }

    if (line.length() > 0 && IsEndOfParagraphMarker(line.last_char()))
    {
        line.remove(line.length() - 1);
        cur_paragraph_id++;
    }

    line.trim();

    if (!line.empty())
        count++;

    return true;
}