//-------------------------------------------------------------------- // 完全一致の辞書検索 (再起にすると時間がかかりすぎるので再起なし) // static public WordChain DividedWordSearch(string str) { WordTable wt; WordChain wc; #if DEBUG_LOG KJ_Analyzer.WriteDebugLog("DividedWordSearch:" + str); #endif SearchResult sResult = KJ_dict.SearchFull(str); if (sResult == null) { // strが辞書にない // wc = WordPartProc(wt); return(null); } wt = new WordTable(str); wc = new WordChain(); // 検索できた wt.SetResult(sResult); // wt3に検索結果を入れる //wt.IsDevided=true; // 分割語であるマーク wc.Add(wt); return(wc); }
//--------------------------------------------------------------------- // 入力文字列の変換を試みる。 public String Trans(String inputstring) { TextScanner scanner = new TextScanner(); // ブラウザからならHTMLとしてscanさせる(タグをまとめる) if (isBrowser) { scanner.htmlText = true; } // inputstringを語のchainに分解する WordChain wc = scanner.Scan(inputstring); if (this.pBar != null) { this.pBar.Maximum = wc.Length * 2; } // 形態素解析 & 翻訳処理 (本格的じゃないよ) KJ_Analyzer analyzer = new KJ_Analyzer(this); wc = analyzer.MorphologicScan(wc); // 翻訳はここ // WordChainから翻訳後文字列を作り出す if (showoriginal) { return(Chain2String_for_Web(wc)); // Web用 } else { return(Chain2String(wc)); } }
//-------------------------------------------------------------- //------------------------------------------------------------------ // 分割も考慮し詳しい(?)解析 // 分解後チェーンの最後の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); }
//---------------------------------------------------------------- // 語分割ありの熟語チェック // 공부하지는 못할 것이라는==> 공부 + 하지는 못할 것이라는 // ~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~ // startwt ここのWordTableはdivided=Trail // static public WordTable Search2(WordChain wc, WordTable startwt) { String str = startwt.word; if (!startwt.IsWord()) { return(null); // 空白などで始まる場合は、は処理しない } int target_len = 1; int str_len = str.Length; // 前から1文字ずつ落としつつ,熟語検索。 while (true) { if (target_len >= str_len) { break; } // 文字列を分割する // str --> str2 + str3 String str2 = str.Substring(0, target_len); String str3 = str.Remove(0, target_len); WordTable wt3 = new WordTable(str3); wt3.next = startwt.next; wt3.prev = startwt.prev; WordTable idiomTable = Idiom.Search(wc, wt3); if (idiomTable != null) { // 熟語確定 WordTable wt2 = new WordTable(str2); wc.InsertBefore(idiomTable, wt2); WordChain wc2 = KJ_Analyzer.WordPartProc(wt2); if (wc2 != null) { wc.Swap(wt2, wc2); } idiomTable.divided = Divided.Trail; return(idiomTable); } target_len++; } return(null); }
//------------------------------------------------------- // 翻訳のメイン // KJ_browserの中にも同じものをコピーで持っている点注意 // public WordChain MorphologicScan(WordChain wChain) { #if DEBUG_LOG KJ_Analyzer.StartDebugLog(); KJ_Analyzer.WriteDebugLog("MorphologicScan"); #endif if (!wChain.Exist()) { return(wChain); } WordTable wTable = wChain.Head; // 解析ループ 1回目 // 翻訳前処理(助詞分離など先に 熟語の精度を上げるため) // 고정 관념을 ---> 고정 관념 을に分離しておくため(熟語判定用) while (wTable != null) { this.sTrans.pBarStep(); // プログレスバーを進める // 1回目処理 wTable = firstScan(wChain, wTable); wTable = wTable.next; // 次の語へ } // 翻訳前処理ここまで // 解析ループ 2回目 (翻訳のメインループ) wTable = wChain.Head; // 再度先頭から while (wTable != null) { this.sTrans.pBarStep(); // プログレスバーを進める // 2回目処理 wTable = secondScan(wChain, wTable); wTable = wTable.next; // 次の語へ } // 翻訳のメインループ ここまで #if DEBUG_LOG KJ_Analyzer.EndDebugLog(); #endif return(wChain); }
//------------------------------------------------------------------ private WordChain WordDivider(WordTable wTable) { WordChain wc1 = null; #if DEBUG_LOG KJ_Analyzer.WriteDebugLog("WordDivider"); #endif // 辞書検索なしの助詞チェック if (KJ_dict.inputIsHangul) { wc1 = KJ_pp.CheckPPwithoutDictKr(wTable); } // 3文字の「ハングルまたは漢字」なら特別チェック if (wTable.word.Length == 3 && (CodeCheck.IsHangul(wTable.word) || CodeCheck.IsKanji(wTable.word)) ) { WordChain wcThree = Check3Chars(wTable); if (wcThree != null) { return(wcThree); } } // 全体でmatchしないなら部分文字列で検索(再起 語分解あり) WordChain wc2 = null; wc2 = WordPartProc(wTable); // wtは最後の語テーブル。未変換なら再調査 // WordChain wc3 = CheckLastWord(wChain, wTable); // costが小さい方を採用 WordChain rtnWc = WordChain.GetMinimunCostChain(wc1, wc2); return(rtnWc); }
//-------------------------------------------------------------------- // 語の変換 (語の分解あり) // 語分解で翻訳済み末尾がずれることがあるので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を返す }