Grammalecte  Hex Artifact Content

Artifact 56b76111df120eced64df6f83d26a566d1a55bf6ee781bfc3d015452d39b6b4b:


0000: 23 21 70 79 74 68 6f 6e 33 0a 0a 69 6d 70 6f 72  #!python3..impor
0010: 74 20 6f 73 0a 69 6d 70 6f 72 74 20 74 72 61 63  t os.import trac
0020: 65 62 61 63 6b 0a 69 6d 70 6f 72 74 20 70 6b 67  eback.import pkg
0030: 75 74 69 6c 0a 69 6d 70 6f 72 74 20 72 65 0a 66  util.import re.f
0040: 72 6f 6d 20 66 75 6e 63 74 6f 6f 6c 73 20 69 6d  rom functools im
0050: 70 6f 72 74 20 77 72 61 70 73 0a 69 6d 70 6f 72  port wraps.impor
0060: 74 20 64 61 74 65 74 69 6d 65 0a 69 6d 70 6f 72  t datetime.impor
0070: 74 20 74 69 6d 65 0a 69 6d 70 6f 72 74 20 6a 73  t time.import js
0080: 6f 6e 0a 0a 23 69 6d 70 6f 72 74 20 6c 6f 67 67  on..#import logg
0090: 69 6e 67 0a 23 6c 6f 67 67 69 6e 67 2e 62 61 73  ing.#logging.bas
00a0: 69 63 43 6f 6e 66 69 67 28 66 69 6c 65 6e 61 6d  icConfig(filenam
00b0: 65 3d 22 73 75 67 67 65 73 74 69 6f 6e 73 2e 6c  e="suggestions.l
00c0: 6f 67 22 2c 20 6c 65 76 65 6c 3d 6c 6f 67 67 69  og", level=loggi
00d0: 6e 67 2e 44 45 42 55 47 29 0a 0a 66 72 6f 6d 20  ng.DEBUG)..from 
00e0: 2e 20 69 6d 70 6f 72 74 20 73 74 72 5f 74 72 61  . import str_tra
00f0: 6e 73 66 6f 72 6d 20 61 73 20 73 74 0a 66 72 6f  nsform as st.fro
0100: 6d 20 2e 20 69 6d 70 6f 72 74 20 63 68 61 72 5f  m . import char_
0110: 70 6c 61 79 65 72 20 61 73 20 63 70 0a 66 72 6f  player as cp.fro
0120: 6d 20 2e 65 63 68 6f 20 69 6d 70 6f 72 74 20 65  m .echo import e
0130: 63 68 6f 0a 0a 0a 64 65 66 20 74 69 6d 65 74 68  cho...def timeth
0140: 69 73 20 28 66 75 6e 63 29 3a 0a 20 20 20 20 22  is (func):.    "
0150: 64 65 63 6f 72 61 74 6f 72 20 66 6f 72 20 74 68  decorator for th
0160: 65 20 65 78 65 63 75 74 69 6f 6e 20 74 69 6d 65  e execution time
0170: 22 0a 20 20 20 20 40 77 72 61 70 73 28 66 75 6e  ".    @wraps(fun
0180: 63 29 0a 20 20 20 20 64 65 66 20 77 72 61 70 70  c).    def wrapp
0190: 65 72 20 28 2a 61 72 67 73 2c 20 2a 2a 6b 77 61  er (*args, **kwa
01a0: 72 67 73 29 3a 0a 20 20 20 20 20 20 20 20 66 53  rgs):.        fS
01b0: 74 61 72 74 20 3d 20 74 69 6d 65 2e 74 69 6d 65  tart = time.time
01c0: 28 29 0a 20 20 20 20 20 20 20 20 72 65 73 75 6c  ().        resul
01d0: 74 20 3d 20 66 75 6e 63 28 2a 61 72 67 73 2c 20  t = func(*args, 
01e0: 2a 2a 6b 77 61 72 67 73 29 0a 20 20 20 20 20 20  **kwargs).      
01f0: 20 20 66 45 6e 64 20 3d 20 74 69 6d 65 2e 74 69    fEnd = time.ti
0200: 6d 65 28 29 0a 20 20 20 20 20 20 20 20 70 72 69  me().        pri
0210: 6e 74 28 66 75 6e 63 2e 5f 5f 6e 61 6d 65 5f 5f  nt(func.__name__
0220: 2c 20 66 45 6e 64 20 2d 20 66 53 74 61 72 74 29  , fEnd - fStart)
0230: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
0240: 72 65 73 75 6c 74 0a 20 20 20 20 72 65 74 75 72  result.    retur
0250: 6e 20 77 72 61 70 70 65 72 0a 0a 0a 63 6c 61 73  n wrapper...clas
0260: 73 20 53 75 67 67 52 65 73 75 6c 74 3a 0a 20 20  s SuggResult:.  
0270: 20 20 22 22 22 53 74 72 75 63 74 75 72 65 20 66    """Structure f
0280: 6f 72 20 73 74 6f 72 69 6e 67 2c 20 63 6c 61 73  or storing, clas
0290: 73 69 66 79 69 6e 67 20 61 6e 64 20 66 69 6c 74  sifying and filt
02a0: 65 72 69 6e 67 20 73 75 67 67 65 73 74 69 6f 6e  ering suggestion
02b0: 73 22 22 22 0a 0a 20 20 20 20 64 65 66 20 5f 5f  s"""..    def __
02c0: 69 6e 69 74 5f 5f 20 28 73 65 6c 66 2c 20 73 57  init__ (self, sW
02d0: 6f 72 64 2c 20 6e 44 69 73 74 4c 69 6d 69 74 3d  ord, nDistLimit=
02e0: 2d 31 29 3a 0a 20 20 20 20 20 20 20 20 73 65 6c  -1):.        sel
02f0: 66 2e 73 57 6f 72 64 20 3d 20 73 57 6f 72 64 0a  f.sWord = sWord.
0300: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73 53 69          self.sSi
0310: 6d 70 6c 69 66 69 65 64 57 6f 72 64 20 3d 20 63  mplifiedWord = c
0320: 70 2e 73 69 6d 70 6c 69 66 79 57 6f 72 64 28 73  p.simplifyWord(s
0330: 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20 73 65  Word).        se
0340: 6c 66 2e 6e 44 69 73 74 4c 69 6d 69 74 20 3d 20  lf.nDistLimit = 
0350: 6e 44 69 73 74 4c 69 6d 69 74 20 20 69 66 20 6e  nDistLimit  if n
0360: 44 69 73 74 4c 69 6d 69 74 20 3e 3d 20 30 20 20  DistLimit >= 0  
0370: 65 6c 73 65 20 20 28 6c 65 6e 28 73 57 6f 72 64  else  (len(sWord
0380: 29 20 2f 2f 20 33 29 20 2b 20 31 0a 20 20 20 20  ) // 3) + 1.    
0390: 20 20 20 20 73 65 6c 66 2e 6e 4d 69 6e 44 69 73      self.nMinDis
03a0: 74 20 3d 20 31 30 30 30 0a 20 20 20 20 20 20 20  t = 1000.       
03b0: 20 73 65 6c 66 2e 61 53 75 67 67 20 3d 20 73 65   self.aSugg = se
03c0: 74 28 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66  t().        self
03d0: 2e 64 53 75 67 67 20 3d 20 7b 20 30 3a 20 5b 5d  .dSugg = { 0: []
03e0: 2c 20 20 31 3a 20 5b 5d 2c 20 20 32 3a 20 5b 5d  ,  1: [],  2: []
03f0: 20 7d 0a 0a 20 20 20 20 64 65 66 20 61 64 64 53   }..    def addS
0400: 75 67 67 20 28 73 65 6c 66 2c 20 73 53 75 67 67  ugg (self, sSugg
0410: 2c 20 6e 44 65 65 70 3d 30 29 3a 0a 20 20 20 20  , nDeep=0):.    
0420: 20 20 20 20 22 61 64 64 20 61 20 73 75 67 67 65      "add a sugge
0430: 73 74 69 6f 6e 22 0a 20 20 20 20 20 20 20 20 23  stion".        #
0440: 6c 6f 67 67 69 6e 67 2e 69 6e 66 6f 28 28 6e 44  logging.info((nD
0450: 65 65 70 20 2a 20 22 20 20 22 29 20 2b 20 22 5f  eep * "  ") + "_
0460: 5f 22 20 2b 20 73 53 75 67 67 20 2b 20 22 5f 5f  _" + sSugg + "__
0470: 22 29 0a 20 20 20 20 20 20 20 20 69 66 20 73 53  ").        if sS
0480: 75 67 67 20 6e 6f 74 20 69 6e 20 73 65 6c 66 2e  ugg not in self.
0490: 61 53 75 67 67 3a 0a 20 20 20 20 20 20 20 20 20  aSugg:.         
04a0: 20 20 20 6e 44 69 73 74 20 3d 20 73 74 2e 64 69     nDist = st.di
04b0: 73 74 61 6e 63 65 44 61 6d 65 72 61 75 4c 65 76  stanceDamerauLev
04c0: 65 6e 73 68 74 65 69 6e 28 73 65 6c 66 2e 73 53  enshtein(self.sS
04d0: 69 6d 70 6c 69 66 69 65 64 57 6f 72 64 2c 20 63  implifiedWord, c
04e0: 70 2e 73 69 6d 70 6c 69 66 79 57 6f 72 64 28 73  p.simplifyWord(s
04f0: 53 75 67 67 29 29 0a 20 20 20 20 20 20 20 20 20  Sugg)).         
0500: 20 20 20 69 66 20 6e 44 69 73 74 20 3c 3d 20 73     if nDist <= s
0510: 65 6c 66 2e 6e 44 69 73 74 4c 69 6d 69 74 3a 0a  elf.nDistLimit:.
0520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0530: 69 66 20 6e 44 69 73 74 20 6e 6f 74 20 69 6e 20  if nDist not in 
0540: 73 65 6c 66 2e 64 53 75 67 67 3a 0a 20 20 20 20  self.dSugg:.    
0550: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0560: 73 65 6c 66 2e 64 53 75 67 67 5b 6e 44 69 73 74  self.dSugg[nDist
0570: 5d 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 20  ] = [].         
0580: 20 20 20 20 20 20 20 73 65 6c 66 2e 64 53 75 67         self.dSug
0590: 67 5b 6e 44 69 73 74 5d 2e 61 70 70 65 6e 64 28  g[nDist].append(
05a0: 73 53 75 67 67 29 0a 20 20 20 20 20 20 20 20 20  sSugg).         
05b0: 20 20 20 20 20 20 20 73 65 6c 66 2e 61 53 75 67         self.aSug
05c0: 67 2e 61 64 64 28 73 53 75 67 67 29 0a 20 20 20  g.add(sSugg).   
05d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
05e0: 6e 44 69 73 74 20 3c 20 73 65 6c 66 2e 6e 4d 69  nDist < self.nMi
05f0: 6e 44 69 73 74 3a 0a 20 20 20 20 20 20 20 20 20  nDist:.         
0600: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
0610: 6e 4d 69 6e 44 69 73 74 20 3d 20 6e 44 69 73 74  nMinDist = nDist
0620: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
0630: 20 73 65 6c 66 2e 6e 44 69 73 74 4c 69 6d 69 74   self.nDistLimit
0640: 20 3d 20 6d 69 6e 28 73 65 6c 66 2e 6e 44 69 73   = min(self.nDis
0650: 74 4c 69 6d 69 74 2c 20 73 65 6c 66 2e 6e 4d 69  tLimit, self.nMi
0660: 6e 44 69 73 74 2b 32 29 0a 0a 20 20 20 20 64 65  nDist+2)..    de
0670: 66 20 67 65 74 53 75 67 67 65 73 74 69 6f 6e 73  f getSuggestions
0680: 20 28 73 65 6c 66 2c 20 6e 53 75 67 67 4c 69 6d   (self, nSuggLim
0690: 69 74 3d 31 30 2c 20 6e 44 69 73 74 4c 69 6d 69  it=10, nDistLimi
06a0: 74 3d 2d 31 29 3a 0a 20 20 20 20 20 20 20 20 22  t=-1):.        "
06b0: 72 65 74 75 72 6e 20 61 20 6c 69 73 74 20 6f 66  return a list of
06c0: 20 73 75 67 67 65 73 74 69 6f 6e 73 22 0a 20 20   suggestions".  
06d0: 20 20 20 20 20 20 6c 52 65 73 20 3d 20 5b 5d 0a        lRes = [].
06e0: 20 20 20 20 20 20 20 20 69 66 20 73 65 6c 66 2e          if self.
06f0: 64 53 75 67 67 5b 30 5d 3a 0a 20 20 20 20 20 20  dSugg[0]:.      
0700: 20 20 20 20 20 20 23 20 77 65 20 73 6f 72 74 20        # we sort 
0710: 74 68 65 20 62 65 74 74 65 72 20 72 65 73 75 6c  the better resul
0720: 74 73 20 77 69 74 68 20 74 68 65 20 6f 72 69 67  ts with the orig
0730: 69 6e 61 6c 20 77 6f 72 64 0a 20 20 20 20 20 20  inal word.      
0740: 20 20 20 20 20 20 73 65 6c 66 2e 64 53 75 67 67        self.dSugg
0750: 5b 30 5d 2e 73 6f 72 74 28 6b 65 79 3d 6c 61 6d  [0].sort(key=lam
0760: 62 64 61 20 73 53 75 67 67 3a 20 73 74 2e 64 69  bda sSugg: st.di
0770: 73 74 61 6e 63 65 44 61 6d 65 72 61 75 4c 65 76  stanceDamerauLev
0780: 65 6e 73 68 74 65 69 6e 28 73 65 6c 66 2e 73 57  enshtein(self.sW
0790: 6f 72 64 2c 20 73 53 75 67 67 29 29 0a 20 20 20  ord, sSugg)).   
07a0: 20 20 20 20 20 66 6f 72 20 6c 53 75 67 67 20 69       for lSugg i
07b0: 6e 20 73 65 6c 66 2e 64 53 75 67 67 2e 76 61 6c  n self.dSugg.val
07c0: 75 65 73 28 29 3a 0a 20 20 20 20 20 20 20 20 20  ues():.         
07d0: 20 20 20 6c 52 65 73 2e 65 78 74 65 6e 64 28 6c     lRes.extend(l
07e0: 53 75 67 67 29 0a 20 20 20 20 20 20 20 20 20 20  Sugg).          
07f0: 20 20 69 66 20 6c 65 6e 28 6c 52 65 73 29 20 3e    if len(lRes) >
0800: 20 6e 53 75 67 67 4c 69 6d 69 74 3a 0a 20 20 20   nSuggLimit:.   
0810: 20 20 20 20 20 20 20 20 20 20 20 20 20 62 72 65               bre
0820: 61 6b 0a 20 20 20 20 20 20 20 20 6c 52 65 73 20  ak.        lRes 
0830: 3d 20 6c 69 73 74 28 63 70 2e 66 69 6c 74 65 72  = list(cp.filter
0840: 53 75 67 67 28 6c 52 65 73 29 29 0a 20 20 20 20  Sugg(lRes)).    
0850: 20 20 20 20 69 66 20 73 65 6c 66 2e 73 57 6f 72      if self.sWor
0860: 64 2e 69 73 74 69 74 6c 65 28 29 3a 0a 20 20 20  d.istitle():.   
0870: 20 20 20 20 20 20 20 20 20 6c 52 65 73 20 3d 20           lRes = 
0880: 6c 69 73 74 28 6d 61 70 28 6c 61 6d 62 64 61 20  list(map(lambda 
0890: 73 53 75 67 67 3a 20 73 53 75 67 67 2e 74 69 74  sSugg: sSugg.tit
08a0: 6c 65 28 29 2c 20 6c 52 65 73 29 29 0a 20 20 20  le(), lRes)).   
08b0: 20 20 20 20 20 65 6c 69 66 20 73 65 6c 66 2e 73       elif self.s
08c0: 57 6f 72 64 2e 69 73 75 70 70 65 72 28 29 3a 0a  Word.isupper():.
08d0: 20 20 20 20 20 20 20 20 20 20 20 20 6c 52 65 73              lRes
08e0: 20 3d 20 6c 69 73 74 28 6d 61 70 28 6c 61 6d 62   = list(map(lamb
08f0: 64 61 20 73 53 75 67 67 3a 20 73 53 75 67 67 2e  da sSugg: sSugg.
0900: 75 70 70 65 72 28 29 2c 20 6c 52 65 73 29 29 0a  upper(), lRes)).
0910: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 6c          return l
0920: 52 65 73 5b 3a 6e 53 75 67 67 4c 69 6d 69 74 5d  Res[:nSuggLimit]
0930: 0a 0a 20 20 20 20 64 65 66 20 72 65 73 65 74 20  ..    def reset 
0940: 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20  (self):.        
0950: 73 65 6c 66 2e 61 53 75 67 67 2e 63 6c 65 61 72  self.aSugg.clear
0960: 28 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e  ().        self.
0970: 64 53 75 67 67 2e 63 6c 65 61 72 28 29 0a 0a 0a  dSugg.clear()...
0980: 63 6c 61 73 73 20 49 42 44 41 57 47 3a 0a 20 20  class IBDAWG:.  
0990: 20 20 22 22 22 49 4e 44 45 58 41 42 4c 45 20 42    """INDEXABLE B
09a0: 49 4e 41 52 59 20 44 49 52 45 43 54 20 41 43 59  INARY DIRECT ACY
09b0: 43 4c 49 43 20 57 4f 52 44 20 47 52 41 50 48 22  CLIC WORD GRAPH"
09c0: 22 22 0a 0a 20 20 20 20 64 65 66 20 5f 5f 69 6e  ""..    def __in
09d0: 69 74 5f 5f 20 28 73 65 6c 66 2c 20 73 66 44 69  it__ (self, sfDi
09e0: 63 74 29 3a 0a 20 20 20 20 20 20 20 20 73 65 6c  ct):.        sel
09f0: 66 2e 62 79 20 3d 20 70 6b 67 75 74 69 6c 2e 67  f.by = pkgutil.g
0a00: 65 74 5f 64 61 74 61 28 5f 5f 70 61 63 6b 61 67  et_data(__packag
0a10: 65 5f 5f 2c 20 22 5f 64 69 63 74 69 6f 6e 61 72  e__, "_dictionar
0a20: 69 65 73 2f 22 20 2b 20 73 66 44 69 63 74 29 0a  ies/" + sfDict).
0a30: 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 73          if not s
0a40: 65 6c 66 2e 62 79 3a 0a 20 20 20 20 20 20 20 20  elf.by:.        
0a50: 20 20 20 20 72 61 69 73 65 20 4f 53 45 72 72 6f      raise OSErro
0a60: 72 28 22 23 20 45 72 72 6f 72 2e 20 46 69 6c 65  r("# Error. File
0a70: 20 6e 6f 74 20 66 6f 75 6e 64 20 6f 72 20 6e 6f   not found or no
0a80: 74 20 6c 6f 61 64 61 62 6c 65 3a 20 22 2b 73 66  t loadable: "+sf
0a90: 44 69 63 74 29 0a 0a 20 20 20 20 20 20 20 20 69  Dict)..        i
0aa0: 66 20 73 66 44 69 63 74 2e 65 6e 64 73 77 69 74  f sfDict.endswit
0ab0: 68 28 22 2e 62 64 69 63 22 29 3a 0a 20 20 20 20  h(".bdic"):.    
0ac0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 69 6e          self._in
0ad0: 69 74 42 69 6e 61 72 79 28 29 0a 20 20 20 20 20  itBinary().     
0ae0: 20 20 20 65 6c 69 66 20 73 66 44 69 63 74 2e 65     elif sfDict.e
0af0: 6e 64 73 77 69 74 68 28 22 2e 6a 73 6f 6e 22 29  ndswith(".json")
0b00: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65  :.            se
0b10: 6c 66 2e 5f 69 6e 69 74 4a 53 4f 4e 28 29 0a 20  lf._initJSON(). 
0b20: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
0b30: 20 20 20 20 20 20 20 20 20 72 61 69 73 65 20 4f           raise O
0b40: 53 45 72 72 6f 72 28 22 23 20 45 72 72 6f 72 2e  SError("# Error.
0b50: 20 55 6e 6b 6e 6f 77 6e 20 66 69 6c 65 20 74 79   Unknown file ty
0b60: 70 65 3a 20 22 2b 73 66 44 69 63 74 29 0a 0a 20  pe: "+sfDict).. 
0b70: 20 20 20 20 20 20 20 73 65 6c 66 2e 73 46 69 6c         self.sFil
0b80: 65 4e 61 6d 65 20 3d 20 73 66 44 69 63 74 0a 0a  eName = sfDict..
0b90: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 61 72          self._ar
0ba0: 63 4d 61 73 6b 20 3d 20 28 32 20 2a 2a 20 28 28  cMask = (2 ** ((
0bb0: 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 20 2a  self.nBytesArc *
0bc0: 20 38 29 20 2d 20 33 29 29 20 2d 20 31 0a 20 20   8) - 3)) - 1.  
0bd0: 20 20 20 20 20 20 73 65 6c 66 2e 5f 66 69 6e 61        self._fina
0be0: 6c 4e 6f 64 65 4d 61 73 6b 20 3d 20 31 20 3c 3c  lNodeMask = 1 <<
0bf0: 20 28 28 73 65 6c 66 2e 6e 42 79 74 65 73 41 72   ((self.nBytesAr
0c00: 63 20 2a 20 38 29 20 2d 20 31 29 0a 20 20 20 20  c * 8) - 1).    
0c10: 20 20 20 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72      self._lastAr
0c20: 63 4d 61 73 6b 20 3d 20 31 20 3c 3c 20 28 28 73  cMask = 1 << ((s
0c30: 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 20 2a 20  elf.nBytesArc * 
0c40: 38 29 20 2d 20 32 29 0a 20 20 20 20 20 20 20 20  8) - 2).        
0c50: 73 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73  self._addrBitMas
0c60: 6b 20 3d 20 31 20 3c 3c 20 28 28 73 65 6c 66 2e  k = 1 << ((self.
0c70: 6e 42 79 74 65 73 41 72 63 20 2a 20 38 29 20 2d  nBytesArc * 8) -
0c80: 20 33 29 20 20 23 20 76 65 72 73 69 6f 6e 20 32   3)  # version 2
0c90: 0a 0a 20 20 20 20 20 20 20 20 23 20 66 75 6e 63  ..        # func
0ca0: 74 69 6f 6e 20 74 6f 20 64 65 63 6f 64 65 20 74  tion to decode t
0cb0: 68 65 20 61 66 66 69 78 2f 73 75 66 66 69 78 20  he affix/suffix 
0cc0: 63 6f 64 65 0a 20 20 20 20 20 20 20 20 69 66 20  code.        if 
0cd0: 73 65 6c 66 2e 63 53 74 65 6d 6d 69 6e 67 20 3d  self.cStemming =
0ce0: 3d 20 22 53 22 3a 0a 20 20 20 20 20 20 20 20 20  = "S":.         
0cf0: 20 20 20 73 65 6c 66 2e 66 75 6e 63 53 74 65 6d     self.funcStem
0d00: 6d 69 6e 67 20 3d 20 73 74 2e 63 68 61 6e 67 65  ming = st.change
0d10: 57 6f 72 64 57 69 74 68 53 75 66 66 69 78 43 6f  WordWithSuffixCo
0d20: 64 65 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20  de.        elif 
0d30: 73 65 6c 66 2e 63 53 74 65 6d 6d 69 6e 67 20 3d  self.cStemming =
0d40: 3d 20 22 41 22 3a 0a 20 20 20 20 20 20 20 20 20  = "A":.         
0d50: 20 20 20 73 65 6c 66 2e 66 75 6e 63 53 74 65 6d     self.funcStem
0d60: 6d 69 6e 67 20 3d 20 73 74 2e 63 68 61 6e 67 65  ming = st.change
0d70: 57 6f 72 64 57 69 74 68 41 66 66 69 78 43 6f 64  WordWithAffixCod
0d80: 65 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a  e.        else:.
0d90: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
0da0: 2e 66 75 6e 63 53 74 65 6d 6d 69 6e 67 20 3d 20  .funcStemming = 
0db0: 73 74 2e 6e 6f 53 74 65 6d 6d 69 6e 67 0a 0a 20  st.noStemming.. 
0dc0: 20 20 20 20 20 20 20 23 20 43 6f 6e 66 69 67 75         # Configu
0dd0: 72 69 6e 67 20 44 41 57 47 20 66 75 6e 63 74 69  ring DAWG functi
0de0: 6f 6e 73 20 61 63 63 6f 72 64 69 6e 67 20 74 6f  ons according to
0df0: 20 6e 43 6f 6d 70 72 65 73 73 69 6f 6e 4d 65 74   nCompressionMet
0e00: 68 6f 64 0a 20 20 20 20 20 20 20 20 69 66 20 73  hod.        if s
0e10: 65 6c 66 2e 6e 43 6f 6d 70 72 65 73 73 69 6f 6e  elf.nCompression
0e20: 4d 65 74 68 6f 64 20 3d 3d 20 31 3a 0a 20 20 20  Method == 1:.   
0e30: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6d 6f           self.mo
0e40: 72 70 68 20 3d 20 73 65 6c 66 2e 5f 6d 6f 72 70  rph = self._morp
0e50: 68 31 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  h1.            s
0e60: 65 6c 66 2e 73 74 65 6d 20 3d 20 73 65 6c 66 2e  elf.stem = self.
0e70: 5f 73 74 65 6d 31 0a 20 20 20 20 20 20 20 20 20  _stem1.         
0e80: 20 20 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41     self._lookupA
0e90: 72 63 4e 6f 64 65 20 3d 20 73 65 6c 66 2e 5f 6c  rcNode = self._l
0ea0: 6f 6f 6b 75 70 41 72 63 4e 6f 64 65 31 0a 20 20  ookupArcNode1.  
0eb0: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f            self._
0ec0: 67 65 74 41 72 63 73 20 3d 20 73 65 6c 66 2e 5f  getArcs = self._
0ed0: 67 65 74 41 72 63 73 31 0a 20 20 20 20 20 20 20  getArcs1.       
0ee0: 20 20 20 20 20 73 65 6c 66 2e 5f 77 72 69 74 65       self._write
0ef0: 4e 6f 64 65 73 20 3d 20 73 65 6c 66 2e 5f 77 72  Nodes = self._wr
0f00: 69 74 65 4e 6f 64 65 73 31 0a 20 20 20 20 20 20  iteNodes1.      
0f10: 20 20 65 6c 69 66 20 73 65 6c 66 2e 6e 43 6f 6d    elif self.nCom
0f20: 70 72 65 73 73 69 6f 6e 4d 65 74 68 6f 64 20 3d  pressionMethod =
0f30: 3d 20 32 3a 0a 20 20 20 20 20 20 20 20 20 20 20  = 2:.           
0f40: 20 73 65 6c 66 2e 6d 6f 72 70 68 20 3d 20 73 65   self.morph = se
0f50: 6c 66 2e 5f 6d 6f 72 70 68 32 0a 20 20 20 20 20  lf._morph2.     
0f60: 20 20 20 20 20 20 20 73 65 6c 66 2e 73 74 65 6d         self.stem
0f70: 20 3d 20 73 65 6c 66 2e 5f 73 74 65 6d 32 0a 20   = self._stem2. 
0f80: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
0f90: 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64 65 20 3d  _lookupArcNode =
0fa0: 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63   self._lookupArc
0fb0: 4e 6f 64 65 32 0a 20 20 20 20 20 20 20 20 20 20  Node2.          
0fc0: 20 20 73 65 6c 66 2e 5f 67 65 74 41 72 63 73 20    self._getArcs 
0fd0: 3d 20 73 65 6c 66 2e 5f 67 65 74 41 72 63 73 32  = self._getArcs2
0fe0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c  .            sel
0ff0: 66 2e 5f 77 72 69 74 65 4e 6f 64 65 73 20 3d 20  f._writeNodes = 
1000: 73 65 6c 66 2e 5f 77 72 69 74 65 4e 6f 64 65 73  self._writeNodes
1010: 32 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 73  2.        elif s
1020: 65 6c 66 2e 6e 43 6f 6d 70 72 65 73 73 69 6f 6e  elf.nCompression
1030: 4d 65 74 68 6f 64 20 3d 3d 20 33 3a 0a 20 20 20  Method == 3:.   
1040: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6d 6f           self.mo
1050: 72 70 68 20 3d 20 73 65 6c 66 2e 5f 6d 6f 72 70  rph = self._morp
1060: 68 33 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  h3.            s
1070: 65 6c 66 2e 73 74 65 6d 20 3d 20 73 65 6c 66 2e  elf.stem = self.
1080: 5f 73 74 65 6d 33 0a 20 20 20 20 20 20 20 20 20  _stem3.         
1090: 20 20 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41     self._lookupA
10a0: 72 63 4e 6f 64 65 20 3d 20 73 65 6c 66 2e 5f 6c  rcNode = self._l
10b0: 6f 6f 6b 75 70 41 72 63 4e 6f 64 65 33 0a 20 20  ookupArcNode3.  
10c0: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f            self._
10d0: 67 65 74 41 72 63 73 20 3d 20 73 65 6c 66 2e 5f  getArcs = self._
10e0: 67 65 74 41 72 63 73 33 0a 20 20 20 20 20 20 20  getArcs3.       
10f0: 20 20 20 20 20 73 65 6c 66 2e 5f 77 72 69 74 65       self._write
1100: 4e 6f 64 65 73 20 3d 20 73 65 6c 66 2e 5f 77 72  Nodes = self._wr
1110: 69 74 65 4e 6f 64 65 73 33 0a 20 20 20 20 20 20  iteNodes3.      
1120: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
1130: 20 20 20 20 72 61 69 73 65 20 56 61 6c 75 65 45      raise ValueE
1140: 72 72 6f 72 28 22 20 20 23 20 45 72 72 6f 72 3a  rror("  # Error:
1150: 20 75 6e 6b 6e 6f 77 6e 20 63 6f 64 65 3a 20 7b   unknown code: {
1160: 7d 22 2e 66 6f 72 6d 61 74 28 73 65 6c 66 2e 6e  }".format(self.n
1170: 43 6f 6d 70 72 65 73 73 69 6f 6e 4d 65 74 68 6f  CompressionMetho
1180: 64 29 29 0a 0a 20 20 20 20 20 20 20 20 73 65 6c  d))..        sel
1190: 66 2e 62 4f 70 74 4e 75 6d 53 69 67 6c 65 20 3d  f.bOptNumSigle =
11a0: 20 46 61 6c 73 65 0a 20 20 20 20 20 20 20 20 73   False.        s
11b0: 65 6c 66 2e 62 4f 70 74 4e 75 6d 41 74 4c 61 73  elf.bOptNumAtLas
11c0: 74 20 3d 20 46 61 6c 73 65 0a 0a 20 20 20 20 64  t = False..    d
11d0: 65 66 20 5f 69 6e 69 74 42 69 6e 61 72 79 20 28  ef _initBinary (
11e0: 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20 20 22  self):.        "
11f0: 69 6e 69 74 69 61 6c 69 7a 65 20 77 69 74 68 20  initialize with 
1200: 62 69 6e 61 72 79 20 73 74 72 75 63 74 75 72 65  binary structure
1210: 20 66 69 6c 65 22 0a 20 20 20 20 20 20 20 20 69   file".        i
1220: 66 20 73 65 6c 66 2e 62 79 5b 30 3a 37 5d 20 21  f self.by[0:7] !
1230: 3d 20 62 22 2f 70 79 66 73 61 2f 22 3a 0a 20 20  = b"/pyfsa/":.  
1240: 20 20 20 20 20 20 20 20 20 20 72 61 69 73 65 20            raise 
1250: 54 79 70 65 45 72 72 6f 72 28 22 23 20 45 72 72  TypeError("# Err
1260: 6f 72 2e 20 4e 6f 74 20 61 20 70 79 66 73 61 20  or. Not a pyfsa 
1270: 62 69 6e 61 72 79 20 64 69 63 74 69 6f 6e 61 72  binary dictionar
1280: 79 2e 20 48 65 61 64 65 72 3a 20 7b 7d 22 2e 66  y. Header: {}".f
1290: 6f 72 6d 61 74 28 73 65 6c 66 2e 62 79 5b 30 3a  ormat(self.by[0:
12a0: 39 5d 29 29 0a 20 20 20 20 20 20 20 20 69 66 20  9])).        if 
12b0: 6e 6f 74 28 73 65 6c 66 2e 62 79 5b 37 3a 38 5d  not(self.by[7:8]
12c0: 20 3d 3d 20 62 22 31 22 20 6f 72 20 73 65 6c 66   == b"1" or self
12d0: 2e 62 79 5b 37 3a 38 5d 20 3d 3d 20 62 22 32 22  .by[7:8] == b"2"
12e0: 20 6f 72 20 73 65 6c 66 2e 62 79 5b 37 3a 38 5d   or self.by[7:8]
12f0: 20 3d 3d 20 62 22 33 22 29 3a 0a 20 20 20 20 20   == b"3"):.     
1300: 20 20 20 20 20 20 20 72 61 69 73 65 20 56 61 6c         raise Val
1310: 75 65 45 72 72 6f 72 28 22 23 20 45 72 72 6f 72  ueError("# Error
1320: 2e 20 55 6e 6b 6e 6f 77 6e 20 64 69 63 74 69 6f  . Unknown dictio
1330: 6e 61 72 79 20 76 65 72 73 69 6f 6e 3a 20 7b 7d  nary version: {}
1340: 22 2e 66 6f 72 6d 61 74 28 73 65 6c 66 2e 62 79  ".format(self.by
1350: 5b 37 3a 38 5d 29 29 0a 20 20 20 20 20 20 20 20  [7:8])).        
1360: 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20  try:.           
1370: 20 68 65 61 64 65 72 2c 20 69 6e 66 6f 2c 20 76   header, info, v
1380: 61 6c 75 65 73 2c 20 62 64 69 63 20 3d 20 73 65  alues, bdic = se
1390: 6c 66 2e 62 79 2e 73 70 6c 69 74 28 62 22 5c 30  lf.by.split(b"\0
13a0: 5c 30 5c 30 5c 30 22 2c 20 33 29 0a 20 20 20 20  \0\0\0", 3).    
13b0: 20 20 20 20 65 78 63 65 70 74 20 45 78 63 65 70      except Excep
13c0: 74 69 6f 6e 3a 0a 20 20 20 20 20 20 20 20 20 20  tion:.          
13d0: 20 20 72 61 69 73 65 20 45 78 63 65 70 74 69 6f    raise Exceptio
13e0: 6e 0a 20 20 20 20 20 20 20 20 0a 20 20 20 20 20  n.        .     
13f0: 20 20 20 73 65 6c 66 2e 6e 43 6f 6d 70 72 65 73     self.nCompres
1400: 73 69 6f 6e 4d 65 74 68 6f 64 20 3d 20 69 6e 74  sionMethod = int
1410: 28 73 65 6c 66 2e 62 79 5b 37 3a 38 5d 2e 64 65  (self.by[7:8].de
1420: 63 6f 64 65 28 22 75 74 66 2d 38 22 29 29 0a 20  code("utf-8")). 
1430: 20 20 20 20 20 20 20 73 65 6c 66 2e 73 48 65 61         self.sHea
1440: 64 65 72 20 3d 20 68 65 61 64 65 72 2e 64 65 63  der = header.dec
1450: 6f 64 65 28 22 75 74 66 2d 38 22 29 0a 20 20 20  ode("utf-8").   
1460: 20 20 20 20 20 73 65 6c 66 2e 6c 41 72 63 56 61       self.lArcVa
1470: 6c 20 3d 20 76 61 6c 75 65 73 2e 64 65 63 6f 64  l = values.decod
1480: 65 28 22 75 74 66 2d 38 22 29 2e 73 70 6c 69 74  e("utf-8").split
1490: 28 22 5c 74 22 29 0a 20 20 20 20 20 20 20 20 73  ("\t").        s
14a0: 65 6c 66 2e 6e 41 72 63 56 61 6c 20 3d 20 6c 65  elf.nArcVal = le
14b0: 6e 28 73 65 6c 66 2e 6c 41 72 63 56 61 6c 29 0a  n(self.lArcVal).
14c0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 62 79 44          self.byD
14d0: 69 63 20 3d 20 62 64 69 63 0a 0a 20 20 20 20 20  ic = bdic..     
14e0: 20 20 20 6c 20 3d 20 69 6e 66 6f 2e 64 65 63 6f     l = info.deco
14f0: 64 65 28 22 75 74 66 2d 38 22 29 2e 73 70 6c 69  de("utf-8").spli
1500: 74 28 22 2f 22 29 0a 20 20 20 20 20 20 20 20 73  t("/").        s
1510: 65 6c 66 2e 73 4c 61 6e 67 43 6f 64 65 20 3d 20  elf.sLangCode = 
1520: 22 78 78 22 0a 20 20 20 20 20 20 20 20 73 65 6c  "xx".        sel
1530: 66 2e 73 4c 61 6e 67 4e 61 6d 65 20 3d 20 6c 5b  f.sLangName = l[
1540: 30 5d 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e  0].        self.
1550: 73 44 69 63 4e 61 6d 65 20 3d 20 22 22 0a 20 20  sDicName = "".  
1560: 20 20 20 20 20 20 73 65 6c 66 2e 6e 43 68 61 72        self.nChar
1570: 20 3d 20 69 6e 74 28 6c 5b 31 5d 29 0a 20 20 20   = int(l[1]).   
1580: 20 20 20 20 20 73 65 6c 66 2e 6e 42 79 74 65 73       self.nBytes
1590: 41 72 63 20 3d 20 69 6e 74 28 6c 5b 32 5d 29 0a  Arc = int(l[2]).
15a0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6e 42 79          self.nBy
15b0: 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 20 3d  tesNodeAddress =
15c0: 20 69 6e 74 28 6c 5b 33 5d 29 0a 20 20 20 20 20   int(l[3]).     
15d0: 20 20 20 73 65 6c 66 2e 6e 45 6e 74 72 79 20 3d     self.nEntry =
15e0: 20 69 6e 74 28 6c 5b 34 5d 29 0a 20 20 20 20 20   int(l[4]).     
15f0: 20 20 20 73 65 6c 66 2e 6e 4e 6f 64 65 20 3d 20     self.nNode = 
1600: 69 6e 74 28 6c 5b 35 5d 29 0a 20 20 20 20 20 20  int(l[5]).      
1610: 20 20 73 65 6c 66 2e 6e 41 72 63 20 3d 20 69 6e    self.nArc = in
1620: 74 28 6c 5b 36 5d 29 0a 20 20 20 20 20 20 20 20  t(l[6]).        
1630: 73 65 6c 66 2e 6e 41 66 66 20 3d 20 69 6e 74 28  self.nAff = int(
1640: 6c 5b 37 5d 29 0a 20 20 20 20 20 20 20 20 73 65  l[7]).        se
1650: 6c 66 2e 63 53 74 65 6d 6d 69 6e 67 20 3d 20 6c  lf.cStemming = l
1660: 5b 38 5d 0a 20 20 20 20 20 20 20 20 73 65 6c 66  [8].        self
1670: 2e 6e 54 61 67 20 3d 20 73 65 6c 66 2e 6e 41 72  .nTag = self.nAr
1680: 63 56 61 6c 20 2d 20 73 65 6c 66 2e 6e 43 68 61  cVal - self.nCha
1690: 72 20 2d 20 73 65 6c 66 2e 6e 41 66 66 0a 20 20  r - self.nAff.  
16a0: 20 20 20 20 20 20 23 20 3c 64 43 68 61 72 3e 20        # <dChar> 
16b0: 74 6f 20 67 65 74 20 74 68 65 20 76 61 6c 75 65  to get the value
16c0: 20 6f 66 20 61 6e 20 61 72 63 2c 20 3c 64 43 68   of an arc, <dCh
16d0: 61 72 56 61 6c 3e 20 74 6f 20 67 65 74 20 74 68  arVal> to get th
16e0: 65 20 63 68 61 72 20 6f 66 20 61 6e 20 61 72 63  e char of an arc
16f0: 20 77 69 74 68 20 69 74 73 20 76 61 6c 75 65 0a   with its value.
1700: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64 43 68          self.dCh
1710: 61 72 20 3d 20 7b 7d 0a 20 20 20 20 20 20 20 20  ar = {}.        
1720: 66 6f 72 20 69 20 69 6e 20 72 61 6e 67 65 28 31  for i in range(1
1730: 2c 20 73 65 6c 66 2e 6e 43 68 61 72 29 3a 0a 20  , self.nChar):. 
1740: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
1750: 64 43 68 61 72 5b 73 65 6c 66 2e 6c 41 72 63 56  dChar[self.lArcV
1760: 61 6c 5b 69 5d 5d 20 3d 20 69 0a 20 20 20 20 20  al[i]] = i.     
1770: 20 20 20 73 65 6c 66 2e 64 43 68 61 72 56 61 6c     self.dCharVal
1780: 20 3d 20 7b 20 76 3a 20 6b 20 20 66 6f 72 20 6b   = { v: k  for k
1790: 2c 20 76 20 69 6e 20 73 65 6c 66 2e 64 43 68 61  , v in self.dCha
17a0: 72 2e 69 74 65 6d 73 28 29 20 7d 0a 20 20 20 20  r.items() }.    
17b0: 20 20 20 20 73 65 6c 66 2e 6e 42 79 74 65 73 4f      self.nBytesO
17c0: 66 66 73 65 74 20 3d 20 31 20 23 20 76 65 72 73  ffset = 1 # vers
17d0: 69 6f 6e 20 33 0a 0a 20 20 20 20 64 65 66 20 5f  ion 3..    def _
17e0: 69 6e 69 74 4a 53 4f 4e 20 28 73 65 6c 66 29 3a  initJSON (self):
17f0: 0a 20 20 20 20 20 20 20 20 22 69 6e 69 74 69 61  .        "initia
1800: 6c 69 7a 65 20 77 69 74 68 20 61 20 4a 53 4f 4e  lize with a JSON
1810: 20 74 65 78 74 20 66 69 6c 65 22 0a 20 20 20 20   text file".    
1820: 20 20 20 20 73 65 6c 66 2e 5f 5f 64 69 63 74 5f      self.__dict_
1830: 5f 2e 75 70 64 61 74 65 28 6a 73 6f 6e 2e 6c 6f  _.update(json.lo
1840: 61 64 73 28 73 65 6c 66 2e 62 79 2e 64 65 63 6f  ads(self.by.deco
1850: 64 65 28 22 75 74 66 2d 38 22 29 29 29 0a 20 20  de("utf-8"))).  
1860: 20 20 20 20 20 20 23 73 65 6c 66 2e 5f 5f 64 69        #self.__di
1870: 63 74 5f 5f 2e 75 70 64 61 74 65 28 6a 73 6f 6e  ct__.update(json
1880: 2e 6c 6f 61 64 73 28 73 65 6c 66 2e 62 79 29 29  .loads(self.by))
1890: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
18a0: 20 20 23 20 49 6e 20 50 79 74 68 6f 6e 20 33 2e    # In Python 3.
18b0: 36 2c 20 63 61 6e 20 72 65 61 64 20 64 69 72 65  6, can read dire
18c0: 63 74 6c 79 20 62 69 6e 61 72 79 20 73 74 72 69  ctly binary stri
18d0: 6e 67 73 0a 0a 20 20 20 20 64 65 66 20 67 65 74  ngs..    def get
18e0: 49 6e 66 6f 20 28 73 65 6c 66 29 3a 0a 20 20 20  Info (self):.   
18f0: 20 20 20 20 20 72 65 74 75 72 6e 20 20 22 20 20       return  "  
1900: 4c 61 6e 67 75 61 67 65 3a 20 7b 30 2e 73 4c 61  Language: {0.sLa
1910: 6e 67 4e 61 6d 65 7d 20 20 20 4c 61 6e 67 20 63  ngName}   Lang c
1920: 6f 64 65 3a 20 7b 30 2e 73 4c 61 6e 67 43 6f 64  ode: {0.sLangCod
1930: 65 7d 20 20 20 44 69 63 74 69 6f 6e 61 72 79 20  e}   Dictionary 
1940: 6e 61 6d 65 3a 20 7b 30 2e 73 44 69 63 4e 61 6d  name: {0.sDicNam
1950: 65 7d 22 20 5c 0a 20 20 20 20 20 20 20 20 20 20  e}" \.          
1960: 20 20 20 20 20 20 22 20 20 43 6f 6d 70 72 65 73        "  Compres
1970: 73 69 6f 6e 20 6d 65 74 68 6f 64 3a 20 7b 30 2e  sion method: {0.
1980: 6e 43 6f 6d 70 72 65 73 73 69 6f 6e 4d 65 74 68  nCompressionMeth
1990: 6f 64 3a 3e 32 7d 20 20 20 44 61 74 65 3a 20 7b  od:>2}   Date: {
19a0: 30 2e 73 44 61 74 65 7d 20 20 20 53 74 65 6d 6d  0.sDate}   Stemm
19b0: 69 6e 67 3a 20 7b 30 2e 63 53 74 65 6d 6d 69 6e  ing: {0.cStemmin
19c0: 67 7d 46 58 5c 6e 22 20 5c 0a 20 20 20 20 20 20  g}FX\n" \.      
19d0: 20 20 20 20 20 20 20 20 20 20 22 20 20 41 72 63            "  Arc
19e0: 73 20 76 61 6c 75 65 73 3a 20 20 7b 30 2e 6e 41  s values:  {0.nA
19f0: 72 63 56 61 6c 3a 3e 31 30 2c 7d 20 3d 20 7b 30  rcVal:>10,} = {0
1a00: 2e 6e 43 68 61 72 3a 3e 35 2c 7d 20 63 68 61 72  .nChar:>5,} char
1a10: 61 63 74 65 72 73 2c 20 20 7b 30 2e 6e 41 66 66  acters,  {0.nAff
1a20: 3a 3e 36 2c 7d 20 61 66 66 69 78 65 73 2c 20 20  :>6,} affixes,  
1a30: 7b 30 2e 6e 54 61 67 3a 3e 36 2c 7d 20 74 61 67  {0.nTag:>6,} tag
1a40: 73 5c 6e 22 20 5c 0a 20 20 20 20 20 20 20 20 20  s\n" \.         
1a50: 20 20 20 20 20 20 20 22 20 20 44 69 63 74 69 6f         "  Dictio
1a60: 6e 61 72 79 3a 20 7b 30 2e 6e 45 6e 74 72 79 3a  nary: {0.nEntry:
1a70: 3e 31 32 2c 7d 20 65 6e 74 72 69 65 73 2c 20 20  >12,} entries,  
1a80: 20 20 7b 30 2e 6e 4e 6f 64 65 3a 3e 31 31 2c 7d    {0.nNode:>11,}
1a90: 20 6e 6f 64 65 73 2c 20 20 20 7b 30 2e 6e 41 72   nodes,   {0.nAr
1aa0: 63 3a 3e 31 31 2c 7d 20 61 72 63 73 5c 6e 22 20  c:>11,} arcs\n" 
1ab0: 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  \.              
1ac0: 20 20 22 20 20 41 64 64 72 65 73 73 20 73 69 7a    "  Address siz
1ad0: 65 3a 20 7b 30 2e 6e 42 79 74 65 73 4e 6f 64 65  e: {0.nBytesNode
1ae0: 41 64 64 72 65 73 73 3a 3e 31 7d 20 62 79 74 65  Address:>1} byte
1af0: 73 2c 20 20 41 72 63 20 73 69 7a 65 3a 20 7b 30  s,  Arc size: {0
1b00: 2e 6e 42 79 74 65 73 41 72 63 3a 3e 31 7d 20 62  .nBytesArc:>1} b
1b10: 79 74 65 73 5c 6e 22 2e 66 6f 72 6d 61 74 28 73  ytes\n".format(s
1b20: 65 6c 66 29 0a 0a 20 20 20 20 64 65 66 20 77 72  elf)..    def wr
1b30: 69 74 65 41 73 4a 53 4f 62 6a 65 63 74 20 28 73  iteAsJSObject (s
1b40: 65 6c 66 2c 20 73 70 66 44 65 73 74 2c 20 62 49  elf, spfDest, bI
1b50: 6e 4a 53 4d 6f 64 75 6c 65 3d 46 61 6c 73 65 2c  nJSModule=False,
1b60: 20 62 42 69 6e 61 72 79 44 69 63 74 41 73 48 65   bBinaryDictAsHe
1b70: 78 53 74 72 69 6e 67 3d 46 61 6c 73 65 29 3a 0a  xString=False):.
1b80: 20 20 20 20 20 20 20 20 22 77 72 69 74 65 20 49          "write I
1b90: 42 44 41 57 47 20 61 73 20 61 20 4a 61 76 61 53  BDAWG as a JavaS
1ba0: 63 72 69 70 74 20 6f 62 6a 65 63 74 20 69 6e 20  cript object in 
1bb0: 61 20 4a 61 76 61 53 63 72 69 70 74 20 6d 6f 64  a JavaScript mod
1bc0: 75 6c 65 22 0a 20 20 20 20 20 20 20 20 77 69 74  ule".        wit
1bd0: 68 20 6f 70 65 6e 28 73 70 66 44 65 73 74 2c 20  h open(spfDest, 
1be0: 22 77 22 2c 20 65 6e 63 6f 64 69 6e 67 3d 22 75  "w", encoding="u
1bf0: 74 66 2d 38 22 2c 20 6e 65 77 6c 69 6e 65 3d 22  tf-8", newline="
1c00: 5c 6e 22 29 20 61 73 20 68 44 73 74 3a 0a 20 20  \n") as hDst:.  
1c10: 20 20 20 20 20 20 20 20 20 20 69 66 20 62 49 6e            if bIn
1c20: 4a 53 4d 6f 64 75 6c 65 3a 0a 20 20 20 20 20 20  JSModule:.      
1c30: 20 20 20 20 20 20 20 20 20 20 68 44 73 74 2e 77            hDst.w
1c40: 72 69 74 65 28 27 2f 2f 20 4a 61 76 61 53 63 72  rite('// JavaScr
1c50: 69 70 74 5c 6e 2f 2f 20 47 65 6e 65 72 61 74 65  ipt\n// Generate
1c60: 64 20 64 61 74 61 20 28 64 6f 20 6e 6f 74 20 65  d data (do not e
1c70: 64 69 74 29 5c 6e 5c 6e 22 75 73 65 20 73 74 72  dit)\n\n"use str
1c80: 69 63 74 22 3b 5c 6e 5c 6e 63 6f 6e 73 74 20 64  ict";\n\nconst d
1c90: 69 63 74 69 6f 6e 61 72 79 20 3d 20 27 29 0a 20  ictionary = '). 
1ca0: 20 20 20 20 20 20 20 20 20 20 20 68 44 73 74 2e             hDst.
1cb0: 77 72 69 74 65 28 6a 73 6f 6e 2e 64 75 6d 70 73  write(json.dumps
1cc0: 28 7b 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ({.             
1cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22                 "
1ce0: 73 48 65 61 64 65 72 22 3a 20 22 2f 70 79 66 73  sHeader": "/pyfs
1cf0: 61 2f 22 2c 0a 20 20 20 20 20 20 20 20 20 20 20  a/",.           
1d00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d10: 20 22 73 4c 61 6e 67 43 6f 64 65 22 3a 20 73 65   "sLangCode": se
1d20: 6c 66 2e 73 4c 61 6e 67 43 6f 64 65 2c 0a 20 20  lf.sLangCode,.  
1d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d40: 20 20 20 20 20 20 20 20 20 20 22 73 4c 61 6e 67            "sLang
1d50: 4e 61 6d 65 22 3a 20 73 65 6c 66 2e 73 4c 61 6e  Name": self.sLan
1d60: 67 4e 61 6d 65 2c 0a 20 20 20 20 20 20 20 20 20  gName,.         
1d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d80: 20 20 20 22 73 44 69 63 4e 61 6d 65 22 3a 20 73     "sDicName": s
1d90: 65 6c 66 2e 73 44 69 63 4e 61 6d 65 2c 0a 20 20  elf.sDicName,.  
1da0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1db0: 20 20 20 20 20 20 20 20 20 20 22 73 46 69 6c 65            "sFile
1dc0: 4e 61 6d 65 22 3a 20 73 65 6c 66 2e 73 46 69 6c  Name": self.sFil
1dd0: 65 4e 61 6d 65 2c 0a 20 20 20 20 20 20 20 20 20  eName,.         
1de0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1df0: 20 20 20 22 73 44 61 74 65 22 3a 20 73 74 72 28     "sDate": str(
1e00: 64 61 74 65 74 69 6d 65 2e 64 61 74 65 74 69 6d  datetime.datetim
1e10: 65 2e 6e 6f 77 28 29 29 5b 3a 2d 37 5d 2c 0a 20  e.now())[:-7],. 
1e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e30: 20 20 20 20 20 20 20 20 20 20 20 22 6e 45 6e 74             "nEnt
1e40: 72 79 22 3a 20 73 65 6c 66 2e 6e 45 6e 74 72 79  ry": self.nEntry
1e50: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
1e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 6e                "n
1e70: 43 68 61 72 22 3a 20 73 65 6c 66 2e 6e 43 68 61  Char": self.nCha
1e80: 72 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r,.             
1e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22                 "
1ea0: 6e 41 66 66 22 3a 20 73 65 6c 66 2e 6e 41 66 66  nAff": self.nAff
1eb0: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
1ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 6e                "n
1ed0: 54 61 67 22 3a 20 73 65 6c 66 2e 6e 54 61 67 2c  Tag": self.nTag,
1ee0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1ef0: 20 20 20 20 20 20 20 20 20 20 20 20 20 22 63 53               "cS
1f00: 74 65 6d 6d 69 6e 67 22 3a 20 73 65 6c 66 2e 63  temming": self.c
1f10: 53 74 65 6d 6d 69 6e 67 2c 0a 20 20 20 20 20 20  Stemming,.      
1f20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f30: 20 20 20 20 20 20 22 64 43 68 61 72 22 3a 20 73        "dChar": s
1f40: 65 6c 66 2e 64 43 68 61 72 2c 0a 20 20 20 20 20  elf.dChar,.     
1f50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f60: 20 20 20 20 20 20 20 22 6e 4e 6f 64 65 22 3a 20         "nNode": 
1f70: 73 65 6c 66 2e 6e 4e 6f 64 65 2c 0a 20 20 20 20  self.nNode,.    
1f80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f90: 20 20 20 20 20 20 20 20 22 6e 41 72 63 22 3a 20          "nArc": 
1fa0: 73 65 6c 66 2e 6e 41 72 63 2c 0a 20 20 20 20 20  self.nArc,.     
1fb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1fc0: 20 20 20 20 20 20 20 22 6e 41 72 63 56 61 6c 22         "nArcVal"
1fd0: 3a 20 73 65 6c 66 2e 6e 41 72 63 56 61 6c 2c 0a  : self.nArcVal,.
1fe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ff0: 20 20 20 20 20 20 20 20 20 20 20 20 22 6c 41 72              "lAr
2000: 63 56 61 6c 22 3a 20 73 65 6c 66 2e 6c 41 72 63  cVal": self.lArc
2010: 56 61 6c 2c 0a 20 20 20 20 20 20 20 20 20 20 20  Val,.           
2020: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2030: 20 22 6e 43 6f 6d 70 72 65 73 73 69 6f 6e 4d 65   "nCompressionMe
2040: 74 68 6f 64 22 3a 20 73 65 6c 66 2e 6e 43 6f 6d  thod": self.nCom
2050: 70 72 65 73 73 69 6f 6e 4d 65 74 68 6f 64 2c 0a  pressionMethod,.
2060: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2070: 20 20 20 20 20 20 20 20 20 20 20 20 22 6e 42 79              "nBy
2080: 74 65 73 41 72 63 22 3a 20 73 65 6c 66 2e 6e 42  tesArc": self.nB
2090: 79 74 65 73 41 72 63 2c 0a 20 20 20 20 20 20 20  ytesArc,.       
20a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
20b0: 20 20 20 20 20 22 6e 42 79 74 65 73 4e 6f 64 65       "nBytesNode
20c0: 41 64 64 72 65 73 73 22 3a 20 73 65 6c 66 2e 6e  Address": self.n
20d0: 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73  BytesNodeAddress
20e0: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
20f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 6e                "n
2100: 42 79 74 65 73 4f 66 66 73 65 74 22 3a 20 73 65  BytesOffset": se
2110: 6c 66 2e 6e 42 79 74 65 73 4f 66 66 73 65 74 2c  lf.nBytesOffset,
2120: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
2130: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 4a               # J
2140: 61 76 61 53 63 72 69 70 74 20 69 73 20 61 20 70  avaScript is a p
2150: 69 6c 65 20 6f 66 20 73 68 69 74 2c 20 73 6f 20  ile of shit, so 
2160: 4d 6f 7a 69 6c 6c 61 e2 80 99 73 20 4a 53 20 70  Mozilla...s JS p
2170: 61 72 73 65 72 20 64 6f 6e e2 80 99 74 20 6c 69  arser don...t li
2180: 6b 65 20 66 69 6c 65 20 62 69 67 67 65 72 20 74  ke file bigger t
2190: 68 61 6e 20 34 20 4d 62 21 0a 20 20 20 20 20 20  han 4 Mb!.      
21a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
21b0: 20 20 20 20 20 20 23 20 53 6f 2c 20 69 66 20 6e        # So, if n
21c0: 65 63 65 73 73 61 72 79 2c 20 77 65 20 75 73 65  ecessary, we use
21d0: 20 61 6e 20 68 65 78 61 64 65 63 69 6d 61 6c 20   an hexadecimal 
21e0: 73 74 72 69 6e 67 2c 20 74 68 61 74 20 77 65 20  string, that we 
21f0: 77 69 6c 6c 20 63 6f 6e 76 65 72 74 20 6c 61 74  will convert lat
2200: 65 72 20 69 6e 20 46 69 72 65 66 6f 78 e2 80 99  er in Firefox...
2210: 73 20 65 78 74 65 6e 73 69 6f 6e 2e 0a 20 20 20  s extension..   
2220: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2230: 20 20 20 20 20 20 20 20 20 23 20 68 74 74 70 73           # https
2240: 3a 2f 2f 67 69 74 68 75 62 2e 63 6f 6d 2f 6d 6f  ://github.com/mo
2250: 7a 69 6c 6c 61 2f 61 64 64 6f 6e 73 2d 6c 69 6e  zilla/addons-lin
2260: 74 65 72 2f 69 73 73 75 65 73 2f 31 33 36 31 0a  ter/issues/1361.
2270: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2280: 20 20 20 20 20 20 20 20 20 20 20 20 22 73 42 79              "sBy
2290: 44 69 63 22 3a 20 73 65 6c 66 2e 62 79 44 69 63  Dic": self.byDic
22a0: 2e 68 65 78 28 29 20 20 69 66 20 62 42 69 6e 61  .hex()  if bBina
22b0: 72 79 44 69 63 74 41 73 48 65 78 53 74 72 69 6e  ryDictAsHexStrin
22c0: 67 20 20 65 6c 73 65 20 5b 20 65 20 20 66 6f 72  g  else [ e  for
22d0: 20 65 20 69 6e 20 73 65 6c 66 2e 62 79 44 69 63   e in self.byDic
22e0: 20 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   ].             
22f0: 20 20 20 20 20 20 20 20 20 20 20 7d 2c 20 65 6e             }, en
2300: 73 75 72 65 5f 61 73 63 69 69 3d 46 61 6c 73 65  sure_ascii=False
2310: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  )).            i
2320: 66 20 62 49 6e 4a 53 4d 6f 64 75 6c 65 3a 0a 20  f bInJSModule:. 
2330: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 68                 h
2340: 44 73 74 2e 77 72 69 74 65 28 22 3b 5c 6e 5c 6e  Dst.write(";\n\n
2350: 65 78 70 6f 72 74 73 2e 64 69 63 74 69 6f 6e 61  exports.dictiona
2360: 72 79 20 3d 20 64 69 63 74 69 6f 6e 61 72 79 3b  ry = dictionary;
2370: 5c 6e 22 29 0a 0a 20 20 20 20 64 65 66 20 69 73  \n")..    def is
2380: 56 61 6c 69 64 54 6f 6b 65 6e 20 28 73 65 6c 66  ValidToken (self
2390: 2c 20 73 54 6f 6b 65 6e 29 3a 0a 20 20 20 20 20  , sToken):.     
23a0: 20 20 20 22 63 68 65 63 6b 73 20 69 66 20 3c 73     "checks if <s
23b0: 54 6f 6b 65 6e 3e 20 69 73 20 76 61 6c 69 64 20  Token> is valid 
23c0: 28 69 66 20 74 68 65 72 65 20 69 73 20 68 79 70  (if there is hyp
23d0: 68 65 6e 73 20 69 6e 20 3c 73 54 6f 6b 65 6e 3e  hens in <sToken>
23e0: 2c 20 3c 73 54 6f 6b 65 6e 3e 20 69 73 20 73 70  , <sToken> is sp
23f0: 6c 69 74 2c 20 65 61 63 68 20 70 61 72 74 20 69  lit, each part i
2400: 73 20 63 68 65 63 6b 65 64 29 22 0a 20 20 20 20  s checked)".    
2410: 20 20 20 20 69 66 20 73 65 6c 66 2e 69 73 56 61      if self.isVa
2420: 6c 69 64 28 73 54 6f 6b 65 6e 29 3a 0a 20 20 20  lid(sToken):.   
2430: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
2440: 54 72 75 65 0a 20 20 20 20 20 20 20 20 69 66 20  True.        if 
2450: 22 2d 22 20 69 6e 20 73 54 6f 6b 65 6e 3a 0a 20  "-" in sToken:. 
2460: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73 54             if sT
2470: 6f 6b 65 6e 2e 63 6f 75 6e 74 28 22 2d 22 29 20  oken.count("-") 
2480: 3e 20 34 3a 0a 20 20 20 20 20 20 20 20 20 20 20  > 4:.           
2490: 20 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65       return True
24a0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
24b0: 75 72 6e 20 61 6c 6c 28 73 65 6c 66 2e 69 73 56  urn all(self.isV
24c0: 61 6c 69 64 28 73 57 6f 72 64 29 20 20 66 6f 72  alid(sWord)  for
24d0: 20 73 57 6f 72 64 20 69 6e 20 73 54 6f 6b 65 6e   sWord in sToken
24e0: 2e 73 70 6c 69 74 28 22 2d 22 29 29 0a 20 20 20  .split("-")).   
24f0: 20 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73       return Fals
2500: 65 0a 0a 20 20 20 20 64 65 66 20 69 73 56 61 6c  e..    def isVal
2510: 69 64 20 28 73 65 6c 66 2c 20 73 57 6f 72 64 29  id (self, sWord)
2520: 3a 0a 20 20 20 20 20 20 20 20 22 63 68 65 63 6b  :.        "check
2530: 73 20 69 66 20 3c 73 57 6f 72 64 3e 20 69 73 20  s if <sWord> is 
2540: 76 61 6c 69 64 20 28 64 69 66 66 65 72 65 6e 74  valid (different
2550: 20 63 61 73 69 6e 67 20 74 65 73 74 65 64 20 69   casing tested i
2560: 66 20 74 68 65 20 66 69 72 73 74 20 6c 65 74 74  f the first lett
2570: 65 72 20 69 73 20 61 20 63 61 70 69 74 61 6c 29  er is a capital)
2580: 22 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74  ".        if not
2590: 20 73 57 6f 72 64 3a 0a 20 20 20 20 20 20 20 20   sWord:.        
25a0: 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e 65 0a      return None.
25b0: 20 20 20 20 20 20 20 20 69 66 20 22 e2 80 99 22          if "..."
25c0: 20 69 6e 20 73 57 6f 72 64 3a 20 23 20 75 67 6c   in sWord: # ugl
25d0: 79 20 68 61 63 6b 0a 20 20 20 20 20 20 20 20 20  y hack.         
25e0: 20 20 20 73 57 6f 72 64 20 3d 20 73 57 6f 72 64     sWord = sWord
25f0: 2e 72 65 70 6c 61 63 65 28 22 e2 80 99 22 2c 20  .replace("...", 
2600: 22 27 22 29 0a 20 20 20 20 20 20 20 20 69 66 20  "'").        if 
2610: 73 65 6c 66 2e 6c 6f 6f 6b 75 70 28 73 57 6f 72  self.lookup(sWor
2620: 64 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  d):.            
2630: 72 65 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20  return True.    
2640: 20 20 20 20 69 66 20 73 57 6f 72 64 5b 30 3a 31      if sWord[0:1
2650: 5d 2e 69 73 75 70 70 65 72 28 29 3a 0a 20 20 20  ].isupper():.   
2660: 20 20 20 20 20 20 20 20 20 69 66 20 6c 65 6e 28           if len(
2670: 73 57 6f 72 64 29 20 3e 20 31 3a 0a 20 20 20 20  sWord) > 1:.    
2680: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73              if s
2690: 57 6f 72 64 2e 69 73 74 69 74 6c 65 28 29 3a 0a  Word.istitle():.
26a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
26b0: 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e      return self.
26c0: 6c 6f 6f 6b 75 70 28 73 57 6f 72 64 2e 6c 6f 77  lookup(sWord.low
26d0: 65 72 28 29 29 0a 20 20 20 20 20 20 20 20 20 20  er()).          
26e0: 20 20 20 20 20 20 69 66 20 73 57 6f 72 64 2e 69        if sWord.i
26f0: 73 75 70 70 65 72 28 29 3a 0a 20 20 20 20 20 20  supper():.      
2700: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
2710: 20 73 65 6c 66 2e 62 4f 70 74 4e 75 6d 53 69 67   self.bOptNumSig
2720: 6c 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  le:.            
2730: 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
2740: 72 6e 20 54 72 75 65 0a 20 20 20 20 20 20 20 20  rn True.        
2750: 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
2760: 72 6e 20 73 65 6c 66 2e 6c 6f 6f 6b 75 70 28 73  rn self.lookup(s
2770: 57 6f 72 64 2e 6c 6f 77 65 72 28 29 29 20 6f 72  Word.lower()) or
2780: 20 73 65 6c 66 2e 6c 6f 6f 6b 75 70 28 73 57 6f   self.lookup(sWo
2790: 72 64 2e 63 61 70 69 74 61 6c 69 7a 65 28 29 29  rd.capitalize())
27a0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
27b0: 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 6c 6f 6f   return self.loo
27c0: 6b 75 70 28 73 57 6f 72 64 5b 3a 31 5d 2e 6c 6f  kup(sWord[:1].lo
27d0: 77 65 72 28 29 20 2b 20 73 57 6f 72 64 5b 31 3a  wer() + sWord[1:
27e0: 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 65  ]).            e
27f0: 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  lse:.           
2800: 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66       return self
2810: 2e 6c 6f 6f 6b 75 70 28 73 57 6f 72 64 2e 6c 6f  .lookup(sWord.lo
2820: 77 65 72 28 29 29 0a 20 20 20 20 20 20 20 20 72  wer()).        r
2830: 65 74 75 72 6e 20 46 61 6c 73 65 0a 0a 20 20 20  eturn False..   
2840: 20 64 65 66 20 6c 6f 6f 6b 75 70 20 28 73 65 6c   def lookup (sel
2850: 66 2c 20 73 57 6f 72 64 29 3a 0a 20 20 20 20 20  f, sWord):.     
2860: 20 20 20 22 72 65 74 75 72 6e 73 20 54 72 75 65     "returns True
2870: 20 69 66 20 3c 73 57 6f 72 64 3e 20 69 6e 20 64   if <sWord> in d
2880: 69 63 74 69 6f 6e 61 72 79 20 28 73 74 72 69 63  ictionary (stric
2890: 74 20 76 65 72 69 66 69 63 61 74 69 6f 6e 29 22  t verification)"
28a0: 0a 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d  .        iAddr =
28b0: 20 30 0a 20 20 20 20 20 20 20 20 66 6f 72 20 63   0.        for c
28c0: 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20 20 20 20   in sWord:.     
28d0: 20 20 20 20 20 20 20 69 66 20 63 20 6e 6f 74 20         if c not 
28e0: 69 6e 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a 20  in self.dChar:. 
28f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72                 r
2900: 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20  eturn False.    
2910: 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20          iAddr = 
2920: 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e  self._lookupArcN
2930: 6f 64 65 28 73 65 6c 66 2e 64 43 68 61 72 5b 63  ode(self.dChar[c
2940: 5d 2c 20 69 41 64 64 72 29 0a 20 20 20 20 20 20  ], iAddr).      
2950: 20 20 20 20 20 20 69 66 20 69 41 64 64 72 20 3d        if iAddr =
2960: 3d 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20  = None:.        
2970: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 46          return F
2980: 61 6c 73 65 0a 20 20 20 20 20 20 20 20 72 65 74  alse.        ret
2990: 75 72 6e 20 62 6f 6f 6c 28 69 6e 74 2e 66 72 6f  urn bool(int.fro
29a0: 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44  m_bytes(self.byD
29b0: 69 63 5b 69 41 64 64 72 3a 69 41 64 64 72 2b 73  ic[iAddr:iAddr+s
29c0: 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20  elf.nBytesArc], 
29d0: 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29  byteorder='big')
29e0: 20 26 20 73 65 6c 66 2e 5f 66 69 6e 61 6c 4e 6f   & self._finalNo
29f0: 64 65 4d 61 73 6b 29 0a 0a 20 20 20 20 64 65 66  deMask)..    def
2a00: 20 67 65 74 4d 6f 72 70 68 20 28 73 65 6c 66 2c   getMorph (self,
2a10: 20 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20 20   sWord):.       
2a20: 20 22 72 65 74 72 69 65 76 65 73 20 6d 6f 72 70   "retrieves morp
2a30: 68 6f 6c 6f 67 69 65 73 20 6c 69 73 74 2c 20 64  hologies list, d
2a40: 69 66 66 65 72 65 6e 74 20 63 61 73 69 6e 67 20  ifferent casing 
2a50: 61 6c 6c 6f 77 65 64 22 0a 20 20 20 20 20 20 20  allowed".       
2a60: 20 6c 20 3d 20 73 65 6c 66 2e 6d 6f 72 70 68 28   l = self.morph(
2a70: 73 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20 69  sWord).        i
2a80: 66 20 73 57 6f 72 64 5b 30 3a 31 5d 2e 69 73 75  f sWord[0:1].isu
2a90: 70 70 65 72 28 29 3a 0a 20 20 20 20 20 20 20 20  pper():.        
2aa0: 20 20 20 20 6c 2e 65 78 74 65 6e 64 28 73 65 6c      l.extend(sel
2ab0: 66 2e 6d 6f 72 70 68 28 73 57 6f 72 64 2e 6c 6f  f.morph(sWord.lo
2ac0: 77 65 72 28 29 29 29 0a 20 20 20 20 20 20 20 20  wer())).        
2ad0: 20 20 20 20 69 66 20 73 57 6f 72 64 2e 69 73 75      if sWord.isu
2ae0: 70 70 65 72 28 29 20 61 6e 64 20 6c 65 6e 28 73  pper() and len(s
2af0: 57 6f 72 64 29 20 3e 20 31 3a 0a 20 20 20 20 20  Word) > 1:.     
2b00: 20 20 20 20 20 20 20 20 20 20 20 6c 2e 65 78 74             l.ext
2b10: 65 6e 64 28 73 65 6c 66 2e 6d 6f 72 70 68 28 73  end(self.morph(s
2b20: 57 6f 72 64 2e 63 61 70 69 74 61 6c 69 7a 65 28  Word.capitalize(
2b30: 29 29 29 0a 20 20 20 20 20 20 20 20 72 65 74 75  ))).        retu
2b40: 72 6e 20 6c 0a 0a 20 20 20 20 23 40 74 69 6d 65  rn l..    #@time
2b50: 74 68 69 73 0a 20 20 20 20 64 65 66 20 73 75 67  this.    def sug
2b60: 67 65 73 74 20 28 73 65 6c 66 2c 20 73 57 6f 72  gest (self, sWor
2b70: 64 2c 20 6e 53 75 67 67 4c 69 6d 69 74 3d 31 30  d, nSuggLimit=10
2b80: 29 3a 0a 20 20 20 20 20 20 20 20 22 72 65 74 75  ):.        "retu
2b90: 72 6e 73 20 61 20 73 65 74 20 6f 66 20 73 75 67  rns a set of sug
2ba0: 67 65 73 74 69 6f 6e 73 20 66 6f 72 20 3c 73 57  gestions for <sW
2bb0: 6f 72 64 3e 22 0a 20 20 20 20 20 20 20 20 73 50  ord>".        sP
2bc0: 66 78 2c 20 73 57 6f 72 64 2c 20 73 53 66 78 20  fx, sWord, sSfx 
2bd0: 3d 20 63 70 2e 63 75 74 28 73 57 6f 72 64 29 0a  = cp.cut(sWord).
2be0: 20 20 20 20 20 20 20 20 6e 4d 61 78 53 77 69 74          nMaxSwit
2bf0: 63 68 20 3d 20 6d 61 78 28 6c 65 6e 28 73 57 6f  ch = max(len(sWo
2c00: 72 64 29 20 2f 2f 20 33 2c 20 31 29 0a 20 20 20  rd) // 3, 1).   
2c10: 20 20 20 20 20 6e 4d 61 78 44 65 6c 20 3d 20 6c       nMaxDel = l
2c20: 65 6e 28 73 57 6f 72 64 29 20 2f 2f 20 35 0a 20  en(sWord) // 5. 
2c30: 20 20 20 20 20 20 20 6e 4d 61 78 48 61 72 64 52         nMaxHardR
2c40: 65 70 6c 20 3d 20 6d 61 78 28 28 6c 65 6e 28 73  epl = max((len(s
2c50: 57 6f 72 64 29 20 2d 20 35 29 20 2f 2f 20 34 2c  Word) - 5) // 4,
2c60: 20 31 29 0a 20 20 20 20 20 20 20 20 6f 53 75 67   1).        oSug
2c70: 67 52 65 73 75 6c 74 20 3d 20 53 75 67 67 52 65  gResult = SuggRe
2c80: 73 75 6c 74 28 73 57 6f 72 64 29 0a 20 20 20 20  sult(sWord).    
2c90: 20 20 20 20 73 65 6c 66 2e 5f 73 75 67 67 65 73      self._sugges
2ca0: 74 28 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 73  t(oSuggResult, s
2cb0: 57 6f 72 64 2c 20 6e 4d 61 78 53 77 69 74 63 68  Word, nMaxSwitch
2cc0: 3d 6e 4d 61 78 53 77 69 74 63 68 2c 20 6e 4d 61  =nMaxSwitch, nMa
2cd0: 78 44 65 6c 3d 6e 4d 61 78 44 65 6c 2c 20 6e 4d  xDel=nMaxDel, nM
2ce0: 61 78 48 61 72 64 52 65 70 6c 3d 6e 4d 61 78 48  axHardRepl=nMaxH
2cf0: 61 72 64 52 65 70 6c 29 0a 20 20 20 20 20 20 20  ardRepl).       
2d00: 20 69 66 20 73 57 6f 72 64 2e 69 73 74 69 74 6c   if sWord.istitl
2d10: 65 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  e():.           
2d20: 20 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28 6f   self._suggest(o
2d30: 53 75 67 67 52 65 73 75 6c 74 2c 20 73 57 6f 72  SuggResult, sWor
2d40: 64 2e 6c 6f 77 65 72 28 29 2c 20 6e 4d 61 78 53  d.lower(), nMaxS
2d50: 77 69 74 63 68 3d 6e 4d 61 78 53 77 69 74 63 68  witch=nMaxSwitch
2d60: 2c 20 6e 4d 61 78 44 65 6c 3d 6e 4d 61 78 44 65  , nMaxDel=nMaxDe
2d70: 6c 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 3d  l, nMaxHardRepl=
2d80: 6e 4d 61 78 48 61 72 64 52 65 70 6c 29 0a 20 20  nMaxHardRepl).  
2d90: 20 20 20 20 20 20 65 6c 69 66 20 73 57 6f 72 64        elif sWord
2da0: 2e 69 73 6c 6f 77 65 72 28 29 3a 0a 20 20 20 20  .islower():.    
2db0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73 75          self._su
2dc0: 67 67 65 73 74 28 6f 53 75 67 67 52 65 73 75 6c  ggest(oSuggResul
2dd0: 74 2c 20 73 57 6f 72 64 2e 74 69 74 6c 65 28 29  t, sWord.title()
2de0: 2c 20 6e 4d 61 78 53 77 69 74 63 68 3d 6e 4d 61  , nMaxSwitch=nMa
2df0: 78 53 77 69 74 63 68 2c 20 6e 4d 61 78 44 65 6c  xSwitch, nMaxDel
2e00: 3d 6e 4d 61 78 44 65 6c 2c 20 6e 4d 61 78 48 61  =nMaxDel, nMaxHa
2e10: 72 64 52 65 70 6c 3d 6e 4d 61 78 48 61 72 64 52  rdRepl=nMaxHardR
2e20: 65 70 6c 29 0a 20 20 20 20 20 20 20 20 61 53 75  epl).        aSu
2e30: 67 67 20 3d 20 6f 53 75 67 67 52 65 73 75 6c 74  gg = oSuggResult
2e40: 2e 67 65 74 53 75 67 67 65 73 74 69 6f 6e 73 28  .getSuggestions(
2e50: 6e 53 75 67 67 4c 69 6d 69 74 29 0a 20 20 20 20  nSuggLimit).    
2e60: 20 20 20 20 69 66 20 73 53 66 78 20 6f 72 20 73      if sSfx or s
2e70: 50 66 78 3a 0a 20 20 20 20 20 20 20 20 20 20 20  Pfx:.           
2e80: 20 23 20 77 65 20 61 64 64 20 77 68 61 74 20 77   # we add what w
2e90: 65 20 72 65 6d 6f 76 65 64 0a 20 20 20 20 20 20  e removed.      
2ea0: 20 20 20 20 20 20 72 65 74 75 72 6e 20 6c 69 73        return lis
2eb0: 74 28 6d 61 70 28 6c 61 6d 62 64 61 20 73 53 75  t(map(lambda sSu
2ec0: 67 3a 20 73 50 66 78 20 2b 20 73 53 75 67 20 2b  g: sPfx + sSug +
2ed0: 20 73 53 66 78 2c 20 61 53 75 67 67 29 29 0a 20   sSfx, aSugg)). 
2ee0: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 61 53         return aS
2ef0: 75 67 67 0a 0a 20 20 20 20 64 65 66 20 5f 73 75  ugg..    def _su
2f00: 67 67 65 73 74 20 28 73 65 6c 66 2c 20 6f 53 75  ggest (self, oSu
2f10: 67 67 52 65 73 75 6c 74 2c 20 73 52 65 6d 61 69  ggResult, sRemai
2f20: 6e 2c 20 6e 4d 61 78 53 77 69 74 63 68 3d 30 2c  n, nMaxSwitch=0,
2f30: 20 6e 4d 61 78 44 65 6c 3d 30 2c 20 6e 4d 61 78   nMaxDel=0, nMax
2f40: 48 61 72 64 52 65 70 6c 3d 30 2c 20 6e 44 65 65  HardRepl=0, nDee
2f50: 70 3d 30 2c 20 69 41 64 64 72 3d 30 2c 20 73 4e  p=0, iAddr=0, sN
2f60: 65 77 57 6f 72 64 3d 22 22 2c 20 62 41 76 6f 69  ewWord="", bAvoi
2f70: 64 4c 6f 6f 70 3d 46 61 6c 73 65 29 3a 0a 20 20  dLoop=False):.  
2f80: 20 20 20 20 20 20 23 20 72 65 63 75 72 73 69 76        # recursiv
2f90: 65 20 66 75 6e 63 74 69 6f 6e 0a 20 20 20 20 20  e function.     
2fa0: 20 20 20 23 6c 6f 67 67 69 6e 67 2e 69 6e 66 6f     #logging.info
2fb0: 28 28 6e 44 65 65 70 20 2a 20 22 20 20 22 29 20  ((nDeep * "  ") 
2fc0: 2b 20 73 4e 65 77 57 6f 72 64 20 2b 20 22 3a 22  + sNewWord + ":"
2fd0: 20 2b 20 73 52 65 6d 61 69 6e 29 0a 20 20 20 20   + sRemain).    
2fe0: 20 20 20 20 69 66 20 6e 6f 74 20 73 52 65 6d 61      if not sRema
2ff0: 69 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  in:.            
3000: 69 66 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65  if int.from_byte
3010: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64  s(self.byDic[iAd
3020: 64 72 3a 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dr:iAddr+self.nB
3030: 79 74 65 73 41 72 63 5d 2c 20 62 79 74 65 6f 72  ytesArc], byteor
3040: 64 65 72 3d 27 62 69 67 27 29 20 26 20 73 65 6c  der='big') & sel
3050: 66 2e 5f 66 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b  f._finalNodeMask
3060: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
3070: 20 20 6f 53 75 67 67 52 65 73 75 6c 74 2e 61 64    oSuggResult.ad
3080: 64 53 75 67 67 28 73 4e 65 77 57 6f 72 64 2c 20  dSugg(sNewWord, 
3090: 6e 44 65 65 70 29 0a 20 20 20 20 20 20 20 20 20  nDeep).         
30a0: 20 20 20 66 6f 72 20 73 54 61 69 6c 20 69 6e 20     for sTail in 
30b0: 73 65 6c 66 2e 5f 67 65 74 54 61 69 6c 73 28 69  self._getTails(i
30c0: 41 64 64 72 29 3a 0a 20 20 20 20 20 20 20 20 20  Addr):.         
30d0: 20 20 20 20 20 20 20 6f 53 75 67 67 52 65 73 75         oSuggResu
30e0: 6c 74 2e 61 64 64 53 75 67 67 28 73 4e 65 77 57  lt.addSugg(sNewW
30f0: 6f 72 64 2b 73 54 61 69 6c 2c 20 6e 44 65 65 70  ord+sTail, nDeep
3100: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  ).            re
3110: 74 75 72 6e 0a 20 20 20 20 20 20 20 20 63 43 75  turn.        cCu
3120: 72 72 65 6e 74 20 3d 20 73 52 65 6d 61 69 6e 5b  rrent = sRemain[
3130: 30 3a 31 5d 0a 20 20 20 20 20 20 20 20 66 6f 72  0:1].        for
3140: 20 63 43 68 61 72 2c 20 6a 41 64 64 72 20 69 6e   cChar, jAddr in
3150: 20 73 65 6c 66 2e 5f 67 65 74 43 68 61 72 41 72   self._getCharAr
3160: 63 73 28 69 41 64 64 72 29 3a 0a 20 20 20 20 20  cs(iAddr):.     
3170: 20 20 20 20 20 20 20 69 66 20 63 43 68 61 72 20         if cChar 
3180: 69 6e 20 63 70 2e 64 31 74 6f 31 2e 67 65 74 28  in cp.d1to1.get(
3190: 63 43 75 72 72 65 6e 74 2c 20 63 43 75 72 72 65  cCurrent, cCurre
31a0: 6e 74 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  nt):.           
31b0: 20 20 20 20 20 73 65 6c 66 2e 5f 73 75 67 67 65       self._sugge
31c0: 73 74 28 6f 53 75 67 67 52 65 73 75 6c 74 2c 20  st(oSuggResult, 
31d0: 73 52 65 6d 61 69 6e 5b 31 3a 5d 2c 20 6e 4d 61  sRemain[1:], nMa
31e0: 78 53 77 69 74 63 68 2c 20 6e 4d 61 78 44 65 6c  xSwitch, nMaxDel
31f0: 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 2c 20  , nMaxHardRepl, 
3200: 6e 44 65 65 70 2b 31 2c 20 6a 41 64 64 72 2c 20  nDeep+1, jAddr, 
3210: 73 4e 65 77 57 6f 72 64 2b 63 43 68 61 72 29 0a  sNewWord+cChar).
3220: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66              elif
3230: 20 6e 6f 74 20 62 41 76 6f 69 64 4c 6f 6f 70 20   not bAvoidLoop 
3240: 61 6e 64 20 6e 4d 61 78 48 61 72 64 52 65 70 6c  and nMaxHardRepl
3250: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
3260: 20 20 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28    self._suggest(
3270: 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 73 52 65  oSuggResult, sRe
3280: 6d 61 69 6e 5b 31 3a 5d 2c 20 6e 4d 61 78 53 77  main[1:], nMaxSw
3290: 69 74 63 68 2c 20 6e 4d 61 78 44 65 6c 2c 20 6e  itch, nMaxDel, n
32a0: 4d 61 78 48 61 72 64 52 65 70 6c 2d 31 2c 20 6e  MaxHardRepl-1, n
32b0: 44 65 65 70 2b 31 2c 20 6a 41 64 64 72 2c 20 73  Deep+1, jAddr, s
32c0: 4e 65 77 57 6f 72 64 2b 63 43 68 61 72 2c 20 54  NewWord+cChar, T
32d0: 72 75 65 29 0a 20 20 20 20 20 20 20 20 69 66 20  rue).        if 
32e0: 6e 6f 74 20 62 41 76 6f 69 64 4c 6f 6f 70 3a 20  not bAvoidLoop: 
32f0: 23 20 61 76 6f 69 64 20 69 6e 66 69 6e 69 74 65  # avoid infinite
3300: 20 6c 6f 6f 70 0a 20 20 20 20 20 20 20 20 20 20   loop.          
3310: 20 20 69 66 20 6c 65 6e 28 73 52 65 6d 61 69 6e    if len(sRemain
3320: 29 20 3e 20 31 3a 0a 20 20 20 20 20 20 20 20 20  ) > 1:.         
3330: 20 20 20 20 20 20 20 69 66 20 63 43 75 72 72 65         if cCurre
3340: 6e 74 20 3d 3d 20 73 52 65 6d 61 69 6e 5b 31 3a  nt == sRemain[1:
3350: 32 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  2]:.            
3360: 20 20 20 20 20 20 20 20 23 20 73 61 6d 65 20 63          # same c
3370: 68 61 72 2c 20 77 65 20 72 65 6d 6f 76 65 20 31  har, we remove 1
3380: 20 63 68 61 72 20 77 69 74 68 6f 75 74 20 61 64   char without ad
3390: 64 69 6e 67 20 31 20 74 6f 20 3c 73 4e 65 77 57  ding 1 to <sNewW
33a0: 6f 72 64 3e 0a 20 20 20 20 20 20 20 20 20 20 20  ord>.           
33b0: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73           self._s
33c0: 75 67 67 65 73 74 28 6f 53 75 67 67 52 65 73 75  uggest(oSuggResu
33d0: 6c 74 2c 20 73 52 65 6d 61 69 6e 5b 31 3a 5d 2c  lt, sRemain[1:],
33e0: 20 6e 4d 61 78 53 77 69 74 63 68 2c 20 6e 4d 61   nMaxSwitch, nMa
33f0: 78 44 65 6c 2c 20 6e 4d 61 78 48 61 72 64 52 65  xDel, nMaxHardRe
3400: 70 6c 2c 20 6e 44 65 65 70 2b 31 2c 20 69 41 64  pl, nDeep+1, iAd
3410: 64 72 2c 20 73 4e 65 77 57 6f 72 64 29 0a 20 20  dr, sNewWord).  
3420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c                el
3430: 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
3440: 20 20 20 20 20 20 20 20 23 20 73 77 69 74 63 68          # switch
3450: 69 6e 67 20 63 68 61 72 73 0a 20 20 20 20 20 20  ing chars.      
3460: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
3470: 20 6e 4d 61 78 53 77 69 74 63 68 3a 0a 20 20 20   nMaxSwitch:.   
3480: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3490: 20 20 20 20 20 73 65 6c 66 2e 5f 73 75 67 67 65       self._sugge
34a0: 73 74 28 6f 53 75 67 67 52 65 73 75 6c 74 2c 20  st(oSuggResult, 
34b0: 73 52 65 6d 61 69 6e 5b 31 3a 32 5d 2b 73 52 65  sRemain[1:2]+sRe
34c0: 6d 61 69 6e 5b 30 3a 31 5d 2b 73 52 65 6d 61 69  main[0:1]+sRemai
34d0: 6e 5b 32 3a 5d 2c 20 6e 4d 61 78 53 77 69 74 63  n[2:], nMaxSwitc
34e0: 68 2d 31 2c 20 6e 4d 61 78 44 65 6c 2c 20 6e 4d  h-1, nMaxDel, nM
34f0: 61 78 48 61 72 64 52 65 70 6c 2c 20 6e 44 65 65  axHardRepl, nDee
3500: 70 2b 31 2c 20 69 41 64 64 72 2c 20 73 4e 65 77  p+1, iAddr, sNew
3510: 57 6f 72 64 2c 20 54 72 75 65 29 0a 20 20 20 20  Word, True).    
3520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3530: 23 20 64 65 6c 65 74 65 20 63 68 61 72 0a 20 20  # delete char.  
3540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3550: 20 20 69 66 20 6e 4d 61 78 44 65 6c 3a 0a 20 20    if nMaxDel:.  
3560: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3570: 20 20 20 20 20 20 73 65 6c 66 2e 5f 73 75 67 67        self._sugg
3580: 65 73 74 28 6f 53 75 67 67 52 65 73 75 6c 74 2c  est(oSuggResult,
3590: 20 73 52 65 6d 61 69 6e 5b 31 3a 5d 2c 20 6e 4d   sRemain[1:], nM
35a0: 61 78 53 77 69 74 63 68 2c 20 6e 4d 61 78 44 65  axSwitch, nMaxDe
35b0: 6c 2d 31 2c 20 6e 4d 61 78 48 61 72 64 52 65 70  l-1, nMaxHardRep
35c0: 6c 2c 20 6e 44 65 65 70 2b 31 2c 20 69 41 64 64  l, nDeep+1, iAdd
35d0: 72 2c 20 73 4e 65 77 57 6f 72 64 2c 20 54 72 75  r, sNewWord, Tru
35e0: 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e).             
35f0: 20 20 20 23 20 50 68 6f 6e 65 74 69 63 20 72 65     # Phonetic re
3600: 70 6c 61 63 65 6d 65 6e 74 73 0a 20 20 20 20 20  placements.     
3610: 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 73             for s
3620: 52 65 70 6c 20 69 6e 20 63 70 2e 67 65 74 31 74  Repl in cp.get1t
3630: 6f 58 52 65 70 6c 61 63 65 6d 65 6e 74 28 73 4e  oXReplacement(sN
3640: 65 77 57 6f 72 64 5b 2d 31 3a 5d 2c 20 63 43 75  ewWord[-1:], cCu
3650: 72 72 65 6e 74 2c 20 73 52 65 6d 61 69 6e 5b 31  rrent, sRemain[1
3660: 3a 32 5d 29 3a 0a 20 20 20 20 20 20 20 20 20 20  :2]):.          
3670: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f            self._
3680: 73 75 67 67 65 73 74 28 6f 53 75 67 67 52 65 73  suggest(oSuggRes
3690: 75 6c 74 2c 20 73 52 65 70 6c 20 2b 20 73 52 65  ult, sRepl + sRe
36a0: 6d 61 69 6e 5b 31 3a 5d 2c 20 6e 4d 61 78 53 77  main[1:], nMaxSw
36b0: 69 74 63 68 2c 20 6e 4d 61 78 44 65 6c 2c 20 6e  itch, nMaxDel, n
36c0: 4d 61 78 48 61 72 64 52 65 70 6c 2c 20 6e 44 65  MaxHardRepl, nDe
36d0: 65 70 2b 31 2c 20 69 41 64 64 72 2c 20 73 4e 65  ep+1, iAddr, sNe
36e0: 77 57 6f 72 64 2c 20 54 72 75 65 29 0a 20 20 20  wWord, True).   
36f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72               for
3700: 20 73 52 65 70 6c 20 69 6e 20 63 70 2e 64 32 74   sRepl in cp.d2t
3710: 6f 58 2e 67 65 74 28 73 52 65 6d 61 69 6e 5b 30  oX.get(sRemain[0
3720: 3a 32 5d 2c 20 28 29 29 3a 0a 20 20 20 20 20 20  :2], ()):.      
3730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
3740: 6c 66 2e 5f 73 75 67 67 65 73 74 28 6f 53 75 67  lf._suggest(oSug
3750: 67 52 65 73 75 6c 74 2c 20 73 52 65 70 6c 20 2b  gResult, sRepl +
3760: 20 73 52 65 6d 61 69 6e 5b 32 3a 5d 2c 20 6e 4d   sRemain[2:], nM
3770: 61 78 53 77 69 74 63 68 2c 20 6e 4d 61 78 44 65  axSwitch, nMaxDe
3780: 6c 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 2c  l, nMaxHardRepl,
3790: 20 6e 44 65 65 70 2b 31 2c 20 69 41 64 64 72 2c   nDeep+1, iAddr,
37a0: 20 73 4e 65 77 57 6f 72 64 2c 20 54 72 75 65 29   sNewWord, True)
37b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 20 65  .            # e
37c0: 6e 64 20 6f 66 20 77 6f 72 64 0a 20 20 20 20 20  nd of word.     
37d0: 20 20 20 20 20 20 20 69 66 20 6c 65 6e 28 73 52         if len(sR
37e0: 65 6d 61 69 6e 29 20 3d 3d 20 32 3a 0a 20 20 20  emain) == 2:.   
37f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72               for
3800: 20 73 52 65 70 6c 20 69 6e 20 63 70 2e 64 46 69   sRepl in cp.dFi
3810: 6e 61 6c 32 2e 67 65 74 28 73 52 65 6d 61 69 6e  nal2.get(sRemain
3820: 2c 20 28 29 29 3a 0a 20 20 20 20 20 20 20 20 20  , ()):.         
3830: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
3840: 5f 73 75 67 67 65 73 74 28 6f 53 75 67 67 52 65  _suggest(oSuggRe
3850: 73 75 6c 74 2c 20 73 52 65 70 6c 2c 20 6e 4d 61  sult, sRepl, nMa
3860: 78 53 77 69 74 63 68 2c 20 6e 4d 61 78 44 65 6c  xSwitch, nMaxDel
3870: 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 2c 20  , nMaxHardRepl, 
3880: 6e 44 65 65 70 2b 31 2c 20 69 41 64 64 72 2c 20  nDeep+1, iAddr, 
3890: 73 4e 65 77 57 6f 72 64 2c 20 54 72 75 65 29 0a  sNewWord, True).
38a0: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66              elif
38b0: 20 6c 65 6e 28 73 52 65 6d 61 69 6e 29 20 3d 3d   len(sRemain) ==
38c0: 20 31 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20   1:.            
38d0: 20 20 20 20 73 65 6c 66 2e 5f 73 75 67 67 65 73      self._sugges
38e0: 74 28 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 22  t(oSuggResult, "
38f0: 22 2c 20 6e 4d 61 78 53 77 69 74 63 68 2c 20 6e  ", nMaxSwitch, n
3900: 4d 61 78 44 65 6c 2c 20 6e 4d 61 78 48 61 72 64  MaxDel, nMaxHard
3910: 52 65 70 6c 2c 20 6e 44 65 65 70 2b 31 2c 20 69  Repl, nDeep+1, i
3920: 41 64 64 72 2c 20 73 4e 65 77 57 6f 72 64 2c 20  Addr, sNewWord, 
3930: 54 72 75 65 29 20 23 20 72 65 6d 6f 76 65 20 6c  True) # remove l
3940: 61 73 74 20 63 68 61 72 20 61 6e 64 20 67 6f 20  ast char and go 
3950: 6f 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  on.             
3960: 20 20 20 66 6f 72 20 73 52 65 70 6c 20 69 6e 20     for sRepl in 
3970: 63 70 2e 64 46 69 6e 61 6c 31 2e 67 65 74 28 73  cp.dFinal1.get(s
3980: 52 65 6d 61 69 6e 2c 20 28 29 29 3a 0a 20 20 20  Remain, ()):.   
3990: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
39a0: 20 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28 6f   self._suggest(o
39b0: 53 75 67 67 52 65 73 75 6c 74 2c 20 73 52 65 70  SuggResult, sRep
39c0: 6c 2c 20 6e 4d 61 78 53 77 69 74 63 68 2c 20 6e  l, nMaxSwitch, n
39d0: 4d 61 78 44 65 6c 2c 20 6e 4d 61 78 48 61 72 64  MaxDel, nMaxHard
39e0: 52 65 70 6c 2c 20 6e 44 65 65 70 2b 31 2c 20 69  Repl, nDeep+1, i
39f0: 41 64 64 72 2c 20 73 4e 65 77 57 6f 72 64 2c 20  Addr, sNewWord, 
3a00: 54 72 75 65 29 0a 0a 20 20 20 20 23 40 74 69 6d  True)..    #@tim
3a10: 65 74 68 69 73 0a 20 20 20 20 64 65 66 20 73 75  ethis.    def su
3a20: 67 67 65 73 74 32 20 28 73 65 6c 66 2c 20 73 57  ggest2 (self, sW
3a30: 6f 72 64 2c 20 6e 4d 61 78 53 75 67 67 3d 31 30  ord, nMaxSugg=10
3a40: 29 3a 0a 20 20 20 20 20 20 20 20 22 72 65 74 75  ):.        "retu
3a50: 72 6e 73 20 61 20 73 65 74 20 6f 66 20 73 75 67  rns a set of sug
3a60: 67 65 73 74 69 6f 6e 73 20 66 6f 72 20 3c 73 57  gestions for <sW
3a70: 6f 72 64 3e 22 0a 20 20 20 20 20 20 20 20 73 50  ord>".        sP
3a80: 66 78 2c 20 73 57 6f 72 64 2c 20 73 53 66 78 20  fx, sWord, sSfx 
3a90: 3d 20 63 70 2e 63 75 74 28 73 57 6f 72 64 29 0a  = cp.cut(sWord).
3aa0: 20 20 20 20 20 20 20 20 6f 53 75 67 67 52 65 73          oSuggRes
3ab0: 75 6c 74 20 3d 20 53 75 67 67 52 65 73 75 6c 74  ult = SuggResult
3ac0: 28 73 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20  (sWord).        
3ad0: 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 32 28 6f  self._suggest2(o
3ae0: 53 75 67 67 52 65 73 75 6c 74 29 0a 20 20 20 20  SuggResult).    
3af0: 20 20 20 20 61 53 75 67 67 20 3d 20 6f 53 75 67      aSugg = oSug
3b00: 67 52 65 73 75 6c 74 2e 67 65 74 53 75 67 67 65  gResult.getSugge
3b10: 73 74 69 6f 6e 73 28 29 0a 20 20 20 20 20 20 20  stions().       
3b20: 20 69 66 20 73 53 66 78 20 6f 72 20 73 50 66 78   if sSfx or sPfx
3b30: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 20  :.            # 
3b40: 77 65 20 61 64 64 20 77 68 61 74 20 77 65 20 72  we add what we r
3b50: 65 6d 6f 76 65 64 0a 20 20 20 20 20 20 20 20 20  emoved.         
3b60: 20 20 20 72 65 74 75 72 6e 20 6c 69 73 74 28 6d     return list(m
3b70: 61 70 28 6c 61 6d 62 64 61 20 73 53 75 67 3a 20  ap(lambda sSug: 
3b80: 73 50 66 78 20 2b 20 73 53 75 67 20 2b 20 73 53  sPfx + sSug + sS
3b90: 66 78 2c 20 61 53 75 67 67 29 29 0a 20 20 20 20  fx, aSugg)).    
3ba0: 20 20 20 20 72 65 74 75 72 6e 20 61 53 75 67 67      return aSugg
3bb0: 0a 0a 20 20 20 20 64 65 66 20 5f 73 75 67 67 65  ..    def _sugge
3bc0: 73 74 32 20 28 73 65 6c 66 2c 20 6f 53 75 67 67  st2 (self, oSugg
3bd0: 52 65 73 75 6c 74 2c 20 6e 44 65 65 70 3d 30 2c  Result, nDeep=0,
3be0: 20 69 41 64 64 72 3d 30 2c 20 73 4e 65 77 57 6f   iAddr=0, sNewWo
3bf0: 72 64 3d 22 22 29 3a 0a 20 20 20 20 20 20 20 20  rd=""):.        
3c00: 23 20 72 65 63 75 72 73 69 76 65 20 66 75 6e 63  # recursive func
3c10: 74 69 6f 6e 0a 20 20 20 20 20 20 20 20 23 6c 6f  tion.        #lo
3c20: 67 67 69 6e 67 2e 69 6e 66 6f 28 28 6e 44 65 65  gging.info((nDee
3c30: 70 20 2a 20 22 20 20 22 29 20 2b 20 73 4e 65 77  p * "  ") + sNew
3c40: 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20 69 66  Word).        if
3c50: 20 6e 44 65 65 70 20 3e 3d 20 6f 53 75 67 67 52   nDeep >= oSuggR
3c60: 65 73 75 6c 74 2e 6e 44 69 73 74 4c 69 6d 69 74  esult.nDistLimit
3c70: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 43  :.            sC
3c80: 6c 65 61 6e 4e 65 77 57 6f 72 64 20 3d 20 63 70  leanNewWord = cp
3c90: 2e 73 69 6d 70 6c 69 66 79 57 6f 72 64 28 73 4e  .simplifyWord(sN
3ca0: 65 77 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20  ewWord).        
3cb0: 20 20 20 20 69 66 20 73 74 2e 64 69 73 74 61 6e      if st.distan
3cc0: 63 65 53 69 66 74 34 28 6f 53 75 67 67 52 65 73  ceSift4(oSuggRes
3cd0: 75 6c 74 2e 73 43 6c 65 61 6e 57 6f 72 64 5b 3a  ult.sCleanWord[:
3ce0: 6c 65 6e 28 73 43 6c 65 61 6e 4e 65 77 57 6f 72  len(sCleanNewWor
3cf0: 64 29 5d 2c 20 73 43 6c 65 61 6e 4e 65 77 57 6f  d)], sCleanNewWo
3d00: 72 64 29 20 3e 20 6f 53 75 67 67 52 65 73 75 6c  rd) > oSuggResul
3d10: 74 2e 6e 44 69 73 74 4c 69 6d 69 74 3a 0a 20 20  t.nDistLimit:.  
3d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
3d30: 74 75 72 6e 0a 20 20 20 20 20 20 20 20 69 66 20  turn.        if 
3d40: 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73  int.from_bytes(s
3d50: 65 6c 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a  elf.byDic[iAddr:
3d60: 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  iAddr+self.nByte
3d70: 73 41 72 63 5d 2c 20 62 79 74 65 6f 72 64 65 72  sArc], byteorder
3d80: 3d 27 62 69 67 27 29 20 26 20 73 65 6c 66 2e 5f  ='big') & self._
3d90: 66 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b 3a 0a 20  finalNodeMask:. 
3da0: 20 20 20 20 20 20 20 20 20 20 20 6f 53 75 67 67             oSugg
3db0: 52 65 73 75 6c 74 2e 61 64 64 53 75 67 67 28 73  Result.addSugg(s
3dc0: 4e 65 77 57 6f 72 64 2c 20 6e 44 65 65 70 29 0a  NewWord, nDeep).
3dd0: 20 20 20 20 20 20 20 20 66 6f 72 20 63 43 68 61          for cCha
3de0: 72 2c 20 6a 41 64 64 72 20 69 6e 20 73 65 6c 66  r, jAddr in self
3df0: 2e 5f 67 65 74 43 68 61 72 41 72 63 73 57 69 74  ._getCharArcsWit
3e00: 68 50 72 69 6f 72 69 74 79 28 69 41 64 64 72 2c  hPriority(iAddr,
3e10: 20 6f 53 75 67 67 52 65 73 75 6c 74 2e 73 57 6f   oSuggResult.sWo
3e20: 72 64 5b 6e 44 65 65 70 3a 6e 44 65 65 70 2b 31  rd[nDeep:nDeep+1
3e30: 5d 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ]):.            
3e40: 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 32 28 6f  self._suggest2(o
3e50: 53 75 67 67 52 65 73 75 6c 74 2c 20 6e 44 65 65  SuggResult, nDee
3e60: 70 2b 31 2c 20 6a 41 64 64 72 2c 20 73 4e 65 77  p+1, jAddr, sNew
3e70: 57 6f 72 64 2b 63 43 68 61 72 29 0a 20 20 20 20  Word+cChar).    
3e80: 20 20 20 20 72 65 74 75 72 6e 0a 0a 20 20 20 20      return..    
3e90: 64 65 66 20 5f 67 65 74 43 68 61 72 41 72 63 73  def _getCharArcs
3ea0: 20 28 73 65 6c 66 2c 20 69 41 64 64 72 29 3a 0a   (self, iAddr):.
3eb0: 20 20 20 20 20 20 20 20 22 67 65 6e 65 72 61 74          "generat
3ec0: 6f 72 3a 20 79 69 65 6c 64 20 61 6c 6c 20 63 68  or: yield all ch
3ed0: 61 72 73 20 61 6e 64 20 61 64 64 72 65 73 73 65  ars and addresse
3ee0: 73 20 66 72 6f 6d 20 6e 6f 64 65 20 61 74 20 61  s from node at a
3ef0: 64 64 72 65 73 73 20 3c 69 41 64 64 72 3e 22 0a  ddress <iAddr>".
3f00: 20 20 20 20 20 20 20 20 66 6f 72 20 6e 56 61 6c          for nVal
3f10: 2c 20 6a 41 64 64 72 20 69 6e 20 73 65 6c 66 2e  , jAddr in self.
3f20: 5f 67 65 74 41 72 63 73 28 69 41 64 64 72 29 3a  _getArcs(iAddr):
3f30: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
3f40: 6e 56 61 6c 20 3c 20 73 65 6c 66 2e 6e 43 68 61  nVal < self.nCha
3f50: 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r:.             
3f60: 20 20 20 79 69 65 6c 64 20 28 73 65 6c 66 2e 64     yield (self.d
3f70: 43 68 61 72 56 61 6c 5b 6e 56 61 6c 5d 2c 20 6a  CharVal[nVal], j
3f80: 41 64 64 72 29 0a 0a 20 20 20 20 64 65 66 20 5f  Addr)..    def _
3f90: 67 65 74 53 69 6d 69 6c 61 72 43 68 61 72 41 72  getSimilarCharAr
3fa0: 63 73 20 28 73 65 6c 66 2c 20 63 43 68 61 72 2c  cs (self, cChar,
3fb0: 20 69 41 64 64 72 29 3a 0a 20 20 20 20 20 20 20   iAddr):.       
3fc0: 20 22 67 65 6e 65 72 61 74 6f 72 3a 20 79 69 65   "generator: yie
3fd0: 6c 64 20 73 69 6d 69 6c 61 72 20 63 68 61 72 20  ld similar char 
3fe0: 6f 66 20 3c 63 43 68 61 72 3e 20 61 6e 64 20 61  of <cChar> and a
3ff0: 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 66 6f  ddress of the fo
4000: 6c 6c 6f 77 69 6e 67 20 6e 6f 64 65 22 0a 20 20  llowing node".  
4010: 20 20 20 20 20 20 66 6f 72 20 63 20 69 6e 20 63        for c in c
4020: 70 2e 64 31 74 6f 31 2e 67 65 74 28 63 43 68 61  p.d1to1.get(cCha
4030: 72 2c 20 5b 63 43 68 61 72 5d 29 3a 0a 20 20 20  r, [cChar]):.   
4040: 20 20 20 20 20 20 20 20 20 69 66 20 63 20 69 6e           if c in
4050: 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a 20 20 20   self.dChar:.   
4060: 20 20 20 20 20 20 20 20 20 20 20 20 20 6a 41 64               jAd
4070: 64 72 20 3d 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75  dr = self._looku
4080: 70 41 72 63 4e 6f 64 65 28 73 65 6c 66 2e 64 43  pArcNode(self.dC
4090: 68 61 72 5b 63 5d 2c 20 69 41 64 64 72 29 0a 20  har[c], iAddr). 
40a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
40b0: 66 20 6a 41 64 64 72 3a 0a 20 20 20 20 20 20 20  f jAddr:.       
40c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65               yie
40d0: 6c 64 20 28 63 2c 20 6a 41 64 64 72 29 0a 0a 20  ld (c, jAddr).. 
40e0: 20 20 20 64 65 66 20 5f 67 65 74 43 68 61 72 41     def _getCharA
40f0: 72 63 73 57 69 74 68 50 72 69 6f 72 69 74 79 20  rcsWithPriority 
4100: 28 73 65 6c 66 2c 20 69 41 64 64 72 2c 20 63 43  (self, iAddr, cC
4110: 68 61 72 29 3a 0a 20 20 20 20 20 20 20 20 69 66  har):.        if
4120: 20 6e 6f 74 20 63 43 68 61 72 3a 0a 20 20 20 20   not cChar:.    
4130: 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 66 72          yield fr
4140: 6f 6d 20 73 65 6c 66 2e 5f 67 65 74 43 68 61 72  om self._getChar
4150: 41 72 63 73 28 69 41 64 64 72 29 0a 20 20 20 20  Arcs(iAddr).    
4160: 20 20 20 20 6c 54 75 70 6c 65 20 3d 20 6c 69 73      lTuple = lis
4170: 74 28 73 65 6c 66 2e 5f 67 65 74 43 68 61 72 41  t(self._getCharA
4180: 72 63 73 28 69 41 64 64 72 29 29 0a 20 20 20 20  rcs(iAddr)).    
4190: 20 20 20 20 6c 54 75 70 6c 65 2e 73 6f 72 74 28      lTuple.sort(
41a0: 6b 65 79 3d 6c 61 6d 62 64 61 20 74 3a 20 30 20  key=lambda t: 0 
41b0: 20 69 66 20 74 5b 30 5d 20 69 6e 20 63 70 2e 64   if t[0] in cp.d
41c0: 31 74 6f 31 2e 67 65 74 28 63 43 68 61 72 2c 20  1to1.get(cChar, 
41d0: 63 43 68 61 72 29 20 20 65 6c 73 65 20 20 31 29  cChar)  else  1)
41e0: 0a 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 66  .        yield f
41f0: 72 6f 6d 20 6c 54 75 70 6c 65 0a 0a 20 20 20 20  rom lTuple..    
4200: 64 65 66 20 5f 67 65 74 54 61 69 6c 73 20 28 73  def _getTails (s
4210: 65 6c 66 2c 20 69 41 64 64 72 2c 20 73 54 61 69  elf, iAddr, sTai
4220: 6c 3d 22 22 2c 20 6e 3d 32 29 3a 0a 20 20 20 20  l="", n=2):.    
4230: 20 20 20 20 22 72 65 74 75 72 6e 20 61 20 6c 69      "return a li
4240: 73 74 20 6f 66 20 73 75 66 66 69 78 65 73 20 65  st of suffixes e
4250: 6e 64 69 6e 67 20 61 74 20 61 20 64 69 73 74 61  nding at a dista
4260: 6e 63 65 20 6f 66 20 3c 6e 3e 20 66 72 6f 6d 20  nce of <n> from 
4270: 3c 69 41 64 64 72 3e 22 0a 20 20 20 20 20 20 20  <iAddr>".       
4280: 20 61 54 61 69 6c 73 20 3d 20 73 65 74 28 29 0a   aTails = set().
4290: 20 20 20 20 20 20 20 20 66 6f 72 20 6e 56 61 6c          for nVal
42a0: 2c 20 6a 41 64 64 72 20 69 6e 20 73 65 6c 66 2e  , jAddr in self.
42b0: 5f 67 65 74 41 72 63 73 28 69 41 64 64 72 29 3a  _getArcs(iAddr):
42c0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
42d0: 6e 56 61 6c 20 3c 20 73 65 6c 66 2e 6e 43 68 61  nVal < self.nCha
42e0: 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r:.             
42f0: 20 20 20 69 66 20 69 6e 74 2e 66 72 6f 6d 5f 62     if int.from_b
4300: 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b  ytes(self.byDic[
4310: 6a 41 64 64 72 3a 6a 41 64 64 72 2b 73 65 6c 66  jAddr:jAddr+self
4320: 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20 62 79 74  .nBytesArc], byt
4330: 65 6f 72 64 65 72 3d 27 62 69 67 27 29 20 26 20  eorder='big') & 
4340: 73 65 6c 66 2e 5f 66 69 6e 61 6c 4e 6f 64 65 4d  self._finalNodeM
4350: 61 73 6b 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ask:.           
4360: 20 20 20 20 20 20 20 20 20 61 54 61 69 6c 73 2e           aTails.
4370: 61 64 64 28 73 54 61 69 6c 20 2b 20 73 65 6c 66  add(sTail + self
4380: 2e 64 43 68 61 72 56 61 6c 5b 6e 56 61 6c 5d 29  .dCharVal[nVal])
4390: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
43a0: 20 69 66 20 6e 20 61 6e 64 20 6e 6f 74 20 61 54   if n and not aT
43b0: 61 69 6c 73 3a 0a 20 20 20 20 20 20 20 20 20 20  ails:.          
43c0: 20 20 20 20 20 20 20 20 20 20 61 54 61 69 6c 73            aTails
43d0: 2e 75 70 64 61 74 65 28 73 65 6c 66 2e 5f 67 65  .update(self._ge
43e0: 74 54 61 69 6c 73 28 6a 41 64 64 72 2c 20 73 54  tTails(jAddr, sT
43f0: 61 69 6c 2b 73 65 6c 66 2e 64 43 68 61 72 56 61  ail+self.dCharVa
4400: 6c 5b 6e 56 61 6c 5d 2c 20 6e 2d 31 29 29 0a 20  l[nVal], n-1)). 
4410: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 61 54         return aT
4420: 61 69 6c 73 0a 0a 20 20 20 20 64 65 66 20 64 72  ails..    def dr
4430: 61 77 50 61 74 68 20 28 73 65 6c 66 2c 20 73 57  awPath (self, sW
4440: 6f 72 64 2c 20 69 41 64 64 72 3d 30 29 3a 0a 20  ord, iAddr=0):. 
4450: 20 20 20 20 20 20 20 22 73 68 6f 77 20 74 68 65         "show the
4460: 20 70 61 74 68 20 74 61 6b 65 6e 20 62 79 20 3c   path taken by <
4470: 73 57 6f 72 64 3e 20 69 6e 20 74 68 65 20 67 72  sWord> in the gr
4480: 61 70 68 22 0a 20 20 20 20 20 20 20 20 63 31 20  aph".        c1 
4490: 3d 20 73 57 6f 72 64 5b 30 3a 31 5d 20 20 69 66  = sWord[0:1]  if
44a0: 20 73 57 6f 72 64 20 20 65 6c 73 65 20 22 20 22   sWord  else " "
44b0: 0a 20 20 20 20 20 20 20 20 69 50 6f 73 20 3d 20  .        iPos = 
44c0: 2d 31 0a 20 20 20 20 20 20 20 20 6e 20 3d 20 30  -1.        n = 0
44d0: 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 63  .        print(c
44e0: 31 20 2b 20 22 3a 20 22 2c 20 65 6e 64 3d 22 22  1 + ": ", end=""
44f0: 29 0a 20 20 20 20 20 20 20 20 66 6f 72 20 63 32  ).        for c2
4500: 2c 20 6a 41 64 64 72 20 69 6e 20 73 65 6c 66 2e  , jAddr in self.
4510: 5f 67 65 74 43 68 61 72 41 72 63 73 28 69 41 64  _getCharArcs(iAd
4520: 64 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  dr):.           
4530: 20 70 72 69 6e 74 28 63 32 2c 20 65 6e 64 3d 22   print(c2, end="
4540: 22 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  ").            i
4550: 66 20 63 32 20 3d 3d 20 73 57 6f 72 64 5b 30 3a  f c2 == sWord[0:
4560: 31 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  1]:.            
4570: 20 20 20 20 69 4e 65 78 74 4e 6f 64 65 41 64 64      iNextNodeAdd
4580: 72 20 3d 20 6a 41 64 64 72 0a 20 20 20 20 20 20  r = jAddr.      
4590: 20 20 20 20 20 20 20 20 20 20 69 50 6f 73 20 3d            iPos =
45a0: 20 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e   n.            n
45b0: 20 2b 3d 20 31 0a 20 20 20 20 20 20 20 20 69 66   += 1.        if
45c0: 20 6e 6f 74 20 73 57 6f 72 64 3a 0a 20 20 20 20   not sWord:.    
45d0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 0a 20          return. 
45e0: 20 20 20 20 20 20 20 69 66 20 69 50 6f 73 20 3e         if iPos >
45f0: 3d 20 30 3a 0a 20 20 20 20 20 20 20 20 20 20 20  = 0:.           
4600: 20 70 72 69 6e 74 28 22 5c 6e 20 20 20 22 2b 20   print("\n   "+ 
4610: 22 20 22 20 2a 20 69 50 6f 73 20 2b 20 22 7c 22  " " * iPos + "|"
4620: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65  ).            se
4630: 6c 66 2e 64 72 61 77 50 61 74 68 28 73 57 6f 72  lf.drawPath(sWor
4640: 64 5b 31 3a 5d 2c 20 69 4e 65 78 74 4e 6f 64 65  d[1:], iNextNode
4650: 41 64 64 72 29 0a 0a 20 20 20 20 64 65 66 20 73  Addr)..    def s
4660: 65 6c 65 63 74 20 28 73 65 6c 66 2c 20 73 50 61  elect (self, sPa
4670: 74 74 65 72 6e 3d 22 22 29 3a 0a 20 20 20 20 20  ttern=""):.     
4680: 20 20 20 22 67 65 6e 65 72 61 74 6f 72 3a 20 72     "generator: r
4690: 65 74 75 72 6e 73 20 61 6c 6c 20 65 6e 74 72 69  eturns all entri
46a0: 65 73 20 77 68 69 63 68 20 6d 6f 72 70 68 6f 6c  es which morphol
46b0: 6f 67 79 20 66 69 74 73 20 3c 73 50 61 74 74 65  ogy fits <sPatte
46c0: 72 6e 3e 22 0a 20 20 20 20 20 20 20 20 7a 50 61  rn>".        zPa
46d0: 74 74 65 72 6e 20 3d 20 4e 6f 6e 65 0a 20 20 20  ttern = None.   
46e0: 20 20 20 20 20 69 66 20 73 50 61 74 74 65 72 6e       if sPattern
46f0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 74 72  :.            tr
4700: 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  y:.             
4710: 20 20 20 7a 50 61 74 74 65 72 6e 20 3d 20 72 65     zPattern = re
4720: 2e 63 6f 6d 70 69 6c 65 28 73 50 61 74 74 65 72  .compile(sPatter
4730: 6e 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 65  n).            e
4740: 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20 20  xcept:.         
4750: 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 23 20         print("# 
4760: 45 72 72 6f 72 20 69 6e 20 72 65 67 65 78 20 70  Error in regex p
4770: 61 74 74 65 72 6e 22 29 0a 20 20 20 20 20 20 20  attern").       
4780: 20 20 20 20 20 20 20 20 20 74 72 61 63 65 62 61           traceba
4790: 63 6b 2e 70 72 69 6e 74 5f 65 78 63 28 29 0a 20  ck.print_exc(). 
47a0: 20 20 20 20 20 20 20 79 69 65 6c 64 20 66 72 6f         yield fro
47b0: 6d 20 73 65 6c 66 2e 5f 73 65 6c 65 63 74 31 28  m self._select1(
47c0: 7a 50 61 74 74 65 72 6e 2c 20 30 2c 20 22 22 29  zPattern, 0, "")
47d0: 0a 0a 20 20 20 20 23 20 64 65 66 20 6d 6f 72 70  ..    # def morp
47e0: 68 20 28 73 65 6c 66 2c 20 73 57 6f 72 64 29 3a  h (self, sWord):
47f0: 0a 20 20 20 20 23 20 20 20 20 20 69 73 20 64 65  .    #     is de
4800: 66 69 6e 65 64 20 69 6e 20 5f 5f 69 6e 69 74 5f  fined in __init_
4810: 5f 0a 0a 20 20 20 20 23 20 56 45 52 53 49 4f 4e  _..    # VERSION
4820: 20 31 0a 20 20 20 20 64 65 66 20 5f 73 65 6c 65   1.    def _sele
4830: 63 74 31 20 28 73 65 6c 66 2c 20 7a 50 61 74 74  ct1 (self, zPatt
4840: 65 72 6e 2c 20 69 41 64 64 72 2c 20 73 57 6f 72  ern, iAddr, sWor
4850: 64 29 3a 0a 20 20 20 20 20 20 20 20 23 20 72 65  d):.        # re
4860: 63 75 72 73 69 76 65 20 67 65 6e 65 72 61 74 6f  cursive generato
4870: 72 0a 20 20 20 20 20 20 20 20 66 6f 72 20 6e 56  r.        for nV
4880: 61 6c 2c 20 6a 41 64 64 72 20 69 6e 20 73 65 6c  al, jAddr in sel
4890: 66 2e 5f 67 65 74 41 72 63 73 31 28 69 41 64 64  f._getArcs1(iAdd
48a0: 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  r):.            
48b0: 69 66 20 6e 56 61 6c 20 3c 3d 20 73 65 6c 66 2e  if nVal <= self.
48c0: 6e 43 68 61 72 3a 0a 20 20 20 20 20 20 20 20 20  nChar:.         
48d0: 20 20 20 20 20 20 20 23 20 73 69 6d 70 6c 65 20         # simple 
48e0: 63 68 61 72 61 63 74 65 72 0a 20 20 20 20 20 20  character.      
48f0: 20 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20            yield 
4900: 66 72 6f 6d 20 73 65 6c 66 2e 5f 73 65 6c 65 63  from self._selec
4910: 74 31 28 7a 50 61 74 74 65 72 6e 2c 20 6a 41 64  t1(zPattern, jAd
4920: 64 72 2c 20 73 57 6f 72 64 20 2b 20 73 65 6c 66  dr, sWord + self
4930: 2e 6c 41 72 63 56 61 6c 5b 6e 56 61 6c 5d 29 0a  .lArcVal[nVal]).
4940: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
4950: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
4960: 20 20 73 45 6e 74 72 79 20 3d 20 73 57 6f 72 64    sEntry = sWord
4970: 20 2b 20 22 5c 74 22 20 2b 20 73 65 6c 66 2e 66   + "\t" + self.f
4980: 75 6e 63 53 74 65 6d 6d 69 6e 67 28 73 57 6f 72  uncStemming(sWor
4990: 64 2c 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b  d, self.lArcVal[
49a0: 6e 56 61 6c 5d 29 0a 20 20 20 20 20 20 20 20 20  nVal]).         
49b0: 20 20 20 20 20 20 20 66 6f 72 20 6e 4d 6f 72 70         for nMorp
49c0: 68 56 61 6c 2c 20 5f 20 69 6e 20 73 65 6c 66 2e  hVal, _ in self.
49d0: 5f 67 65 74 41 72 63 73 31 28 6a 41 64 64 72 29  _getArcs1(jAddr)
49e0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
49f0: 20 20 20 20 20 20 69 66 20 6e 6f 74 20 7a 50 61        if not zPa
4a00: 74 74 65 72 6e 20 6f 72 20 7a 50 61 74 74 65 72  ttern or zPatter
4a10: 6e 2e 73 65 61 72 63 68 28 73 65 6c 66 2e 6c 41  n.search(self.lA
4a20: 72 63 56 61 6c 5b 6e 4d 6f 72 70 68 56 61 6c 5d  rcVal[nMorphVal]
4a30: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
4a40: 20 20 20 20 20 20 20 20 20 20 20 79 69 65 6c 64             yield
4a50: 20 73 45 6e 74 72 79 20 2b 20 22 5c 74 22 20 2b   sEntry + "\t" +
4a60: 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 4d   self.lArcVal[nM
4a70: 6f 72 70 68 56 61 6c 5d 0a 0a 20 20 20 20 64 65  orphVal]..    de
4a80: 66 20 5f 6d 6f 72 70 68 31 20 28 73 65 6c 66 2c  f _morph1 (self,
4a90: 20 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20 20   sWord):.       
4aa0: 20 22 72 65 74 75 72 6e 73 20 6d 6f 72 70 68 6f   "returns morpho
4ab0: 6c 6f 67 69 65 73 20 6f 66 20 3c 73 57 6f 72 64  logies of <sWord
4ac0: 3e 22 0a 20 20 20 20 20 20 20 20 69 41 64 64 72  >".        iAddr
4ad0: 20 3d 20 30 0a 20 20 20 20 20 20 20 20 66 6f 72   = 0.        for
4ae0: 20 63 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20 20   c in sWord:.   
4af0: 20 20 20 20 20 20 20 20 20 69 66 20 63 20 6e 6f           if c no
4b00: 74 20 69 6e 20 73 65 6c 66 2e 64 43 68 61 72 3a  t in self.dChar:
4b10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4b20: 20 72 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20 20   return [].     
4b30: 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 73         iAddr = s
4b40: 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f  elf._lookupArcNo
4b50: 64 65 28 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d  de(self.dChar[c]
4b60: 2c 20 69 41 64 64 72 29 0a 20 20 20 20 20 20 20  , iAddr).       
4b70: 20 20 20 20 20 69 66 20 69 41 64 64 72 20 3d 3d       if iAddr ==
4b80: 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 20   None:.         
4b90: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d         return []
4ba0: 0a 20 20 20 20 20 20 20 20 69 66 20 28 69 6e 74  .        if (int
4bb0: 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66  .from_bytes(self
4bc0: 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 41 64  .byDic[iAddr:iAd
4bd0: 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72  dr+self.nBytesAr
4be0: 63 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62  c], byteorder='b
4bf0: 69 67 27 29 20 26 20 73 65 6c 66 2e 5f 66 69 6e  ig') & self._fin
4c00: 61 6c 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20 20 20  alNodeMask):.   
4c10: 20 20 20 20 20 20 20 20 20 6c 20 3d 20 5b 5d 0a           l = [].
4c20: 20 20 20 20 20 20 20 20 20 20 20 20 6e 52 61 77              nRaw
4c30: 41 72 63 20 3d 20 30 0a 20 20 20 20 20 20 20 20  Arc = 0.        
4c40: 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28 6e      while not (n
4c50: 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 6c  RawArc & self._l
4c60: 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20  astArcMask):.   
4c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 45 6e               iEn
4c80: 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64 72  dArcAddr = iAddr
4c90: 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72   + self.nBytesAr
4ca0: 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  c.              
4cb0: 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74 2e    nRawArc = int.
4cc0: 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e  from_bytes(self.
4cd0: 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e 64  byDic[iAddr:iEnd
4ce0: 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f 72  ArcAddr], byteor
4cf0: 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20  der='big').     
4d00: 20 20 20 20 20 20 20 20 20 20 20 6e 41 72 63 20             nArc 
4d10: 3d 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66  = nRawArc & self
4d20: 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20 20  ._arcMask.      
4d30: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 41 72            if nAr
4d40: 63 20 3e 3d 20 73 65 6c 66 2e 6e 43 68 61 72 3a  c >= self.nChar:
4d50: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4d60: 20 20 20 20 20 23 20 54 68 69 73 20 76 61 6c 75       # This valu
4d70: 65 20 69 73 20 6e 6f 74 20 61 20 63 68 61 72 2c  e is not a char,
4d80: 20 74 68 69 73 20 69 73 20 61 20 73 74 65 6d 6d   this is a stemm
4d90: 69 6e 67 20 63 6f 64 65 20 0a 20 20 20 20 20 20  ing code .      
4da0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 53                sS
4db0: 74 65 6d 20 3d 20 22 3e 22 20 2b 20 73 65 6c 66  tem = ">" + self
4dc0: 2e 66 75 6e 63 53 74 65 6d 6d 69 6e 67 28 73 57  .funcStemming(sW
4dd0: 6f 72 64 2c 20 73 65 6c 66 2e 6c 41 72 63 56 61  ord, self.lArcVa
4de0: 6c 5b 6e 41 72 63 5d 29 0a 20 20 20 20 20 20 20  l[nArc]).       
4df0: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 4e               # N
4e00: 6f 77 20 2c 20 77 65 20 67 6f 20 74 6f 20 74 68  ow , we go to th
4e10: 65 20 6e 65 78 74 20 6e 6f 64 65 20 61 6e 64 20  e next node and 
4e20: 72 65 74 72 69 65 76 65 20 61 6c 6c 20 66 6f 6c  retrieve all fol
4e30: 6c 6f 77 69 6e 67 20 61 72 63 73 20 76 61 6c 75  lowing arcs valu
4e40: 65 73 2c 20 61 6c 6c 20 6f 66 20 74 68 65 6d 20  es, all of them 
4e50: 61 72 65 20 74 61 67 73 0a 20 20 20 20 20 20 20  are tags.       
4e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64               iAd
4e70: 64 72 32 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62  dr2 = int.from_b
4e80: 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b  ytes(self.byDic[
4e90: 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e 64  iEndArcAddr:iEnd
4ea0: 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  ArcAddr+self.nBy
4eb0: 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 5d 2c  tesNodeAddress],
4ec0: 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27   byteorder='big'
4ed0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
4ee0: 20 20 20 20 20 20 6e 52 61 77 41 72 63 32 20 3d        nRawArc2 =
4ef0: 20 30 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   0.             
4f00: 20 20 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74         while not
4f10: 20 28 6e 52 61 77 41 72 63 32 20 26 20 73 65 6c   (nRawArc2 & sel
4f20: 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a  f._lastArcMask):
4f30: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4f40: 20 20 20 20 20 20 20 20 20 69 45 6e 64 41 72 63           iEndArc
4f50: 41 64 64 72 32 20 3d 20 69 41 64 64 72 32 20 2b  Addr2 = iAddr2 +
4f60: 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a   self.nBytesArc.
4f70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4f80: 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63 32          nRawArc2
4f90: 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65   = int.from_byte
4fa0: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64  s(self.byDic[iAd
4fb0: 64 72 32 3a 69 45 6e 64 41 72 63 41 64 64 72 32  dr2:iEndArcAddr2
4fc0: 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69  ], byteorder='bi
4fd0: 67 27 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  g').            
4fe0: 20 20 20 20 20 20 20 20 20 20 20 20 6c 2e 61 70              l.ap
4ff0: 70 65 6e 64 28 73 53 74 65 6d 20 2b 20 22 20 22  pend(sStem + " "
5000: 20 2b 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b   + self.lArcVal[
5010: 6e 52 61 77 41 72 63 32 20 26 20 73 65 6c 66 2e  nRawArc2 & self.
5020: 5f 61 72 63 4d 61 73 6b 5d 29 0a 20 20 20 20 20  _arcMask]).     
5030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5040: 20 20 20 69 41 64 64 72 32 20 3d 20 69 45 6e 64     iAddr2 = iEnd
5050: 41 72 63 41 64 64 72 32 2b 73 65 6c 66 2e 6e 42  ArcAddr2+self.nB
5060: 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 0a  ytesNodeAddress.
5070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5080: 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72 63 41  iAddr = iEndArcA
5090: 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e  ddr+self.nBytesN
50a0: 6f 64 65 41 64 64 72 65 73 73 0a 20 20 20 20 20  odeAddress.     
50b0: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 6c 0a         return l.
50c0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b          return [
50d0: 5d 0a 0a 20 20 20 20 64 65 66 20 5f 73 74 65 6d  ]..    def _stem
50e0: 31 20 28 73 65 6c 66 2c 20 73 57 6f 72 64 29 3a  1 (self, sWord):
50f0: 0a 20 20 20 20 20 20 20 20 22 72 65 74 75 72 6e  .        "return
5100: 73 20 73 74 65 6d 73 20 6c 69 73 74 20 6f 66 20  s stems list of 
5110: 3c 73 57 6f 72 64 3e 22 0a 20 20 20 20 20 20 20  <sWord>".       
5120: 20 69 41 64 64 72 20 3d 20 30 0a 20 20 20 20 20   iAddr = 0.     
5130: 20 20 20 66 6f 72 20 63 20 69 6e 20 73 57 6f 72     for c in sWor
5140: 64 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  d:.            i
5150: 66 20 63 20 6e 6f 74 20 69 6e 20 73 65 6c 66 2e  f c not in self.
5160: 64 43 68 61 72 3a 0a 20 20 20 20 20 20 20 20 20  dChar:.         
5170: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d         return []
5180: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64  .            iAd
5190: 64 72 20 3d 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75  dr = self._looku
51a0: 70 41 72 63 4e 6f 64 65 28 73 65 6c 66 2e 64 43  pArcNode(self.dC
51b0: 68 61 72 5b 63 5d 2c 20 69 41 64 64 72 29 0a 20  har[c], iAddr). 
51c0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 69 41             if iA
51d0: 64 64 72 20 3d 3d 20 4e 6f 6e 65 3a 0a 20 20 20  ddr == None:.   
51e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74               ret
51f0: 75 72 6e 20 5b 5d 0a 20 20 20 20 20 20 20 20 69  urn [].        i
5200: 66 20 28 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65  f (int.from_byte
5210: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64  s(self.byDic[iAd
5220: 64 72 3a 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dr:iAddr+self.nB
5230: 79 74 65 73 41 72 63 5d 2c 20 62 79 74 65 6f 72  ytesArc], byteor
5240: 64 65 72 3d 27 62 69 67 27 29 20 26 20 73 65 6c  der='big') & sel
5250: 66 2e 5f 66 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b  f._finalNodeMask
5260: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6c  ):.            l
5270: 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 20 20   = [].          
5280: 20 20 6e 52 61 77 41 72 63 20 3d 20 30 0a 20 20    nRawArc = 0.  
5290: 20 20 20 20 20 20 20 20 20 20 77 68 69 6c 65 20            while 
52a0: 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73  not (nRawArc & s
52b0: 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b  elf._lastArcMask
52c0: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
52d0: 20 20 20 69 45 6e 64 41 72 63 41 64 64 72 20 3d     iEndArcAddr =
52e0: 20 69 41 64 64 72 20 2b 20 73 65 6c 66 2e 6e 42   iAddr + self.nB
52f0: 79 74 65 73 41 72 63 0a 20 20 20 20 20 20 20 20  ytesArc.        
5300: 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63 20          nRawArc 
5310: 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73  = int.from_bytes
5320: 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64 64  (self.byDic[iAdd
5330: 72 3a 69 45 6e 64 41 72 63 41 64 64 72 5d 2c 20  r:iEndArcAddr], 
5340: 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29  byteorder='big')
5350: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5360: 20 6e 41 72 63 20 3d 20 6e 52 61 77 41 72 63 20   nArc = nRawArc 
5370: 26 20 73 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 0a  & self._arcMask.
5380: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5390: 69 66 20 6e 41 72 63 20 3e 3d 20 73 65 6c 66 2e  if nArc >= self.
53a0: 6e 43 68 61 72 3a 0a 20 20 20 20 20 20 20 20 20  nChar:.         
53b0: 20 20 20 20 20 20 20 20 20 20 20 23 20 54 68 69             # Thi
53c0: 73 20 76 61 6c 75 65 20 69 73 20 6e 6f 74 20 61  s value is not a
53d0: 20 63 68 61 72 2c 20 74 68 69 73 20 69 73 20 61   char, this is a
53e0: 20 73 74 65 6d 6d 69 6e 67 20 63 6f 64 65 20 0a   stemming code .
53f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5400: 20 20 20 20 6c 2e 61 70 70 65 6e 64 28 73 65 6c      l.append(sel
5410: 66 2e 66 75 6e 63 53 74 65 6d 6d 69 6e 67 28 73  f.funcStemming(s
5420: 57 6f 72 64 2c 20 73 65 6c 66 2e 6c 41 72 63 56  Word, self.lArcV
5430: 61 6c 5b 6e 41 72 63 5d 29 29 0a 20 20 20 20 20  al[nArc])).     
5440: 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72             iAddr
5450: 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72 2b 73   = iEndArcAddr+s
5460: 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64  elf.nBytesNodeAd
5470: 64 72 65 73 73 0a 20 20 20 20 20 20 20 20 20 20  dress.          
5480: 20 20 72 65 74 75 72 6e 20 6c 0a 20 20 20 20 20    return l.     
5490: 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 0a 20 20     return []..  
54a0: 20 20 64 65 66 20 5f 6c 6f 6f 6b 75 70 41 72 63    def _lookupArc
54b0: 4e 6f 64 65 31 20 28 73 65 6c 66 2c 20 6e 56 61  Node1 (self, nVa
54c0: 6c 2c 20 69 41 64 64 72 29 3a 0a 20 20 20 20 20  l, iAddr):.     
54d0: 20 20 20 22 6c 6f 6f 6b 73 20 69 66 20 3c 6e 56     "looks if <nV
54e0: 61 6c 3e 20 69 73 20 61 6e 20 61 72 63 20 61 74  al> is an arc at
54f0: 20 74 68 65 20 6e 6f 64 65 20 61 74 20 3c 69 41   the node at <iA
5500: 64 64 72 3e 2c 20 69 66 20 79 65 73 2c 20 72 65  ddr>, if yes, re
5510: 74 75 72 6e 73 20 61 64 64 72 65 73 73 20 6f 66  turns address of
5520: 20 6e 65 78 74 20 6e 6f 64 65 20 65 6c 73 65 20   next node else 
5530: 4e 6f 6e 65 22 0a 20 20 20 20 20 20 20 20 77 68  None".        wh
5540: 69 6c 65 20 54 72 75 65 3a 0a 20 20 20 20 20 20  ile True:.      
5550: 20 20 20 20 20 20 69 45 6e 64 41 72 63 41 64 64        iEndArcAdd
5560: 72 20 3d 20 69 41 64 64 72 2b 73 65 6c 66 2e 6e  r = iAddr+self.n
5570: 42 79 74 65 73 41 72 63 0a 20 20 20 20 20 20 20  BytesArc.       
5580: 20 20 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69       nRawArc = i
5590: 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65  nt.from_bytes(se
55a0: 6c 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69  lf.byDic[iAddr:i
55b0: 45 6e 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74  EndArcAddr], byt
55c0: 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20  eorder='big').  
55d0: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 56 61            if nVa
55e0: 6c 20 3d 3d 20 28 6e 52 61 77 41 72 63 20 26 20  l == (nRawArc & 
55f0: 73 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 29 3a 0a  self._arcMask):.
5600: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5610: 23 20 74 68 65 20 76 61 6c 75 65 20 77 65 20 61  # the value we a
5620: 72 65 20 6c 6f 6f 6b 69 6e 67 20 66 6f 72 20 0a  re looking for .
5630: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5640: 23 20 77 65 20 72 65 74 75 72 6e 20 74 68 65 20  # we return the 
5650: 61 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 6e  address of the n
5660: 65 78 74 20 6e 6f 64 65 0a 20 20 20 20 20 20 20  ext node.       
5670: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
5680: 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73  int.from_bytes(s
5690: 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41 72  elf.byDic[iEndAr
56a0: 63 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64  cAddr:iEndArcAdd
56b0: 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64  r+self.nBytesNod
56c0: 65 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65 6f  eAddress], byteo
56d0: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
56e0: 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20          else:.  
56f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
5700: 76 61 6c 75 65 20 6e 6f 74 20 66 6f 75 6e 64 0a  value not found.
5710: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5720: 69 66 20 28 6e 52 61 77 41 72 63 20 26 20 73 65  if (nRawArc & se
5730: 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29  lf._lastArcMask)
5740: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
5750: 20 20 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e        return Non
5760: 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e.              
5770: 20 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72    iAddr = iEndAr
5780: 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  cAddr+self.nByte
5790: 73 4e 6f 64 65 41 64 64 72 65 73 73 0a 0a 20 20  sNodeAddress..  
57a0: 20 20 64 65 66 20 5f 67 65 74 41 72 63 73 31 20    def _getArcs1 
57b0: 28 73 65 6c 66 2c 20 69 41 64 64 72 29 3a 0a 20  (self, iAddr):. 
57c0: 20 20 20 20 20 20 20 22 67 65 6e 65 72 61 74 6f         "generato
57d0: 72 3a 20 72 65 74 75 72 6e 20 61 6c 6c 20 61 72  r: return all ar
57e0: 63 73 20 61 74 20 3c 69 41 64 64 72 3e 20 61 73  cs at <iAddr> as
57f0: 20 74 75 70 6c 65 73 20 6f 66 20 28 6e 56 61 6c   tuples of (nVal
5800: 2c 20 69 41 64 64 72 29 22 0a 20 20 20 20 20 20  , iAddr)".      
5810: 20 20 77 68 69 6c 65 20 54 72 75 65 3a 0a 20 20    while True:.  
5820: 20 20 20 20 20 20 20 20 20 20 69 45 6e 64 41 72            iEndAr
5830: 63 41 64 64 72 20 3d 20 69 41 64 64 72 2b 73 65  cAddr = iAddr+se
5840: 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a 20 20 20  lf.nBytesArc.   
5850: 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63           nRawArc
5860: 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65   = int.from_byte
5870: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64  s(self.byDic[iAd
5880: 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72 5d 2c  dr:iEndArcAddr],
5890: 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27   byteorder='big'
58a0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 79 69  ).            yi
58b0: 65 6c 64 20 28 6e 52 61 77 41 72 63 20 26 20 73  eld (nRawArc & s
58c0: 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 2c 20 69 6e  elf._arcMask, in
58d0: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
58e0: 66 2e 62 79 44 69 63 5b 69 45 6e 64 41 72 63 41  f.byDic[iEndArcA
58f0: 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72 2b  ddr:iEndArcAddr+
5900: 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41  self.nBytesNodeA
5910: 64 64 72 65 73 73 5d 2c 20 62 79 74 65 6f 72 64  ddress], byteord
5920: 65 72 3d 27 62 69 67 27 29 29 0a 20 20 20 20 20  er='big')).     
5930: 20 20 20 20 20 20 20 69 66 20 28 6e 52 61 77 41         if (nRawA
5940: 72 63 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41  rc & self._lastA
5950: 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20  rcMask):.       
5960: 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 0a 20           break. 
5970: 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72             iAddr
5980: 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72 2b 73   = iEndArcAddr+s
5990: 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64  elf.nBytesNodeAd
59a0: 64 72 65 73 73 0a 0a 20 20 20 20 64 65 66 20 5f  dress..    def _
59b0: 77 72 69 74 65 4e 6f 64 65 73 31 20 28 73 65 6c  writeNodes1 (sel
59c0: 66 2c 20 73 70 66 44 65 73 74 29 3a 0a 20 20 20  f, spfDest):.   
59d0: 20 20 20 20 20 22 66 6f 72 20 64 65 62 75 67 67       "for debugg
59e0: 69 6e 67 20 6f 6e 6c 79 22 0a 20 20 20 20 20 20  ing only".      
59f0: 20 20 70 72 69 6e 74 28 22 20 3e 20 57 72 69 74    print(" > Writ
5a00: 65 20 62 69 6e 61 72 79 20 6e 6f 64 65 73 22 29  e binary nodes")
5a10: 0a 20 20 20 20 20 20 20 20 77 69 74 68 20 63 6f  .        with co
5a20: 64 65 63 73 2e 6f 70 65 6e 28 73 70 66 44 65 73  decs.open(spfDes
5a30: 74 2c 20 27 77 27 2c 20 27 75 74 66 2d 38 27 2c  t, 'w', 'utf-8',
5a40: 20 6e 65 77 6c 69 6e 65 3d 22 5c 6e 22 29 20 61   newline="\n") a
5a50: 73 20 68 44 73 74 3a 0a 20 20 20 20 20 20 20 20  s hDst:.        
5a60: 20 20 20 20 69 41 64 64 72 20 3d 20 30 0a 20 20      iAddr = 0.  
5a70: 20 20 20 20 20 20 20 20 20 20 68 44 73 74 2e 77            hDst.w
5a80: 72 69 74 65 28 22 69 7b 3a 5f 3e 31 30 7d 20 2d  rite("i{:_>10} -
5a90: 2d 20 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f  - #{:_>10}\n".fo
5aa0: 72 6d 61 74 28 22 30 22 2c 20 69 41 64 64 72 29  rmat("0", iAddr)
5ab0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 77 68  ).            wh
5ac0: 69 6c 65 20 69 41 64 64 72 20 3c 20 6c 65 6e 28  ile iAddr < len(
5ad0: 73 65 6c 66 2e 62 79 44 69 63 29 3a 0a 20 20 20  self.byDic):.   
5ae0: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 45 6e               iEn
5af0: 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64 72  dArcAddr = iAddr
5b00: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a  +self.nBytesArc.
5b10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5b20: 6e 52 61 77 41 72 63 20 3d 20 69 6e 74 2e 66 72  nRawArc = int.fr
5b30: 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79  om_bytes(self.by
5b40: 44 69 63 5b 69 41 64 64 72 3a 69 45 6e 64 41 72  Dic[iAddr:iEndAr
5b50: 63 41 64 64 72 5d 2c 20 62 79 74 65 6f 72 64 65  cAddr], byteorde
5b60: 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20 20  r='big').       
5b70: 20 20 20 20 20 20 20 20 20 6e 41 72 63 20 3d 20           nArc = 
5b80: 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f  nRawArc & self._
5b90: 61 72 63 4d 61 73 6b 0a 20 20 20 20 20 20 20 20  arcMask.        
5ba0: 20 20 20 20 20 20 20 20 68 44 73 74 2e 77 72 69          hDst.wri
5bb0: 74 65 28 22 20 20 7b 3a 3c 32 30 7d 20 20 7b 3a  te("  {:<20}  {:
5bc0: 30 3e 31 36 7d 20 20 69 7b 3a 3e 31 30 7d 20 20  0>16}  i{:>10}  
5bd0: 20 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72   #{:_>10}\n".for
5be0: 6d 61 74 28 73 65 6c 66 2e 6c 41 72 63 56 61 6c  mat(self.lArcVal
5bf0: 5b 6e 41 72 63 5d 2c 20 62 69 6e 28 6e 52 61 77  [nArc], bin(nRaw
5c00: 41 72 63 29 5b 32 3a 5d 2c 20 22 3f 22 2c 20 5c  Arc)[2:], "?", \
5c10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5c20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5c30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5c40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 6e 74               int
5c60: 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66  .from_bytes(self
5c70: 2e 62 79 44 69 63 5b 69 45 6e 64 41 72 63 41 64  .byDic[iEndArcAd
5c80: 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72 2b 73  dr:iEndArcAddr+s
5c90: 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64  elf.nBytesNodeAd
5ca0: 64 72 65 73 73 5d 2c 20 5c 0a 20 20 20 20 20 20  dress], \.      
5cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5cc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ce0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5cf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5d00: 20 20 20 20 20 62 79 74 65 6f 72 64 65 72 3d 27       byteorder='
5d10: 62 69 67 27 29 29 29 0a 20 20 20 20 20 20 20 20  big'))).        
5d20: 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20          iAddr = 
5d30: 69 45 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66  iEndArcAddr+self
5d40: 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65  .nBytesNodeAddre
5d50: 73 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ss.             
5d60: 20 20 20 69 66 20 28 6e 52 61 77 41 72 63 20 26     if (nRawArc &
5d70: 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61   self._lastArcMa
5d80: 73 6b 29 20 61 6e 64 20 69 41 64 64 72 20 3c 20  sk) and iAddr < 
5d90: 6c 65 6e 28 73 65 6c 66 2e 62 79 44 69 63 29 3a  len(self.byDic):
5da0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5db0: 20 20 20 20 20 68 44 73 74 2e 77 72 69 74 65 28       hDst.write(
5dc0: 22 5c 6e 69 7b 3a 5f 3e 31 30 7d 20 2d 2d 20 23  "\ni{:_>10} -- #
5dd0: 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d 61  {:_>10}\n".forma
5de0: 74 28 22 3f 22 2c 20 69 41 64 64 72 29 29 0a 20  t("?", iAddr)). 
5df0: 20 20 20 20 20 20 20 20 20 20 20 68 44 73 74 2e             hDst.
5e00: 63 6c 6f 73 65 28 29 0a 0a 20 20 20 20 23 20 56  close()..    # V
5e10: 45 52 53 49 4f 4e 20 32 0a 20 20 20 20 64 65 66  ERSION 2.    def
5e20: 20 5f 6d 6f 72 70 68 32 20 28 73 65 6c 66 2c 20   _morph2 (self, 
5e30: 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20 20 20  sWord):.        
5e40: 22 72 65 74 75 72 6e 73 20 6d 6f 72 70 68 6f 6c  "returns morphol
5e50: 6f 67 69 65 73 20 6f 66 20 3c 73 57 6f 72 64 3e  ogies of <sWord>
5e60: 22 0a 20 20 20 20 20 20 20 20 69 41 64 64 72 20  ".        iAddr 
5e70: 3d 20 30 0a 20 20 20 20 20 20 20 20 66 6f 72 20  = 0.        for 
5e80: 63 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20 20 20  c in sWord:.    
5e90: 20 20 20 20 20 20 20 20 69 66 20 63 20 6e 6f 74          if c not
5ea0: 20 69 6e 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a   in self.dChar:.
5eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ec0: 72 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20 20 20  return [].      
5ed0: 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 73 65        iAddr = se
5ee0: 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64  lf._lookupArcNod
5ef0: 65 28 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d 2c  e(self.dChar[c],
5f00: 20 69 41 64 64 72 29 0a 20 20 20 20 20 20 20 20   iAddr).        
5f10: 20 20 20 20 69 66 20 69 41 64 64 72 20 3d 3d 20      if iAddr == 
5f20: 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 20 20  None:.          
5f30: 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a        return [].
5f40: 20 20 20 20 20 20 20 20 69 66 20 28 69 6e 74 2e          if (int.
5f50: 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e  from_bytes(self.
5f60: 62 79 44 69 63 5b 69 41 64 64 72 3a 69 41 64 64  byDic[iAddr:iAdd
5f70: 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63  r+self.nBytesArc
5f80: 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69  ], byteorder='bi
5f90: 67 27 29 20 26 20 73 65 6c 66 2e 5f 66 69 6e 61  g') & self._fina
5fa0: 6c 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20 20 20 20  lNodeMask):.    
5fb0: 20 20 20 20 20 20 20 20 6c 20 3d 20 5b 5d 0a 20          l = []. 
5fc0: 20 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41             nRawA
5fd0: 72 63 20 3d 20 30 0a 20 20 20 20 20 20 20 20 20  rc = 0.         
5fe0: 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28 6e 52     while not (nR
5ff0: 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 6c 61  awArc & self._la
6000: 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20  stArcMask):.    
6010: 20 20 20 20 20 20 20 20 20 20 20 20 69 45 6e 64              iEnd
6020: 41 72 63 41 64 64 72 20 3d 20 69 41 64 64 72 20  ArcAddr = iAddr 
6030: 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63  + self.nBytesArc
6040: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6050: 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74 2e 66   nRawArc = int.f
6060: 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62  rom_bytes(self.b
6070: 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e 64 41  yDic[iAddr:iEndA
6080: 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f 72 64  rcAddr], byteord
6090: 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20  er='big').      
60a0: 20 20 20 20 20 20 20 20 20 20 6e 41 72 63 20 3d            nArc =
60b0: 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e   nRawArc & self.
60c0: 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20 20 20  _arcMask.       
60d0: 20 20 20 20 20 20 20 20 20 69 66 20 6e 41 72 63           if nArc
60e0: 20 3e 3d 20 73 65 6c 66 2e 6e 43 68 61 72 3a 0a   >= self.nChar:.
60f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6100: 20 20 20 20 23 20 54 68 69 73 20 76 61 6c 75 65      # This value
6110: 20 69 73 20 6e 6f 74 20 61 20 63 68 61 72 2c 20   is not a char, 
6120: 74 68 69 73 20 69 73 20 61 20 73 74 65 6d 6d 69  this is a stemmi
6130: 6e 67 20 63 6f 64 65 20 0a 20 20 20 20 20 20 20  ng code .       
6140: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 53 74               sSt
6150: 65 6d 20 3d 20 22 3e 22 20 2b 20 73 65 6c 66 2e  em = ">" + self.
6160: 66 75 6e 63 53 74 65 6d 6d 69 6e 67 28 73 57 6f  funcStemming(sWo
6170: 72 64 2c 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c  rd, self.lArcVal
6180: 5b 6e 41 72 63 5d 29 0a 20 20 20 20 20 20 20 20  [nArc]).        
6190: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 4e 6f              # No
61a0: 77 20 2c 20 77 65 20 67 6f 20 74 6f 20 74 68 65  w , we go to the
61b0: 20 6e 65 78 74 20 6e 6f 64 65 20 61 6e 64 20 72   next node and r
61c0: 65 74 72 69 65 76 65 20 61 6c 6c 20 66 6f 6c 6c  etrieve all foll
61d0: 6f 77 69 6e 67 20 61 72 63 73 20 76 61 6c 75 65  owing arcs value
61e0: 73 2c 20 61 6c 6c 20 6f 66 20 74 68 65 6d 20 61  s, all of them a
61f0: 72 65 20 74 61 67 73 0a 20 20 20 20 20 20 20 20  re tags.        
6200: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
6210: 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73 65  ot (nRawArc & se
6220: 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29  lf._addrBitMask)
6230: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
6240: 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72 32            iAddr2
6250: 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65   = int.from_byte
6260: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e  s(self.byDic[iEn
6270: 64 41 72 63 41 64 64 72 3a 69 45 6e 64 41 72 63  dArcAddr:iEndArc
6280: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
6290: 4e 6f 64 65 41 64 64 72 65 73 73 5d 2c 20 62 79  NodeAddress], by
62a0: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20  teorder='big'). 
62b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
62c0: 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20     else:.       
62d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
62e0: 20 23 20 77 65 20 67 6f 20 74 6f 20 74 68 65 20   # we go to the 
62f0: 65 6e 64 20 6f 66 20 74 68 65 20 6e 6f 64 65 0a  end of the node.
6300: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6310: 20 20 20 20 20 20 20 20 69 41 64 64 72 32 20 3d          iAddr2 =
6320: 20 69 45 6e 64 41 72 63 41 64 64 72 0a 20 20 20   iEndArcAddr.   
6330: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6340: 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28       while not (
6350: 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f  nRawArc & self._
6360: 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20  lastArcMask):.  
6370: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6380: 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72            nRawAr
6390: 63 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74  c = int.from_byt
63a0: 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41  es(self.byDic[iA
63b0: 64 64 72 32 3a 69 41 64 64 72 32 2b 73 65 6c 66  ddr2:iAddr2+self
63c0: 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20 62 79 74  .nBytesArc], byt
63d0: 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20  eorder='big').  
63e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
63f0: 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72 32            iAddr2
6400: 20 2b 3d 20 73 65 6c 66 2e 6e 42 79 74 65 73 41   += self.nBytesA
6410: 72 63 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73  rc + self.nBytes
6420: 4e 6f 64 65 41 64 64 72 65 73 73 0a 20 20 20 20  NodeAddress.    
6430: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6440: 6e 52 61 77 41 72 63 32 20 3d 20 30 0a 20 20 20  nRawArc2 = 0.   
6450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6460: 20 77 68 69 6c 65 20 6e 6f 74 20 28 6e 52 61 77   while not (nRaw
6470: 41 72 63 32 20 26 20 73 65 6c 66 2e 5f 6c 61 73  Arc2 & self._las
6480: 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20  tArcMask):.     
6490: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
64a0: 20 20 20 69 45 6e 64 41 72 63 41 64 64 72 32 20     iEndArcAddr2 
64b0: 3d 20 69 41 64 64 72 32 20 2b 20 73 65 6c 66 2e  = iAddr2 + self.
64c0: 6e 42 79 74 65 73 41 72 63 0a 20 20 20 20 20 20  nBytesArc.      
64d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
64e0: 20 20 6e 52 61 77 41 72 63 32 20 3d 20 69 6e 74    nRawArc2 = int
64f0: 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66  .from_bytes(self
6500: 2e 62 79 44 69 63 5b 69 41 64 64 72 32 3a 69 45  .byDic[iAddr2:iE
6510: 6e 64 41 72 63 41 64 64 72 32 5d 2c 20 62 79 74  ndArcAddr2], byt
6520: 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20  eorder='big').  
6530: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6540: 20 20 20 20 20 20 6c 2e 61 70 70 65 6e 64 28 73        l.append(s
6550: 53 74 65 6d 20 2b 20 22 20 22 20 2b 20 73 65 6c  Stem + " " + sel
6560: 66 2e 6c 41 72 63 56 61 6c 5b 6e 52 61 77 41 72  f.lArcVal[nRawAr
6570: 63 32 20 26 20 73 65 6c 66 2e 5f 61 72 63 4d 61  c2 & self._arcMa
6580: 73 6b 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20  sk]).           
6590: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64               iAd
65a0: 64 72 32 20 3d 20 69 45 6e 64 41 72 63 41 64 64  dr2 = iEndArcAdd
65b0: 72 32 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f  r2+self.nBytesNo
65c0: 64 65 41 64 64 72 65 73 73 20 20 69 66 20 6e 6f  deAddress  if no
65d0: 74 20 28 6e 52 61 77 41 72 63 32 20 26 20 73 65  t (nRawArc2 & se
65e0: 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29  lf._addrBitMask)
65f0: 20 65 6c 73 65 20 69 45 6e 64 41 72 63 41 64 64   else iEndArcAdd
6600: 72 32 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r2.             
6610: 20 20 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41     iAddr = iEndA
6620: 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74  rcAddr+self.nByt
6630: 65 73 4e 6f 64 65 41 64 64 72 65 73 73 20 20 69  esNodeAddress  i
6640: 66 20 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26  f not (nRawArc &
6650: 20 73 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61   self._addrBitMa
6660: 73 6b 29 20 20 65 6c 73 65 20 69 45 6e 64 41 72  sk)  else iEndAr
6670: 63 41 64 64 72 0a 20 20 20 20 20 20 20 20 20 20  cAddr.          
6680: 20 20 72 65 74 75 72 6e 20 6c 0a 20 20 20 20 20    return l.     
6690: 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 0a 20 20     return []..  
66a0: 20 20 64 65 66 20 5f 73 74 65 6d 32 20 28 73 65    def _stem2 (se
66b0: 6c 66 2c 20 73 57 6f 72 64 29 3a 0a 20 20 20 20  lf, sWord):.    
66c0: 20 20 20 20 22 72 65 74 75 72 6e 73 20 73 74 65      "returns ste
66d0: 6d 73 20 6c 69 73 74 20 6f 66 20 3c 73 57 6f 72  ms list of <sWor
66e0: 64 3e 22 0a 20 20 20 20 20 20 20 20 69 41 64 64  d>".        iAdd
66f0: 72 20 3d 20 30 0a 20 20 20 20 20 20 20 20 66 6f  r = 0.        fo
6700: 72 20 63 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20  r c in sWord:.  
6710: 20 20 20 20 20 20 20 20 20 20 69 66 20 63 20 6e            if c n
6720: 6f 74 20 69 6e 20 73 65 6c 66 2e 64 43 68 61 72  ot in self.dChar
6730: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
6740: 20 20 72 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20    return [].    
6750: 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20          iAddr = 
6760: 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e  self._lookupArcN
6770: 6f 64 65 28 73 65 6c 66 2e 64 43 68 61 72 5b 63  ode(self.dChar[c
6780: 5d 2c 20 69 41 64 64 72 29 0a 20 20 20 20 20 20  ], iAddr).      
6790: 20 20 20 20 20 20 69 66 20 69 41 64 64 72 20 3d        if iAddr =
67a0: 3d 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20  = None:.        
67b0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b          return [
67c0: 5d 0a 20 20 20 20 20 20 20 20 69 66 20 28 69 6e  ].        if (in
67d0: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
67e0: 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 41  f.byDic[iAddr:iA
67f0: 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41  ddr+self.nBytesA
6800: 72 63 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27  rc], byteorder='
6810: 62 69 67 27 29 20 26 20 73 65 6c 66 2e 5f 66 69  big') & self._fi
6820: 6e 61 6c 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20 20  nalNodeMask):.  
6830: 20 20 20 20 20 20 20 20 20 20 6c 20 3d 20 5b 5d            l = []
6840: 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e 52 61  .            nRa
6850: 77 41 72 63 20 3d 20 30 0a 20 20 20 20 20 20 20  wArc = 0.       
6860: 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28       while not (
6870: 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f  nRawArc & self._
6880: 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20  lastArcMask):.  
6890: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 45                iE
68a0: 6e 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64  ndArcAddr = iAdd
68b0: 72 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41  r + self.nBytesA
68c0: 72 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  rc.             
68d0: 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74     nRawArc = int
68e0: 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66  .from_bytes(self
68f0: 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e  .byDic[iAddr:iEn
6900: 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f  dArcAddr], byteo
6910: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
6920: 20 20 20 20 20 20 20 20 20 20 20 20 6e 41 72 63              nArc
6930: 20 3d 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c   = nRawArc & sel
6940: 66 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20  f._arcMask.     
6950: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 41             if nA
6960: 72 63 20 3e 3d 20 73 65 6c 66 2e 6e 43 68 61 72  rc >= self.nChar
6970: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
6980: 20 20 20 20 20 20 23 20 54 68 69 73 20 76 61 6c        # This val
6990: 75 65 20 69 73 20 6e 6f 74 20 61 20 63 68 61 72  ue is not a char
69a0: 2c 20 74 68 69 73 20 69 73 20 61 20 73 74 65 6d  , this is a stem
69b0: 6d 69 6e 67 20 63 6f 64 65 20 0a 20 20 20 20 20  ming code .     
69c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c                 l
69d0: 2e 61 70 70 65 6e 64 28 73 65 6c 66 2e 66 75 6e  .append(self.fun
69e0: 63 53 74 65 6d 6d 69 6e 67 28 73 57 6f 72 64 2c  cStemming(sWord,
69f0: 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 41   self.lArcVal[nA
6a00: 72 63 5d 29 29 0a 20 20 20 20 20 20 20 20 20 20  rc])).          
6a10: 20 20 20 20 20 20 20 20 20 20 23 20 4e 6f 77 20            # Now 
6a20: 2c 20 77 65 20 67 6f 20 74 6f 20 74 68 65 20 6e  , we go to the n
6a30: 65 78 74 20 6e 6f 64 65 0a 20 20 20 20 20 20 20  ext node.       
6a40: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
6a50: 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73  not (nRawArc & s
6a60: 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b  elf._addrBitMask
6a70: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
6a80: 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72             iAddr
6a90: 32 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74  2 = int.from_byt
6aa0: 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 45  es(self.byDic[iE
6ab0: 6e 64 41 72 63 41 64 64 72 3a 69 45 6e 64 41 72  ndArcAddr:iEndAr
6ac0: 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  cAddr+self.nByte
6ad0: 73 4e 6f 64 65 41 64 64 72 65 73 73 5d 2c 20 62  sNodeAddress], b
6ae0: 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a  yteorder='big').
6af0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6b00: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
6b10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6b20: 20 20 23 20 77 65 20 67 6f 20 74 6f 20 74 68 65    # we go to the
6b30: 20 65 6e 64 20 6f 66 20 74 68 65 20 6e 6f 64 65   end of the node
6b40: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6b50: 20 20 20 20 20 20 20 20 20 69 41 64 64 72 32 20           iAddr2 
6b60: 3d 20 69 45 6e 64 41 72 63 41 64 64 72 0a 20 20  = iEndArcAddr.  
6b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6b80: 20 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20        while not 
6b90: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
6ba0: 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20  _lastArcMask):. 
6bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6bc0: 20 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41             nRawA
6bd0: 72 63 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79  rc = int.from_by
6be0: 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69  tes(self.byDic[i
6bf0: 41 64 64 72 32 3a 69 41 64 64 72 32 2b 73 65 6c  Addr2:iAddr2+sel
6c00: 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20 62 79  f.nBytesArc], by
6c10: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20  teorder='big'). 
6c20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c30: 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72             iAddr
6c40: 32 20 2b 3d 20 73 65 6c 66 2e 6e 42 79 74 65 73  2 += self.nBytes
6c50: 41 72 63 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65  Arc + self.nByte
6c60: 73 4e 6f 64 65 41 64 64 72 65 73 73 0a 20 20 20  sNodeAddress.   
6c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64               iAd
6c80: 64 72 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72  dr = iEndArcAddr
6c90: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65  +self.nBytesNode
6ca0: 41 64 64 72 65 73 73 20 20 69 66 20 6e 6f 74 20  Address  if not 
6cb0: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
6cc0: 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 20 20 65  _addrBitMask)  e
6cd0: 6c 73 65 20 69 45 6e 64 41 72 63 41 64 64 72 0a  lse iEndArcAddr.
6ce0: 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
6cf0: 72 6e 20 6c 0a 20 20 20 20 20 20 20 20 72 65 74  rn l.        ret
6d00: 75 72 6e 20 5b 5d 0a 0a 20 20 20 20 64 65 66 20  urn []..    def 
6d10: 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64 65 32 20  _lookupArcNode2 
6d20: 28 73 65 6c 66 2c 20 6e 56 61 6c 2c 20 69 41 64  (self, nVal, iAd
6d30: 64 72 29 3a 0a 20 20 20 20 20 20 20 20 22 6c 6f  dr):.        "lo
6d40: 6f 6b 73 20 69 66 20 3c 6e 56 61 6c 3e 20 69 73  oks if <nVal> is
6d50: 20 61 6e 20 61 72 63 20 61 74 20 74 68 65 20 6e   an arc at the n
6d60: 6f 64 65 20 61 74 20 3c 69 41 64 64 72 3e 2c 20  ode at <iAddr>, 
6d70: 69 66 20 79 65 73 2c 20 72 65 74 75 72 6e 73 20  if yes, returns 
6d80: 61 64 64 72 65 73 73 20 6f 66 20 6e 65 78 74 20  address of next 
6d90: 6e 6f 64 65 20 65 6c 73 65 20 4e 6f 6e 65 22 0a  node else None".
6da0: 20 20 20 20 20 20 20 20 77 68 69 6c 65 20 54 72          while Tr
6db0: 75 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ue:.            
6dc0: 69 45 6e 64 41 72 63 41 64 64 72 20 3d 20 69 41  iEndArcAddr = iA
6dd0: 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41  ddr+self.nBytesA
6de0: 72 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e  rc.            n
6df0: 52 61 77 41 72 63 20 3d 20 69 6e 74 2e 66 72 6f  RawArc = int.fro
6e00: 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44  m_bytes(self.byD
6e10: 69 63 5b 69 41 64 64 72 3a 69 45 6e 64 41 72 63  ic[iAddr:iEndArc
6e20: 41 64 64 72 5d 2c 20 62 79 74 65 6f 72 64 65 72  Addr], byteorder
6e30: 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20 20 20  ='big').        
6e40: 20 20 20 20 69 66 20 6e 56 61 6c 20 3d 3d 20 28      if nVal == (
6e50: 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f  nRawArc & self._
6e60: 61 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20  arcMask):.      
6e70: 20 20 20 20 20 20 20 20 20 20 23 20 74 68 65 20            # the 
6e80: 76 61 6c 75 65 20 77 65 20 61 72 65 20 6c 6f 6f  value we are loo
6e90: 6b 69 6e 67 20 66 6f 72 20 0a 20 20 20 20 20 20  king for .      
6ea0: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74            if not
6eb0: 20 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66   (nRawArc & self
6ec0: 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 3a 0a  ._addrBitMask):.
6ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ee0: 20 20 20 20 23 20 77 65 20 72 65 74 75 72 6e 20      # we return 
6ef0: 74 68 65 20 61 64 64 72 65 73 73 20 6f 66 20 74  the address of t
6f00: 68 65 20 6e 65 78 74 20 6e 6f 64 65 0a 20 20 20  he next node.   
6f10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6f20: 20 72 65 74 75 72 6e 20 69 6e 74 2e 66 72 6f 6d   return int.from
6f30: 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69  _bytes(self.byDi
6f40: 63 5b 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45  c[iEndArcAddr:iE
6f50: 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e  ndArcAddr+self.n
6f60: 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73  BytesNodeAddress
6f70: 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69  ], byteorder='bi
6f80: 67 27 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  g').            
6f90: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
6fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
6fb0: 77 65 20 67 6f 20 74 6f 20 74 68 65 20 65 6e 64  we go to the end
6fc0: 20 6f 66 20 74 68 65 20 6e 6f 64 65 0a 20 20 20   of the node.   
6fd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6fe0: 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72 63   iAddr = iEndArc
6ff0: 41 64 64 72 0a 20 20 20 20 20 20 20 20 20 20 20  Addr.           
7000: 20 20 20 20 20 20 20 20 20 77 68 69 6c 65 20 6e           while n
7010: 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73 65  ot (nRawArc & se
7020: 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29  lf._lastArcMask)
7030: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
7040: 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72            nRawAr
7050: 63 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74  c = int.from_byt
7060: 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41  es(self.byDic[iA
7070: 64 64 72 3a 69 41 64 64 72 2b 73 65 6c 66 2e 6e  ddr:iAddr+self.n
7080: 42 79 74 65 73 41 72 63 5d 2c 20 62 79 74 65 6f  BytesArc], byteo
7090: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
70a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
70b0: 20 20 20 20 69 41 64 64 72 20 2b 3d 20 73 65 6c      iAddr += sel
70c0: 66 2e 6e 42 79 74 65 73 41 72 63 20 2b 20 73 65  f.nBytesArc + se
70d0: 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64  lf.nBytesNodeAdd
70e0: 72 65 73 73 20 20 69 66 20 6e 6f 74 20 28 6e 52  ress  if not (nR
70f0: 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61 64  awArc & self._ad
7100: 64 72 42 69 74 4d 61 73 6b 29 20 20 65 6c 73 65  drBitMask)  else
7110: 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a   self.nBytesArc.
7120: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7130: 20 20 20 20 72 65 74 75 72 6e 20 69 41 64 64 72      return iAddr
7140: 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73  .            els
7150: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
7160: 20 20 20 23 20 76 61 6c 75 65 20 6e 6f 74 20 66     # value not f
7170: 6f 75 6e 64 0a 20 20 20 20 20 20 20 20 20 20 20  ound.           
7180: 20 20 20 20 20 69 66 20 28 6e 52 61 77 41 72 63       if (nRawArc
7190: 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63   & self._lastArc
71a0: 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20 20 20  Mask):.         
71b0: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
71c0: 6e 20 4e 6f 6e 65 0a 20 20 20 20 20 20 20 20 20  n None.         
71d0: 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 69         iAddr = i
71e0: 45 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e  EndArcAddr+self.
71f0: 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73  nBytesNodeAddres
7200: 73 20 20 69 66 20 6e 6f 74 20 28 6e 52 61 77 41  s  if not (nRawA
7210: 72 63 20 26 20 73 65 6c 66 2e 5f 61 64 64 72 42  rc & self._addrB
7220: 69 74 4d 61 73 6b 29 20 20 65 6c 73 65 20 69 45  itMask)  else iE
7230: 6e 64 41 72 63 41 64 64 72 0a 0a 20 20 20 20 64  ndArcAddr..    d
7240: 65 66 20 5f 77 72 69 74 65 4e 6f 64 65 73 32 20  ef _writeNodes2 
7250: 28 73 65 6c 66 2c 20 73 70 66 44 65 73 74 29 3a  (self, spfDest):
7260: 0a 20 20 20 20 20 20 20 20 22 66 6f 72 20 64 65  .        "for de
7270: 62 75 67 67 69 6e 67 20 6f 6e 6c 79 22 0a 20 20  bugging only".  
7280: 20 20 20 20 20 20 70 72 69 6e 74 28 22 20 3e 20        print(" > 
7290: 57 72 69 74 65 20 62 69 6e 61 72 79 20 6e 6f 64  Write binary nod
72a0: 65 73 22 29 0a 20 20 20 20 20 20 20 20 77 69 74  es").        wit
72b0: 68 20 63 6f 64 65 63 73 2e 6f 70 65 6e 28 73 70  h codecs.open(sp
72c0: 66 44 65 73 74 2c 20 27 77 27 2c 20 27 75 74 66  fDest, 'w', 'utf
72d0: 2d 38 27 2c 20 6e 65 77 6c 69 6e 65 3d 22 5c 6e  -8', newline="\n
72e0: 22 29 20 61 73 20 68 44 73 74 3a 0a 20 20 20 20  ") as hDst:.    
72f0: 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20          iAddr = 
7300: 30 0a 20 20 20 20 20 20 20 20 20 20 20 20 68 44  0.            hD
7310: 73 74 2e 77 72 69 74 65 28 22 69 7b 3a 5f 3e 31  st.write("i{:_>1
7320: 30 7d 20 2d 2d 20 23 7b 3a 5f 3e 31 30 7d 5c 6e  0} -- #{:_>10}\n
7330: 22 2e 66 6f 72 6d 61 74 28 22 30 22 2c 20 69 41  ".format("0", iA
7340: 64 64 72 29 29 0a 20 20 20 20 20 20 20 20 20 20  ddr)).          
7350: 20 20 77 68 69 6c 65 20 69 41 64 64 72 20 3c 20    while iAddr < 
7360: 6c 65 6e 28 73 65 6c 66 2e 62 79 44 69 63 29 3a  len(self.byDic):
7370: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
7380: 20 69 45 6e 64 41 72 63 41 64 64 72 20 3d 20 69   iEndArcAddr = i
7390: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
73a0: 41 72 63 0a 20 20 20 20 20 20 20 20 20 20 20 20  Arc.            
73b0: 20 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e      nRawArc = in
73c0: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
73d0: 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45  f.byDic[iAddr:iE
73e0: 6e 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65  ndArcAddr], byte
73f0: 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20  order='big').   
7400: 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 41 72               nAr
7410: 63 20 3d 20 6e 52 61 77 41 72 63 20 26 20 73 65  c = nRawArc & se
7420: 6c 66 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20  lf._arcMask.    
7430: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
7440: 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73 65  ot (nRawArc & se
7450: 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29  lf._addrBitMask)
7460: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
7470: 20 20 20 20 20 20 69 4e 65 78 74 4e 6f 64 65 41        iNextNodeA
7480: 64 64 72 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62  ddr = int.from_b
7490: 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b  ytes(self.byDic[
74a0: 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e 64  iEndArcAddr:iEnd
74b0: 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  ArcAddr+self.nBy
74c0: 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 5d 2c  tesNodeAddress],
74d0: 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27   byteorder='big'
74e0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
74f0: 20 20 20 20 20 20 68 44 73 74 2e 77 72 69 74 65        hDst.write
7500: 28 22 20 20 7b 3a 3c 32 30 7d 20 20 7b 3a 30 3e  ("  {:<20}  {:0>
7510: 31 36 7d 20 20 69 7b 3a 3e 31 30 7d 20 20 20 23  16}  i{:>10}   #
7520: 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d 61  {:_>10}\n".forma
7530: 74 28 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e  t(self.lArcVal[n
7540: 41 72 63 5d 2c 20 62 69 6e 28 6e 52 61 77 41 72  Arc], bin(nRawAr
7550: 63 29 5b 32 3a 5d 2c 20 22 3f 22 2c 20 69 4e 65  c)[2:], "?", iNe
7560: 78 74 4e 6f 64 65 41 64 64 72 29 29 0a 20 20 20  xtNodeAddr)).   
7570: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7580: 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72 63   iAddr = iEndArc
7590: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
75a0: 4e 6f 64 65 41 64 64 72 65 73 73 0a 20 20 20 20  NodeAddress.    
75b0: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
75c0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
75d0: 20 20 20 20 20 20 68 44 73 74 2e 77 72 69 74 65        hDst.write
75e0: 28 22 20 20 7b 3a 3c 32 30 7d 20 20 7b 3a 30 3e  ("  {:<20}  {:0>
75f0: 31 36 7d 5c 6e 22 2e 66 6f 72 6d 61 74 28 73 65  16}\n".format(se
7600: 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 41 72 63 5d  lf.lArcVal[nArc]
7610: 2c 20 62 69 6e 28 6e 52 61 77 41 72 63 29 5b 32  , bin(nRawArc)[2
7620: 3a 5d 29 29 0a 20 20 20 20 20 20 20 20 20 20 20  :])).           
7630: 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d           iAddr =
7640: 20 69 45 6e 64 41 72 63 41 64 64 72 0a 20 20 20   iEndArcAddr.   
7650: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
7660: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
7670: 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20  _lastArcMask):. 
7680: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7690: 20 20 20 68 44 73 74 2e 77 72 69 74 65 28 22 5c     hDst.write("\
76a0: 6e 69 7b 3a 5f 3e 31 30 7d 20 2d 2d 20 23 7b 3a  ni{:_>10} -- #{:
76b0: 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d 61 74 28  _>10}\n".format(
76c0: 22 3f 22 2c 20 69 41 64 64 72 29 29 0a 20 20 20  "?", iAddr)).   
76d0: 20 20 20 20 20 20 20 20 20 68 44 73 74 2e 63 6c           hDst.cl
76e0: 6f 73 65 28 29 0a 0a 20 20 20 20 23 20 56 45 52  ose()..    # VER
76f0: 53 49 4f 4e 20 33 0a 20 20 20 20 64 65 66 20 5f  SION 3.    def _
7700: 6d 6f 72 70 68 33 20 28 73 65 6c 66 2c 20 73 57  morph3 (self, sW
7710: 6f 72 64 29 3a 0a 20 20 20 20 20 20 20 20 22 72  ord):.        "r
7720: 65 74 75 72 6e 73 20 6d 6f 72 70 68 6f 6c 6f 67  eturns morpholog
7730: 69 65 73 20 6f 66 20 3c 73 57 6f 72 64 3e 22 0a  ies of <sWord>".
7740: 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20          iAddr = 
7750: 30 0a 20 20 20 20 20 20 20 20 66 6f 72 20 63 20  0.        for c 
7760: 69 6e 20 73 57 6f 72 64 3a 0a 20 20 20 20 20 20  in sWord:.      
7770: 20 20 20 20 20 20 69 66 20 63 20 6e 6f 74 20 69        if c not i
7780: 6e 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a 20 20  n self.dChar:.  
7790: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
77a0: 74 75 72 6e 20 5b 5d 0a 20 20 20 20 20 20 20 20  turn [].        
77b0: 20 20 20 20 69 41 64 64 72 20 3d 20 73 65 6c 66      iAddr = self
77c0: 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64 65 28  ._lookupArcNode(
77d0: 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d 2c 20 69  self.dChar[c], i
77e0: 41 64 64 72 29 0a 20 20 20 20 20 20 20 20 20 20  Addr).          
77f0: 20 20 69 66 20 69 41 64 64 72 20 3d 3d 20 4e 6f    if iAddr == No
7800: 6e 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ne:.            
7810: 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 20 20      return [].  
7820: 20 20 20 20 20 20 69 66 20 28 69 6e 74 2e 66 72        if (int.fr
7830: 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79  om_bytes(self.by
7840: 44 69 63 5b 69 41 64 64 72 3a 69 41 64 64 72 2b  Dic[iAddr:iAddr+
7850: 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c  self.nBytesArc],
7860: 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27   byteorder='big'
7870: 29 20 26 20 73 65 6c 66 2e 5f 66 69 6e 61 6c 4e  ) & self._finalN
7880: 6f 64 65 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20  odeMask):.      
7890: 20 20 20 20 20 20 6c 20 3d 20 5b 5d 0a 20 20 20        l = [].   
78a0: 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63           nRawArc
78b0: 20 3d 20 30 0a 20 20 20 20 20 20 20 20 20 20 20   = 0.           
78c0: 20 69 41 64 64 72 4e 6f 64 65 20 3d 20 69 41 64   iAddrNode = iAd
78d0: 64 72 0a 20 20 20 20 20 20 20 20 20 20 20 20 77  dr.            w
78e0: 68 69 6c 65 20 6e 6f 74 20 28 6e 52 61 77 41 72  hile not (nRawAr
78f0: 63 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72  c & self._lastAr
7900: 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20 20  cMask):.        
7910: 20 20 20 20 20 20 20 20 69 45 6e 64 41 72 63 41          iEndArcA
7920: 64 64 72 20 3d 20 69 41 64 64 72 20 2b 20 73 65  ddr = iAddr + se
7930: 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a 20 20 20  lf.nBytesArc.   
7940: 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 52 61               nRa
7950: 77 41 72 63 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f  wArc = int.from_
7960: 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63  bytes(self.byDic
7970: 5b 69 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64  [iAddr:iEndArcAd
7980: 64 72 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27  dr], byteorder='
7990: 62 69 67 27 29 0a 20 20 20 20 20 20 20 20 20 20  big').          
79a0: 20 20 20 20 20 20 6e 41 72 63 20 3d 20 6e 52 61        nArc = nRa
79b0: 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61 72 63  wArc & self._arc
79c0: 4d 61 73 6b 0a 20 20 20 20 20 20 20 20 20 20 20  Mask.           
79d0: 20 20 20 20 20 69 66 20 6e 41 72 63 20 3e 3d 20       if nArc >= 
79e0: 73 65 6c 66 2e 6e 43 68 61 72 3a 0a 20 20 20 20  self.nChar:.    
79f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7a00: 23 20 54 68 69 73 20 76 61 6c 75 65 20 69 73 20  # This value is 
7a10: 6e 6f 74 20 61 20 63 68 61 72 2c 20 74 68 69 73  not a char, this
7a20: 20 69 73 20 61 20 73 74 65 6d 6d 69 6e 67 20 63   is a stemming c
7a30: 6f 64 65 20 0a 20 20 20 20 20 20 20 20 20 20 20  ode .           
7a40: 20 20 20 20 20 20 20 20 20 73 53 74 65 6d 20 3d           sStem =
7a50: 20 22 3e 22 20 2b 20 73 65 6c 66 2e 66 75 6e 63   ">" + self.func
7a60: 53 74 65 6d 6d 69 6e 67 28 73 57 6f 72 64 2c 20  Stemming(sWord, 
7a70: 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 41 72  self.lArcVal[nAr
7a80: 63 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  c]).            
7a90: 20 20 20 20 20 20 20 20 23 20 4e 6f 77 20 2c 20          # Now , 
7aa0: 77 65 20 67 6f 20 74 6f 20 74 68 65 20 6e 65 78  we go to the nex
7ab0: 74 20 6e 6f 64 65 20 61 6e 64 20 72 65 74 72 69  t node and retri
7ac0: 65 76 65 20 61 6c 6c 20 66 6f 6c 6c 6f 77 69 6e  eve all followin
7ad0: 67 20 61 72 63 73 20 76 61 6c 75 65 73 2c 20 61  g arcs values, a
7ae0: 6c 6c 20 6f 66 20 74 68 65 6d 20 61 72 65 20 74  ll of them are t
7af0: 61 67 73 0a 20 20 20 20 20 20 20 20 20 20 20 20  ags.            
7b00: 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 28          if not (
7b10: 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f  nRawArc & self._
7b20: 61 64 64 72 42 69 74 4d 61 73 6b 29 3a 0a 20 20  addrBitMask):.  
7b30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7b40: 20 20 20 20 20 20 69 41 64 64 72 32 20 3d 20 69        iAddr2 = i
7b50: 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65  nt.from_bytes(se
7b60: 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41 72 63  lf.byDic[iEndArc
7b70: 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72  Addr:iEndArcAddr
7b80: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65  +self.nBytesNode
7b90: 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65 6f 72  Address], byteor
7ba0: 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20  der='big').     
7bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
7bc0: 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  lse:.           
7bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64               iAd
7be0: 64 72 32 20 3d 20 69 41 64 64 72 4e 6f 64 65 20  dr2 = iAddrNode 
7bf0: 2b 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73  + int.from_bytes
7c00: 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64  (self.byDic[iEnd
7c10: 41 72 63 41 64 64 72 3a 69 45 6e 64 41 72 63 41  ArcAddr:iEndArcA
7c20: 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4f  ddr+self.nBytesO
7c30: 66 66 73 65 74 5d 2c 20 62 79 74 65 6f 72 64 65  ffset], byteorde
7c40: 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20 20  r='big').       
7c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 52 61               nRa
7c60: 77 41 72 63 32 20 3d 20 30 0a 20 20 20 20 20 20  wArc2 = 0.      
7c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 77 68                wh
7c80: 69 6c 65 20 6e 6f 74 20 28 6e 52 61 77 41 72 63  ile not (nRawArc
7c90: 32 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72  2 & self._lastAr
7ca0: 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20 20  cMask):.        
7cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7cc0: 69 45 6e 64 41 72 63 41 64 64 72 32 20 3d 20 69  iEndArcAddr2 = i
7cd0: 41 64 64 72 32 20 2b 20 73 65 6c 66 2e 6e 42 79  Addr2 + self.nBy
7ce0: 74 65 73 41 72 63 0a 20 20 20 20 20 20 20 20 20  tesArc.         
7cf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e                 n
7d00: 52 61 77 41 72 63 32 20 3d 20 69 6e 74 2e 66 72  RawArc2 = int.fr
7d10: 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79  om_bytes(self.by
7d20: 44 69 63 5b 69 41 64 64 72 32 3a 69 45 6e 64 41  Dic[iAddr2:iEndA
7d30: 72 63 41 64 64 72 32 5d 2c 20 62 79 74 65 6f 72  rcAddr2], byteor
7d40: 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20  der='big').     
7d50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7d60: 20 20 20 6c 2e 61 70 70 65 6e 64 28 73 53 74 65     l.append(sSte
7d70: 6d 20 2b 20 22 20 22 20 2b 20 73 65 6c 66 2e 6c  m + " " + self.l
7d80: 41 72 63 56 61 6c 5b 6e 52 61 77 41 72 63 32 20  ArcVal[nRawArc2 
7d90: 26 20 73 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 5d  & self._arcMask]
7da0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
7db0: 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72 32            iAddr2
7dc0: 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72 32 2b   = iEndArcAddr2+
7dd0: 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41  self.nBytesNodeA
7de0: 64 64 72 65 73 73 20 20 69 66 20 6e 6f 74 20 28  ddress  if not (
7df0: 6e 52 61 77 41 72 63 32 20 26 20 73 65 6c 66 2e  nRawArc2 & self.
7e00: 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 20 65 6c  _addrBitMask) el
7e10: 73 65 20 69 45 6e 64 41 72 63 41 64 64 72 32 2b  se iEndArcAddr2+
7e20: 73 65 6c 66 2e 6e 42 79 74 65 73 4f 66 66 73 65  self.nBytesOffse
7e30: 74 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  t.              
7e40: 20 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72    iAddr = iEndAr
7e50: 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  cAddr+self.nByte
7e60: 73 4e 6f 64 65 41 64 64 72 65 73 73 20 20 69 66  sNodeAddress  if
7e70: 20 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20   not (nRawArc & 
7e80: 73 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73  self._addrBitMas
7e90: 6b 29 20 20 65 6c 73 65 20 69 45 6e 64 41 72 63  k)  else iEndArc
7ea0: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
7eb0: 4f 66 66 73 65 74 0a 20 20 20 20 20 20 20 20 20  Offset.         
7ec0: 20 20 20 72 65 74 75 72 6e 20 6c 0a 20 20 20 20     return l.    
7ed0: 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 0a 20      return [].. 
7ee0: 20 20 20 64 65 66 20 5f 73 74 65 6d 33 20 28 73     def _stem3 (s
7ef0: 65 6c 66 2c 20 73 57 6f 72 64 29 3a 0a 20 20 20  elf, sWord):.   
7f00: 20 20 20 20 20 22 72 65 74 75 72 6e 73 20 73 74       "returns st
7f10: 65 6d 73 20 6c 69 73 74 20 6f 66 20 3c 73 57 6f  ems list of <sWo
7f20: 72 64 3e 22 0a 20 20 20 20 20 20 20 20 69 41 64  rd>".        iAd
7f30: 64 72 20 3d 20 30 0a 20 20 20 20 20 20 20 20 66  dr = 0.        f
7f40: 6f 72 20 63 20 69 6e 20 73 57 6f 72 64 3a 0a 20  or c in sWord:. 
7f50: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 63 20             if c 
7f60: 6e 6f 74 20 69 6e 20 73 65 6c 66 2e 64 43 68 61  not in self.dCha
7f70: 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r:.             
7f80: 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 20 20 20     return [].   
7f90: 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d           iAddr =
7fa0: 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63   self._lookupArc
7fb0: 4e 6f 64 65 28 73 65 6c 66 2e 64 43 68 61 72 5b  Node(self.dChar[
7fc0: 63 5d 2c 20 69 41 64 64 72 29 0a 20 20 20 20 20  c], iAddr).     
7fd0: 20 20 20 20 20 20 20 69 66 20 69 41 64 64 72 20         if iAddr 
7fe0: 3d 3d 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20  == None:.       
7ff0: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
8000: 5b 5d 0a 20 20 20 20 20 20 20 20 69 66 20 28 69  [].        if (i
8010: 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65  nt.from_bytes(se
8020: 6c 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69  lf.byDic[iAddr:i
8030: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
8040: 41 72 63 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d  Arc], byteorder=
8050: 27 62 69 67 27 29 20 26 20 73 65 6c 66 2e 5f 66  'big') & self._f
8060: 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20  inalNodeMask):. 
8070: 20 20 20 20 20 20 20 20 20 20 20 6c 20 3d 20 5b             l = [
8080: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e 52  ].            nR
8090: 61 77 41 72 63 20 3d 20 30 0a 20 20 20 20 20 20  awArc = 0.      
80a0: 20 20 20 20 20 20 69 41 64 64 72 4e 6f 64 65 20        iAddrNode 
80b0: 3d 20 69 41 64 64 72 0a 20 20 20 20 20 20 20 20  = iAddr.        
80c0: 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28 6e      while not (n
80d0: 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 6c  RawArc & self._l
80e0: 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20  astArcMask):.   
80f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 45 6e               iEn
8100: 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64 72  dArcAddr = iAddr
8110: 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72   + self.nBytesAr
8120: 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  c.              
8130: 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74 2e    nRawArc = int.
8140: 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e  from_bytes(self.
8150: 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e 64  byDic[iAddr:iEnd
8160: 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f 72  ArcAddr], byteor
8170: 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20  der='big').     
8180: 20 20 20 20 20 20 20 20 20 20 20 6e 41 72 63 20             nArc 
8190: 3d 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66  = nRawArc & self
81a0: 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20 20  ._arcMask.      
81b0: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 41 72            if nAr
81c0: 63 20 3e 3d 20 73 65 6c 66 2e 6e 43 68 61 72 3a  c >= self.nChar:
81d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
81e0: 20 20 20 20 20 23 20 54 68 69 73 20 76 61 6c 75       # This valu
81f0: 65 20 69 73 20 6e 6f 74 20 61 20 63 68 61 72 2c  e is not a char,
8200: 20 74 68 69 73 20 69 73 20 61 20 73 74 65 6d 6d   this is a stemm
8210: 69 6e 67 20 63 6f 64 65 20 0a 20 20 20 20 20 20  ing code .      
8220: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c 2e                l.
8230: 61 70 70 65 6e 64 28 73 65 6c 66 2e 66 75 6e 63  append(self.func
8240: 53 74 65 6d 6d 69 6e 67 28 73 57 6f 72 64 2c 20  Stemming(sWord, 
8250: 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 41 72  self.lArcVal[nAr
8260: 63 5d 29 29 0a 20 20 20 20 20 20 20 20 20 20 20  c])).           
8270: 20 20 20 20 20 69 41 64 64 72 20 3d 20 69 45 6e       iAddr = iEn
8280: 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dArcAddr+self.nB
8290: 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 20  ytesNodeAddress 
82a0: 20 69 66 20 6e 6f 74 20 28 6e 52 61 77 41 72 63   if not (nRawArc
82b0: 20 26 20 73 65 6c 66 2e 5f 61 64 64 72 42 69 74   & self._addrBit
82c0: 4d 61 73 6b 29 20 20 65 6c 73 65 20 69 45 6e 64  Mask)  else iEnd
82d0: 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  ArcAddr+self.nBy
82e0: 74 65 73 4f 66 66 73 65 74 0a 20 20 20 20 20 20  tesOffset.      
82f0: 20 20 20 20 20 20 72 65 74 75 72 6e 20 6c 0a 20        return l. 
8300: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d         return []
8310: 0a 0a 20 20 20 20 64 65 66 20 5f 6c 6f 6f 6b 75  ..    def _looku
8320: 70 41 72 63 4e 6f 64 65 33 20 28 73 65 6c 66 2c  pArcNode3 (self,
8330: 20 6e 56 61 6c 2c 20 69 41 64 64 72 29 3a 0a 20   nVal, iAddr):. 
8340: 20 20 20 20 20 20 20 22 6c 6f 6f 6b 73 20 69 66         "looks if
8350: 20 3c 6e 56 61 6c 3e 20 69 73 20 61 6e 20 61 72   <nVal> is an ar
8360: 63 20 61 74 20 74 68 65 20 6e 6f 64 65 20 61 74  c at the node at
8370: 20 3c 69 41 64 64 72 3e 2c 20 69 66 20 79 65 73   <iAddr>, if yes
8380: 2c 20 72 65 74 75 72 6e 73 20 61 64 64 72 65 73  , returns addres
8390: 73 20 6f 66 20 6e 65 78 74 20 6e 6f 64 65 20 65  s of next node e
83a0: 6c 73 65 20 4e 6f 6e 65 22 0a 20 20 20 20 20 20  lse None".      
83b0: 20 20 69 41 64 64 72 4e 6f 64 65 20 3d 20 69 41    iAddrNode = iA
83c0: 64 64 72 0a 20 20 20 20 20 20 20 20 77 68 69 6c  ddr.        whil
83d0: 65 20 54 72 75 65 3a 0a 20 20 20 20 20 20 20 20  e True:.        
83e0: 20 20 20 20 69 45 6e 64 41 72 63 41 64 64 72 20      iEndArcAddr 
83f0: 3d 20 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  = iAddr+self.nBy
8400: 74 65 73 41 72 63 0a 20 20 20 20 20 20 20 20 20  tesArc.         
8410: 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74     nRawArc = int
8420: 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66  .from_bytes(self
8430: 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e  .byDic[iAddr:iEn
8440: 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f  dArcAddr], byteo
8450: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
8460: 20 20 20 20 20 20 20 20 69 66 20 6e 56 61 6c 20          if nVal 
8470: 3d 3d 20 28 6e 52 61 77 41 72 63 20 26 20 73 65  == (nRawArc & se
8480: 6c 66 2e 5f 61 72 63 4d 61 73 6b 29 3a 0a 20 20  lf._arcMask):.  
8490: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
84a0: 74 68 65 20 76 61 6c 75 65 20 77 65 20 61 72 65  the value we are
84b0: 20 6c 6f 6f 6b 69 6e 67 20 66 6f 72 20 0a 20 20   looking for .  
84c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
84d0: 20 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20   not (nRawArc & 
84e0: 73 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73  self._addrBitMas
84f0: 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  k):.            
8500: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 69          return i
8510: 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65  nt.from_bytes(se
8520: 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41 72 63  lf.byDic[iEndArc
8530: 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72  Addr:iEndArcAddr
8540: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65  +self.nBytesNode
8550: 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65 6f 72  Address], byteor
8560: 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20  der='big').     
8570: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
8580: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8590: 20 20 20 20 20 72 65 74 75 72 6e 20 69 41 64 64       return iAdd
85a0: 72 4e 6f 64 65 20 2b 20 69 6e 74 2e 66 72 6f 6d  rNode + int.from
85b0: 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69  _bytes(self.byDi
85c0: 63 5b 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45  c[iEndArcAddr:iE
85d0: 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e  ndArcAddr+self.n
85e0: 42 79 74 65 73 4f 66 66 73 65 74 5d 2c 20 62 79  BytesOffset], by
85f0: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20  teorder='big'). 
8600: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
8610: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8620: 20 23 20 76 61 6c 75 65 20 6e 6f 74 20 66 6f 75   # value not fou
8630: 6e 64 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  nd.             
8640: 20 20 20 69 66 20 28 6e 52 61 77 41 72 63 20 26     if (nRawArc &
8650: 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61   self._lastArcMa
8660: 73 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  sk):.           
8670: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
8680: 4e 6f 6e 65 0a 20 20 20 20 20 20 20 20 20 20 20  None.           
8690: 20 20 20 20 20 69 41 64 64 72 20 3d 20 69 45 6e       iAddr = iEn
86a0: 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dArcAddr+self.nB
86b0: 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 20  ytesNodeAddress 
86c0: 20 69 66 20 6e 6f 74 20 28 6e 52 61 77 41 72 63   if not (nRawArc
86d0: 20 26 20 73 65 6c 66 2e 5f 61 64 64 72 42 69 74   & self._addrBit
86e0: 4d 61 73 6b 29 20 20 65 6c 73 65 20 69 45 6e 64  Mask)  else iEnd
86f0: 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  ArcAddr+self.nBy
8700: 74 65 73 4f 66 66 73 65 74 0a 0a 20 20 20 20 64  tesOffset..    d
8710: 65 66 20 5f 77 72 69 74 65 4e 6f 64 65 73 33 20  ef _writeNodes3 
8720: 28 73 65 6c 66 2c 20 73 70 66 44 65 73 74 29 3a  (self, spfDest):
8730: 0a 20 20 20 20 20 20 20 20 22 66 6f 72 20 64 65  .        "for de
8740: 62 75 67 67 69 6e 67 20 6f 6e 6c 79 22 0a 20 20  bugging only".  
8750: 20 20 20 20 20 20 70 72 69 6e 74 28 22 20 3e 20        print(" > 
8760: 57 72 69 74 65 20 62 69 6e 61 72 79 20 6e 6f 64  Write binary nod
8770: 65 73 22 29 0a 20 20 20 20 20 20 20 20 77 69 74  es").        wit
8780: 68 20 63 6f 64 65 63 73 2e 6f 70 65 6e 28 73 70  h codecs.open(sp
8790: 66 44 65 73 74 2c 20 27 77 27 2c 20 27 75 74 66  fDest, 'w', 'utf
87a0: 2d 38 27 2c 20 6e 65 77 6c 69 6e 65 3d 22 5c 6e  -8', newline="\n
87b0: 22 29 20 61 73 20 68 44 73 74 3a 0a 20 20 20 20  ") as hDst:.    
87c0: 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20          iAddr = 
87d0: 30 0a 20 20 20 20 20 20 20 20 20 20 20 20 68 44  0.            hD
87e0: 73 74 2e 77 72 69 74 65 28 22 69 7b 3a 5f 3e 31  st.write("i{:_>1
87f0: 30 7d 20 2d 2d 20 23 7b 3a 5f 3e 31 30 7d 5c 6e  0} -- #{:_>10}\n
8800: 22 2e 66 6f 72 6d 61 74 28 22 30 22 2c 20 69 41  ".format("0", iA
8810: 64 64 72 29 29 0a 20 20 20 20 20 20 20 20 20 20  ddr)).          
8820: 20 20 77 68 69 6c 65 20 69 41 64 64 72 20 3c 20    while iAddr < 
8830: 6c 65 6e 28 73 65 6c 66 2e 62 79 44 69 63 29 3a  len(self.byDic):
8840: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8850: 20 69 45 6e 64 41 72 63 41 64 64 72 20 3d 20 69   iEndArcAddr = i
8860: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
8870: 41 72 63 0a 20 20 20 20 20 20 20 20 20 20 20 20  Arc.            
8880: 20 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e      nRawArc = in
8890: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
88a0: 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45  f.byDic[iAddr:iE
88b0: 6e 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65  ndArcAddr], byte
88c0: 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20  order='big').   
88d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 41 72               nAr
88e0: 63 20 3d 20 6e 52 61 77 41 72 63 20 26 20 73 65  c = nRawArc & se
88f0: 6c 66 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20  lf._arcMask.    
8900: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
8910: 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73 65  ot (nRawArc & se
8920: 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29  lf._addrBitMask)
8930: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
8940: 20 20 20 20 20 20 69 4e 65 78 74 4e 6f 64 65 41        iNextNodeA
8950: 64 64 72 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62  ddr = int.from_b
8960: 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b  ytes(self.byDic[
8970: 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e 64  iEndArcAddr:iEnd
8980: 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  ArcAddr+self.nBy
8990: 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 5d 2c  tesNodeAddress],
89a0: 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27   byteorder='big'
89b0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
89c0: 20 20 20 20 20 20 68 44 73 74 2e 77 72 69 74 65        hDst.write
89d0: 28 22 20 20 7b 3a 3c 32 30 7d 20 20 7b 3a 30 3e  ("  {:<20}  {:0>
89e0: 31 36 7d 20 20 69 7b 3a 3e 31 30 7d 20 20 20 23  16}  i{:>10}   #
89f0: 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d 61  {:_>10}\n".forma
8a00: 74 28 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e  t(self.lArcVal[n
8a10: 41 72 63 5d 2c 20 62 69 6e 28 6e 52 61 77 41 72  Arc], bin(nRawAr
8a20: 63 29 5b 32 3a 5d 2c 20 22 3f 22 2c 20 69 4e 65  c)[2:], "?", iNe
8a30: 78 74 4e 6f 64 65 41 64 64 72 29 29 0a 20 20 20  xtNodeAddr)).   
8a40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8a50: 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72 63   iAddr = iEndArc
8a60: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
8a70: 4e 6f 64 65 41 64 64 72 65 73 73 0a 20 20 20 20  NodeAddress.    
8a80: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
8a90: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
8aa0: 20 20 20 20 20 20 69 4e 65 78 74 4e 6f 64 65 41        iNextNodeA
8ab0: 64 64 72 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62  ddr = int.from_b
8ac0: 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b  ytes(self.byDic[
8ad0: 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e 64  iEndArcAddr:iEnd
8ae0: 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  ArcAddr+self.nBy
8af0: 74 65 73 4f 66 66 73 65 74 5d 2c 20 62 79 74 65  tesOffset], byte
8b00: 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20  order='big').   
8b10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8b20: 20 68 44 73 74 2e 77 72 69 74 65 28 22 20 20 7b   hDst.write("  {
8b30: 3a 3c 32 30 7d 20 20 7b 3a 30 3e 31 36 7d 20 20  :<20}  {:0>16}  
8b40: 69 7b 3a 3e 31 30 7d 20 20 20 2b 7b 3a 5f 3e 31  i{:>10}   +{:_>1
8b50: 30 7d 5c 6e 22 2e 66 6f 72 6d 61 74 28 73 65 6c  0}\n".format(sel
8b60: 66 2e 6c 41 72 63 56 61 6c 5b 6e 41 72 63 5d 2c  f.lArcVal[nArc],
8b70: 20 62 69 6e 28 6e 52 61 77 41 72 63 29 5b 32 3a   bin(nRawArc)[2:
8b80: 5d 2c 20 22 3f 22 2c 20 69 4e 65 78 74 4e 6f 64  ], "?", iNextNod
8b90: 65 41 64 64 72 29 29 0a 20 20 20 20 20 20 20 20  eAddr)).        
8ba0: 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64              iAdd
8bb0: 72 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72 2b  r = iEndArcAddr+
8bc0: 73 65 6c 66 2e 6e 42 79 74 65 73 4f 66 66 73 65  self.nBytesOffse
8bd0: 74 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  t.              
8be0: 20 20 69 66 20 28 6e 52 61 77 41 72 63 20 26 20    if (nRawArc & 
8bf0: 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73  self._lastArcMas
8c00: 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  k):.            
8c10: 20 20 20 20 20 20 20 20 68 44 73 74 2e 77 72 69          hDst.wri
8c20: 74 65 28 22 5c 6e 69 7b 3a 5f 3e 31 30 7d 20 2d  te("\ni{:_>10} -
8c30: 2d 20 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f  - #{:_>10}\n".fo
8c40: 72 6d 61 74 28 22 3f 22 2c 20 69 41 64 64 72 29  rmat("?", iAddr)
8c50: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 68 44  ).            hD
8c60: 73 74 2e 63 6c 6f 73 65 28 29 0a                 st.close().