@@ -569,82 +569,93 @@ inline static bool prefer_user_phrase(
569569}
570570
571571bool ScriptTranslation::PrepareCandidate () {
572- if (exhausted ()) {
573- candidate_source_ = kUninitialized ;
574- candidate_ = nullptr ;
575- return false ;
576- }
577- if (sentence_) {
578- candidate_source_ = kSentence ;
579- candidate_ = sentence_;
580- return true ;
581- }
582- const size_t full_code_length = end_of_input_ - start_;
583- size_t user_phrase_code_length = 0 ;
584- if (user_phrase_ && user_phrase_iter_ != user_phrase_->rend ()) {
585- user_phrase_code_length = user_phrase_iter_->first ;
586- }
587- size_t phrase_code_length = 0 ;
588- if (phrase_ && phrase_iter_ != phrase_->rend ()) {
589- phrase_code_length = phrase_iter_->first ;
590- }
591- if (user_phrase_code_length > 0 &&
592- prefer_user_phrase (
593- user_phrase_code_length, phrase_code_length,
594- // 編碼長度相同時, 用戶詞優先
595- [this , full_code_length, phrase_code_length]() {
596- UserDictEntryIterator& uter = user_phrase_iter_->second ;
597- DictEntryIterator& iter = phrase_iter_->second ;
598- // 但若用戶詞爲糾錯結果, 則免去優先權, 回歸權重比較
599- bool user_is_correction = syllabifier_->IsCorrection (
600- uter.Peek ()->code , phrase_code_length);
601- if (user_is_correction) {
602- // 因對糾錯候選施加了較大懲罰, 通常結果爲 系統原文 > 用戶糾錯
603- // 兩者皆糾錯時, 用戶詞的動態權重有助達成 用戶糾錯 > 系統糾錯
604- return uter.Peek ()->weight >= iter.Peek ()->weight ;
605- }
606- // 長詞聯想之前須至少出一個嚴格匹配的候選
607- // 故確定首選之際, 系統嚴格匹配 > 用戶長詞聯想
608- const int kNumExactMatchOnTop = 1 ;
609- return candidate_index_ >= kNumExactMatchOnTop ||
610- prefer_user_phrase (
611- has_exact_match_phrase (user_phrase_, user_phrase_iter_,
612- full_code_length),
613- has_exact_match_phrase (phrase_, phrase_iter_,
614- full_code_length));
615- })) {
616- UserDictEntryIterator& uter = user_phrase_iter_->second ;
617- const auto & entry = uter.Peek ();
618- DLOG (INFO) << " user phrase '" << entry->text
619- << " ', code length: " << user_phrase_code_length;
620- candidate_source_ = kUserPhrase ;
621- candidate_ =
622- New<Phrase>(translator_->language (),
623- entry->IsPredictiveMatch () ? " completion" : " user_phrase" ,
624- start_, start_ + user_phrase_code_length, entry);
625- candidate_->set_quality (std::exp (entry->weight ) +
626- translator_->initial_quality () +
627- (entry->quality_len / full_code_length));
628- return true ;
629- } else if (phrase_code_length > 0 ) {
630- DictEntryIterator& iter = phrase_iter_->second ;
631- const auto & entry = iter.Peek ();
632- DLOG (INFO) << " phrase '" << entry->text
633- << " ', code length: " << phrase_code_length;
634- candidate_source_ = kSysPhrase ;
635- candidate_ =
636- New<Phrase>(translator_->language (),
637- entry->IsPredictiveMatch () ? " completion" : " phrase" ,
638- start_, start_ + phrase_code_length, entry);
639- candidate_->set_quality (std::exp (entry->weight ) +
640- translator_->initial_quality () +
641- (entry->quality_len / full_code_length));
642- return true ;
643- } else {
644- candidate_source_ = kUninitialized ;
645- candidate_ = nullptr ;
646- return false ;
647- }
572+ do {
573+ if (exhausted ()) {
574+ candidate_source_ = kUninitialized ;
575+ candidate_ = nullptr ;
576+ return false ;
577+ }
578+ if (sentence_) {
579+ candidate_source_ = kSentence ;
580+ candidate_ = sentence_;
581+ return true ;
582+ }
583+ const size_t full_code_length = end_of_input_ - start_;
584+ size_t user_phrase_code_length = 0 ;
585+ if (user_phrase_ && user_phrase_iter_ != user_phrase_->rend ()) {
586+ user_phrase_code_length = user_phrase_iter_->first ;
587+ }
588+ size_t phrase_code_length = 0 ;
589+ if (phrase_ && phrase_iter_ != phrase_->rend ()) {
590+ phrase_code_length = phrase_iter_->first ;
591+ }
592+ if (user_phrase_code_length > 0 &&
593+ prefer_user_phrase (
594+ user_phrase_code_length, phrase_code_length,
595+ // 編碼長度相同時, 用戶詞優先
596+ [this , full_code_length, phrase_code_length]() {
597+ UserDictEntryIterator& uter = user_phrase_iter_->second ;
598+ DictEntryIterator& iter = phrase_iter_->second ;
599+ // 但若用戶詞爲糾錯結果, 則免去優先權, 回歸權重比較
600+ bool user_is_correction = syllabifier_->IsCorrection (
601+ uter.Peek ()->code , phrase_code_length);
602+ if (user_is_correction) {
603+ // 因對糾錯候選施加了較大懲罰, 通常結果爲 系統原文 > 用戶糾錯
604+ // 兩者皆糾錯時, 用戶詞的動態權重有助達成 用戶糾錯 > 系統糾錯
605+ return uter.Peek ()->weight >= iter.Peek ()->weight ;
606+ }
607+ // 長詞聯想之前須至少出一個嚴格匹配的候選
608+ // 故確定首選之際, 系統嚴格匹配 > 用戶長詞聯想
609+ const int kNumExactMatchOnTop = 1 ;
610+ return candidate_index_ >= kNumExactMatchOnTop ||
611+ prefer_user_phrase (
612+ has_exact_match_phrase (user_phrase_, user_phrase_iter_,
613+ full_code_length),
614+ has_exact_match_phrase (phrase_, phrase_iter_,
615+ full_code_length));
616+ })) {
617+ UserDictEntryIterator& uter = user_phrase_iter_->second ;
618+ const auto & entry = uter.Peek ();
619+ if (!entry) {
620+ ++user_phrase_iter_;
621+ continue ;
622+ }
623+ DLOG (INFO) << " user phrase '" << entry->text
624+ << " ', code length: " << user_phrase_code_length;
625+ candidate_source_ = kUserPhrase ;
626+ candidate_ =
627+ New<Phrase>(translator_->language (),
628+ entry->IsPredictiveMatch () ? " completion" : " user_phrase" ,
629+ start_, start_ + user_phrase_code_length, entry);
630+ candidate_->set_quality (std::exp (entry->weight ) +
631+ translator_->initial_quality () +
632+ (entry->quality_len / full_code_length));
633+ return true ;
634+ } else if (phrase_code_length > 0 ) {
635+ DictEntryIterator& iter = phrase_iter_->second ;
636+ const auto & entry = iter.Peek ();
637+ if (!entry) {
638+ ++phrase_iter_;
639+ continue ;
640+ }
641+ DLOG (INFO) << " phrase '" << entry->text
642+ << " ', code length: " << phrase_code_length;
643+ candidate_source_ = kSysPhrase ;
644+ candidate_ =
645+ New<Phrase>(translator_->language (),
646+ entry->IsPredictiveMatch () ? " completion" : " phrase" ,
647+ start_, start_ + phrase_code_length, entry);
648+ candidate_->set_quality (std::exp (entry->weight ) +
649+ translator_->initial_quality () +
650+ (entry->quality_len / full_code_length));
651+ return true ;
652+ } else {
653+ candidate_source_ = kUninitialized ;
654+ candidate_ = nullptr ;
655+ return false ;
656+ }
657+ } while (!exhausted () && !candidate_);
658+ return false ;
648659}
649660
650661bool ScriptTranslation::CheckEmpty () {
0 commit comments