(linenum→info "unix/slp.c:2238")

anthy/9100e/src-splitter/evalborder.c

    1: /*
    2:  * 文節の境界を検出する。
    3:  *
    4:  * metawordの選択にはビタビアルゴリズムを使う
    5:  *
    6:  * anthy_eval_border() で指定された領域を文節に分割する
    7:  *
    8:  * Funded by IPA未踏ソフトウェア創造事業 2001 10/29
    9:  * Copyright (C) 2000-2003 TABATA Yusuke, UGAWA Tomoharu
   10:  */
   11: #include <stdio.h>
   12: #include <stdlib.h>
   13: 
   14: #include <anthy/alloc.h>
   15: #include <anthy/splitter.h>
   16: #include "wordborder.h"
   17: 
   18: static int
   19: border_check(struct meta_word* mw,
   20:              int from,
   21:              int border)
   22: {
   23:   if (mw->from < border) {
   24:     /* 先頭の文節の中から始まるmwは文節区切りにぴったりあっていないとダメ */
   25:     if (mw->from == from && mw->from + mw->len == border) {
   26:       return 1;
   27:     } else {
   28:       return 0;
   29:     }
   30:   } else {
   31:     /* 後ろの文節は無条件に使用可能 */
   32:     return 1;
   33:   }
   34: }
   35: 
   36: /*
   37:  * 再帰的にmetawordが使用可能かチェックする
   38:  */
   39: static void
   40: metaword_constraint_check(struct splitter_context *sc,
   41:                           struct meta_word *mw,
   42:                           int from, 
   43:                           int border)
   44: {
   45:   if (!mw) return;
   46:   if (mw->can_use != unchecked) return;
   47: 
   48:   switch(anthy_metaword_type_tab[mw->type].check){
   49:   case MW_CHECK_SINGLE:
   50:     mw->can_use = border_check(mw, from, border) ? ok : ng;
   51:     break;
   52:   case MW_CHECK_BORDER:
   53:     {
   54:       struct meta_word* mw1 = mw->mw1;
   55:       struct meta_word* mw2 = mw->mw2;
   56: 
   57:       if (mw1&&mw2&&mw1->from + mw1->len == border) {
   58:         /* ちょうど境目にマークが入ってる */
   59:         mw->can_use = ng;
   60:         break;
   61:       }
   62:       if (mw1)
   63:         metaword_constraint_check(sc, mw1, from, border);
   64:       if (mw2)
   65:         metaword_constraint_check(sc, mw2, mw2->from, border);
   66:       
   67:       if ((!mw1 || mw1->can_use == ok) && (!mw2 || mw2->can_use == ok)) {
   68:         mw->can_use = ok;
   69:       } else {
   70:         mw->can_use = ng;
   71:       }
   72:     }
   73:     break;
   74:   case MW_CHECK_WRAP:
   75:     metaword_constraint_check(sc, mw->mw1, from, border);
   76:     mw->can_use = mw->mw1->can_use;
   77:     break;
   78:   case MW_CHECK_NUMBER:
   79:     {
   80:       struct meta_word* itr = mw;
   81:       mw->can_use = ok;
   82:       
   83:       /* 個々の文節の一つでも文節区切りをまたがっていれば、この複合語は使えない */
   84:       for (; itr && itr->type == MW_NUMBER; itr = itr->mw2) {
   85:         struct meta_word* mw1 = itr->mw1;
   86:         if (!border_check(mw1, from, border)) {
   87:           mw->can_use = ng;
   88:           break;
   89:         }
   90:       }
   91:     }
   92:     break;
   93:   case MW_CHECK_COMPOUND:
   94:     {
   95:       struct meta_word* itr = mw;
   96:       mw->can_use = ok;
   97:       
   98:       /* 個々の文節の一つでも文節区切りをまたがっていれば、この複合語は使えない */
   99:       for (; itr && (itr->type == MW_COMPOUND_HEAD || itr->type == MW_COMPOUND); itr = itr->mw2) {
  100:         struct meta_word* mw1 = itr->mw1;
  101:         if (!border_check(mw1, from, border)) {
  102:           mw->can_use = ng;
  103:           break;
  104:         }
  105:       }
  106:     }
  107:     break;
  108:   case MW_CHECK_OCHAIRE:
  109:     {
  110:       struct meta_word* mw1;
  111:       if (border_check(mw, from, border)) {
  112:         for (mw1 = mw; mw1; mw1 = mw1->mw1) {
  113:           mw1->can_use = ok;
  114:         }
  115:       } else {
  116:         for (mw1 = mw; mw1; mw1 = mw1->mw1) {
  117:           mw1->can_use = ng;
  118:         }      
  119:       }
  120:     }
  121:     break;
  122:   case MW_CHECK_NONE:
  123:     break;
  124:   default:
  125:     printf("try to check unknown type of metaword (%d).\n", mw->type);
  126:   }
  127: }
  128: 
  129: /*
  130:  * 全てのmetawordについて使用できるかどうかをチェックする
  131:  */
  132: static void
  133: metaword_constraint_check_all(struct splitter_context *sc,
  134:                               int from, int to,
  135:                               int border)
  136: {
  137:   int i;
  138:   struct word_split_info_cache *info;
  139:   info = sc->word_split_info;
  140: 
  141:   /* まずuncheckedにする */
  142:   for (i = from; i < to; i ++) {
  143:     struct meta_word *mw;
  144:     for (mw = info->cnode[i].mw;
  145:          mw; mw = mw->next) {
  146:       mw->can_use = unchecked;
  147:     }
  148:   }
  149: 
  150:   /* 次に合成されたmetawordについてチェック */
  151:   for (i = from; i < to; i ++) {
  152:     struct meta_word *mw;
  153:     for (mw = info->cnode[i].mw; mw; mw = mw->next) {
  154:       metaword_constraint_check(sc, mw, from, border);
  155:     }
  156:   }
  157: }
  158: 
  159: /*
  160:  * ここから文節境界をマークする
  161:  */
  162: void
  163: anthy_eval_border(struct splitter_context *sc, int from, int from2, int to)
  164: {
  165:   struct meta_word *mw;
  166:   int nr;
  167: 
  168:   /* 文節候補のうち使えるもののみ選択 */
  169:   metaword_constraint_check_all(sc, from, to, from2);
  170: 
  171:   /* fromとfrom2の間をカバーするmeta_wordがあるかどうかを探す。
  172:    * あれば、fromから解析を行い、なければfrom2から解析をする。
  173:    */
  174:   nr = 0;
  175:   for (mw = sc->word_split_info->cnode[from].mw; mw; mw = mw->next) {
  176:     if (mw->can_use == ok) {
  177:       nr ++;
  178:       break;
  179:     }
  180:   }
  181:   if (nr == 0) {
  182:     from = from2;
  183:   }
  184: 
  185:   /* 文節の境界を設定する */
  186:   anthy_mark_borders(sc, from, to);
  187: }
Syntax (Markdown)