CPP C++ logo

В прошлом году мне понадобилось доработать токенизатор в моем движке. Поэтому я быстро набросал новую простейшую версию.

Токенизатор хранит лишь начало/конец токена аля std::string_view. Поддерживается UTF-8. Поддерживает произвольный набор разделителей и их произвольную длину. Может быть достаточно легко доработан до поддержки японского, корейского, тайского и прочих языков.

Тут выкладываю лишь свой набросок токенизатора. Доработанная версия, вошедшая в движок, была сделана на его основе.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include <iostream>
#include <string>
#include <vector>
class Tokenizer
{
public:
using DelimetersList = std::vector<std::string>;
Tokenizer(const DelimetersList& delimiters)
: m_delimiters(delimiters)
{
}
void tokenize(const std::string& str)
{
m_tokens.clear();
size_t start = 0;
size_t end = 0;
while (end != str.length())
{
auto delimiter = findDelimiter(str, start);
end = delimiter.pos;
m_tokens.push_back({ start, end - start });
start = end + delimiter.length;
}
}
struct Token
{
size_t begin;
size_t length;
};
using TokensList = std::vector<Token>;
const TokensList& getTokens() const
{
return m_tokens;
}
private:
struct Delimiter
{
size_t pos;
size_t length;
};
Delimiter findDelimiter(const std::string& str, size_t start) const
{
size_t minPos = str.length();
size_t length = 0;
for (auto& delimiter : m_delimiters)
{
auto pos = str.find(delimiter, start);
if (pos < minPos)
{
minPos = pos;
length = delimiter.length();
}
}
return { minPos, length };
}
private:
const DelimetersList m_delimiters;
private:
TokensList m_tokens;
};
int main()
{
std::string s = "お客#様のレビ#ュー\nはゲー\nム#の改善に役#立ちます!";
std::cout << "string: \n" << s << "\n----\n" << std::endl;
Tokenizer tokenizer({ " ", "\n", "\r", "#" });
tokenizer.tokenize(s);
for (auto& t : tokenizer.getTokens())
{
std::cout << s.substr(t.begin, t.length) << std::endl;
}
return 0;
}
#include <iostream> #include <string> #include <vector> class Tokenizer { public: using DelimetersList = std::vector<std::string>; Tokenizer(const DelimetersList& delimiters) : m_delimiters(delimiters) { } void tokenize(const std::string& str) { m_tokens.clear(); size_t start = 0; size_t end = 0; while (end != str.length()) { auto delimiter = findDelimiter(str, start); end = delimiter.pos; m_tokens.push_back({ start, end - start }); start = end + delimiter.length; } } struct Token { size_t begin; size_t length; }; using TokensList = std::vector<Token>; const TokensList& getTokens() const { return m_tokens; } private: struct Delimiter { size_t pos; size_t length; }; Delimiter findDelimiter(const std::string& str, size_t start) const { size_t minPos = str.length(); size_t length = 0; for (auto& delimiter : m_delimiters) { auto pos = str.find(delimiter, start); if (pos < minPos) { minPos = pos; length = delimiter.length(); } } return { minPos, length }; } private: const DelimetersList m_delimiters; private: TokensList m_tokens; }; int main() { std::string s = "お客#様のレビ#ュー\nはゲー\nム#の改善に役#立ちます!"; std::cout << "string: \n" << s << "\n----\n" << std::endl; Tokenizer tokenizer({ " ", "\n", "\r", "#" }); tokenizer.tokenize(s); for (auto& t : tokenizer.getTokens()) { std::cout << s.substr(t.begin, t.length) << std::endl; } return 0; }
#include <iostream>
#include <string>
#include <vector>

class Tokenizer
{
public:
    using DelimetersList = std::vector<std::string>;

    Tokenizer(const DelimetersList& delimiters)
        : m_delimiters(delimiters)
    {
    }

    void tokenize(const std::string& str)
    {
        m_tokens.clear();

        size_t start = 0;
        size_t end = 0;

        while (end != str.length())
        {
            auto delimiter = findDelimiter(str, start);
            end = delimiter.pos;

            m_tokens.push_back({ start, end - start });

            start = end + delimiter.length;
        }
    }

    struct Token
    {
        size_t begin;
        size_t length;
    };

    using TokensList = std::vector<Token>;

    const TokensList& getTokens() const
    {
        return m_tokens;
    }

private:
    struct Delimiter
    {
        size_t pos;
        size_t length;
    };

    Delimiter findDelimiter(const std::string& str, size_t start) const
    {
        size_t minPos = str.length();
        size_t length = 0;

        for (auto& delimiter : m_delimiters)
        {
            auto pos = str.find(delimiter, start);
            if (pos < minPos)
            {
                minPos = pos;
                length = delimiter.length();
            }
        }

        return { minPos, length };
    }

private:
    const DelimetersList m_delimiters;

private:
    TokensList m_tokens;
};

int main()
{
    std::string s = "お客#様のレビ#ュー\nはゲー\nム#の改善に役#立ちます!";

    std::cout << "string: \n" << s << "\n----\n" << std::endl;

    Tokenizer tokenizer({ " ", "\n", "\r", "#" });
    tokenizer.tokenize(s);

    for (auto& t : tokenizer.getTokens())
    {
        std::cout << s.substr(t.begin, t.length) << std::endl;
    }

    return 0;
}