/* 文節境界の検出に使うデータ */
#ifndef _wordborder_h_included_
#define _wordborder_h_included_


#include <dic.h>
#include <alloc.h>
#include <segclass.h>

struct splitter_context;
struct seg_info;

/* 制約のチェックの状態 */
enum constraint_stat {
  unchecked, ok, ng
};


/*
 * 0: 接頭辞
 * 1: 自立語部
 * 2: 接尾辞
 */
#define NR_PARTS 4
#define PART_PREFIX 0
#define PART_CORE 1
#define PART_POSTFIX 2
#define PART_DEPWORD 3

struct part_info {
  /* このpartの長さ */
  int from, len;
  /* 品詞 */
  wtype_t wt;
  seq_ent_t seq;
  /* 頻度 */
  int freq;
  /* スコアの比率 */
  int ratio;
  /* 品詞 */
  int pos;
  /* 活用形 */
  int ct;
};

/*
 * word_list: 文節を形成するもの
 * 接頭語、自立語、接尾語、付属語を含む
 */
struct word_list {
  /**/
  int from, len; /* 文節全体 */
  int score;/* スコア */
  struct seg_class seg_class;
  enum constraint_stat can_use; /* セグメント境界に跨がっていない */

  /**/
  int last_part;
  struct part_info part[NR_PARTS];

  /* このword_listを作った際の情報 */
  int node_id; /* 付属語グラフの検索開始のnodeのid*/
  char *core_wt_name; /* word_list生成に用いたルールの名前 */

  /* 同じfromを持つword_listのリスト */
  struct word_list *next;
};


/* とりあえず、適当に増やしてみて問題が出たら分類する */
enum metaword_type {
  /* ダミー : seginfoを持たない */
  MW_DUMMY,
  /* wordlistを0個 or 一個含むもの */
  MW_SINGLE,
  /* 別のmetaword一個を含む: metaword + 句読点 など :seginfoはmw1から取る */
  MW_WRAP,
  /* 苗字と名前のペア */
  MW_NAMEPAIR,
  /* 動詞の連用形 + 形容詞 */
  MW_V_RENYOU_A,
  /* 動詞の連用形 + 名詞 */
  MW_V_RENYOU_NOUN,
  /* 何十何 */
  MW_NUM_XX,
  /**/
  MW_NOUN_NOUN_PREFIX,
  MW_OCHAIRE,
  MW_OCHAIRE_LEAF,
  /* 主語述語の関係 */
  MW_SENTENCE,
  /* 修飾、披修飾の関係 */
  MW_MODIFIED,
  /**/
  MW_END
};

/*
 * meta_wordからのseginfoの取り出し方
 */
enum mw_seginfo {
  /* SEGINFOを持たない */
  MW_SEGINFO_NONE,
  /* mw->mw1からSEGINFOを取り出す */
  MW_SEGINFO_WRAPPED,
  /* mw-mw1とmw->mw2から連結 */
  MW_SEGINFO_COMBINED,
  /* OCHAIRE学習から取り出す */
  MW_SEGINFO_OCHAIRE_LEAF
};

/*
 * meta_wordによる文節境界のmarkの仕方
 */
enum mw_mark {
  /* マークしない */
  MW_MARK_NONE,
  /* mw->mw1, mw->mw2両方をマークする */
  MW_MARK_PAIR,
  /* mw->mw1をマークする */
  MW_MARK_OCHAIRE,
  /* mwの左側をマークして、mw->mw1をマークする */
  MW_MARK_OCHAIRE_LEAF,
  /* MW_MARK_OCAHAIREに同じ */
  MW_MARK_WRAP,
  /* mw->wlがあればその左にマーク(MW_SINGLEの場合) */
  MW_MARK_WL,
  /* mw->mw1->wlがあればその左にマーク(2meta_wordの結合の場合) */
  MW_MARK_LEFT_WL
};

/*
 * meta_wordの使用可能チェックのやり方
 */
enum mw_check {
  /* なにもせず */
  MW_CHECK_NONE,
  /* mw->wlの範囲に境界が無い */
  MW_CHECK_WL_STR,
  /* mw->wlが無いか、wlが使える場合 */
  MW_CHECK_WL_SINGLE,
  /**/
  MW_CHECK_WL_WRAP,
  MW_CHECK_BORDER,
  MW_CHECK_PAIR,
  MW_CHECK_OCHAIRE
};

/* metawordの種類による処理の違い (metaword.c) */
extern struct metaword_type_tab_ {
  enum metaword_type type;
  int score;
  enum mw_seginfo si;
  enum mw_mark mark;
  enum mw_check check;
} anthy_metaword_type_tab[];


/*
 * meta_word: 境界の検索の対象となるもの
 * 単一のword_listを含むものの他にいくつかの種類がある．
 * 
 */
