//------------------------------------------------------- // 分割なし完全一致の語 static public WordTable Scan(WordChain wChain, WordTable wTable) { if (wTable.IsTranslated()) { return(wTable); // 変換済みなら何もしない } // 翻訳しなくていい文字は抜ける if (!wTable.IsWord() || // 空白や制御文字 wTable.IsDigit() || wTable.IsOther()) // 記号 { return(wTable); } // 助詞なら抜ける if (wTable.posCategory == PosCategory.PP) { return(wTable); } // 独立した1文字の語は辞書より先に検索 (単独の이など) if (wTable.word.Length == 1) { CheckOneWord(wTable); if (wTable.transWord != "") { return(wTable); // match } } // 全体で完全一致で検索 SearchResult sResult = KJ_dict.SearchFull(wTable.word); if (sResult != null) { wTable.SetResult(sResult); return(wTable); // 完全一致で見つかった } // 4文字語の調査 (部分分割後は使わない) WordChain wc = Check4Chars(wTable); if (wc != null) { wChain.Swap(wTable, wc); return(wc.Tail); } return(wTable); }
//-------------------------------------------------------------- //------------------------------------------------------------------ // 分割も考慮し詳しい(?)解析 // 分解後チェーンの最後のwTableを返す // // // PalDalHan WordTable ←input // ↓ // PalDal WordTable // Han WordTable ←return // private WordTable ScanDetail(WordChain wChain, WordTable wTable) { if (wTable.IsTranslated()) { return(wTable); // 変換済みなら何もしない } #if DEBUG_LOG KJ_Analyzer.WriteDebugLog("ScanDetail"); #endif // 各国固有部 if (KJ_dict.inputIsHangul) { WordTable rtnWt = ScanDetailKr(wChain, wTable); if (rtnWt != null) { return(rtnWt); } } else { WordTable rtnWt = ScanDetailJp(wChain, wTable); if (rtnWt != null) { return(rtnWt); } } // 語分割ありで、熟語をチェック WordTable idiomwt = Idiom.Search2(wChain, wTable); if (idiomwt != null) { // 熟語が解決できた return(idiomwt); } // 語の分解 WordChain devChain = WordDivider(wTable); if (devChain != null) // 分解できた? { if (AcceptableTransWord(wTable, devChain)) // 採用できるか? // 採用できるならwTableを分解したチェーンdevChainで入れ替え { wChain.Swap(wTable, devChain); return(devChain.Tail); // 分解した最後の位置へ } } // それでも変換なしならカタカナまたはハングルに自動変換 wTable = ConvAutoConv(wTable); return(wTable); }
//------------------------------------------------------------------ // Chain中が全て翻訳済みWordTableならtrue // 1つでも翻訳できていないならfalse public bool IsFullTranslated() { WordTable wt = this.head; while (wt != null) { if (!wt.IsTranslated()) { return(false); } wt = wt.next; } return(true); }
//------------------------------------------------------------------ // Chain中の何文字翻訳できているか public int TranslatedCharCount() { WordTable wt = this.head; int rtnCnt = 0; while (wt != null) { if (wt.IsTranslated()) { rtnCnt += wt.word.Length; } wt = wt.next; } return(rtnCnt); }
static public WordTable Scan(WordChain wChain, WordTable wTable) { if (wTable.IsTranslated()) { return(wTable); // 変換済みなら何もしない } if (KJ_dict.inputIsHangul) { wTable = ScanPPKr(wChain, wTable); } else { wTable = ScanPPJp(wChain, wTable); } return(wTable); }
//------------------------------------------------------------------- // チェーンの前処理。 // 句読点の判定、置換など // private WordTable ChainPreProc(WordChain wChain, WordTable wTable) { if (wTable.IsTranslated()) { return(wTable); // 変換済みなら何もしない } if (wTable.charCategory == CharCategory.Letter) { // 一種の正規化 if (wTable.word == "ㆍ") // 0x318D 韓国で使われる中点 { wTable.word = "・"; // 0x30FB 日本語の全角中点 } } if (wTable.charCategory == CharCategory.Punctuation) { if (KJ_dict.inputIsHangul) { if (wTable.word == ".") { if (wTable.next == null || !wTable.next.IsWord()) { wTable.transWord = "。"; } } } else { if (wTable.word == "、") { wTable.transWord = ", "; } if (wTable.word == "。") { wTable.transWord = ". "; } } } return(wTable); }
//------------------------------------------------------------------------ // 辞書に見つからなかった語を自動変換する // ハングル <---> カタカナ private WordTable ConvAutoConv(WordTable wt) { if (wt.IsTranslated()) { return(wt); // 変換済みなら何もしない } if (!this.sTrans.AutoConv) { return(wt); // AutoConvをoffにしている場合は何もせず抜ける。 } if (KJ_dict.inputIsHangul) { // K-->J方向 if (CodeCheck.IsHangul(wt.word)) { wt.transWord = Hangul.Hangul2Kana(wt.word); } } else { // J-->方向 if (wt.charCategory == CharCategory.Katakana) { // カタカナの場合 wt.transWord = Kana.Kana2Hangul(wt.word); } else { if (wt.charCategory == CharCategory.Hiragana) { // ひらがなの場合 wt.transWord = Kana.Hira2Hangul(wt.word); } } } return(wt); }
//------------------------------------------------------- // 語のchainを先頭から舐め、助詞(Postpositional Particle)を分解する。 static private WordTable ScanPPJp(WordChain wChain, WordTable wTable) { // 語を舐め、助詞を分解する。 if (wTable.IsTranslated() || wTable.IsDigit()) { // 翻訳済み または 数字ならなにもしない。 return(wTable); } // J-->K方向の場合、ハングルは // 前の語に依存するので訳語(ハングル)の設定は別途。 // 助詞である事の確定だけ試みる // 分離されたひらがなの助詞判定だけ PosCategory pp = CheckPos_Hira(wTable.word); if (PosCategory.PP == pp) { wTable.posCategory = pp; } // 漢字+ひらがなの形での助詞分離 if (wTable.charCategory == CharCategory.KanHira) { WordChain resultChain = DivideJapanesePP(wTable); if (resultChain != null) { wChain.Swap(wTable, resultChain); // 前の語は未翻訳なのでそれを返す wTable = resultChain.Head; } } return(wTable); }
//------------------------------------------------------- // 語のchainを先頭から舐め、助数詞・冠数詞を解析する。 static public WordTable Scan(WordChain wChain, WordTable wTable) { if (wTable.IsTranslated()) { return(wTable); // 変換済みなら何もしない } WordTable next = wTable.NextWord(); // 次の有効な語を返す。(空白skip) // 前後を数字(Digit)に挟まれる場合 if ((wTable.prev != null && wTable.prev.IsDigit()) && (next != null && next.IsDigit())) { string transword = KJ_Filter.SearchNumConnecting(wTable.word); if (transword != "") { wTable.transWord = transword; wTable.posCategory = PosCategory.Numerative; wTable.Cost = 1; return(wTable); } } // 1つ前のWordTableは数字(Digit)の場合 // または数詞(Numeral)である場合 if ((wTable.prev != null && wTable.prev.IsDigit()) || // 800억 の 억 (wTable.PrevWord() != null && wTable.PrevWord().posCategory == PosCategory.Numeral) // 800억원 --> 800+억+원の원 // 160억 개의 のように空白をはさむ事があるので空白skipで前の語を調べる ) { WordChain dividedChain = DivideCountable(wTable); if (dividedChain != null) { // 助数詞であった // devidedChainは 助数詞+語のチェーン。wTableと入れ替える // (+語はない場合もある) wChain.Swap(wTable, dividedChain); // 処理済みTable変更 wTable = dividedChain.Head; } } else { // 次の語が数字である場合 (冠数詞) NumerativePrefix // ★前数字と違い、空白はさんでも許す (약 90만 or 약90만) if (next != null && next.IsDigit()) { string transword = KJ_Filter.SearchPreNum(wTable.word); // string transword = CheckPreNum(wTable); if (transword != "") { wTable.transWord = transword; wTable.posCategory = PosCategory.NumerativePrefix; // ちょっと違うか。あとで wTable.Cost = 1; } } } return(wTable); }
//-------------------------------------------------------------------- // 語の変換 (語の分解あり) // 語分解で翻訳済み末尾がずれることがあるのでWordTableを返す // ABCDEF という語に対し、 // ABCDE + F // ABCD + EF // ABC + DEF // : : // と調べていき、最小コストの訳語がとれる分割を採用する // static public WordChain WordPartProc(WordTable wt) { SearchResult sResult; String str = wt.word; if (wt == null) { return(null); } if (wt.word != null && wt.word.Length == 1) // 1文字検索はしない { return(null); } if (wt.IsTranslated() || wt.IsDigit()) { return(null); // 翻訳済みまたは 数字なら 何もしない } #if DEBUG_LOG KJ_Analyzer.WriteDebugLog("WordPartProc:" + wt.word); #endif // 再起に備え,まず完全一致で検索 sResult = KJ_dict.SearchFull(str); if (sResult != null) { wt.SetResult(sResult); // 全体でmatch WordChain wc = new WordChain(wt); return(wc); } // 部分語の2文字は分割しない if (wt.word != null && wt.word.Length == 2 && wt.divided != Divided.Non) { return(null); } // 3文字の「ハングルまたは漢字」なら特別チェック if (wt.word != null && wt.word.Length == 3 && wt.divided != Divided.Non && // 部分語の3文字語は除外 (CodeCheck.IsHangul(wt.word) || CodeCheck.IsKanji(wt.word)) ) { WordChain wc3 = Check3Chars(wt); if (wc3 != null) { return(wc3); } } // int target_len=2; // 2005.09.03 やっぱり1文字まで切らないとだめだ int target_len = 1; int str_len = str.Length; int minimumCost = 9999; WordChain minimumCostChain = null; // 前から1文字ずつ落としつつ,検索。 while (true) { int start = str_len - target_len; // if( start <= 1 ){ // 2005.09.03 if (start <= 0) { break; } // 文字列を分割する // str --> str2 + str3 // String str2 = str.Remove (start, target_len ); // String str3 = str.Substring(start, target_len ); // 前から分割に変えた(2005.08) String str2 = str.Remove(target_len, start); String str3 = str.Substring(target_len, start); //あとできれいに // 前と後ろを、それぞれ検索 WordChain wc2 = DividedWordSearch(str2); WordChain wc3 = DividedWordSearch(str3); #if DEBUG_LOG KJ_Analyzer.WriteDebugLog("str2/str3:" + str2 + "/" + str3); #endif WordTable wt2, wt3; if (wc2 == null) { wt2 = new WordTable(str2); wc2 = new WordChain(wt2); } if (wc3 == null) { wt3 = new WordTable(str3); wc3 = new WordChain(wt3); } // 分割情報設定 if (wt.divided == Divided.Non) { wc2.Head.divided = Divided.Lead; wc3.Head.divided = Divided.Trail; } if (wt.divided == Divided.Lead) { wc2.Head.divided = Divided.Lead; wc3.Head.divided = Divided.Middle; } if (wt.divided == Divided.Middle) { wc2.Head.divided = Divided.Middle; wc3.Head.divided = Divided.Middle; } if (wt.divided == Divided.Trail) { wc2.Head.divided = Divided.Middle; wc3.Head.divided = Divided.Trail; } // wc2とwc3をつなぐ wc2.Add(wc3); // wc2---wc3 のコストを計算 int divChainCost = wc2.GetChainCost(); if (minimumCost >= divChainCost) { minimumCostChain = wc2; minimumCost = divChainCost; //最小コストの更新 } #if DEBUG_LOG KJ_Analyzer.WriteDebugLog("wc2:" + wc2.Head.word + "," + wc2.Head.Cost); KJ_Analyzer.WriteDebugLog("wc3:" + wc3.Head.word + "," + wc3.Head.Cost); KJ_Analyzer.WriteDebugLog("divChainCost:" + divChainCost); #endif target_len++; } // end of while // Chain中のwordが全て翻訳できていない if (minimumCostChain == null || (minimumCostChain != null && !minimumCostChain.IsTranslated())) { return(null); } // 翻訳できていない部分chainを再起実行 WordTable subT = minimumCostChain.Head; while (subT != null) { if (!subT.IsTranslated()) { WordChain subWc = WordPartProc(subT); if (subWc != null) { WordTable wNext = subT.next; minimumCostChain.Swap(subT, subWc); subT = wNext; continue; } } subT = subT.next; } return(minimumCostChain); }
//------------------------------------------------------- // 辞書チェックなしのハングル助詞チェック // // 末尾が助詞と一致するなら分離する。 // static public WordChain CheckPPwithoutDictKr(WordTable wt) { if (wt.IsTranslated()) { // 翻訳済みなら何もしない。 return(null); } if (wt.charCategory != CharCategory.Hangul && wt.charCategory != CharCategory.LetterMix) { // ハングルでないなら、または英字+ハングルでないなら何もしない。 return(null); } WordTable rtnWt = wt; // 戻りのdefault StringDivider sd = new StringDivider(wt.word); string trans = ""; // 前から1文字ずつ落としつつ,検索。 while (sd.eof() == false) { // 文字列を分割する HYAM.KJ_dict.Pair pair = sd.DivideForward(); if (Hangul.withPachim(pair.head)) { trans = KJ_Filter.SearchPP_Pachim(pair.tail); } else { trans = KJ_Filter.SearchPP_NoPachim(pair.tail); } if (trans == "") { continue; } // wtをwt1とwt2に分割 WordTable wt1 = new WordTable(pair.head); wt1.divided = Divided.Lead; // 分離できた。 wT2は助詞と仮定。訳語も入れておく WordTable wt2 = new WordTable(pair.tail, trans); wt2.posCategory = PosCategory.PP; wt2.Cost = 2; wt2.divided = Divided.Trail; WordChain rtnChain; // 返却チェーン // wt1を調査 // (未知語なので分割してみる) WordChain wc1 = KJ_Analyzer.WordPartProc(wt1); if (wc1 == null) { // 分割できなかった rtnChain = new WordChain(wt1, wt2); } else { wc1.Add(wt2); rtnChain = wc1; } return(rtnChain); } return(null); // 分離できなかったらnullを返す }