//------------------------------------------------------- // 語のchainを先頭から舐め、熟語を探す。 static public WordTable Scan(WordChain wChain, WordTable wTable) { // 熟語は優先のため変換済みチェックなし //if(wTable.IsTranslated()){ // return wTable; // 変換済みなら何もしない //} // wtで始まる熟語のチェック WordTable idiomwt = Idiom.Search(wChain, wTable); if (idiomwt != null) { // 熟語が解決できた return(idiomwt); } return(wTable); }
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); }
// Chainの最後にChainを追加 public void Add(WordChain wc2) { if (wc2 == null) { return; // 何もしない } if (head == null) { this.head = wc2.head; this.tail = wc2.tail; return; } this.tail.next = wc2.head; wc2.head.prev = this.tail; this.tail = wc2.tail; }
// 前の有効な語を返す。(空白skip) public WordTable PrevWord() { WordTable wt = this.prev; while (true) { if (wt == null) { break; } if (wt.IsWord()) { return(wt); } wt = wt.prev; } return(null); }
//--------------------------------------------- // 次の有効な語を返す。(空白skip) public WordTable NextWord() { WordTable wt = this.next; while (true) { if (wt == null) { break; } if (wt.IsWord()) { return(wt); } wt = wt.next; } return(null); }
//------------------------------------------------------------------- // チェーンの前処理。 // 句読点の判定、置換など // 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); }
//-------------------------------------------------------------- public WordTable firstScan(WordChain wChain, WordTable wTable) { // 速度向上のため、skipさせる if (wTable.IsTransSkipWord()) { return(wTable); // 何もせずreturn } // 前処理 wTable = ChainPreProc(wChain, wTable); // 数助詞,冠数詞をチェック wTable = Numerative.Scan(wChain, wTable); // 助詞の解析を試す (前の語の辞書引きあり) wTable = KJ_pp.Scan(wChain, wTable); //2005.08.26 数詞の前に return(wTable); }
//------------------------------------------------------- static private WordChain DivideCountableMain(WordTable wTable, PosCategory poscategory) { WordChain wc = null; StringDivider sd = new StringDivider(wTable.word); // 後から1文字ずつ落としつつ,検索。 string trans = ""; while (sd.eof() == false) { // 文字列を分割する HYAM.KJ_dict.Pair pair = sd.DivideBackward(); if (poscategory == PosCategory.Numeral) { trans = KJ_Filter.SearchNumeral(pair.head); } else { trans = KJ_Filter.SearchNumerative(pair.head); } if (trans != "") { WordTable wt_num = new WordTable(pair.head, trans); wt_num.posCategory = poscategory; wc = new WordChain(wt_num); if (pair.tail != "") { WordTable wt_tail = new WordTable(pair.tail); wc.Add(wt_tail); } return(wc); } } // end of while return(null); }
//------------------------------------------------------------------ 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); }
//-------------------------------------------------------------- public WordTable secondScan(WordChain wChain, WordTable wTable) { // 速度向上のため、skipさせる if (wTable.IsTransSkipWord2()) // 少しゆるいskip { return(wTable); // 何もせずreturn } // 熟語をチェック wTable = Idiom.Scan(wChain, wTable); // 分割なし完全一致の語 wTable = DelimitedWord.Scan(wChain, wTable); // 分割も考慮し詳しい(?)解析 // (辞書引きなし助詞解析あり) // 分解した最後のwTableを返す wTable = ScanDetail(wChain, wTable); return(wTable); }
//------------------------------------------------------------------- // 形容動詞の語幹となる名詞なら,その日本語訳を返す private string IsNounWithAdverb(WordTable wTable) { if (wTable.sResult == null) { return(""); } if (wTable.sResult.documents == null) { return(""); } // wTableはハダ動詞(動詞・形容動詞)になる名詞? foreach (DocumentData sdata in wTable.sResult.documents) { string src = sdata.GetSrc(); if (src == "hyam(noun.adverb)") { return(sdata.GetData("key2")); } } return(""); }
//------------------------------------------------------------------------ // 辞書に見つからなかった語を自動変換する // ハングル <---> カタカナ 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); }
//------------------------------------------------------------------- // private WordTable ScanDetailJp(WordChain wChain, WordTable wTable) { // 助詞を処理 // (助詞で始まる熟語があるので熟語の後) if (wTable.posCategory == PosCategory.PP) { // 改めて訳語を設定 string pp = KJ_pp.TransJapanesePP(wTable); if (pp != "") { // 訳語設定 wTable.transWord = pp; wTable.Cost = 0; // ハングルの助詞なら、分かち書きのため空白を置く。 wTable.transWord = wTable.transWord + " "; return(wTable); } } return(null); }
//------------------------------------------------------------------- private void MakeDebugInfo(StringBuilder result, WordTable wt) { string indent = " "; result.Append(indent); result.Append(" (" + wt.charCategory + ") "); result.Append(" (" + wt.posCategory + ") "); result.Append(" (" + wt.GetWordCost() + ") "); result.Append(" (" + wt.divided + ") "); if (wt.IsSentenseHead) { result.Append(" (sentense head)"); } if (wt.IsSentenseTail) { result.Append(" (sentense tail)"); } result.Append("\n"); SearchResult sResult = wt.sResult; if (sResult != null && sResult.documents != null) { foreach (DocumentData ddata in sResult.documents) { result.Append(indent); result.Append(ddata.GetData("key2")); result.Append(" " + ddata.GetData("cost2")); result.Append(" " + ddata.GetData("src")); result.Append("\n"); } } else { result.Append("\n"); } }
//------------------------------------------------------------------- // 形容動詞の語尾か? private string IsAdverbTail(WordTable wTable) { if (wTable.sResult == null) { return(""); } if (wTable.sResult.documents == null) { return(""); } // wTableはハダ形容動詞の語尾? foreach (DocumentData sdata in wTable.sResult.documents) { string src = sdata.GetSrc(); if (src == "hyam(adverb.hada.parts)") { return(sdata.GetData("key2")); } } return(""); }
//------------------------------------------------------- // 語の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); }
//---------------------------------------------- // // wt2 // | // v // ----wt1--------a---------b--------c----- // (oldnext) public void Insert(WordTable wt1, WordTable wt2) { if (wt1 == null) { this.head = wt2; this.tail = wt2; return; } if (wt1.next == null) { Debug.Assert(this.tail == wt1); wt1.next = wt2; wt2.prev = wt1; wt2.next = null; this.tail = wt2; return; } WordTable oldnext = wt1.next; wt1.next = wt2; wt2.prev = wt1; wt2.next = oldnext; oldnext.prev = wt2; }
//------------------------------------------------------------------ // 4文字語の調査 (部分分割後は使わない) static private WordChain Check4Chars(WordTable wTable) { SearchResult sResult; if (KJ_dict.inputIsHangul) { // 4文字以外は抜ける。 if (wTable.word.Length != 4) { return(null); } if (wTable.word.EndsWith("하게")) { string head = wTable.word.Remove(2, 2); // 4文字なので固定 sResult = KJ_dict.SearchFull(head); if (sResult != null) { WordTable tempwt = new WordTable(head); tempwt.SetResult(sResult); string trans = tempwt.GetTranslatedText(); wTable.transWord = trans + "に"; wTable.Cost = 10; wTable.posCategory = PosCategory.PP; WordChain wc = new WordChain(wTable); // これだけならwtでもいいが、汎用化のためwcで返す return(wc); } } } return(null); }
//------------------------------------------------------- // wordがハングルの助詞と完全一致なら、訳語をreturn で返す。 static private String CheckHangulPP_Full(WordTable wordT) { string word = wordT.word; string prevword = ""; if (wordT.prev == null) { return(""); } // 前の語が空白なら助詞とは判断しない。 // 초파리에서 이 유전자를 の「이」は「が」ではない if (!wordT.prev.IsWord()) { return(""); // 何もせず抜ける } prevword = wordT.prev.word; // 前の語 // 前の語がハングルならつながっているから // このタイプの判断が必要なのは前が英数字 // ex. MP3의 return(KJ_Filter.SearchPPall(word)); }
//---------------------------------------------- // // chain中のwt1を別chainで置き換える // // wc( wt2----------wt3---------wt4 ) // | wc.head wc.tail // v // ----wt1--------a---------b--------c----- // (oldnext) // public void Swap(WordTable wt1, WordChain wc) { Insert(wt1, wc); Delete(wt1); }
//---------------------------------------------- // // chain中のwt1を wt2+wt3に置き換える // public void Swap(WordTable wt1, WordTable wt2, WordTable wt3) { Insert(wt1, wt2); Insert(wt2, wt3); Delete(wt1); }
//-------------------------------------------- // constructor public WordChain() { this.head = null; this.tail = null; }
//-------------------------------------------------------------- // startwtで始まる熟語を最長一致でチェックする // // (before) // -----wt1-----wt2-----wt3-----wt4-----wt5-----wt6----- // ↑ ↑ // startwt matched // // (after) // -----wt1-----idiomwt-----wt5-----wt6----- // // チェーン中の熟語を成すテーブルは1つにまとめる。 // (正確には熟語のテーブルを挿入し、個々の語のテーブルは削除) // static public WordTable Search(WordChain wc, WordTable startwt) { //熟語は語単位より優先 // if(startwt.IsTranslated()){ // return null; // 翻訳済みの語は触らない // } bool isExist; // 辞書中にチェック対象の語(熟語)が存在するか? WordTable idiomwt = null; // 熟語テーブル SearchResult sResult; string word = startwt.word; // startwtが翻訳済みで助詞なら何もしない // 暫定的 2005.08.26 // if(startwt.IsTranslated() && startwt.pos == PosCategory.PP ){ // return(null); // not found // } // 前方一致で該当なしなら // この語で始まる熟語は辞書にない isExist = KJ_dict.CheckForward(word); if (!isExist) { return(null); // not found } // 前方一致でmatchしたので先読みして熟語チェック String word2 = ""; string next = ""; WordTable nextTable = startwt.next; WordTable matched = startwt; // 次の語以降を足しながらチェック while (nextTable != null) { if (nextTable == null || nextTable.word == "") { break; // 次の語なしなら抜ける } next = nextTable.word; char ch = next[0]; if (Char.IsSeparator(ch)) { next = " "; } if (next == " ") { word = word + next; nextTable = nextTable.next; // 次の語へ continue; // 空白付加だけでは再検索しない } word2 = word + next; //次の語を足して前方一致チェック isExist = KJ_dict.CheckForward(word2); if (!isExist) { // nextを足したら,一致しない。→ これ以上先を見る必要なし break; } // 一致した部分まででで完全一致検索 sResult = KJ_dict.SearchFull(word2); if (sResult != null) { // string trimword = word2; // trimword = trimword.Replace(" ", ""); // 空白削除 if (IsValidIdiom(sResult)) // 長さ4以上でないと採用しない // 熟語が見つかった { idiomwt = new WordTable(word2); idiomwt.charCategory = startwt.charCategory; // 先頭文字種で (混ざっている可能性あるが) idiomwt.posCategory = PosCategory.Idiom; idiomwt.SetResult(sResult); matched = nextTable; // 完全一致した最後のテーブル } } // さらに次の語へ word = word2; // nextを足したものを元とする。 nextTable = nextTable.next; // 次の語へ } // while loop if (startwt.word == word) { // 熟語でなく単なる入力語の完全一致の時は返さない return(null); } if (idiomwt != null) { // 熟語が見つかっている wc.Insert(matched, idiomwt); // startwtからmatchedまでは消していい。 WordTable delwt = startwt; while (true) { wc.Delete(delwt); if (delwt == matched) { break; } delwt = delwt.next; } // 熟語のテーブルを返す return(idiomwt); } // 熟語なし return(null); }
//------------------------------------------------------- static private WordChain DivideJapanesePP(WordTable wTable) { StringDivider sd = new StringDivider(wTable.word); // 前から1文字ずつ落としつつ,検索。 string trans = ""; 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; } SearchResult result = KJ_dict.SearchFull(pair.head); if (result != null) { // 助詞確定 // 助詞に先行しない語は除外 // 산은 (은が助詞なら、산は動詞[連体詞]ではない) // result = SearchResult.CheckPPConnectable(result); // もし語が全部落ちたならば何もしない if (result.documents.Count == 0) { // nop } else { // 先行語+助詞のチェーンを作る WordTable wt1 = new WordTable(pair.head); wt1.SetResult(result); wt1.divided = Divided.Lead; // wt2.transWord はまだ設定しない。 // 前の訳語のパッチムに影響されるため。 WordTable wt2 = new WordTable(pair.tail); wt2.posCategory = PosCategory.PP; wt2.divided = Divided.Trail; // 長い助詞ほどコストを低くする // wt2.Cost = 0; if (wt2.word.Length > 2) { wt2.Cost = 0; } else if (wt2.word.Length == 2) { wt2.Cost = 3; } else { wt2.Cost = 5; } WordChain rtnChain = new WordChain(wt1, wt2); return(rtnChain); } } } // end of while return(null); // 分離できなかったらnullを返す。 }
//------------------------------------------------------- // 語のchainを先頭から舐め、助詞(Postpositional Particle)を分解する。 static private WordTable ScanPPKr(WordChain wChain, WordTable wTable) { bool inputIsHangul = KJ_dict.inputIsHangul; // 語を舐め、助詞を分解する。 if (wTable.charCategory != CharCategory.Hangul && wTable.charCategory != CharCategory.LetterMix) { // ハングルでないなら、または英字+ハングルでないなら何もしない。 return(wTable); } // 完全一致の助詞なら情報をセットし、終了 string pp_trans = CheckHangulPP_Full(wTable); if (pp_trans != "") { wTable.transWord = pp_trans; wTable.posCategory = PosCategory.PP; if (wTable.word.Length > 2) { wTable.Cost = 0; } else if (wTable.word.Length == 2) { wTable.Cost = 3; } else { wTable.Cost = 5; } return(wTable); } // wordTableが辞書に完全一致で存在するか調べる。 bool isExist = KJ_dict.CheckFull(wTable.word); if (isExist) { // 完全一致した語は判定せず、なにもしない。 return(wTable); } // 助詞の分解を試みる WordChain resultChain = DivideHangulPP(wTable); if (resultChain == null) { // 助詞はついてなかった。なにもしない。 return(wTable); } // resultChainは 語+助詞のチェーン。WordTと入れ替える wChain.Swap(wTable, resultChain); // 助詞で始まる熟語でないかチェック WordTable idiomwt = Idiom.Search(wChain, resultChain.Tail); // resultChainの先頭は未処理。 // いったんcurrentをresultChainの先頭に戻す // 위원회를 ---> 위원회 + 를 // wTable resultChain.Head [を]:翻訳済み wTable = resultChain.Head; 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); }
//------------------------------------------------------------------- // WordChainの各WordTableから翻訳結果を取り出し翻訳後文字列を返す // (ブラウザ用) public String Chain2String_for_Web(WordChain wc) { StringBuilder result; // 出力文字列 result = new StringBuilder(); string translatedText = ""; string originalText = ""; // 先頭にマーカ // 語のchainを先頭から舐め、翻訳結果をresultに順次追加。 WordTable wt = wc.Head; while (wt != null) { // タグの内容のテーブル if (wt.charCategory == CharCategory.HTMLtag) { if (translatedText.Trim() != "") { if (String.Compare(originalText, translatedText) != 0) { // 翻訳データを埋める originalText += ("<font color=blue size=-1>" + translatedText + "</font>"); } else { // NOP // 英文など無変換のものは併記しない } result.Append(originalText); // バッファクリア originalText = ""; translatedText = ""; } // htmlタグのwordをそのまま追加 result.Append(wt.word); // この書き換えは効かない... [2009/09/26 09:56:07] // string noblank = wt.word.Replace("target=\"_blank\"", ""); // result.Append( noblank ); wt = wt.next; continue; } // htmlタグの外 (訳すべきテキスト) // 原文の退避 originalText += wt.word; // 翻訳用前処理 TranslationPreproc(wt); // wtから翻訳済みテキストを取り出す string translated = wt.GetTranslatedText(); // 翻訳できなかったら元文字をそのまま返す if (translated == "") { translated = wt.word; } translatedText += translated; wt = wt.next; } return(result.ToString()); }
public WordChain(WordTable wt1, WordTable wt2) : this() { this.Add(wt1); this.Add(wt2); }
//------------------------------------------------------- // 語の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); }
//-------------------------------------------------------------- // 非常に簡易的な文字列分解。文字種が変わった所で切る。 // this.inputString から文字を取り出し // 語(と思われる)単位にまとめて,その語をWordTableで返す。 private WordTable PicupWordTable() { StringBuilder rtn_str = new StringBuilder(); rtn_str.Length = 0; bool inHTMLtag = false; // Tagの中か否か? // 採取取り出し文字の文字種 CharCategory lastCharCategory = CharCategory.Null; // 取り出す語の文字種 CharCategory charCategory = CharCategory.Null; WordTable wordT = new WordTable(); while (true) { if (this.stringIndex >= this.inputString.Length) { break; } // 入力文字列のinstr_inex位置から 1文字取り出し char ch = this.inputString[this.stringIndex]; // 取り出した文字の種別を判定 lastCharCategory = GetCharCategory(ch); // 例えば <font size=+1>の "<"から ">"までを // HTMLtagというカテゴリにまとめる。 if (this.htmltext) { if (ch == '<') { inHTMLtag = true; } if (inHTMLtag) { lastCharCategory = CharCategory.HTMLtag; } if (ch == '>') { inHTMLtag = false; } } if (charCategory != CharCategory.Null) { if (charCategory != lastCharCategory) { break; // 文字種が変わったら抜ける } } else { charCategory = lastCharCategory; } rtn_str.Append(ch.ToString()); this.stringIndex++; // 取り出し位置を進める } wordT.word = rtn_str.ToString(); // 文字列の設定 wordT.charCategory = charCategory; // 文字種別の設定 if (charCategory == CharCategory.Katakana) { wordT.posCategory = PosCategory.Noun; } else if (charCategory == CharCategory.HiraganaWo) { wordT.posCategory = PosCategory.PP; wordT.Cost = 0; } else if (charCategory == CharCategory.Other) { wordT.posCategory = PosCategory.Other; wordT.Cost = 0; } else if (charCategory == CharCategory.Separator) { wordT.posCategory = PosCategory.Other; wordT.Cost = 0; } else { wordT.posCategory = PosCategory.Other; } return(wordT); }