예제 #1
0
        //---------------------------------------------------------------------
        // 入力文字列の変換を試みる。
        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));
            }
        }
예제 #2
0
        //--------------------------------------------------------------------
        // 完全一致の辞書検索 (再起にすると時間がかかりすぎるので再起なし)
        //
        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);
        }
예제 #3
0
        // Insert chain
        //         wc( wt2---wt3---wt4 )
        //
        //  ----wt1---wt2---wt3---wt4------a----b----c-----
        //
        public void Insert(WordTable wt1, WordChain wc)
        {
            if (wt1 == null)
            {
                this.head = wc.head;
                this.tail = wc.tail;
                return;
            }
            if (wc == null || wc.head == null)
            {
                return;
            }
            if (wt1.next == null)
            {
                Debug.Assert(this.tail == wt1);
                wt1.next     = wc.head;
                wc.head.prev = wt1;
                this.tail    = wc.tail;
                return;
            }

            WordTable oldnext = wt1.next;

            wt1.next     = wc.head;
            wc.head.prev = wt1;
            wc.tail.next = oldnext;
            oldnext.prev = wc.tail;
        }
예제 #4
0
        static public WordChain GetMinimunCostChain(WordChain wc1,
                                                    WordChain wc2,
                                                    WordChain wc3)
        {
            WordChain min_wc = GetMinimunCostChain(wc1, wc2);

            return(GetMinimunCostChain(min_wc, wc3));
        }
예제 #5
0
        //-------------------------------------------------------
        //  分割なし完全一致の語
        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);
        }
예제 #6
0
        //--------------------------------------------------------------


        //------------------------------------------------------------------
        // 分割も考慮し詳しい(?)解析
        //    分解後チェーンの最後の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);
        }
예제 #7
0
        public WordChain Scan(string inputstring)
        {
            this.inputString = inputstring;
            this.stringIndex = 0;

            WordChain wChain = new WordChain();

            WordTable wordT;

            // inputStringから語のchainを作成する。
            while (true)
            {
                // inputStringから1語切り出す
                wordT = PicupWordTable();
                if (wordT.word == "")
                {
                    break;  // 取り出せなかったら終了
                }

                wChain.Add(wordT);
            } // end of while ( PicupWordTable loop )


            // 漢字+ひらがな などいくつかの並びはまとめる。 ( wordT merge loop )
            CharCategory prevCharCategory = CharCategory.Null;
            WordTable    prevwordT        = new WordTable();

            wordT = wChain.Head;
            while (wordT != null)
            {
                CharCategory mergedCharCategory;
                mergedCharCategory = IsMergedable(prevCharCategory,
                                                  wordT.charCategory);

                if (mergedCharCategory != CharCategory.Null)
                {
                    WordTable newWt = new WordTable(prevwordT.word + wordT.word);;
                    newWt.charCategory = mergedCharCategory;
                    newWt.posCategory  = PosCategory.Other;

                    wChain.Delete(prevwordT);
                    wChain.Insert(wordT, newWt);
                    wChain.Delete(wordT);

                    wordT = newWt;
                }

                prevCharCategory = wordT.charCategory;

                prevwordT = wordT;

                wordT = wordT.next;   // 次の語へ
            } // end of while ( wordT merge loop )

            return(wChain);
        }
예제 #8
0
        //-------------------------------------------------------------------
        //
        private WordTable ScanDetailKr(WordChain wChain, WordTable wTable)
        {
            if (wTable.posCategory == PosCategory.PP)
            {
                //  PosCategory.PPが設定されているK->J方向なら助詞は翻訳済み。
                return(wTable);
            }

            return(null);
        }
예제 #9
0
        static public WordChain GetMinimunCostChain(WordChain wc1,
                                                    WordChain wc2,
                                                    WordChain wc3,
                                                    WordChain wc4)
        {
            WordChain min_wc1 = GetMinimunCostChain(wc1, wc2);
            WordChain min_wc2 = GetMinimunCostChain(wc3, wc4);

            return(GetMinimunCostChain(min_wc1, min_wc2));
        }
예제 #10
0
        //-------------------------------------------------------------------
        // WordChainの各WordTableから翻訳結果を取り出し翻訳後文字列を返す
        private String Chain2String(WordChain wc)
        {
            StringBuilder result;           // 出力文字列

            result = new StringBuilder();


            // debuginfo is True
            if (this.debugInfo)
            {
                result.Append("original ⇒ result " +
                              "(char)(pos)(GetWordCost)(divided)\n");
            }

            // 語のchainを先頭から舐め、翻訳結果をresultに順次追加。
            WordTable wt = wc.Head;

            while (wt != null)
            {
                // debuginfo is True
                if (this.debugInfo)
                {
                    if (wt.IsWord())
                    {
                        result.Append(wt.word + " ⇒ ");
                    }
                }

                // 翻訳用前処理
                TranslationPreproc(wt);

                // wtから翻訳済みテキストを取り出す
                string translated = wt.GetTranslatedText();
                // 翻訳できなかったら元文字をそのまま返す
                if (translated == "")
                {
                    translated = wt.word;
                }

                result.Append(translated);

                // debuginfo is True
                if (this.debugInfo)
                {
                    result.Append("\n");
                    MakeDebugInfo(result, wt);
                }

                // 次のWordTableへ
                wt = wt.next;
            }

            return(result.ToString());
        }
