convertinput.py
5.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
'''
Created on Oct 23, 2013
@author: mlenart
'''
import logging
from common import Interpretation4Analyzer
from morfeuszbuilder.fsa.common import Interpretation4Generator
def _mergeEntries(inputLines, lowercase):
prevKey = None
prevInterps = None
for key, interp in inputLines:
key = key.lower() if lowercase else key
# print 'key=', key, 'interp=', interp
assert key
if prevKey and prevKey == key:
prevInterps.append(interp)
else:
if prevKey:
yield (prevKey, frozenset(prevInterps))
prevKey = key
prevInterps = [interp]
yield (prevKey, frozenset(prevInterps))
def _parseLine(line):
splitLine = line.strip().split(u'\t')
if len(splitLine) == 5:
orth, base, tag, name, qualifier = splitLine
elif len(splitLine) == 4:
orth, base, tag, name = splitLine
qualifier = ''
elif len(splitLine) == 3:
orth, base, tag = splitLine
name = ''
qualifier = ''
else:
raise ValueError('input line "%s" does not have 3, 4 or 5 tab-separated fields' % line)
return orth, base, tag, name, qualifier
class PolimorfConverter4Analyzer(object):
def __init__(self, tagset, encoder, inputEncoding, segmentRulesManager):
self.tagset = tagset
self.encoder = encoder
self.inputEncoding = inputEncoding
self.segmentRulesManager = segmentRulesManager
# we do it the ugly way (parse to plain text) because it is way more memory-efficient
def _partiallyParseLines(self, inputLines):
for line in inputLines:
line = line.decode(self.inputEncoding).strip('\n')
orth, base, tag, name, qualifier = _parseLine(line)
tagnum = self.tagset.getTagnum4Tag(tag)
namenum = self.tagset.getNamenum4Name(name)
typenum = self.segmentRulesManager.lexeme2SegmentTypeNum(base, tagnum)
yield '\t'.join((
orth.encode(self.inputEncoding),
base.encode(self.inputEncoding),
str(tagnum),
str(namenum),
str(typenum),
qualifier.encode(self.inputEncoding)))
# input lines are encoded and partially parsed
def _sortLines(self, inputLines):
return sorted(inputLines, key=lambda line: self.encoder.word2SortKey(line.split('\t')[0].decode('utf8')))
def _reallyParseLines(self, inputLines):
for line in inputLines:
line = line.decode(self.inputEncoding).strip(u'\n')
if line:
orth, base, tagnum, namenum, typenum, qualifierStr = line.split(u'\t')
tagnum = int(tagnum)
namenum = int(namenum)
typenum = int(typenum)
qualifiers = qualifierStr.split('|') if qualifierStr else []
yield (orth, Interpretation4Analyzer(orth, base, tagnum, namenum, typenum, qualifiers))
def convert(self, inputLines):
return _mergeEntries(self._reallyParseLines(self._sortLines(self._partiallyParseLines(inputLines))), lowercase=True)
class PolimorfConverter4Generator(object):
def __init__(self, tagset, encoder, inputEncoding, segmentRulesManager):
self.tagset = tagset
self.encoder = encoder
self.inputEncoding = inputEncoding
self.segmentRulesManager = segmentRulesManager
# we do it the ugly way (parse to plain text) because it is way more memory-efficient
def _partiallyParseLines(self, inputLines):
for line in inputLines:
line = line.decode(self.inputEncoding).strip('\n')
orth, base, tag, name, qualifier = _parseLine(line)
if base:
if u':' in base and len(base) > 1 and base.split(u':', 1)[1] != u'':
base, homonymId = base.split(u':', 1)
else:
homonymId = ''
tagnum = self.tagset.getTagnum4Tag(tag)
namenum = self.tagset.getNamenum4Name(name)
typenum = self.segmentRulesManager.lexeme2SegmentTypeNum(base, tagnum)
yield '\t'.join((
orth.encode(self.inputEncoding),
base.encode(self.inputEncoding),
str(tagnum),
str(namenum),
str(typenum),
homonymId.encode(self.inputEncoding),
qualifier.encode(self.inputEncoding)))
else:
logging.warn('Ignoring line: "%s" - contains empty lemma', line.strip())
# input lines are encoded and partially parsed
def _sortLines(self, inputLines):
return sorted(inputLines, key=lambda line: (self.encoder.word2SortKey(line.split('\t')[1].decode('utf8')), line))
def _reallyParseLines(self, inputLines):
prevLine = None
for line in inputLines:
line = line.decode(self.inputEncoding).strip(u'\n')
if line and line != prevLine:
orth, base, tagnum, namenum, typenum, homonymId, qualifierStr = line.split(u'\t')
# print orth.encode('utf8'), base.encode('utf8'), homonymId
tagnum = int(tagnum)
namenum = int(namenum)
typenum = int(typenum)
prevLine = line
qualifiers = qualifierStr.split('|') if qualifierStr else ()
yield (base, Interpretation4Generator(orth, base, tagnum, namenum, typenum, homonymId, qualifiers))
def convert(self, inputLines):
return _mergeEntries(self._reallyParseLines(self._sortLines(self._partiallyParseLines(inputLines))), lowercase=False)