Improves HiraganaMatcher.
This commit is contained in:
parent
5d667f2894
commit
59d84172c5
@ -6,94 +6,248 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
static const std::vector<std::pair<std::wstring, std::wstring>> kPatterns = {
|
static const size_t kPatternMax = 3;
|
||||||
{ L"ka", L"か", },
|
|
||||||
{ L"ki", L"き", },
|
static const std::map<std::wstring, std::vector<std::wstring>> kPatterns = {
|
||||||
{ L"ku", L"く", },
|
{ L"あ", { L"a" } },
|
||||||
{ L"ke", L"け", },
|
{ L"い", { L"i" } },
|
||||||
{ L"ko", L"こ", },
|
{ L"う", { L"u" } },
|
||||||
{ L"sa", L"さ", },
|
{ L"え", { L"e" } },
|
||||||
{ L"si", L"し", },
|
{ L"お", { L"o" } },
|
||||||
{ L"su", L"す", },
|
{ L"か", { L"ka" } },
|
||||||
{ L"se", L"せ", },
|
{ L"き", { L"ki" } },
|
||||||
{ L"so", L"そ", },
|
{ L"く", { L"ku" } },
|
||||||
{ L"ta", L"た", },
|
{ L"け", { L"ke" } },
|
||||||
{ L"ti", L"ち", },
|
{ L"こ", { L"ko" } },
|
||||||
{ L"tu", L"つ", },
|
{ L"が", { L"ga" } },
|
||||||
{ L"te", L"て", },
|
{ L"ぎ", { L"gi" } },
|
||||||
{ L"to", L"と", },
|
{ L"ぐ", { L"gu" } },
|
||||||
{ L"na", L"な", },
|
{ L"げ", { L"ge" } },
|
||||||
{ L"ni", L"に", },
|
{ L"ご", { L"go" } },
|
||||||
{ L"nu", L"ぬ", },
|
{ L"さ", { L"sa" } },
|
||||||
{ L"ne", L"ね", },
|
{ L"し", { L"si", L"shi" }},
|
||||||
{ L"no", L"の", },
|
{ L"す", { L"su" } },
|
||||||
{ L"a", L"あ", },
|
{ L"せ", { L"se" } },
|
||||||
{ L"i", L"い", },
|
{ L"そ", { L"so" } },
|
||||||
{ L"u", L"う", },
|
{ L"ざ", { L"za" } },
|
||||||
{ L"e", L"え", },
|
{ L"じ", { L"zi", L"ji" }},
|
||||||
{ L"o", L"お", },
|
{ 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());
|
assert(!done());
|
||||||
|
|
||||||
|
const std::wstring newbuf = force_cut? buffer_: buffer_ + c;
|
||||||
const std::wstring remain = state_.text.substr(state_.match);
|
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;
|
bool accept = false;
|
||||||
for (size_t i = 0; i < kPatterns.size(); ++i) {
|
size_t part_match = 0;
|
||||||
const auto& pattern = kPatterns[i];
|
size_t comp_match = 0;
|
||||||
if (pattern.first.substr(0, n) == newbuf) {
|
for (size_t i = 1; i <= pattern_len; ++i) {
|
||||||
const size_t pn = pattern.second.size();
|
const auto& p = kPatterns.find(remain.substr(0, i));
|
||||||
if (remain.substr(0, pn) == pattern.second) {
|
if (p == kPatterns.end()) continue;
|
||||||
accept = true;
|
|
||||||
last_match = i;
|
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;
|
if (itr.substr(0, newbuf.size()) == newbuf) {
|
||||||
state_.match += pn;
|
accept = true;
|
||||||
buffer_ = L"";
|
if (itr.size() == newbuf.size()) {
|
||||||
UpdateExpects(i);
|
comp_match = i;
|
||||||
return true;
|
if (force_cut) {
|
||||||
|
buffer_ = {c};
|
||||||
|
state_.match += i;
|
||||||
|
UpdateExpects_();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
part_match = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accept) {
|
if (force_cut) {
|
||||||
buffer_ = newbuf;
|
return false;
|
||||||
UpdateExpects(last_match);
|
|
||||||
}
|
}
|
||||||
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) {
|
void gj::HiraganaMatcher::UpdateExpects_() {
|
||||||
std::wstring text = state_.text.substr(state_.match);
|
std::wstring remain = state_.text.substr(state_.match);
|
||||||
|
|
||||||
expects_ = L"";
|
expects_ = L"";
|
||||||
if (text.empty()) return;
|
|
||||||
|
|
||||||
if (last_match < SIZE_MAX && buffer_.size()) {
|
bool first = true;
|
||||||
expects_ = kPatterns[last_match].first.substr(buffer_.size());
|
while (remain.size()) {
|
||||||
text = text.substr(kPatterns[last_match].second.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()) {
|
const auto& preds = p->second;
|
||||||
bool match = false;
|
if (first) {
|
||||||
for (const auto& pattern : kPatterns) {
|
for (const auto& itr : preds) {
|
||||||
const size_t n = pattern.second.size();
|
if (itr.size() < buffer_.size()) continue;
|
||||||
if (text.size() < n) continue;
|
if (itr.substr(0, buffer_.size()) == buffer_) {
|
||||||
|
expects_ += itr.substr(buffer_.size());
|
||||||
if (text.substr(0, n) == pattern.second) {
|
first = false;
|
||||||
expects_ += pattern.first;
|
break;
|
||||||
text = text.substr(n);
|
}
|
||||||
match = true;
|
}
|
||||||
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,10 +16,12 @@ class HiraganaMatcher : public iInputMatcher {
|
|||||||
HiraganaMatcher& operator=(const HiraganaMatcher&) = default;
|
HiraganaMatcher& operator=(const HiraganaMatcher&) = default;
|
||||||
|
|
||||||
HiraganaMatcher(const std::wstring& text) : state_{text, 0} {
|
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 {
|
const std::wstring& expects() const override {
|
||||||
return expects_;
|
return expects_;
|
||||||
@ -33,11 +35,13 @@ class HiraganaMatcher : public iInputMatcher {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::wstring buffer_;
|
std::wstring buffer_;
|
||||||
|
|
||||||
std::wstring expects_;
|
std::wstring expects_;
|
||||||
|
|
||||||
State state_;
|
State state_;
|
||||||
|
|
||||||
void UpdateExpects(size_t last_match = SIZE_MAX);
|
bool Input_(wchar_t c, bool force_cut);
|
||||||
|
void UpdateExpects_();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user