예제 #11
0
        //-------------------------------------------------------
        static private WordChain DivideCountable(WordTable wTable)
        {
            // 数詞チェック
            WordChain wc = DivideCountableMain(wTable, PosCategory.Numeral);

            if (wc == null)
            {
                // 数詞でなかったら、助数詞チェック
                wc = DivideCountableMain(wTable, PosCategory.Numerative);
            }

            return(wc);
        }
예제 #12
0
        //------------------------------------------------------------------
        // 3文字語の調査 (部分分割後も使う)
        static private WordChain Check3Chars(WordTable wTable)
        {
            SearchResult sResult;

            // ABC --->  AB + C
            String head   = wTable.word.Remove(2, 1);
            String suffix = wTable.word.Substring(2, 1);

            sResult = KJ_dict.SearchFull(head);
            if (sResult != null)
            {
                // lastWordListにあるか調べる
                string translatedSuffix = KJ_Filter.SearchSuffix(suffix);
                if (translatedSuffix != "")
                {
                    WordTable headWt = new WordTable(head);
                    headWt.SetResult(sResult);
                    WordChain wc = new WordChain(headWt);

                    WordTable wt = new WordTable(suffix, translatedSuffix);
                    wt.Cost = 5;
                    wc.Add(wt);
                    return(wc);
                }
            }

            // ABC --->  A + BC
            String prefix = wTable.word.Remove(1, 2);
            String tail   = wTable.word.Substring(1, 2);

            sResult = KJ_dict.SearchFull(tail);
            if (sResult != null)
            {
                // lastWordListにあるか調べる
                string translatedPrefix = KJ_Filter.SearchPrefix(prefix);
                if (translatedPrefix != "")
                {
                    WordTable wt = new WordTable(prefix, translatedPrefix);
                    wt.Cost = 5;
                    WordChain wc = new WordChain(wt);

                    WordTable tailWt = new WordTable(tail);
                    tailWt.SetResult(sResult); // 全体でmatch

                    wc.Add(tailWt);
                    return(wc);
                }
            }

            return(null);
        }
예제 #13
0
        //----------------------------------------------------------------
        // 語分割ありの熟語チェック
        //     공부하지는 못할 것이라는==> 공부 + 하지는 못할 것이라는
        //     ~~~~~~~~~~                         ~~~~~~~~~~~~~~~~~~~~
        //      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);
        }
예제 #14
0
        //-------------------------------------------------------
        // 翻訳のメイン
        //     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);
        }
예제 #15
0
        //--------------------------------------------------------------------
        // wTableを翻訳した結果のチェーンが使えるかどうか?
        private bool AcceptableTransWord(WordTable wTable, WordChain wChain)
        {
            // 3文字以上で、翻訳語の同じチェーンなら不採用
            if (wTable.word.Length > 2 &&
                wTable.word.Length == wChain.Length)
            {
                return(false);
            }

            // 翻訳済み長が全体の3分の1以下なら不採用
            if (wChain.TranslatedCharCount() <= wTable.word.Length / 3)
            {
                return(false);
            }

            return(true);  // 採用可
        }
예제 #16
0
        // 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;
        }
예제 #17
0
        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);
        }
예제 #18
0
        //-------------------------------------------------------
        // 語の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);
        }
예제 #19
0
        //-------------------------------------------------------------------
        // チェーンの前処理。
        //     句読点の判定、置換など
        //
        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);
        }
예제 #20
0
        //--------------------------------------------------------------
        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);
        }
예제 #21
0
        //-------------------------------------------------------
        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);
        }
예제 #22
0
 //--------------------------------------------
 //
 //  static public method
 //
 static public WordChain GetMinimunCostChain(WordChain wc1,
                                             WordChain wc2)
 {
     if (wc1 == null)
     {
         return(wc2);
     }
     if (wc2 == null)
     {
         return(wc1);
     }
     if (wc1.GetChainCost() < wc2.GetChainCost())
     {
         return(wc1);
     }
     else
     {
         return(wc2);
     }
 }
예제 #23
0
        //------------------------------------------------------------------
        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);
        }
예제 #24
0
        //--------------------------------------------------------------
        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);
        }
예제 #25
0
        //-------------------------------------------------------------------
        //
        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);
        }
예제 #26
0
        //-------------------------------------------------------
        // 語の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);
        }
예제 #27
0
        //------------------------------------------------------------------
        // 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);
        }
예제 #28
0
 //----------------------------------------------
 //
 //  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);
 }
예제 #29
0
        //--------------------------------------------------------------
        // 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);
        }
예제 #30
0
        //-------------------------------------------------------
        // 語の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);
        }