# -*- encoding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
from .morpheme import Morpheme, JUMAN_FORMAT
import unittest
[docs]class MList(object):
"""
ある文に関する形態素列を保持するオブジェクト.
"""
[docs] def __init__(self, spec="", juman_format=JUMAN_FORMAT.DEFAULT):
self._mrph = []
self._readonly = False
self.comment = ""
mid = 1
if spec != "":
for line in spec.split("\n"):
if line.strip() == "":
continue
elif line.startswith('#'):
self.comment += line
elif line.startswith('@') and not line.startswith('@ @'):
self._mrph[-1].push_doukei(Morpheme(line[2:], mid, juman_format))
mid += 1
else:
mrph = Morpheme(line, mid, juman_format)
if juman_format == JUMAN_FORMAT.LATTICE_TOP_ONE:
if 1 not in mrph.ranks:
continue
elif self._mrph and self._mrph[-1].mrph_id == mrph.mrph_id:
self._mrph[-1].push_doukei(mrph)
continue
self.push_mrph(mrph)
mid += 1
[docs] def push_mrph(self, mrph):
if self._readonly:
return
self._mrph.append(mrph)
[docs] def set_readonly(self):
self._readonly = True
[docs] def spec(self):
"""
形態素列の全文字列を返す.Juman による出力と同じ形式の結果が得られる.
"""
spec = ""
for mrph in self._mrph:
spec = "%s%s" % (spec, mrph.spec())
for doukei in mrph.doukei:
spec = "%s@ %s" % (spec, doukei.spec())
return spec
[docs] def new_spec(self):
prev_mids = [0]
length = 0
out = []
for mrph in self._mrph:
ms = [mrph] + mrph.doukei
tmp_prev_mids = []
for m in ms:
out.append(m.new_spec(prev_mids, length))
tmp_prev_mids.append(m.mrph_id)
length += len(mrph.midasi)
prev_mids = tmp_prev_mids
return "".join(out)
[docs] def mrph_list(self):
""" 保持する全ての形態素のリストを返す.
Returns:
list of Morpheme: 形態素オブジェクトMorphemeのリスト
"""
return self._mrph
def __getitem__(self, index):
return self._mrph[index]
def __len__(self):
return len(self._mrph)
def __repr__(self):
return 'MList(%s)' % repr(self.spec())
class MListTest(unittest.TestCase):
def setUp(self):
self.spec1 = """構文 こうぶん 構文 名詞 6 普通名詞 1 * 0 * 0 "代表表記:構文/こうぶん カテゴリ:抽象物"\n"""
self.spec2 = """解析 かいせき 解析 名詞 6 サ変名詞 2 * 0 * 0 "代表表記:解析/かいせき カテゴリ:抽象物 ドメイン:教育・学習;科学・技術"\n"""
self.mlist = MList(self.spec1+self.spec2)
def test_mrph(self):
self.assertEqual(len(self.mlist), 2)
self.assertEqual(self.mlist[0].midasi, '構文')
self.assertEqual(self.mlist[-1].midasi, '解析')
def test_mrph_list(self):
self.assertEqual(''.join([x.midasi for x in self.mlist]), '構文解析')
self.assertEqual(self.mlist.spec(), self.spec1 + self.spec2)
new_spec = """-\t1\t0\t0\t1\t構文\t構文/こうぶん\tこうぶん\t構文\t名詞\t6\t普通名詞\t1\t*\t0\t*\t0\tカテゴリ:抽象物\n""" + \
"""-\t2\t1\t2\t3\t解析\t解析/かいせき\tかいせき\t解析\t名詞\t6\tサ変名詞\t2\t*\t0\t*\t0\tカテゴリ:抽象物|ドメイン:教育・学習;科学・技術\n"""
self.assertEqual(self.mlist.new_spec(), new_spec)
def test_doukei(self):
spec = """母 はは 母 名詞 6 普通名詞 1 * 0 * 0 "代表表記:母/はは 漢字読み:訓 カテゴリ:人 ドメイン:家庭・暮らし"
@ 母 ぼ 母 名詞 6 普通名詞 1 * 0 * 0 "代表表記:母/ぼ 漢字読み:音 カテゴリ:人"
です です だ 判定詞 4 * 0 判定詞 25 デス列基本形 27 NIL
"""
new_spec = """-\t1\t0\t0\t0\t母\t母/はは\tはは\t母\t名詞\t6\t普通名詞\t1\t*\t0\t*\t0\t漢字読み:訓|カテゴリ:人|ドメイン:家庭・暮らし
-\t2\t0\t0\t0\t母\t母/ぼ\tぼ\t母\t名詞\t6\t普通名詞\t1\t*\t0\t*\t0\t漢字読み:音|カテゴリ:人
-\t3\t1;2\t1\t2\tです\tだ/だ\tです\tだ\t判定詞\t4\t*\t0\t判定詞\t25\tデス列基本形\t27\t
"""
mlist = MList(spec)
self.assertEqual(mlist.spec(), spec)
self.assertEqual(mlist.new_spec(), new_spec)
def test_repr(self):
import pyknp
spec = """母 はは 母 名詞 6 普通名詞 1 * 0 * 0 "代表表記:母/はは 漢字読み:訓 カテゴリ:人 ドメイン:家庭・暮らし"
@ 母 ぼ 母 名詞 6 普通名詞 1 * 0 * 0 "代表表記:母/ぼ 漢字読み:音 カテゴリ:人"
です です だ 判定詞 4 * 0 判定詞 25 デス列基本形 27 NIL
"""
mlist = MList(spec)
repr_mlist = eval(repr(mlist))
self.assertEqual(repr_mlist.spec(), mlist.spec())
if __name__ == '__main__':
unittest.main()