struct meta_word {
  int from, len;
  int score;
  struct seg_class seg_class;
  int mw_count;/* metawordの数 */
  enum constraint_stat can_use; /* セグメント境界に跨がっていない */
  enum metaword_type type;
  struct word_list *wl;
  struct meta_word *mw1, *mw2;
  struct seg_info *si;
  xstr* cand_hint;

  /* listのリンク */
  struct meta_word *next;
  struct meta_word *same_extent;
  struct meta_word *composed;

  /* 以下は構造をコミットしたときに使うメンバ */
  struct meta_word *parent;
};

/*
 * 文字列中のある範囲を指す
 */
struct extent {
  /* 文節の伸縮のたびに再評価して，更新される */
  int score;
  /* 範囲 */
  int from, len;
  /* metawordの数 */
  int mw_count;
  /**/
  int is_dummy_char;
  /* meta_wordのリスト */
  struct meta_word *mw;
  /**/
  struct meta_word *best;
};

/*
 * 文字列中のある場所を表し，
 * そこから始まるextent, meta_word, word_listのセットを持つ
 */
struct char_node {
  int max_len;
  struct extent **ex;
  struct meta_word *mw;
  struct word_list *wl;
};

/*
 * コンテキスト中の自立語などの情報、最初に変換ボタンを押したときに
 * 構築される
 */
struct word_split_info_cache {
  struct char_node *cnode;

  /* キャッシュ構成時に使う情報 */
  /* 接尾辞を探すのに使う */
  int *seq_len;/* そこから始まる最長の単語の長さ */
  /* 接頭辞を探すのに使う */
  int *rev_seq_len;/* そこで終わる最長の単語の長さ */
  /* 文節境界contextからのコピー */
  int *seg_border;
  /* アロケータ */
  allocator MwAllocator, WlAllocator, ExAllocator;
};


/* splitter.c */
#define SPLITTER_DEBUG_NONE 0
/* wordlistの表示 */
#define SPLITTER_DEBUG_WL 1
/* metawordの表示 */
#define SPLITTER_DEBUG_MW 2
/* A*nodeの表示 */
#define SPLITTER_DEBUG_AN 4
/* 自立語のマッチした品詞 */
#define SPLITTER_DEBUG_ID 8
/* 一文節だけ */
#define SPLITTER_DEBUG_1 16
/* syntactic解析をoff */
#define SPLITTER_DEBUG_S 32
int anthy_splitter_debug_flags(void);


/* defined in wordseq.c */
/* 自立語以降の接続の処理 */
void anthy_scan_node(struct splitter_context *sc,
		     struct word_list *wl,
		     xstr *follow, int node);
int anthy_get_node_id_by_name(const char *name);
int anthy_init_depword_tab(void);
void anthy_release_depword_tab(void);


/* defined in wordlist.c */
void anthy_commit_word_list(struct splitter_context *, struct word_list *wl);
struct word_list *anthy_alloc_word_list(struct splitter_context *);
void anthy_print_word_list(struct splitter_context *, struct word_list *);
void anthy_make_word_list_all(struct splitter_context *);
int anthy_init_wordlist(void);
/* extent */
struct extent *anthy_find_extent(struct splitter_context *,
				 int from, int len, int force);

/* defined in metaword.c */
void anthy_make_metaword_all(struct splitter_context *);
void anthy_print_metaword(struct splitter_context *, struct meta_word *);
struct meta_word *
anthy_do_combine_metaword(struct splitter_context *sc,
			  enum metaword_type type,
			  struct meta_word *mw, struct meta_word *mw2);


/* defined in evalborder.c */
void anthy_eval_border(struct splitter_context *, int, int);


/* syntactic.c */
void anthy_make_syntactic_metaword(struct splitter_context *);


/* 品詞(anthy_init_splitterで初期化される) */
extern wtype_t anthy_wtype_noun;
extern wtype_t anthy_wtype_name_noun;
extern wtype_t anthy_wtype_num_noun;
extern wtype_t anthy_wtype_prefix;
extern wtype_t anthy_wtype_num_prefix;
extern wtype_t anthy_wtype_postfix;
extern wtype_t anthy_wtype_num_postfix;
extern wtype_t anthy_wtype_name_postfix;
extern wtype_t anthy_wtype_sv_postfix;
extern wtype_t anthy_wtype_a_tail_of_v_renyou;
extern wtype_t anthy_wtype_v_renyou;
extern wtype_t anthy_wtype_noun_tail;/* いれ「たて」とか */
extern wtype_t anthy_wtype_n1;
extern wtype_t anthy_wtype_n10;
extern wtype_t anthy_wtype_noun_and_postfix;


#endif
