From 59d84172c5efa3123915998e8704b105ed92b77e Mon Sep 17 00:00:00 2001 From: falsycat Date: Thu, 26 Aug 2021 20:26:13 +0900 Subject: [PATCH] Improves HiraganaMatcher. --- src/HiraganaMatcher.cc | 286 +++++++++++++++++++++++++++++++---------- src/HiraganaMatcher.h | 10 +- 2 files changed, 227 insertions(+), 69 deletions(-) diff --git a/src/HiraganaMatcher.cc b/src/HiraganaMatcher.cc index d3fd70f..5e396ee 100644 --- a/src/HiraganaMatcher.cc +++ b/src/HiraganaMatcher.cc @@ -6,94 +6,248 @@ #include "common.h" -static const std::vector> kPatterns = { - { L"ka", L"か", }, - { L"ki", L"き", }, - { L"ku", L"く", }, - { L"ke", L"け", }, - { L"ko", L"こ", }, - { L"sa", L"さ", }, - { L"si", L"し", }, - { L"su", L"す", }, - { L"se", L"せ", }, - { L"so", L"そ", }, - { L"ta", L"た", }, - { L"ti", L"ち", }, - { L"tu", L"つ", }, - { L"te", L"て", }, - { L"to", L"と", }, - { L"na", L"な", }, - { L"ni", L"に", }, - { L"nu", L"ぬ", }, - { L"ne", L"ね", }, - { L"no", L"の", }, - { L"a", L"あ", }, - { L"i", L"い", }, - { L"u", L"う", }, - { L"e", L"え", }, - { L"o", L"お", }, +static const size_t kPatternMax = 3; + +static const std::map> kPatterns = { + { L"あ", { L"a" } }, + { L"い", { L"i" } }, + { L"う", { L"u" } }, + { L"え", { L"e" } }, + { L"お", { L"o" } }, + { L"か", { L"ka" } }, + { L"き", { L"ki" } }, + { L"く", { L"ku" } }, + { L"け", { L"ke" } }, + { L"こ", { L"ko" } }, + { L"が", { L"ga" } }, + { L"ぎ", { L"gi" } }, + { L"ぐ", { L"gu" } }, + { L"げ", { L"ge" } }, + { L"ご", { L"go" } }, + { L"さ", { L"sa" } }, + { L"し", { L"si", L"shi" }}, + { L"す", { L"su" } }, + { L"せ", { L"se" } }, + { L"そ", { L"so" } }, + { L"ざ", { L"za" } }, + { L"じ", { L"zi", L"ji" }}, + { L"ず", { L"zu" } }, + { L"ぜ", { L"ze" } }, + { L"ぞ", { L"zo" } }, + { L"た", { L"ta" } }, + { L"ち", { L"ti", L"chi" }}, + { L"つ", { L"tu", L"tsu"}}, + { L"て", { L"te" } }, + { L"と", { L"to" } }, + { L"だ", { L"da" } }, + { L"ぢ", { L"di" } }, + { L"づ", { L"du" } }, + { L"で", { L"de" } }, + { L"ど", { L"do" } }, + { L"な", { L"na" } }, + { L"に", { L"ni" } }, + { L"ぬ", { L"nu" } }, + { L"ね", { L"ne" } }, + { L"の", { L"no" } }, + { L"は", { L"ha" } }, + { L"ひ", { L"hi" } }, + { L"ふ", { L"hu", L"fu" }}, + { L"へ", { L"he" } }, + { L"ほ", { L"ho" } }, + { L"ば", { L"ba" } }, + { L"び", { L"bi" } }, + { L"ぶ", { L"bu" } }, + { L"べ", { L"be" } }, + { L"ぼ", { L"bo" } }, + { L"ぱ", { L"pa" } }, + { L"ぴ", { L"pi" } }, + { L"ぷ", { L"pu" } }, + { L"ぺ", { L"pe" } }, + { L"ぽ", { L"po" } }, + { L"ま", { L"ma" } }, + { L"み", { L"mi" } }, + { L"む", { L"mu" } }, + { L"め", { L"me" } }, + { L"も", { L"mo" } }, + { L"や", { L"ya" } }, + { L"ゆ", { L"yu" } }, + { L"よ", { L"yo" } }, + { L"きゃ", { L"kya" } }, + { L"きゅ", { L"kyu" } }, + { L"きょ", { L"kyo" } }, + { L"しゃ", { L"sha", L"sya" }}, + { L"しゅ", { L"shu", L"syu" }}, + { L"しょ", { L"sho", L"syo" }}, + { L"じゃ", { L"ja", L"zya" }}, + { L"じゅ", { L"ju", L"zyu" }}, + { L"じぇ", { L"je", L"zye" }}, + { L"じょ", { L"jo", L"zyo" }}, + { L"ちゃ", { L"cha", L"tya" }}, + { L"ちゅ", { L"chu", L"tyu" }}, + { L"ちょ", { L"cho", L"tyo" }}, + { L"ら", { L"ra" } }, + { L"り", { L"ri" } }, + { L"る", { L"ru" } }, + { L"れ", { L"re" } }, + { L"ろ", { L"ro" } }, + { L"わ", { L"wa" } }, + { L"を", { L"wo" } }, + { L"ん", { L"n", L"nn"}}, + + { L"っ", { L"ltu", L"xtu" }}, + { L"っか", { L"kka" } }, + { L"っき", { L"kki" } }, + { L"っく", { L"kku" } }, + { L"っけ", { L"kke" } }, + { L"っこ", { L"kko" } }, + { L"っが", { L"gga" } }, + { L"っぎ", { L"ggi" } }, + { L"っぐ", { L"ggu" } }, + { L"っげ", { L"gge" } }, + { L"っご", { L"ggo" } }, + { L"っさ", { L"ssa" } }, + { L"っし", { L"ssi" } }, + { L"っす", { L"ssu" } }, + { L"っせ", { L"sse" } }, + { L"っそ", { L"sso" } }, + { L"っざ", { L"zza" } }, + { L"っじ", { L"zzi", L"jji" }}, + { L"っず", { L"zzu" } }, + { L"っぜ", { L"zze" } }, + { L"っぞ", { L"zzo" } }, + { L"った", { L"tta" } }, + { L"っち", { L"tti", L"cchi" }}, + { L"っつ", { L"ttu", L"ttsu"}}, + { L"って", { L"tte" } }, + { L"っと", { L"tto" } }, + { L"っだ", { L"dda" } }, + { L"っぢ", { L"ddi" } }, + { L"っづ", { L"ddu" } }, + { L"っで", { L"dde" } }, + { L"っど", { L"ddo" } }, + { L"っな", { L"nna" } }, + { L"っに", { L"nni" } }, + { L"っぬ", { L"nnu" } }, + { L"っね", { L"nne" } }, + { L"っの", { L"nno" } }, + { L"っは", { L"hha" } }, + { L"っひ", { L"hhi" } }, + { L"っふ", { L"hhu", L"ffu" }}, + { L"っへ", { L"hhe" } }, + { L"っほ", { L"hho" } }, + { L"っば", { L"bba" } }, + { L"っび", { L"bbi" } }, + { L"っぶ", { L"bbu" } }, + { L"っべ", { L"bbe" } }, + { L"っぼ", { L"bbo" } }, + { L"っぱ", { L"ppa" } }, + { L"っぴ", { L"ppi" } }, + { L"っぷ", { L"ppu" } }, + { L"っぺ", { L"ppe" } }, + { L"っぽ", { L"ppo" } }, + { L"っま", { L"mma" } }, + { L"っみ", { L"mmi" } }, + { L"っむ", { L"mmu" } }, + { L"っめ", { L"mme" } }, + { L"っも", { L"mmo" } }, + { L"っや", { L"yya" } }, + { L"っゆ", { L"yyu" } }, + { L"っよ", { L"yyo" } }, + { L"っら", { L"rra" } }, + { L"っり", { L"rri" } }, + { L"っる", { L"rru" } }, + { L"っれ", { L"rre" } }, + { L"っろ", { L"rro" } }, + { L"わ", { L"wwa" } }, + { L"を", { L"wwo" } }, }; -bool gj::HiraganaMatcher::Input(wchar_t c) { +bool gj::HiraganaMatcher::Input_(wchar_t c, bool force_cut) { assert(!done()); + const std::wstring newbuf = force_cut? buffer_: buffer_ + c; const std::wstring remain = state_.text.substr(state_.match); - const std::wstring newbuf = buffer_ + c; - const size_t n = newbuf.size(); + const size_t pattern_len = std::min(kPatternMax, remain.size()); - size_t last_match = 0; bool accept = false; - for (size_t i = 0; i < kPatterns.size(); ++i) { - const auto& pattern = kPatterns[i]; - if (pattern.first.substr(0, n) == newbuf) { - const size_t pn = pattern.second.size(); - if (remain.substr(0, pn) == pattern.second) { - accept = true; - last_match = i; + size_t part_match = 0; + size_t comp_match = 0; + for (size_t i = 1; i <= pattern_len; ++i) { + const auto& p = kPatterns.find(remain.substr(0, i)); + if (p == kPatterns.end()) continue; + + const auto& preds = p->second; + for (const auto& itr : preds) { + if (newbuf.size() == 0 || itr.size() < newbuf.size()) { + continue; } - if (pattern.first.size() == n) { - if (!accept) return false; - state_.match += pn; - buffer_ = L""; - UpdateExpects(i); - return true; + + if (itr.substr(0, newbuf.size()) == newbuf) { + accept = true; + if (itr.size() == newbuf.size()) { + comp_match = i; + if (force_cut) { + buffer_ = {c}; + state_.match += i; + UpdateExpects_(); + return true; + } + } else { + part_match = i; + } } } } - if (accept) { - buffer_ = newbuf; - UpdateExpects(last_match); + if (force_cut) { + return false; } - return accept; + if (!accept) { + return Input_(c, true); + } + + if (comp_match > part_match) { + buffer_ = L""; + state_.match += comp_match; + UpdateExpects_(); + return true; + } + + buffer_ += c; + UpdateExpects_(); + return true; } -void gj::HiraganaMatcher::UpdateExpects(size_t last_match) { - std::wstring text = state_.text.substr(state_.match); +void gj::HiraganaMatcher::UpdateExpects_() { + std::wstring remain = state_.text.substr(state_.match); expects_ = L""; - if (text.empty()) return; - if (last_match < SIZE_MAX && buffer_.size()) { - expects_ = kPatterns[last_match].first.substr(buffer_.size()); - text = text.substr(kPatterns[last_match].second.size()); - } + bool first = true; + while (remain.size()) { + const size_t prev = remain.size(); + for (size_t len = std::min(kPatternMax, remain.size()); len > 0; --len) { + const auto& p = kPatterns.find(remain.substr(0, len)); + if (p == kPatterns.end()) continue; - while (text.size()) { - bool match = false; - for (const auto& pattern : kPatterns) { - const size_t n = pattern.second.size(); - if (text.size() < n) continue; - - if (text.substr(0, n) == pattern.second) { - expects_ += pattern.first; - text = text.substr(n); - match = true; - break; + const auto& preds = p->second; + if (first) { + for (const auto& itr : preds) { + if (itr.size() < buffer_.size()) continue; + if (itr.substr(0, buffer_.size()) == buffer_) { + expects_ += itr.substr(buffer_.size()); + first = false; + break; + } + } + if (first) continue; + } else { + expects_ += preds[0]; } + remain = remain.substr(len); } - if (!match) Abort("hiragana janai"); + if (prev == remain.size()) Abort("invalid pattern for InputWin"); } } \ No newline at end of file diff --git a/src/HiraganaMatcher.h b/src/HiraganaMatcher.h index e4a9de6..5b02a81 100644 --- a/src/HiraganaMatcher.h +++ b/src/HiraganaMatcher.h @@ -16,10 +16,12 @@ class HiraganaMatcher : public iInputMatcher { HiraganaMatcher& operator=(const HiraganaMatcher&) = default; HiraganaMatcher(const std::wstring& text) : state_{text, 0} { - UpdateExpects(); + UpdateExpects_(); } - bool Input(wchar_t c) override; + bool Input(wchar_t c) override { + return Input_(c, false); + } const std::wstring& expects() const override { return expects_; @@ -33,11 +35,13 @@ class HiraganaMatcher : public iInputMatcher { private: std::wstring buffer_; + std::wstring expects_; State state_; - void UpdateExpects(size_t last_match = SIZE_MAX); + bool Input_(wchar_t c, bool force_cut); + void UpdateExpects_(); };