#1. はじめに
この記事では、日本語形態素解析エンジン MeCab ver.0.996 における辞書ファイルの設定について記載しています。OSは、Windowsを前提としています。
MeCab: Yet Another Part-of-Speech and Morphological Analyzerには、何故かWindowsのインストールについては、自己解凍インストーラの話しか書いてありません。辞書ファイルの設定が何も記載されていません。
Windows
バイナリをインストールする場合は, 自己解凍インストーラ (mecab-X.X.exe) を実行してください. 辞書も同時にインストールされます。
以下は、MeCab ver.0.996 のソースコードから読み取った手探りです。
なお、以下のソリューションでデパッグすると、以下の動作がトレース可能です。
https://github.com/k-ayaki/mecab-msvc
#2. MeCabの辞書ファイルについて
MeCabの辞書ファイルは、以下のものです。これは、C:\Program Files (x86)\MeCab\dic\ipadic に格納されているものです。
ファイル名 | 機能 |
---|---|
sys.dic | システム辞書 |
unk.dic | 未知語辞書 |
dicrc | IPA辞書の定義ファイル |
辞書の定義ファイルには、sys.dicとunk.dic のコストファクター、評価サイズ、文字コードなどが記載されています。これは書き換えたことはありません。
;
; Configuration file of IPADIC
;
; $Id: dicrc,v 1.4 2006/04/08 06:41:36 taku-ku Exp $;
;
cost-factor = 800
bos-feature = BOS/EOS,*,*,*,*,*,*,*,*
eval-size = 8
unk-eval-size = 4
config-charset = SHIFT-JIS
; yomi
node-format-yomi = %pS%f[7]
unk-format-yomi = %M
eos-format-yomi = \n
; simple
node-format-simple = %m\t%F-[0,1,2,3]\n
eos-format-simple = EOS\n
; ChaSen
node-format-chasen = %m\t%f[7]\t%f[6]\t%F-[0,1,2,3]\t%f[4]\t%f[5]\n
unk-format-chasen = %m\t%m\t%m\t%F-[0,1,2,3]\t\t\n
eos-format-chasen = EOS\n
; ChaSen (include spaces)
node-format-chasen2 = %M\t%f[7]\t%f[6]\t%F-[0,1,2,3]\t%f[4]\t%f[5]\n
unk-format-chasen2 = %M\t%m\t%m\t%F-[0,1,2,3]\t\t\n
eos-format-chasen2 = EOS\n
この辞書ファイルの場所を指定しているのが、C:\Program Files (x86)\MeCab\etc\mecabrc です。
dicdir に、ipa辞書のパスが格納されています。なお、$(rcpath)は、当該ファイルのパスのことです。
;
; Configuration file of MeCab
;
; $Id: mecabrc.in,v 1.3 2006/05/29 15:36:08 taku-ku Exp $;
;
dicdir = $(rcpath)\..\dic\ipadic
; userdic = /home/foo/bar/user.dic
; output-format-type = wakati
; input-buffer-size = 8192
; node-format = %m\n
; bos-format = %S\n
; eos-format = EOS\n
MeCabのライブラリである libmecab.dll は、mecabrcを読み込んでipa辞書ファイルを特定したのち、sys.dic, unk.dic, dicrcなどを読み込んでいます。
#3. libmecab.dll による mecabrc パスの特定方法
#3.1. 環境変数による特定
環境変数 HOMEがあれば、mecabrcのパスとして読み取ります。
次に環境変数MECABRCがあれば、mecabrcのパスとして読み取ります。
なお、コンパイル時のマクロ HAVE_GETENV を定義しないとき、libmecab.dll は環境変数を読み取らなくなります。
#ifdef HAVE_GETENV
if (rcfile.empty()) {
const char *homedir = getenv("HOME");
if (homedir) {
const std::string s = MeCab::create_filename(std::string(homedir),
".mecabrc");
std::ifstream ifs(WPATH(s.c_str()));
if (ifs) {
rcfile = s;
}
}
}
if (rcfile.empty()) {
const char *rcenv = getenv("MECABRC");
if (rcenv) {
rcfile = rcenv;
}
}
#endif
#if defined (HAVE_GETENV) && defined(_WIN32) && !defined(__CYGWIN__)
if (rcfile.empty()) {
scoped_fixed_array<wchar_t, BUF_SIZE> buf;
const DWORD len = ::GetEnvironmentVariableW(L"MECABRC",
buf.get(),
buf.size());
if (len < buf.size() && len > 0) {
rcfile = WideToUtf8(buf.get());
}
}
#endif
#3.2. レジストリによる特定(Windows固有)
環境変数が定義されておらず、且つ、レジストリ HKEY_LOCAL_MACHINE\software\mecab に、mecabrcキーがあれば、その値を mecabrcのパスとして読み取ります。
レジストリ HKEY_CURRENT_USER\software\mecab に、mecabrcキーがあれば、その値を mecabrcのパスとして読み取ります。
なお、Windows版のMeCab ver.0.996 をインストールしたときには、レジストリ HKEY_CURRENT_USER\software\mecabに、mecabrcキーが書き込まれます。
#if defined(_WIN32) && !defined(__CYGWIN__)
HKEY hKey;
scoped_fixed_array<wchar_t, BUF_SIZE> v;
DWORD vt;
DWORD size = v.size() * sizeof(v[0]);
if (rcfile.empty()) {
::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"software\\mecab", 0, KEY_READ, &hKey);
::RegQueryValueExW(hKey, L"mecabrc", 0, &vt,
reinterpret_cast<BYTE *>(v.get()), &size);
::RegCloseKey(hKey);
if (vt == REG_SZ) {
rcfile = WideToUtf8(v.get());
}
}
if (rcfile.empty()) {
::RegOpenKeyExW(HKEY_CURRENT_USER, L"software\\mecab", 0, KEY_READ, &hKey);
::RegQueryValueExW(hKey, L"mecabrc", 0, &vt,
reinterpret_cast<BYTE *>(v.get()), &size);
::RegCloseKey(hKey);
if (vt == REG_SZ) {
rcfile = WideToUtf8(v.get());
}
}
#3.3. libmecab.dllのパスによる特定(Windows固有)
環境変数とレジストリが定義されていないならば、libmecab.dllのパスを取得して、mecabrcのパスとします。
if (rcfile.empty()) {
vt = ::GetModuleFileNameW(DllInstance, v.get(), size);
if (vt != 0) {
scoped_fixed_array<wchar_t, _MAX_DRIVE> drive;
scoped_fixed_array<wchar_t, _MAX_DIR> dir;
_wsplitpath(v.get(), drive.get(), dir.get(), NULL, NULL);
const std::wstring path =
std::wstring(drive.get()) + std::wstring(dir.get()) + L"mecabrc";
if (::GetFileAttributesW(path.c_str()) != -1) {
rcfile = WideToUtf8(path);
}
}
}
#3.4. マクロ定義したパスによる特定
マクロ MECAB_DEFAULT_RC で定義したパスを、mecabrcのパスとします。
if (rcfile.empty()) {
rcfile = MECAB_DEFAULT_RC;
}
#3.5. 特定したmecabrcパスの読み込み
特定したmecabrcパスに基づき、dicdir(辞書パス)を読み込みます。
if (!param->load(rcfile.c_str())) {
return false;
}
#3.6. dicdir(辞書パス)の決定
特定したmecabrcパスに基づき、dicdir(辞書パス)を読み込みます。
std::string dicdir = param->get<std::string>("dicdir");
if (dicdir.empty()) {
dicdir = "."; // current
}
remove_filename(&rcfile);
replace_string(&dicdir, "$(rcpath)", rcfile);
param->set<std::string>("dicdir", dicdir, true);
dicdir = create_filename(dicdir, DICRC);
if (!param->load(dicdir.c_str())) {
return false;
}
return true;