def decodeTrennung(t): """Hyphenates a word whose hyphenation point are explicitly given. For example "play5er". """ W = [] p = 0 for i in range(len(t)): if t[i] in "123456789": q = int(t[i]) W.append(HyphenationPoint(p, q, 0, SHY, 0, u"")) else: p += 1 return W
def zerlegeWort(self, zusgWort): hyphPoints = [] for left, right in self.hnj.pairs(zusgWort): # Uncomment next line for an example of non-standard hyphenation # if left=="schif" and right=="fahrt": left="schiff" sl = self.shy if left[-1] in [u"-", self.shy]: sl = u"" if left + right == zusgWort: hp = HyphenationPoint(len(left), self.quality, 0, sl, 0, u"") else: # Handle non-standard hyphenation # TODO: Test this. for i, ch in enumerate(left): if ch != zusgWort[i]: nl = len(left) - i sl = left[i:] + sl break else: nl = 0 pos = len(left) thgir = list(right) thgir.reverse() for i, ch in enumerate(thgir): if ch != zusgWort[-i - 1]: nr = 0 sr = right[:-i - 1] break else: nr = 0 sr = right[:len(left) + len(right) - len(zusgWort)] assert sr, ( "This should be handled via left+right==zusgWort", left, right, zusgWort) hp = HyphenationPoint(len(left), self.quality, nl, sl, nr, sr) hyphPoints.append(hp) return hyphPoints
def hyph(self, word): log.debug("DCW hyphenate %r", word) assert isinstance(word, unicode) loesungen = self.zerlegeWort(word) if len(loesungen) > 1: # Trennung ist nicht eindeutig, z.B. bei WachsTube oder WachStube. #hword.info = ("AMBIGUOUS", loesungen) # nimm nur solche Trennstellen, die in allen Lösungen vorkommen, # und für die Qualität nimm die schlechteste. loesung = [] loesung0, andere = loesungen[0], loesungen[1:] for i, hp in enumerate(loesung0): q = hp.quality for a in andere: if q: for hp1 in a: if hp1.indx==hp.indx \ and hp1.nl==hp.nl and hp1.sl==hp.sl \ and hp1.nr==hp.nr and hp1.sr==hp.sr: q = min(q, hp1.quality) break else: # Trennstelle nicht in der anderen Lösung enthalten q = 0 if q: loesung.append( HyphenationPoint(hp.indx, q, hp.nl, hp.sl, hp.nr, hp.sr)) if loesung: # Es gibt mindestens eine Trennstelle, die bei allen Varianten # enthalten ist, z.b. Wachstu-be. pass # hword.info = ("HYPHEN_OK", loesung) else: # Es gibt keine Trennstelle. pass elif len(loesungen) == 1: # Trennung ist eindeutig loesung = loesungen[0] #hword.info = ("HYPHEN_OK", loesung) if not loesung: pass # hword.info = ("NOT_HYPHENATABLE", aWord) else: # Das Wort ist uns unbekannt. return None return HyphenatedWord(word, loesung)
def zerlegeWort(self, zusgWort, maxLevel=20): #Wort erstmal normalisieren assert isinstance(zusgWort, unicode) zusgWort = zusgWort.lower().replace(u'Ä', u'ä').replace(u'Ö', u'ö').replace( u'Ü', u'ü') lenword = len(zusgWort) #print zusgWort loesungen = [] L = self._zerlegeWort(zusgWort) # Trennung für Wortstämme mit Endungen berichtigen for W in L: # Eine mögliche Lösung. Von dieser die einzelnen Wörter betrachten Wneu = [] offset = 0 ok = True #log.debug ("Versuche %r", W) sr = "" for i, w in enumerate(W): if not ok: break offset += len(w.prefix_chars) if i > 0: # @TODO: Hier darf nicht fest shy stehen, da # das letzte Wort mit "-" geendet haben könnte lastWordSuffixChars = W[i - 1].suffix_chars if lastWordSuffixChars and lastWordSuffixChars[ len(lastWordSuffixChars) - 1][-1:] in [u"-", self.shy]: Wneu.append( HyphenationPoint(offset, self.qHaupt, 0, "", 0, sr)) else: Wneu.append( HyphenationPoint(offset, self.qHaupt, 0, self.shy, 0, sr)) if w.konsonantenverkuerzung_3_2: sr = w.root.strval[-1] else: sr = u"" if w.prefix: for f in w.prefix: Wneu += self.schiebe( offset, self.dudentrennung(f.strval, self.qVorsilbe)) offset += len(f.strval) Wneu.append( HyphenationPoint(offset, 7, 0, self.shy, 0, u"")) # @TODO Qualität 7 ist hier fest eingebrannt for p in w.root.props: if isinstance(p, TRENNUNG) or isinstance(p, KEEP_TOGETHER): st = p.args break else: st = self.dudentrennung(w.root.strval, self.qSchlecht) if len(st): Wneu += self.schiebe(offset, st) st, stLast = st[:-1], st[-1] p = stLast.indx offset += p en = w.root.strval[p:] + (u"".join( [s.strval for s in w.suffix])) else: en = w.root.strval + (u"".join( [s.strval for s in w.suffix])) if w.suffix: ent = self.dudentrennung(en, self.qNeben) #print "en=",en,"ent=",ent Wneu += self.schiebe(offset, ent) # Prüfen, ob dieses Wort als letztes stehen muss # #for pf in w.prefix + [w.root] + w.suffix: # if i>0 and pf.props.get(NOT_AFTER_WORD) and str(W[i-1].root) in pf.props.get(NOT_AFTER_WORD): # if VERBOSE: print "'%s' nicht erlaubt nach '%s'" % (pf,W[i-1].root) # ok = False # break # if pf.props.get(ONLY_LAST_WORD) and i<len(W)-1: # if VERBOSE: print "'%s' nur als letztes Wort erlaubt!" % pf # ok = False # break # if pf.props.get(ONLY_FIRST_WORD) and i>0: # if VERBOSE: print "'%s' nur als erstes Wort erlaubt!" % pf # ok = False # break #else: # # letztes Wort # for pf in w.prefix + [w.root] + w.suffix: # #print "letztes Wort, Bestandteil",pf, pf.props # if pf.props.get(NOT_LAST_WORD): # if VERBOSE: print "'%s' nicht als letztes Wort erlaubt!" % pf # ok = False # break offset += len(en) offset += len(w.suffix_chars) if ok and (Wneu not in loesungen): log.debug("Wneu=%r", Wneu) loesungen.append(Wneu) return loesungen
def dudentrennung(self, wort, quality=None): """ The algorithm how to hyphenate a word without knowing about the context. This code is quite specific to German! For other languages, there may be totally different rules. This rule is known as "Ein-Konsonanten-Regel" in German. The rule works (basically) as follows: First, find the vowels in the word, as they mark the syllables (one hyphenation point between two vowels (but consider sequences of vowels counting as one). If there are consonants between two vowels, put all but the last consonant to the left syllable, and only the last consonant to the right syllable (therefore the name one-consonant-rule). However, there are also sequences of consonants counting as one, like "ch" or "sch". """ #print "dudentrennung: %s" % wort if not quality: quality = self.qNeben assert isinstance(wort, unicode) # Jede Silbe muss mindestens einen Vokal enthalten if len(wort) <= 2: return [] # Suche bis zum ersten Vokal for vpos1 in range(len(wort)): if wort[vpos1] in VOWELS: if wort[vpos1 - 1:vpos1 + 1] != 'qu': break else: # Kein Vokal enthalten! return [] # wort[vpos1] ist der erste Vokal fertig = False stpos = vpos1 + 1 while not fertig: fertig = True # Suche bis zum zweiten Vokal for vpos2 in range(stpos, len(wort)): if wort[vpos2] in VOWELS: break else: # Kein zweiter Vokal enthalten! return [] # wort[vpos2] ist der zweite Vokal if vpos2 == 2 and wort[1] not in VOWELS: # Nach Einkonsonantenregel bleibt als erste Silbe nur ein einzelner Buchstabe, # z.B. o-ber. Das wollen wir nicht stpos = vpos2 + 1 fertig = False if vpos2 == vpos1 + 1: # a sequence of two vowels, like German "ei" or "au", or English "ou" or "oi" if wort[vpos1:vpos2 + 1] in [u'äu', u'au', u'eu', u'ei', u'ie', u'ee']: # Treat the sequence as if it was one vowel! stpos = vpos2 + 1 fertig = False else: return [ HyphenationPoint(vpos2, quality, 0, self.shy, 0, u"") ] + self.schiebe(vpos2, self.dudentrennung(wort[vpos2:], quality)) if wort[vpos2 - 3:vpos2] in [ u'sch', ]: return [HyphenationPoint( vpos2 - 3, quality, 0, self.shy, 0, u"")] + self.schiebe( vpos2 - 3, self.dudentrennung(wort[vpos2 - 3:], quality)) elif ALTE_REGELN and wort[vpos2 - 2:vpos2] in [u'st']: return [HyphenationPoint( vpos2 - 2, quality, 0, self.shy, 0, u"")] + self.schiebe( vpos2 - 2, self.dudentrennung(wort[vpos2 - 2:], quality)) elif ALTE_REGELN and wort[vpos2 - 2:vpos2] in [u'ck']: return [ HyphenationPoint(vpos2 - 1, quality, 1, u"k" + self.shy, 0, u"") ] + self.schiebe(vpos2 - 1, self.dudentrennung(wort[vpos2 - 1:], quality)) elif wort[vpos2 - 2:vpos2] in [u'ch', u'ck', u'ph']: return [HyphenationPoint( vpos2 - 2, quality, 0, self.shy, 0, u"")] + self.schiebe( vpos2 - 2, self.dudentrennung(wort[vpos2 - 2:], quality)) elif wort[vpos2 - 1] in VOWELS: return [HyphenationPoint(vpos2, quality, 0, self.shy, 0, u"") ] + self.schiebe(vpos2, self.dudentrennung(wort[vpos2:], quality)) else: return [HyphenationPoint( vpos2 - 1, quality, 0, self.shy, 0, u"")] + self.schiebe( vpos2 - 1, self.dudentrennung(wort[vpos2 - 1:], quality))
def schiebe(self, offset, L): return [ HyphenationPoint(h.indx + offset, h.quality, h.nl, h.sl, h.nr, h.sr) for h in L ]