summaryrefslogtreecommitdiff
path: root/src-splitter/evalborder.c
diff options
context:
space:
mode:
Diffstat (limited to 'src-splitter/evalborder.c')
-rw-r--r--src-splitter/evalborder.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/src-splitter/evalborder.c b/src-splitter/evalborder.c
new file mode 100644
index 0000000..7c4a8c4
--- /dev/null
+++ b/src-splitter/evalborder.c
@@ -0,0 +1,187 @@
+/*
+ * 文節の境界を検出する。
+ *
+ * metawordの選択にはビタビアルゴリズムを使う
+ *
+ * anthy_eval_border() で指定された領域を文節に分割する
+ *
+ * Funded by IPA未踏ソフトウェア創造事業 2001 10/29
+ * Copyright (C) 2000-2003 TABATA Yusuke, UGAWA Tomoharu
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <anthy/alloc.h>
+#include <anthy/splitter.h>
+#include "wordborder.h"
+
+static int
+border_check(struct meta_word* mw,
+ int from,
+ int border)
+{
+ if (mw->from < border) {
+ /* 先頭の文節の中から始まるmwは文節区切りにぴったりあっていないとダメ */
+ if (mw->from == from && mw->from + mw->len == border) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ /* 後ろの文節は無条件に使用可能 */
+ return 1;
+ }
+}
+
+/*
+ * 再帰的にmetawordが使用可能かチェックする
+ */
+static void
+metaword_constraint_check(struct splitter_context *sc,
+ struct meta_word *mw,
+ int from,
+ int border)
+{
+ if (!mw) return;
+ if (mw->can_use != unchecked) return;
+
+ switch(anthy_metaword_type_tab[mw->type].check){
+ case MW_CHECK_SINGLE:
+ mw->can_use = border_check(mw, from, border) ? ok : ng;
+ break;
+ case MW_CHECK_BORDER:
+ {
+ struct meta_word* mw1 = mw->mw1;
+ struct meta_word* mw2 = mw->mw2;
+
+ if (mw1&&mw2&&mw1->from + mw1->len == border) {
+ /* ちょうど境目にマークが入ってる */
+ mw->can_use = ng;
+ break;
+ }
+ if (mw1)
+ metaword_constraint_check(sc, mw1, from, border);
+ if (mw2)
+ metaword_constraint_check(sc, mw2, mw2->from, border);
+
+ if ((!mw1 || mw1->can_use == ok) && (!mw2 || mw2->can_use == ok)) {
+ mw->can_use = ok;
+ } else {
+ mw->can_use = ng;
+ }
+ }
+ break;
+ case MW_CHECK_WRAP:
+ metaword_constraint_check(sc, mw->mw1, from, border);
+ mw->can_use = mw->mw1->can_use;
+ break;
+ case MW_CHECK_NUMBER:
+ {
+ struct meta_word* itr = mw;
+ mw->can_use = ok;
+
+ /* 個々の文節の一つでも文節区切りをまたがっていれば、この複合語は使えない */
+ for (; itr && itr->type == MW_NUMBER; itr = itr->mw2) {
+ struct meta_word* mw1 = itr->mw1;
+ if (!border_check(mw1, from, border)) {
+ mw->can_use = ng;
+ break;
+ }
+ }
+ }
+ break;
+ case MW_CHECK_COMPOUND:
+ {
+ struct meta_word* itr = mw;
+ mw->can_use = ok;
+
+ /* 個々の文節の一つでも文節区切りをまたがっていれば、この複合語は使えない */
+ for (; itr && (itr->type == MW_COMPOUND_HEAD || itr->type == MW_COMPOUND); itr = itr->mw2) {
+ struct meta_word* mw1 = itr->mw1;
+ if (!border_check(mw1, from, border)) {
+ mw->can_use = ng;
+ break;
+ }
+ }
+ }
+ break;
+ case MW_CHECK_OCHAIRE:
+ {
+ struct meta_word* mw1;
+ if (border_check(mw, from, border)) {
+ for (mw1 = mw; mw1; mw1 = mw1->mw1) {
+ mw1->can_use = ok;
+ }
+ } else {
+ for (mw1 = mw; mw1; mw1 = mw1->mw1) {
+ mw1->can_use = ng;
+ }
+ }
+ }
+ break;
+ case MW_CHECK_NONE:
+ break;
+ default:
+ printf("try to check unknown type of metaword (%d).\n", mw->type);
+ }
+}
+
+/*
+ * 全てのmetawordについて使用できるかどうかをチェックする
+ */
+static void
+metaword_constraint_check_all(struct splitter_context *sc,
+ int from, int to,
+ int border)
+{
+ int i;
+ struct word_split_info_cache *info;
+ info = sc->word_split_info;
+
+ /* まずuncheckedにする */
+ for (i = from; i < to; i ++) {
+ struct meta_word *mw;
+ for (mw = info->cnode[i].mw;
+ mw; mw = mw->next) {
+ mw->can_use = unchecked;
+ }
+ }
+
+ /* 次に合成されたmetawordについてチェック */
+ for (i = from; i < to; i ++) {
+ struct meta_word *mw;
+ for (mw = info->cnode[i].mw; mw; mw = mw->next) {
+ metaword_constraint_check(sc, mw, from, border);
+ }
+ }
+}
+
+/*
+ * ここから文節境界をマークする
+ */
+void
+anthy_eval_border(struct splitter_context *sc, int from, int from2, int to)
+{
+ struct meta_word *mw;
+ int nr;
+
+ /* 文節候補のうち使えるもののみ選択 */
+ metaword_constraint_check_all(sc, from, to, from2);
+
+ /* fromとfrom2の間をカバーするmeta_wordがあるかどうかを探す。
+ * あれば、fromから解析を行い、なければfrom2から解析をする。
+ */
+ nr = 0;
+ for (mw = sc->word_split_info->cnode[from].mw; mw; mw = mw->next) {
+ if (mw->can_use == ok) {
+ nr ++;
+ break;
+ }
+ }
+ if (nr == 0) {
+ from = from2;
+ }
+
+ /* 文節の境界を設定する */
+ anthy_mark_borders(sc, from, to);
+}