| |
| |
| |
| |
| |
| |
| |
| |
| |
| #pragma once |
| #include <string> |
| #include <vector> |
| #include <regex> |
| #include <map> |
|
|
| #define _DEFAULT_MARKS ";:,.!?¡¿—…\"«»“”(){}[]" |
|
|
|
|
| typedef std::pair<std::string, std::string> LineMarkPair; |
|
|
| |
| |
| |
| |
| class Punctuator { |
| public: |
| Punctuator(const std::string& marks = _DEFAULT_MARKS): |
| marks_(marks) { |
|
|
| } |
|
|
| ~Punctuator() = default; |
|
|
| static std::string default_marks() { |
| return std::string(_DEFAULT_MARKS); |
| } |
|
|
| inline std::string get_marks() const { |
| return marks_; |
| } |
|
|
| std::vector<LineMarkPair> run(const std::string& text) { |
| return split_by_marks_(text, marks_); |
| } |
|
|
| private: |
| std::vector<LineMarkPair> split_by_marks_( |
| const std::string& str, const std::string& delimiterChars) { |
| |
| std::vector<std::pair<std::string, std::string>> result; |
| |
| if (str.empty()) return result; |
| if (delimiterChars.empty()) { |
| result.emplace_back(str, ""); |
| return result; |
| } |
| |
| |
| std::string escaped; |
| for (char c : delimiterChars) { |
| if (c == '\\' || c == '^' || c == '$' || c == '.' || c == '|' || |
| c == '?' || c == '*' || c == '+' || c == '(' || c == ')' || |
| c == '[' || c == ']' || c == '{' || c == '}') { |
| escaped += '\\'; |
| } |
| escaped += c; |
| } |
| |
| |
| std::string pattern = "([^" + escaped + "]+)|([" + escaped + "])"; |
| std::regex re(pattern); |
| |
| std::sregex_iterator it(str.begin(), str.end(), re); |
| std::sregex_iterator end; |
| |
| while (it != end) { |
| |
| if ((*it)[1].matched) { |
| result.emplace_back((*it)[1].str(), ""); |
| } |
| |
| else if ((*it)[2].matched) { |
| |
| if (!result.empty() && result.back().second.empty()) { |
| result.back().second = (*it)[2].str(); |
| } else { |
| |
| result.emplace_back("", (*it)[2].str()); |
| } |
| } |
| ++it; |
| } |
| |
| return result; |
| } |
|
|
| private: |
| std::string marks_; |
| }; |
|
|