Grammalecte  Hex Artifact Content

Artifact c41b426a86e03e8c3d9734597e4d607bda77ed66ebfa9f0133bc26a7a4073f5e:


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 74 69 6d 65 0a 69 6d 70 6f 72 74 20 6a 73  t time.import js
0070: 6f 6e 0a 69 6d 70 6f 72 74 20 62 69 6e 61 73 63  on.import binasc
0080: 69 69 0a 0a 23 69 6d 70 6f 72 74 20 6c 6f 67 67  ii..#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 2f 22 29 0a 20 20 20 20 20 20 20 20  t("//").        
1510: 73 65 6c 66 2e 73 4c 61 6e 67 43 6f 64 65 20 3d  self.sLangCode =
1520: 20 6c 2e 70 6f 70 28 30 29 0a 20 20 20 20 20 20   l.pop(0).      
1530: 20 20 73 65 6c 66 2e 73 4c 61 6e 67 4e 61 6d 65    self.sLangName
1540: 20 3d 20 6c 2e 70 6f 70 28 30 29 0a 20 20 20 20   = l.pop(0).    
1550: 20 20 20 20 73 65 6c 66 2e 73 44 69 63 4e 61 6d      self.sDicNam
1560: 65 20 3d 20 6c 2e 70 6f 70 28 30 29 0a 20 20 20  e = l.pop(0).   
1570: 20 20 20 20 20 73 65 6c 66 2e 73 44 61 74 65 20       self.sDate 
1580: 3d 20 6c 2e 70 6f 70 28 30 29 0a 20 20 20 20 20  = l.pop(0).     
1590: 20 20 20 73 65 6c 66 2e 6e 43 68 61 72 20 3d 20     self.nChar = 
15a0: 69 6e 74 28 6c 2e 70 6f 70 28 30 29 29 0a 20 20  int(l.pop(0)).  
15b0: 20 20 20 20 20 20 73 65 6c 66 2e 6e 42 79 74 65        self.nByte
15c0: 73 41 72 63 20 3d 20 69 6e 74 28 6c 2e 70 6f 70  sArc = int(l.pop
15d0: 28 30 29 29 0a 20 20 20 20 20 20 20 20 73 65 6c  (0)).        sel
15e0: 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72  f.nBytesNodeAddr
15f0: 65 73 73 20 3d 20 69 6e 74 28 6c 2e 70 6f 70 28  ess = int(l.pop(
1600: 30 29 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66  0)).        self
1610: 2e 6e 45 6e 74 72 79 20 3d 20 69 6e 74 28 6c 2e  .nEntry = int(l.
1620: 70 6f 70 28 30 29 29 0a 20 20 20 20 20 20 20 20  pop(0)).        
1630: 73 65 6c 66 2e 6e 4e 6f 64 65 20 3d 20 69 6e 74  self.nNode = int
1640: 28 6c 2e 70 6f 70 28 30 29 29 0a 20 20 20 20 20  (l.pop(0)).     
1650: 20 20 20 73 65 6c 66 2e 6e 41 72 63 20 3d 20 69     self.nArc = i
1660: 6e 74 28 6c 2e 70 6f 70 28 30 29 29 0a 20 20 20  nt(l.pop(0)).   
1670: 20 20 20 20 20 73 65 6c 66 2e 6e 41 66 66 20 3d       self.nAff =
1680: 20 69 6e 74 28 6c 2e 70 6f 70 28 30 29 29 0a 20   int(l.pop(0)). 
1690: 20 20 20 20 20 20 20 73 65 6c 66 2e 63 53 74 65         self.cSte
16a0: 6d 6d 69 6e 67 20 3d 20 6c 2e 70 6f 70 28 30 29  mming = l.pop(0)
16b0: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6e 54  .        self.nT
16c0: 61 67 20 3d 20 73 65 6c 66 2e 6e 41 72 63 56 61  ag = self.nArcVa
16d0: 6c 20 2d 20 73 65 6c 66 2e 6e 43 68 61 72 20 2d  l - self.nChar -
16e0: 20 73 65 6c 66 2e 6e 41 66 66 0a 20 20 20 20 20   self.nAff.     
16f0: 20 20 20 23 20 3c 64 43 68 61 72 3e 20 74 6f 20     # <dChar> to 
1700: 67 65 74 20 74 68 65 20 76 61 6c 75 65 20 6f 66  get the value of
1710: 20 61 6e 20 61 72 63 2c 20 3c 64 43 68 61 72 56   an arc, <dCharV
1720: 61 6c 3e 20 74 6f 20 67 65 74 20 74 68 65 20 63  al> to get the c
1730: 68 61 72 20 6f 66 20 61 6e 20 61 72 63 20 77 69  har of an arc wi
1740: 74 68 20 69 74 73 20 76 61 6c 75 65 0a 20 20 20  th its value.   
1750: 20 20 20 20 20 73 65 6c 66 2e 64 43 68 61 72 20       self.dChar 
1760: 3d 20 7b 7d 0a 20 20 20 20 20 20 20 20 66 6f 72  = {}.        for
1770: 20 69 20 69 6e 20 72 61 6e 67 65 28 31 2c 20 73   i in range(1, s
1780: 65 6c 66 2e 6e 43 68 61 72 2b 31 29 3a 0a 20 20  elf.nChar+1):.  
1790: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64            self.d
17a0: 43 68 61 72 5b 73 65 6c 66 2e 6c 41 72 63 56 61  Char[self.lArcVa
17b0: 6c 5b 69 5d 5d 20 3d 20 69 0a 20 20 20 20 20 20  l[i]] = i.      
17c0: 20 20 73 65 6c 66 2e 64 43 68 61 72 56 61 6c 20    self.dCharVal 
17d0: 3d 20 7b 20 76 3a 20 6b 20 20 66 6f 72 20 6b 2c  = { v: k  for k,
17e0: 20 76 20 69 6e 20 73 65 6c 66 2e 64 43 68 61 72   v in self.dChar
17f0: 2e 69 74 65 6d 73 28 29 20 7d 0a 20 20 20 20 20  .items() }.     
1800: 20 20 20 73 65 6c 66 2e 6e 42 79 74 65 73 4f 66     self.nBytesOf
1810: 66 73 65 74 20 3d 20 31 20 23 20 76 65 72 73 69  fset = 1 # versi
1820: 6f 6e 20 33 0a 0a 20 20 20 20 64 65 66 20 5f 69  on 3..    def _i
1830: 6e 69 74 4a 53 4f 4e 20 28 73 65 6c 66 29 3a 0a  nitJSON (self):.
1840: 20 20 20 20 20 20 20 20 22 69 6e 69 74 69 61 6c          "initial
1850: 69 7a 65 20 77 69 74 68 20 61 20 4a 53 4f 4e 20  ize with a JSON 
1860: 74 65 78 74 20 66 69 6c 65 22 0a 20 20 20 20 20  text file".     
1870: 20 20 20 73 65 6c 66 2e 5f 5f 64 69 63 74 5f 5f     self.__dict__
1880: 2e 75 70 64 61 74 65 28 6a 73 6f 6e 2e 6c 6f 61  .update(json.loa
1890: 64 73 28 73 65 6c 66 2e 62 79 2e 64 65 63 6f 64  ds(self.by.decod
18a0: 65 28 22 75 74 66 2d 38 22 29 29 29 0a 20 20 20  e("utf-8"))).   
18b0: 20 20 20 20 20 23 73 65 6c 66 2e 5f 5f 64 69 63       #self.__dic
18c0: 74 5f 5f 2e 75 70 64 61 74 65 28 6a 73 6f 6e 2e  t__.update(json.
18d0: 6c 6f 61 64 73 28 73 65 6c 66 2e 62 79 29 29 20  loads(self.by)) 
18e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
18f0: 20 23 20 49 6e 20 50 79 74 68 6f 6e 20 33 2e 36   # In Python 3.6
1900: 2c 20 63 61 6e 20 72 65 61 64 20 64 69 72 65 63  , can read direc
1910: 74 6c 79 20 62 69 6e 61 72 79 20 73 74 72 69 6e  tly binary strin
1920: 67 73 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e  gs.        self.
1930: 62 79 44 69 63 20 3d 20 62 69 6e 61 73 63 69 69  byDic = binascii
1940: 2e 75 6e 68 65 78 6c 69 66 79 28 73 65 6c 66 2e  .unhexlify(self.
1950: 73 42 79 44 69 63 29 0a 0a 20 20 20 20 64 65 66  sByDic)..    def
1960: 20 67 65 74 49 6e 66 6f 20 28 73 65 6c 66 29 3a   getInfo (self):
1970: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
1980: 20 22 20 20 4c 61 6e 67 75 61 67 65 3a 20 7b 30   "  Language: {0
1990: 2e 73 4c 61 6e 67 4e 61 6d 65 7d 20 20 20 4c 61  .sLangName}   La
19a0: 6e 67 20 63 6f 64 65 3a 20 7b 30 2e 73 4c 61 6e  ng code: {0.sLan
19b0: 67 43 6f 64 65 7d 20 20 20 44 69 63 74 69 6f 6e  gCode}   Diction
19c0: 61 72 79 20 6e 61 6d 65 3a 20 7b 30 2e 73 44 69  ary name: {0.sDi
19d0: 63 4e 61 6d 65 7d 22 20 5c 0a 20 20 20 20 20 20  cName}" \.      
19e0: 20 20 20 20 20 20 20 20 20 20 22 20 20 43 6f 6d            "  Com
19f0: 70 72 65 73 73 69 6f 6e 20 6d 65 74 68 6f 64 3a  pression method:
1a00: 20 7b 30 2e 6e 43 6f 6d 70 72 65 73 73 69 6f 6e   {0.nCompression
1a10: 4d 65 74 68 6f 64 3a 3e 32 7d 20 20 20 44 61 74  Method:>2}   Dat
1a20: 65 3a 20 7b 30 2e 73 44 61 74 65 7d 20 20 20 53  e: {0.sDate}   S
1a30: 74 65 6d 6d 69 6e 67 3a 20 7b 30 2e 63 53 74 65  temming: {0.cSte
1a40: 6d 6d 69 6e 67 7d 46 58 5c 6e 22 20 5c 0a 20 20  mming}FX\n" \.  
1a50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 20                " 
1a60: 20 41 72 63 73 20 76 61 6c 75 65 73 3a 20 20 7b   Arcs values:  {
1a70: 30 2e 6e 41 72 63 56 61 6c 3a 3e 31 30 2c 7d 20  0.nArcVal:>10,} 
1a80: 3d 20 7b 30 2e 6e 43 68 61 72 3a 3e 35 2c 7d 20  = {0.nChar:>5,} 
1a90: 63 68 61 72 61 63 74 65 72 73 2c 20 20 7b 30 2e  characters,  {0.
1aa0: 6e 41 66 66 3a 3e 36 2c 7d 20 61 66 66 69 78 65  nAff:>6,} affixe
1ab0: 73 2c 20 20 7b 30 2e 6e 54 61 67 3a 3e 36 2c 7d  s,  {0.nTag:>6,}
1ac0: 20 74 61 67 73 5c 6e 22 20 5c 0a 20 20 20 20 20   tags\n" \.     
1ad0: 20 20 20 20 20 20 20 20 20 20 20 22 20 20 44 69             "  Di
1ae0: 63 74 69 6f 6e 61 72 79 3a 20 7b 30 2e 6e 45 6e  ctionary: {0.nEn
1af0: 74 72 79 3a 3e 31 32 2c 7d 20 65 6e 74 72 69 65  try:>12,} entrie
1b00: 73 2c 20 20 20 20 7b 30 2e 6e 4e 6f 64 65 3a 3e  s,    {0.nNode:>
1b10: 31 31 2c 7d 20 6e 6f 64 65 73 2c 20 20 20 7b 30  11,} nodes,   {0
1b20: 2e 6e 41 72 63 3a 3e 31 31 2c 7d 20 61 72 63 73  .nArc:>11,} arcs
1b30: 5c 6e 22 20 5c 0a 20 20 20 20 20 20 20 20 20 20  \n" \.          
1b40: 20 20 20 20 20 20 22 20 20 41 64 64 72 65 73 73        "  Address
1b50: 20 73 69 7a 65 3a 20 7b 30 2e 6e 42 79 74 65 73   size: {0.nBytes
1b60: 4e 6f 64 65 41 64 64 72 65 73 73 3a 3e 31 7d 20  NodeAddress:>1} 
1b70: 62 79 74 65 73 2c 20 20 41 72 63 20 73 69 7a 65  bytes,  Arc size
1b80: 3a 20 7b 30 2e 6e 42 79 74 65 73 41 72 63 3a 3e  : {0.nBytesArc:>
1b90: 31 7d 20 62 79 74 65 73 5c 6e 22 2e 66 6f 72 6d  1} bytes\n".form
1ba0: 61 74 28 73 65 6c 66 29 0a 0a 20 20 20 20 64 65  at(self)..    de
1bb0: 66 20 77 72 69 74 65 41 73 4a 53 4f 62 6a 65 63  f writeAsJSObjec
1bc0: 74 20 28 73 65 6c 66 2c 20 73 70 66 44 65 73 74  t (self, spfDest
1bd0: 2c 20 62 49 6e 4a 53 4d 6f 64 75 6c 65 3d 46 61  , bInJSModule=Fa
1be0: 6c 73 65 2c 20 62 42 69 6e 61 72 79 44 69 63 74  lse, bBinaryDict
1bf0: 41 73 48 65 78 53 74 72 69 6e 67 3d 46 61 6c 73  AsHexString=Fals
1c00: 65 29 3a 0a 20 20 20 20 20 20 20 20 22 77 72 69  e):.        "wri
1c10: 74 65 20 49 42 44 41 57 47 20 61 73 20 61 20 4a  te IBDAWG as a J
1c20: 61 76 61 53 63 72 69 70 74 20 6f 62 6a 65 63 74  avaScript object
1c30: 20 69 6e 20 61 20 4a 61 76 61 53 63 72 69 70 74   in a JavaScript
1c40: 20 6d 6f 64 75 6c 65 22 0a 20 20 20 20 20 20 20   module".       
1c50: 20 77 69 74 68 20 6f 70 65 6e 28 73 70 66 44 65   with open(spfDe
1c60: 73 74 2c 20 22 77 22 2c 20 65 6e 63 6f 64 69 6e  st, "w", encodin
1c70: 67 3d 22 75 74 66 2d 38 22 2c 20 6e 65 77 6c 69  g="utf-8", newli
1c80: 6e 65 3d 22 5c 6e 22 29 20 61 73 20 68 44 73 74  ne="\n") as hDst
1c90: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  :.            if
1ca0: 20 62 49 6e 4a 53 4d 6f 64 75 6c 65 3a 0a 20 20   bInJSModule:.  
1cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 68 44                hD
1cc0: 73 74 2e 77 72 69 74 65 28 27 2f 2f 20 4a 61 76  st.write('// Jav
1cd0: 61 53 63 72 69 70 74 5c 6e 2f 2f 20 47 65 6e 65  aScript\n// Gene
1ce0: 72 61 74 65 64 20 64 61 74 61 20 28 64 6f 20 6e  rated data (do n
1cf0: 6f 74 20 65 64 69 74 29 5c 6e 5c 6e 22 75 73 65  ot edit)\n\n"use
1d00: 20 73 74 72 69 63 74 22 3b 5c 6e 5c 6e 63 6f 6e   strict";\n\ncon
1d10: 73 74 20 64 69 63 74 69 6f 6e 61 72 79 20 3d 20  st dictionary = 
1d20: 27 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 68  ').            h
1d30: 44 73 74 2e 77 72 69 74 65 28 6a 73 6f 6e 2e 64  Dst.write(json.d
1d40: 75 6d 70 73 28 7b 0a 20 20 20 20 20 20 20 20 20  umps({.         
1d50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d60: 20 20 20 22 73 48 65 61 64 65 72 22 3a 20 22 2f     "sHeader": "/
1d70: 70 79 66 73 61 2f 22 2c 0a 20 20 20 20 20 20 20  pyfsa/",.       
1d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d90: 20 20 20 20 20 22 73 4c 61 6e 67 43 6f 64 65 22       "sLangCode"
1da0: 3a 20 73 65 6c 66 2e 73 4c 61 6e 67 43 6f 64 65  : self.sLangCode
1db0: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
1dc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 73                "s
1dd0: 4c 61 6e 67 4e 61 6d 65 22 3a 20 73 65 6c 66 2e  LangName": self.
1de0: 73 4c 61 6e 67 4e 61 6d 65 2c 0a 20 20 20 20 20  sLangName,.     
1df0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e00: 20 20 20 20 20 20 20 22 73 44 69 63 4e 61 6d 65         "sDicName
1e10: 22 3a 20 73 65 6c 66 2e 73 44 69 63 4e 61 6d 65  ": self.sDicName
1e20: 2c 0a 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 20 20 20 22 73                "s
1e40: 46 69 6c 65 4e 61 6d 65 22 3a 20 73 65 6c 66 2e  FileName": self.
1e50: 73 46 69 6c 65 4e 61 6d 65 2c 0a 20 20 20 20 20  sFileName,.     
1e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e70: 20 20 20 20 20 20 20 22 73 44 61 74 65 22 3a 20         "sDate": 
1e80: 73 65 6c 66 2e 73 44 61 74 65 2c 0a 20 20 20 20  self.sDate,.    
1e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ea0: 20 20 20 20 20 20 20 20 22 6e 45 6e 74 72 79 22          "nEntry"
1eb0: 3a 20 73 65 6c 66 2e 6e 45 6e 74 72 79 2c 0a 20  : self.nEntry,. 
1ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ed0: 20 20 20 20 20 20 20 20 20 20 20 22 6e 43 68 61             "nCha
1ee0: 72 22 3a 20 73 65 6c 66 2e 6e 43 68 61 72 2c 0a  r": self.nChar,.
1ef0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f00: 20 20 20 20 20 20 20 20 20 20 20 20 22 6e 41 66              "nAf
1f10: 66 22 3a 20 73 65 6c 66 2e 6e 41 66 66 2c 0a 20  f": self.nAff,. 
1f20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f30: 20 20 20 20 20 20 20 20 20 20 20 22 6e 54 61 67             "nTag
1f40: 22 3a 20 73 65 6c 66 2e 6e 54 61 67 2c 0a 20 20  ": self.nTag,.  
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 20 20 20 22 63 53 74 65 6d            "cStem
1f70: 6d 69 6e 67 22 3a 20 73 65 6c 66 2e 63 53 74 65  ming": self.cSte
1f80: 6d 6d 69 6e 67 2c 0a 20 20 20 20 20 20 20 20 20  mming,.         
1f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1fa0: 20 20 20 22 64 43 68 61 72 22 3a 20 73 65 6c 66     "dChar": self
1fb0: 2e 64 43 68 61 72 2c 0a 20 20 20 20 20 20 20 20  .dChar,.        
1fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1fd0: 20 20 20 20 22 6e 4e 6f 64 65 22 3a 20 73 65 6c      "nNode": sel
1fe0: 66 2e 6e 4e 6f 64 65 2c 0a 20 20 20 20 20 20 20  f.nNode,.       
1ff0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2000: 20 20 20 20 20 22 6e 41 72 63 22 3a 20 73 65 6c       "nArc": sel
2010: 66 2e 6e 41 72 63 2c 0a 20 20 20 20 20 20 20 20  f.nArc,.        
2020: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2030: 20 20 20 20 22 6e 41 72 63 56 61 6c 22 3a 20 73      "nArcVal": s
2040: 65 6c 66 2e 6e 41 72 63 56 61 6c 2c 0a 20 20 20  elf.nArcVal,.   
2050: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2060: 20 20 20 20 20 20 20 20 20 22 6c 41 72 63 56 61           "lArcVa
2070: 6c 22 3a 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c  l": self.lArcVal
2080: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
2090: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 6e                "n
20a0: 43 6f 6d 70 72 65 73 73 69 6f 6e 4d 65 74 68 6f  CompressionMetho
20b0: 64 22 3a 20 73 65 6c 66 2e 6e 43 6f 6d 70 72 65  d": self.nCompre
20c0: 73 73 69 6f 6e 4d 65 74 68 6f 64 2c 0a 20 20 20  ssionMethod,.   
20d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
20e0: 20 20 20 20 20 20 20 20 20 22 6e 42 79 74 65 73           "nBytes
20f0: 41 72 63 22 3a 20 73 65 6c 66 2e 6e 42 79 74 65  Arc": self.nByte
2100: 73 41 72 63 2c 0a 20 20 20 20 20 20 20 20 20 20  sArc,.          
2110: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2120: 20 20 22 6e 42 79 74 65 73 4e 6f 64 65 41 64 64    "nBytesNodeAdd
2130: 72 65 73 73 22 3a 20 73 65 6c 66 2e 6e 42 79 74  ress": self.nByt
2140: 65 73 4e 6f 64 65 41 64 64 72 65 73 73 2c 0a 20  esNodeAddress,. 
2150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2160: 20 20 20 20 20 20 20 20 20 20 20 22 6e 42 79 74             "nByt
2170: 65 73 4f 66 66 73 65 74 22 3a 20 73 65 6c 66 2e  esOffset": self.
2180: 6e 42 79 74 65 73 4f 66 66 73 65 74 2c 0a 20 20  nBytesOffset,.  
2190: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
21a0: 20 20 20 20 20 20 20 20 20 20 23 20 4a 61 76 61            # Java
21b0: 53 63 72 69 70 74 20 69 73 20 61 20 70 69 6c 65  Script is a pile
21c0: 20 6f 66 20 73 68 69 74 2c 20 73 6f 20 4d 6f 7a   of shit, so Moz
21d0: 69 6c 6c 61 e2 80 99 73 20 4a 53 20 70 61 72 73  illa...s JS pars
21e0: 65 72 20 64 6f 6e e2 80 99 74 20 6c 69 6b 65 20  er don...t like 
21f0: 66 69 6c 65 20 62 69 67 67 65 72 20 74 68 61 6e  file bigger than
2200: 20 34 20 4d 62 21 0a 20 20 20 20 20 20 20 20 20   4 Mb!.         
2210: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2220: 20 20 20 23 20 53 6f 2c 20 69 66 20 6e 65 63 65     # So, if nece
2230: 73 73 61 72 79 2c 20 77 65 20 75 73 65 20 61 6e  ssary, we use an
2240: 20 68 65 78 61 64 65 63 69 6d 61 6c 20 73 74 72   hexadecimal str
2250: 69 6e 67 2c 20 74 68 61 74 20 77 65 20 77 69 6c  ing, that we wil
2260: 6c 20 63 6f 6e 76 65 72 74 20 6c 61 74 65 72 20  l convert later 
2270: 69 6e 20 46 69 72 65 66 6f 78 e2 80 99 73 20 65  in Firefox...s e
2280: 78 74 65 6e 73 69 6f 6e 2e 0a 20 20 20 20 20 20  xtension..      
2290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
22a0: 20 20 20 20 20 20 23 20 68 74 74 70 73 3a 2f 2f        # https://
22b0: 67 69 74 68 75 62 2e 63 6f 6d 2f 6d 6f 7a 69 6c  github.com/mozil
22c0: 6c 61 2f 61 64 64 6f 6e 73 2d 6c 69 6e 74 65 72  la/addons-linter
22d0: 2f 69 73 73 75 65 73 2f 31 33 36 31 0a 20 20 20  /issues/1361.   
22e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
22f0: 20 20 20 20 20 20 20 20 20 22 73 42 79 44 69 63           "sByDic
2300: 22 3a 20 73 65 6c 66 2e 62 79 44 69 63 2e 68 65  ": self.byDic.he
2310: 78 28 29 20 20 69 66 20 62 42 69 6e 61 72 79 44  x()  if bBinaryD
2320: 69 63 74 41 73 48 65 78 53 74 72 69 6e 67 20 20  ictAsHexString  
2330: 65 6c 73 65 20 5b 20 65 20 20 66 6f 72 20 65 20  else [ e  for e 
2340: 69 6e 20 73 65 6c 66 2e 62 79 44 69 63 20 5d 0a  in self.byDic ].
2350: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2360: 20 20 20 20 20 20 20 20 7d 2c 20 65 6e 73 75 72          }, ensur
2370: 65 5f 61 73 63 69 69 3d 46 61 6c 73 65 29 29 0a  e_ascii=False)).
2380: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62              if b
2390: 49 6e 4a 53 4d 6f 64 75 6c 65 3a 0a 20 20 20 20  InJSModule:.    
23a0: 20 20 20 20 20 20 20 20 20 20 20 20 68 44 73 74              hDst
23b0: 2e 77 72 69 74 65 28 22 3b 5c 6e 5c 6e 65 78 70  .write(";\n\nexp
23c0: 6f 72 74 73 2e 64 69 63 74 69 6f 6e 61 72 79 20  orts.dictionary 
23d0: 3d 20 64 69 63 74 69 6f 6e 61 72 79 3b 5c 6e 22  = dictionary;\n"
23e0: 29 0a 0a 20 20 20 20 64 65 66 20 69 73 56 61 6c  )..    def isVal
23f0: 69 64 54 6f 6b 65 6e 20 28 73 65 6c 66 2c 20 73  idToken (self, s
2400: 54 6f 6b 65 6e 29 3a 0a 20 20 20 20 20 20 20 20  Token):.        
2410: 22 63 68 65 63 6b 73 20 69 66 20 3c 73 54 6f 6b  "checks if <sTok
2420: 65 6e 3e 20 69 73 20 76 61 6c 69 64 20 28 69 66  en> is valid (if
2430: 20 74 68 65 72 65 20 69 73 20 68 79 70 68 65 6e   there is hyphen
2440: 73 20 69 6e 20 3c 73 54 6f 6b 65 6e 3e 2c 20 3c  s in <sToken>, <
2450: 73 54 6f 6b 65 6e 3e 20 69 73 20 73 70 6c 69 74  sToken> is split
2460: 2c 20 65 61 63 68 20 70 61 72 74 20 69 73 20 63  , each part is c
2470: 68 65 63 6b 65 64 29 22 0a 20 20 20 20 20 20 20  hecked)".       
2480: 20 73 54 6f 6b 65 6e 20 3d 20 63 70 2e 73 70 65   sToken = cp.spe
2490: 6c 6c 69 6e 67 4e 6f 72 6d 61 6c 69 7a 61 74 69  llingNormalizati
24a0: 6f 6e 28 73 54 6f 6b 65 6e 29 0a 20 20 20 20 20  on(sToken).     
24b0: 20 20 20 69 66 20 73 65 6c 66 2e 69 73 56 61 6c     if self.isVal
24c0: 69 64 28 73 54 6f 6b 65 6e 29 3a 0a 20 20 20 20  id(sToken):.    
24d0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54          return T
24e0: 72 75 65 0a 20 20 20 20 20 20 20 20 69 66 20 22  rue.        if "
24f0: 2d 22 20 69 6e 20 73 54 6f 6b 65 6e 3a 0a 20 20  -" in sToken:.  
2500: 20 20 20 20 20 20 20 20 20 20 69 66 20 73 54 6f            if sTo
2510: 6b 65 6e 2e 63 6f 75 6e 74 28 22 2d 22 29 20 3e  ken.count("-") >
2520: 20 34 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20   4:.            
2530: 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a      return True.
2540: 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
2550: 72 6e 20 61 6c 6c 28 73 65 6c 66 2e 69 73 56 61  rn all(self.isVa
2560: 6c 69 64 28 73 57 6f 72 64 29 20 20 66 6f 72 20  lid(sWord)  for 
2570: 73 57 6f 72 64 20 69 6e 20 73 54 6f 6b 65 6e 2e  sWord in sToken.
2580: 73 70 6c 69 74 28 22 2d 22 29 29 0a 20 20 20 20  split("-")).    
2590: 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65      return False
25a0: 0a 0a 20 20 20 20 64 65 66 20 69 73 56 61 6c 69  ..    def isVali
25b0: 64 20 28 73 65 6c 66 2c 20 73 57 6f 72 64 29 3a  d (self, sWord):
25c0: 0a 20 20 20 20 20 20 20 20 22 63 68 65 63 6b 73  .        "checks
25d0: 20 69 66 20 3c 73 57 6f 72 64 3e 20 69 73 20 76   if <sWord> is v
25e0: 61 6c 69 64 20 28 64 69 66 66 65 72 65 6e 74 20  alid (different 
25f0: 63 61 73 69 6e 67 20 74 65 73 74 65 64 20 69 66  casing tested if
2600: 20 74 68 65 20 66 69 72 73 74 20 6c 65 74 74 65   the first lette
2610: 72 20 69 73 20 61 20 63 61 70 69 74 61 6c 29 22  r is a capital)"
2620: 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20  .        if not 
2630: 73 57 6f 72 64 3a 0a 20 20 20 20 20 20 20 20 20  sWord:.         
2640: 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e 65 0a 20     return None. 
2650: 20 20 20 20 20 20 20 69 66 20 22 e2 80 99 22 20         if "..." 
2660: 69 6e 20 73 57 6f 72 64 3a 20 23 20 75 67 6c 79  in sWord: # ugly
2670: 20 68 61 63 6b 0a 20 20 20 20 20 20 20 20 20 20   hack.          
2680: 20 20 73 57 6f 72 64 20 3d 20 73 57 6f 72 64 2e    sWord = sWord.
2690: 72 65 70 6c 61 63 65 28 22 e2 80 99 22 2c 20 22  replace("...", "
26a0: 27 22 29 0a 20 20 20 20 20 20 20 20 69 66 20 73  '").        if s
26b0: 65 6c 66 2e 6c 6f 6f 6b 75 70 28 73 57 6f 72 64  elf.lookup(sWord
26c0: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  ):.            r
26d0: 65 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 20  eturn True.     
26e0: 20 20 20 69 66 20 73 57 6f 72 64 5b 30 3a 31 5d     if sWord[0:1]
26f0: 2e 69 73 75 70 70 65 72 28 29 3a 0a 20 20 20 20  .isupper():.    
2700: 20 20 20 20 20 20 20 20 69 66 20 6c 65 6e 28 73          if len(s
2710: 57 6f 72 64 29 20 3e 20 31 3a 0a 20 20 20 20 20  Word) > 1:.     
2720: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73 57             if sW
2730: 6f 72 64 2e 69 73 74 69 74 6c 65 28 29 3a 0a 20  ord.istitle():. 
2740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2750: 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 6c     return self.l
2760: 6f 6f 6b 75 70 28 73 57 6f 72 64 2e 6c 6f 77 65  ookup(sWord.lowe
2770: 72 28 29 29 0a 20 20 20 20 20 20 20 20 20 20 20  r()).           
2780: 20 20 20 20 20 69 66 20 73 57 6f 72 64 2e 69 73       if sWord.is
2790: 75 70 70 65 72 28 29 3a 0a 20 20 20 20 20 20 20  upper():.       
27a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
27b0: 73 65 6c 66 2e 62 4f 70 74 4e 75 6d 53 69 67 6c  self.bOptNumSigl
27c0: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
27d0: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
27e0: 6e 20 54 72 75 65 0a 20 20 20 20 20 20 20 20 20  n True.         
27f0: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
2800: 6e 20 73 65 6c 66 2e 6c 6f 6f 6b 75 70 28 73 57  n self.lookup(sW
2810: 6f 72 64 2e 6c 6f 77 65 72 28 29 29 20 6f 72 20  ord.lower()) or 
2820: 73 65 6c 66 2e 6c 6f 6f 6b 75 70 28 73 57 6f 72  self.lookup(sWor
2830: 64 2e 63 61 70 69 74 61 6c 69 7a 65 28 29 29 0a  d.capitalize()).
2840: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2850: 72 65 74 75 72 6e 20 73 65 6c 66 2e 6c 6f 6f 6b  return self.look
2860: 75 70 28 73 57 6f 72 64 5b 3a 31 5d 2e 6c 6f 77  up(sWord[:1].low
2870: 65 72 28 29 20 2b 20 73 57 6f 72 64 5b 31 3a 5d  er() + sWord[1:]
2880: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c  ).            el
2890: 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
28a0: 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e      return self.
28b0: 6c 6f 6f 6b 75 70 28 73 57 6f 72 64 2e 6c 6f 77  lookup(sWord.low
28c0: 65 72 28 29 29 0a 20 20 20 20 20 20 20 20 72 65  er()).        re
28d0: 74 75 72 6e 20 46 61 6c 73 65 0a 0a 20 20 20 20  turn False..    
28e0: 64 65 66 20 6c 6f 6f 6b 75 70 20 28 73 65 6c 66  def lookup (self
28f0: 2c 20 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20  , sWord):.      
2900: 20 20 22 72 65 74 75 72 6e 73 20 54 72 75 65 20    "returns True 
2910: 69 66 20 3c 73 57 6f 72 64 3e 20 69 6e 20 64 69  if <sWord> in di
2920: 63 74 69 6f 6e 61 72 79 20 28 73 74 72 69 63 74  ctionary (strict
2930: 20 76 65 72 69 66 69 63 61 74 69 6f 6e 29 22 0a   verification)".
2940: 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20          iAddr = 
2950: 30 0a 20 20 20 20 20 20 20 20 66 6f 72 20 63 20  0.        for c 
2960: 69 6e 20 73 57 6f 72 64 3a 0a 20 20 20 20 20 20  in sWord:.      
2970: 20 20 20 20 20 20 69 66 20 63 20 6e 6f 74 20 69        if c not i
2980: 6e 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a 20 20  n self.dChar:.  
2990: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
29a0: 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 20  turn False.     
29b0: 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 73         iAddr = s
29c0: 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f  elf._lookupArcNo
29d0: 64 65 28 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d  de(self.dChar[c]
29e0: 2c 20 69 41 64 64 72 29 0a 20 20 20 20 20 20 20  , iAddr).       
29f0: 20 20 20 20 20 69 66 20 69 41 64 64 72 20 3d 3d       if iAddr ==
2a00: 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 20   None:.         
2a10: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 46 61         return Fa
2a20: 6c 73 65 0a 20 20 20 20 20 20 20 20 72 65 74 75  lse.        retu
2a30: 72 6e 20 62 6f 6f 6c 28 69 6e 74 2e 66 72 6f 6d  rn bool(int.from
2a40: 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69  _bytes(self.byDi
2a50: 63 5b 69 41 64 64 72 3a 69 41 64 64 72 2b 73 65  c[iAddr:iAddr+se
2a60: 6c 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20 62  lf.nBytesArc], b
2a70: 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 20  yteorder='big') 
2a80: 26 20 73 65 6c 66 2e 5f 66 69 6e 61 6c 4e 6f 64  & self._finalNod
2a90: 65 4d 61 73 6b 29 0a 0a 20 20 20 20 64 65 66 20  eMask)..    def 
2aa0: 67 65 74 4d 6f 72 70 68 20 28 73 65 6c 66 2c 20  getMorph (self, 
2ab0: 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20 20 20  sWord):.        
2ac0: 22 72 65 74 72 69 65 76 65 73 20 6d 6f 72 70 68  "retrieves morph
2ad0: 6f 6c 6f 67 69 65 73 20 6c 69 73 74 2c 20 64 69  ologies list, di
2ae0: 66 66 65 72 65 6e 74 20 63 61 73 69 6e 67 20 61  fferent casing a
2af0: 6c 6c 6f 77 65 64 22 0a 20 20 20 20 20 20 20 20  llowed".        
2b00: 73 57 6f 72 64 20 3d 20 63 70 2e 73 70 65 6c 6c  sWord = cp.spell
2b10: 69 6e 67 4e 6f 72 6d 61 6c 69 7a 61 74 69 6f 6e  ingNormalization
2b20: 28 73 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20  (sWord).        
2b30: 6c 20 3d 20 73 65 6c 66 2e 6d 6f 72 70 68 28 73  l = self.morph(s
2b40: 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20 69 66  Word).        if
2b50: 20 73 57 6f 72 64 5b 30 3a 31 5d 2e 69 73 75 70   sWord[0:1].isup
2b60: 70 65 72 28 29 3a 0a 20 20 20 20 20 20 20 20 20  per():.         
2b70: 20 20 20 6c 2e 65 78 74 65 6e 64 28 73 65 6c 66     l.extend(self
2b80: 2e 6d 6f 72 70 68 28 73 57 6f 72 64 2e 6c 6f 77  .morph(sWord.low
2b90: 65 72 28 29 29 29 0a 20 20 20 20 20 20 20 20 20  er())).         
2ba0: 20 20 20 69 66 20 73 57 6f 72 64 2e 69 73 75 70     if sWord.isup
2bb0: 70 65 72 28 29 20 61 6e 64 20 6c 65 6e 28 73 57  per() and len(sW
2bc0: 6f 72 64 29 20 3e 20 31 3a 0a 20 20 20 20 20 20  ord) > 1:.      
2bd0: 20 20 20 20 20 20 20 20 20 20 6c 2e 65 78 74 65            l.exte
2be0: 6e 64 28 73 65 6c 66 2e 6d 6f 72 70 68 28 73 57  nd(self.morph(sW
2bf0: 6f 72 64 2e 63 61 70 69 74 61 6c 69 7a 65 28 29  ord.capitalize()
2c00: 29 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  )).        retur
2c10: 6e 20 6c 0a 0a 20 20 20 20 23 40 74 69 6d 65 74  n l..    #@timet
2c20: 68 69 73 0a 20 20 20 20 64 65 66 20 73 75 67 67  his.    def sugg
2c30: 65 73 74 20 28 73 65 6c 66 2c 20 73 57 6f 72 64  est (self, sWord
2c40: 2c 20 6e 53 75 67 67 4c 69 6d 69 74 3d 31 30 29  , nSuggLimit=10)
2c50: 3a 0a 20 20 20 20 20 20 20 20 22 72 65 74 75 72  :.        "retur
2c60: 6e 73 20 61 20 73 65 74 20 6f 66 20 73 75 67 67  ns a set of sugg
2c70: 65 73 74 69 6f 6e 73 20 66 6f 72 20 3c 73 57 6f  estions for <sWo
2c80: 72 64 3e 22 0a 20 20 20 20 20 20 20 20 73 57 6f  rd>".        sWo
2c90: 72 64 20 3d 20 63 70 2e 73 70 65 6c 6c 69 6e 67  rd = cp.spelling
2ca0: 4e 6f 72 6d 61 6c 69 7a 61 74 69 6f 6e 28 73 57  Normalization(sW
2cb0: 6f 72 64 29 0a 20 20 20 20 20 20 20 20 73 50 66  ord).        sPf
2cc0: 78 2c 20 73 57 6f 72 64 2c 20 73 53 66 78 20 3d  x, sWord, sSfx =
2cd0: 20 63 70 2e 63 75 74 28 73 57 6f 72 64 29 0a 20   cp.cut(sWord). 
2ce0: 20 20 20 20 20 20 20 6e 4d 61 78 53 77 69 74 63         nMaxSwitc
2cf0: 68 20 3d 20 6d 61 78 28 6c 65 6e 28 73 57 6f 72  h = max(len(sWor
2d00: 64 29 20 2f 2f 20 33 2c 20 31 29 0a 20 20 20 20  d) // 3, 1).    
2d10: 20 20 20 20 6e 4d 61 78 44 65 6c 20 3d 20 6c 65      nMaxDel = le
2d20: 6e 28 73 57 6f 72 64 29 20 2f 2f 20 35 0a 20 20  n(sWord) // 5.  
2d30: 20 20 20 20 20 20 6e 4d 61 78 48 61 72 64 52 65        nMaxHardRe
2d40: 70 6c 20 3d 20 6d 61 78 28 28 6c 65 6e 28 73 57  pl = max((len(sW
2d50: 6f 72 64 29 20 2d 20 35 29 20 2f 2f 20 34 2c 20  ord) - 5) // 4, 
2d60: 31 29 0a 20 20 20 20 20 20 20 20 6f 53 75 67 67  1).        oSugg
2d70: 52 65 73 75 6c 74 20 3d 20 53 75 67 67 52 65 73  Result = SuggRes
2d80: 75 6c 74 28 73 57 6f 72 64 29 0a 20 20 20 20 20  ult(sWord).     
2d90: 20 20 20 73 65 6c 66 2e 5f 73 75 67 67 65 73 74     self._suggest
2da0: 28 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 73 57  (oSuggResult, sW
2db0: 6f 72 64 2c 20 6e 4d 61 78 53 77 69 74 63 68 3d  ord, nMaxSwitch=
2dc0: 6e 4d 61 78 53 77 69 74 63 68 2c 20 6e 4d 61 78  nMaxSwitch, nMax
2dd0: 44 65 6c 3d 6e 4d 61 78 44 65 6c 2c 20 6e 4d 61  Del=nMaxDel, nMa
2de0: 78 48 61 72 64 52 65 70 6c 3d 6e 4d 61 78 48 61  xHardRepl=nMaxHa
2df0: 72 64 52 65 70 6c 29 0a 20 20 20 20 20 20 20 20  rdRepl).        
2e00: 69 66 20 73 57 6f 72 64 2e 69 73 74 69 74 6c 65  if sWord.istitle
2e10: 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ():.            
2e20: 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28 6f 53  self._suggest(oS
2e30: 75 67 67 52 65 73 75 6c 74 2c 20 73 57 6f 72 64  uggResult, sWord
2e40: 2e 6c 6f 77 65 72 28 29 2c 20 6e 4d 61 78 53 77  .lower(), nMaxSw
2e50: 69 74 63 68 3d 6e 4d 61 78 53 77 69 74 63 68 2c  itch=nMaxSwitch,
2e60: 20 6e 4d 61 78 44 65 6c 3d 6e 4d 61 78 44 65 6c   nMaxDel=nMaxDel
2e70: 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 3d 6e  , nMaxHardRepl=n
2e80: 4d 61 78 48 61 72 64 52 65 70 6c 29 0a 20 20 20  MaxHardRepl).   
2e90: 20 20 20 20 20 65 6c 69 66 20 73 57 6f 72 64 2e       elif sWord.
2ea0: 69 73 6c 6f 77 65 72 28 29 3a 0a 20 20 20 20 20  islower():.     
2eb0: 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73 75 67         self._sug
2ec0: 67 65 73 74 28 6f 53 75 67 67 52 65 73 75 6c 74  gest(oSuggResult
2ed0: 2c 20 73 57 6f 72 64 2e 74 69 74 6c 65 28 29 2c  , sWord.title(),
2ee0: 20 6e 4d 61 78 53 77 69 74 63 68 3d 6e 4d 61 78   nMaxSwitch=nMax
2ef0: 53 77 69 74 63 68 2c 20 6e 4d 61 78 44 65 6c 3d  Switch, nMaxDel=
2f00: 6e 4d 61 78 44 65 6c 2c 20 6e 4d 61 78 48 61 72  nMaxDel, nMaxHar
2f10: 64 52 65 70 6c 3d 6e 4d 61 78 48 61 72 64 52 65  dRepl=nMaxHardRe
2f20: 70 6c 29 0a 20 20 20 20 20 20 20 20 61 53 75 67  pl).        aSug
2f30: 67 20 3d 20 6f 53 75 67 67 52 65 73 75 6c 74 2e  g = oSuggResult.
2f40: 67 65 74 53 75 67 67 65 73 74 69 6f 6e 73 28 6e  getSuggestions(n
2f50: 53 75 67 67 4c 69 6d 69 74 29 0a 20 20 20 20 20  SuggLimit).     
2f60: 20 20 20 69 66 20 73 53 66 78 20 6f 72 20 73 50     if sSfx or sP
2f70: 66 78 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  fx:.            
2f80: 23 20 77 65 20 61 64 64 20 77 68 61 74 20 77 65  # we add what we
2f90: 20 72 65 6d 6f 76 65 64 0a 20 20 20 20 20 20 20   removed.       
2fa0: 20 20 20 20 20 72 65 74 75 72 6e 20 6c 69 73 74       return list
2fb0: 28 6d 61 70 28 6c 61 6d 62 64 61 20 73 53 75 67  (map(lambda sSug
2fc0: 3a 20 73 50 66 78 20 2b 20 73 53 75 67 20 2b 20  : sPfx + sSug + 
2fd0: 73 53 66 78 2c 20 61 53 75 67 67 29 29 0a 20 20  sSfx, aSugg)).  
2fe0: 20 20 20 20 20 20 72 65 74 75 72 6e 20 61 53 75        return aSu
2ff0: 67 67 0a 0a 20 20 20 20 64 65 66 20 5f 73 75 67  gg..    def _sug
3000: 67 65 73 74 20 28 73 65 6c 66 2c 20 6f 53 75 67  gest (self, oSug
3010: 67 52 65 73 75 6c 74 2c 20 73 52 65 6d 61 69 6e  gResult, sRemain
3020: 2c 20 6e 4d 61 78 53 77 69 74 63 68 3d 30 2c 20  , nMaxSwitch=0, 
3030: 6e 4d 61 78 44 65 6c 3d 30 2c 20 6e 4d 61 78 48  nMaxDel=0, nMaxH
3040: 61 72 64 52 65 70 6c 3d 30 2c 20 6e 44 65 65 70  ardRepl=0, nDeep
3050: 3d 30 2c 20 69 41 64 64 72 3d 30 2c 20 73 4e 65  =0, iAddr=0, sNe
3060: 77 57 6f 72 64 3d 22 22 2c 20 62 41 76 6f 69 64  wWord="", bAvoid
3070: 4c 6f 6f 70 3d 46 61 6c 73 65 29 3a 0a 20 20 20  Loop=False):.   
3080: 20 20 20 20 20 23 20 72 65 63 75 72 73 69 76 65       # recursive
3090: 20 66 75 6e 63 74 69 6f 6e 0a 20 20 20 20 20 20   function.      
30a0: 20 20 23 6c 6f 67 67 69 6e 67 2e 69 6e 66 6f 28    #logging.info(
30b0: 28 6e 44 65 65 70 20 2a 20 22 20 20 22 29 20 2b  (nDeep * "  ") +
30c0: 20 73 4e 65 77 57 6f 72 64 20 2b 20 22 3a 22 20   sNewWord + ":" 
30d0: 2b 20 73 52 65 6d 61 69 6e 29 0a 20 20 20 20 20  + sRemain).     
30e0: 20 20 20 69 66 20 6e 6f 74 20 73 52 65 6d 61 69     if not sRemai
30f0: 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  n:.            i
3100: 66 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73  f int.from_bytes
3110: 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64 64  (self.byDic[iAdd
3120: 72 3a 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  r:iAddr+self.nBy
3130: 74 65 73 41 72 63 5d 2c 20 62 79 74 65 6f 72 64  tesArc], byteord
3140: 65 72 3d 27 62 69 67 27 29 20 26 20 73 65 6c 66  er='big') & self
3150: 2e 5f 66 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b 3a  ._finalNodeMask:
3160: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
3170: 20 6f 53 75 67 67 52 65 73 75 6c 74 2e 61 64 64   oSuggResult.add
3180: 53 75 67 67 28 73 4e 65 77 57 6f 72 64 2c 20 6e  Sugg(sNewWord, n
3190: 44 65 65 70 29 0a 20 20 20 20 20 20 20 20 20 20  Deep).          
31a0: 20 20 66 6f 72 20 73 54 61 69 6c 20 69 6e 20 73    for sTail in s
31b0: 65 6c 66 2e 5f 67 65 74 54 61 69 6c 73 28 69 41  elf._getTails(iA
31c0: 64 64 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20  ddr):.          
31d0: 20 20 20 20 20 20 6f 53 75 67 67 52 65 73 75 6c        oSuggResul
31e0: 74 2e 61 64 64 53 75 67 67 28 73 4e 65 77 57 6f  t.addSugg(sNewWo
31f0: 72 64 2b 73 54 61 69 6c 2c 20 6e 44 65 65 70 29  rd+sTail, nDeep)
3200: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
3210: 75 72 6e 0a 20 20 20 20 20 20 20 20 63 43 75 72  urn.        cCur
3220: 72 65 6e 74 20 3d 20 73 52 65 6d 61 69 6e 5b 30  rent = sRemain[0
3230: 3a 31 5d 0a 20 20 20 20 20 20 20 20 66 6f 72 20  :1].        for 
3240: 63 43 68 61 72 2c 20 6a 41 64 64 72 20 69 6e 20  cChar, jAddr in 
3250: 73 65 6c 66 2e 5f 67 65 74 43 68 61 72 41 72 63  self._getCharArc
3260: 73 28 69 41 64 64 72 29 3a 0a 20 20 20 20 20 20  s(iAddr):.      
3270: 20 20 20 20 20 20 69 66 20 63 43 68 61 72 20 69        if cChar i
3280: 6e 20 63 70 2e 64 31 74 6f 31 2e 67 65 74 28 63  n cp.d1to1.get(c
3290: 43 75 72 72 65 6e 74 2c 20 63 43 75 72 72 65 6e  Current, cCurren
32a0: 74 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  t):.            
32b0: 20 20 20 20 73 65 6c 66 2e 5f 73 75 67 67 65 73      self._sugges
32c0: 74 28 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 73  t(oSuggResult, s
32d0: 52 65 6d 61 69 6e 5b 31 3a 5d 2c 20 6e 4d 61 78  Remain[1:], nMax
32e0: 53 77 69 74 63 68 2c 20 6e 4d 61 78 44 65 6c 2c  Switch, nMaxDel,
32f0: 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 2c 20 6e   nMaxHardRepl, n
3300: 44 65 65 70 2b 31 2c 20 6a 41 64 64 72 2c 20 73  Deep+1, jAddr, s
3310: 4e 65 77 57 6f 72 64 2b 63 43 68 61 72 29 0a 20  NewWord+cChar). 
3320: 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66 20             elif 
3330: 6e 6f 74 20 62 41 76 6f 69 64 4c 6f 6f 70 20 61  not bAvoidLoop a
3340: 6e 64 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 3a  nd nMaxHardRepl:
3350: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
3360: 20 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28 6f   self._suggest(o
3370: 53 75 67 67 52 65 73 75 6c 74 2c 20 73 52 65 6d  SuggResult, sRem
3380: 61 69 6e 5b 31 3a 5d 2c 20 6e 4d 61 78 53 77 69  ain[1:], nMaxSwi
3390: 74 63 68 2c 20 6e 4d 61 78 44 65 6c 2c 20 6e 4d  tch, nMaxDel, nM
33a0: 61 78 48 61 72 64 52 65 70 6c 2d 31 2c 20 6e 44  axHardRepl-1, nD
33b0: 65 65 70 2b 31 2c 20 6a 41 64 64 72 2c 20 73 4e  eep+1, jAddr, sN
33c0: 65 77 57 6f 72 64 2b 63 43 68 61 72 2c 20 54 72  ewWord+cChar, Tr
33d0: 75 65 29 0a 20 20 20 20 20 20 20 20 69 66 20 6e  ue).        if n
33e0: 6f 74 20 62 41 76 6f 69 64 4c 6f 6f 70 3a 20 23  ot bAvoidLoop: #
33f0: 20 61 76 6f 69 64 20 69 6e 66 69 6e 69 74 65 20   avoid infinite 
3400: 6c 6f 6f 70 0a 20 20 20 20 20 20 20 20 20 20 20  loop.           
3410: 20 69 66 20 6c 65 6e 28 73 52 65 6d 61 69 6e 29   if len(sRemain)
3420: 20 3e 20 31 3a 0a 20 20 20 20 20 20 20 20 20 20   > 1:.          
3430: 20 20 20 20 20 20 69 66 20 63 43 75 72 72 65 6e        if cCurren
3440: 74 20 3d 3d 20 73 52 65 6d 61 69 6e 5b 31 3a 32  t == sRemain[1:2
3450: 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]:.             
3460: 20 20 20 20 20 20 20 23 20 73 61 6d 65 20 63 68         # same ch
3470: 61 72 2c 20 77 65 20 72 65 6d 6f 76 65 20 31 20  ar, we remove 1 
3480: 63 68 61 72 20 77 69 74 68 6f 75 74 20 61 64 64  char without add
3490: 69 6e 67 20 31 20 74 6f 20 3c 73 4e 65 77 57 6f  ing 1 to <sNewWo
34a0: 72 64 3e 0a 20 20 20 20 20 20 20 20 20 20 20 20  rd>.            
34b0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73 75          self._su
34c0: 67 67 65 73 74 28 6f 53 75 67 67 52 65 73 75 6c  ggest(oSuggResul
34d0: 74 2c 20 73 52 65 6d 61 69 6e 5b 31 3a 5d 2c 20  t, sRemain[1:], 
34e0: 6e 4d 61 78 53 77 69 74 63 68 2c 20 6e 4d 61 78  nMaxSwitch, nMax
34f0: 44 65 6c 2c 20 6e 4d 61 78 48 61 72 64 52 65 70  Del, nMaxHardRep
3500: 6c 2c 20 6e 44 65 65 70 2b 31 2c 20 69 41 64 64  l, nDeep+1, iAdd
3510: 72 2c 20 73 4e 65 77 57 6f 72 64 29 0a 20 20 20  r, sNewWord).   
3520: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73               els
3530: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
3540: 20 20 20 20 20 20 20 23 20 73 77 69 74 63 68 69         # switchi
3550: 6e 67 20 63 68 61 72 73 0a 20 20 20 20 20 20 20  ng chars.       
3560: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
3570: 6e 4d 61 78 53 77 69 74 63 68 3a 0a 20 20 20 20  nMaxSwitch:.    
3580: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3590: 20 20 20 20 73 65 6c 66 2e 5f 73 75 67 67 65 73      self._sugges
35a0: 74 28 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 73  t(oSuggResult, s
35b0: 52 65 6d 61 69 6e 5b 31 3a 32 5d 2b 73 52 65 6d  Remain[1:2]+sRem
35c0: 61 69 6e 5b 30 3a 31 5d 2b 73 52 65 6d 61 69 6e  ain[0:1]+sRemain
35d0: 5b 32 3a 5d 2c 20 6e 4d 61 78 53 77 69 74 63 68  [2:], nMaxSwitch
35e0: 2d 31 2c 20 6e 4d 61 78 44 65 6c 2c 20 6e 4d 61  -1, nMaxDel, nMa
35f0: 78 48 61 72 64 52 65 70 6c 2c 20 6e 44 65 65 70  xHardRepl, nDeep
3600: 2b 31 2c 20 69 41 64 64 72 2c 20 73 4e 65 77 57  +1, iAddr, sNewW
3610: 6f 72 64 2c 20 54 72 75 65 29 0a 20 20 20 20 20  ord, True).     
3620: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
3630: 20 64 65 6c 65 74 65 20 63 68 61 72 0a 20 20 20   delete char.   
3640: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3650: 20 69 66 20 6e 4d 61 78 44 65 6c 3a 0a 20 20 20   if nMaxDel:.   
3660: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3670: 20 20 20 20 20 73 65 6c 66 2e 5f 73 75 67 67 65       self._sugge
3680: 73 74 28 6f 53 75 67 67 52 65 73 75 6c 74 2c 20  st(oSuggResult, 
3690: 73 52 65 6d 61 69 6e 5b 31 3a 5d 2c 20 6e 4d 61  sRemain[1:], nMa
36a0: 78 53 77 69 74 63 68 2c 20 6e 4d 61 78 44 65 6c  xSwitch, nMaxDel
36b0: 2d 31 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c  -1, nMaxHardRepl
36c0: 2c 20 6e 44 65 65 70 2b 31 2c 20 69 41 64 64 72  , nDeep+1, iAddr
36d0: 2c 20 73 4e 65 77 57 6f 72 64 2c 20 54 72 75 65  , sNewWord, True
36e0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
36f0: 20 20 23 20 50 68 6f 6e 65 74 69 63 20 72 65 70    # Phonetic rep
3700: 6c 61 63 65 6d 65 6e 74 73 0a 20 20 20 20 20 20  lacements.      
3710: 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 73 52            for sR
3720: 65 70 6c 20 69 6e 20 63 70 2e 67 65 74 31 74 6f  epl in cp.get1to
3730: 58 52 65 70 6c 61 63 65 6d 65 6e 74 28 73 4e 65  XReplacement(sNe
3740: 77 57 6f 72 64 5b 2d 31 3a 5d 2c 20 63 43 75 72  wWord[-1:], cCur
3750: 72 65 6e 74 2c 20 73 52 65 6d 61 69 6e 5b 31 3a  rent, sRemain[1:
3760: 32 5d 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  2]):.           
3770: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73           self._s
3780: 75 67 67 65 73 74 28 6f 53 75 67 67 52 65 73 75  uggest(oSuggResu
3790: 6c 74 2c 20 73 52 65 70 6c 20 2b 20 73 52 65 6d  lt, sRepl + sRem
37a0: 61 69 6e 5b 31 3a 5d 2c 20 6e 4d 61 78 53 77 69  ain[1:], nMaxSwi
37b0: 74 63 68 2c 20 6e 4d 61 78 44 65 6c 2c 20 6e 4d  tch, nMaxDel, nM
37c0: 61 78 48 61 72 64 52 65 70 6c 2c 20 6e 44 65 65  axHardRepl, nDee
37d0: 70 2b 31 2c 20 69 41 64 64 72 2c 20 73 4e 65 77  p+1, iAddr, sNew
37e0: 57 6f 72 64 2c 20 54 72 75 65 29 0a 20 20 20 20  Word, True).    
37f0: 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20              for 
3800: 73 52 65 70 6c 20 69 6e 20 63 70 2e 64 32 74 6f  sRepl in cp.d2to
3810: 58 2e 67 65 74 28 73 52 65 6d 61 69 6e 5b 30 3a  X.get(sRemain[0:
3820: 32 5d 2c 20 28 29 29 3a 0a 20 20 20 20 20 20 20  2], ()):.       
3830: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c               sel
3840: 66 2e 5f 73 75 67 67 65 73 74 28 6f 53 75 67 67  f._suggest(oSugg
3850: 52 65 73 75 6c 74 2c 20 73 52 65 70 6c 20 2b 20  Result, sRepl + 
3860: 73 52 65 6d 61 69 6e 5b 32 3a 5d 2c 20 6e 4d 61  sRemain[2:], nMa
3870: 78 53 77 69 74 63 68 2c 20 6e 4d 61 78 44 65 6c  xSwitch, nMaxDel
3880: 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 2c 20  , nMaxHardRepl, 
3890: 6e 44 65 65 70 2b 31 2c 20 69 41 64 64 72 2c 20  nDeep+1, iAddr, 
38a0: 73 4e 65 77 57 6f 72 64 2c 20 54 72 75 65 29 0a  sNewWord, True).
38b0: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 65 6e              # en
38c0: 64 20 6f 66 20 77 6f 72 64 0a 20 20 20 20 20 20  d of word.      
38d0: 20 20 20 20 20 20 69 66 20 6c 65 6e 28 73 52 65        if len(sRe
38e0: 6d 61 69 6e 29 20 3d 3d 20 32 3a 0a 20 20 20 20  main) == 2:.    
38f0: 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20              for 
3900: 73 52 65 70 6c 20 69 6e 20 63 70 2e 64 46 69 6e  sRepl in cp.dFin
3910: 61 6c 32 2e 67 65 74 28 73 52 65 6d 61 69 6e 2c  al2.get(sRemain,
3920: 20 28 29 29 3a 0a 20 20 20 20 20 20 20 20 20 20   ()):.          
3930: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f            self._
3940: 73 75 67 67 65 73 74 28 6f 53 75 67 67 52 65 73  suggest(oSuggRes
3950: 75 6c 74 2c 20 73 52 65 70 6c 2c 20 6e 4d 61 78  ult, sRepl, nMax
3960: 53 77 69 74 63 68 2c 20 6e 4d 61 78 44 65 6c 2c  Switch, nMaxDel,
3970: 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 2c 20 6e   nMaxHardRepl, n
3980: 44 65 65 70 2b 31 2c 20 69 41 64 64 72 2c 20 73  Deep+1, iAddr, s
3990: 4e 65 77 57 6f 72 64 2c 20 54 72 75 65 29 0a 20  NewWord, True). 
39a0: 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66 20             elif 
39b0: 6c 65 6e 28 73 52 65 6d 61 69 6e 29 20 3d 3d 20  len(sRemain) == 
39c0: 31 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  1:.             
39d0: 20 20 20 73 65 6c 66 2e 5f 73 75 67 67 65 73 74     self._suggest
39e0: 28 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 22 22  (oSuggResult, ""
39f0: 2c 20 6e 4d 61 78 53 77 69 74 63 68 2c 20 6e 4d  , nMaxSwitch, nM
3a00: 61 78 44 65 6c 2c 20 6e 4d 61 78 48 61 72 64 52  axDel, nMaxHardR
3a10: 65 70 6c 2c 20 6e 44 65 65 70 2b 31 2c 20 69 41  epl, nDeep+1, iA
3a20: 64 64 72 2c 20 73 4e 65 77 57 6f 72 64 2c 20 54  ddr, sNewWord, T
3a30: 72 75 65 29 20 23 20 72 65 6d 6f 76 65 20 6c 61  rue) # remove la
3a40: 73 74 20 63 68 61 72 20 61 6e 64 20 67 6f 20 6f  st char and go o
3a50: 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  n.              
3a60: 20 20 66 6f 72 20 73 52 65 70 6c 20 69 6e 20 63    for sRepl in c
3a70: 70 2e 64 46 69 6e 61 6c 31 2e 67 65 74 28 73 52  p.dFinal1.get(sR
3a80: 65 6d 61 69 6e 2c 20 28 29 29 3a 0a 20 20 20 20  emain, ()):.    
3a90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3aa0: 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28 6f 53  self._suggest(oS
3ab0: 75 67 67 52 65 73 75 6c 74 2c 20 73 52 65 70 6c  uggResult, sRepl
3ac0: 2c 20 6e 4d 61 78 53 77 69 74 63 68 2c 20 6e 4d  , nMaxSwitch, nM
3ad0: 61 78 44 65 6c 2c 20 6e 4d 61 78 48 61 72 64 52  axDel, nMaxHardR
3ae0: 65 70 6c 2c 20 6e 44 65 65 70 2b 31 2c 20 69 41  epl, nDeep+1, iA
3af0: 64 64 72 2c 20 73 4e 65 77 57 6f 72 64 2c 20 54  ddr, sNewWord, T
3b00: 72 75 65 29 0a 0a 20 20 20 20 23 40 74 69 6d 65  rue)..    #@time
3b10: 74 68 69 73 0a 20 20 20 20 64 65 66 20 73 75 67  this.    def sug
3b20: 67 65 73 74 32 20 28 73 65 6c 66 2c 20 73 57 6f  gest2 (self, sWo
3b30: 72 64 2c 20 6e 4d 61 78 53 75 67 67 3d 31 30 29  rd, nMaxSugg=10)
3b40: 3a 0a 20 20 20 20 20 20 20 20 22 72 65 74 75 72  :.        "retur
3b50: 6e 73 20 61 20 73 65 74 20 6f 66 20 73 75 67 67  ns a set of sugg
3b60: 65 73 74 69 6f 6e 73 20 66 6f 72 20 3c 73 57 6f  estions for <sWo
3b70: 72 64 3e 22 0a 20 20 20 20 20 20 20 20 73 57 6f  rd>".        sWo
3b80: 72 64 20 3d 20 63 70 2e 73 70 65 6c 6c 69 6e 67  rd = cp.spelling
3b90: 4e 6f 72 6d 61 6c 69 7a 61 74 69 6f 6e 28 73 57  Normalization(sW
3ba0: 6f 72 64 29 0a 20 20 20 20 20 20 20 20 73 50 66  ord).        sPf
3bb0: 78 2c 20 73 57 6f 72 64 2c 20 73 53 66 78 20 3d  x, sWord, sSfx =
3bc0: 20 63 70 2e 63 75 74 28 73 57 6f 72 64 29 0a 20   cp.cut(sWord). 
3bd0: 20 20 20 20 20 20 20 6f 53 75 67 67 52 65 73 75         oSuggResu
3be0: 6c 74 20 3d 20 53 75 67 67 52 65 73 75 6c 74 28  lt = SuggResult(
3bf0: 73 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20 73  sWord).        s
3c00: 65 6c 66 2e 5f 73 75 67 67 65 73 74 32 28 6f 53  elf._suggest2(oS
3c10: 75 67 67 52 65 73 75 6c 74 29 0a 20 20 20 20 20  uggResult).     
3c20: 20 20 20 61 53 75 67 67 20 3d 20 6f 53 75 67 67     aSugg = oSugg
3c30: 52 65 73 75 6c 74 2e 67 65 74 53 75 67 67 65 73  Result.getSugges
3c40: 74 69 6f 6e 73 28 29 0a 20 20 20 20 20 20 20 20  tions().        
3c50: 69 66 20 73 53 66 78 20 6f 72 20 73 50 66 78 3a  if sSfx or sPfx:
3c60: 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 20 77  .            # w
3c70: 65 20 61 64 64 20 77 68 61 74 20 77 65 20 72 65  e add what we re
3c80: 6d 6f 76 65 64 0a 20 20 20 20 20 20 20 20 20 20  moved.          
3c90: 20 20 72 65 74 75 72 6e 20 6c 69 73 74 28 6d 61    return list(ma
3ca0: 70 28 6c 61 6d 62 64 61 20 73 53 75 67 3a 20 73  p(lambda sSug: s
3cb0: 50 66 78 20 2b 20 73 53 75 67 20 2b 20 73 53 66  Pfx + sSug + sSf
3cc0: 78 2c 20 61 53 75 67 67 29 29 0a 20 20 20 20 20  x, aSugg)).     
3cd0: 20 20 20 72 65 74 75 72 6e 20 61 53 75 67 67 0a     return aSugg.
3ce0: 0a 20 20 20 20 64 65 66 20 5f 73 75 67 67 65 73  .    def _sugges
3cf0: 74 32 20 28 73 65 6c 66 2c 20 6f 53 75 67 67 52  t2 (self, oSuggR
3d00: 65 73 75 6c 74 2c 20 6e 44 65 65 70 3d 30 2c 20  esult, nDeep=0, 
3d10: 69 41 64 64 72 3d 30 2c 20 73 4e 65 77 57 6f 72  iAddr=0, sNewWor
3d20: 64 3d 22 22 29 3a 0a 20 20 20 20 20 20 20 20 23  d=""):.        #
3d30: 20 72 65 63 75 72 73 69 76 65 20 66 75 6e 63 74   recursive funct
3d40: 69 6f 6e 0a 20 20 20 20 20 20 20 20 23 6c 6f 67  ion.        #log
3d50: 67 69 6e 67 2e 69 6e 66 6f 28 28 6e 44 65 65 70  ging.info((nDeep
3d60: 20 2a 20 22 20 20 22 29 20 2b 20 73 4e 65 77 57   * "  ") + sNewW
3d70: 6f 72 64 29 0a 20 20 20 20 20 20 20 20 69 66 20  ord).        if 
3d80: 6e 44 65 65 70 20 3e 3d 20 6f 53 75 67 67 52 65  nDeep >= oSuggRe
3d90: 73 75 6c 74 2e 6e 44 69 73 74 4c 69 6d 69 74 3a  sult.nDistLimit:
3da0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 43 6c  .            sCl
3db0: 65 61 6e 4e 65 77 57 6f 72 64 20 3d 20 63 70 2e  eanNewWord = cp.
3dc0: 73 69 6d 70 6c 69 66 79 57 6f 72 64 28 73 4e 65  simplifyWord(sNe
3dd0: 77 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20 20  wWord).         
3de0: 20 20 20 69 66 20 73 74 2e 64 69 73 74 61 6e 63     if st.distanc
3df0: 65 53 69 66 74 34 28 6f 53 75 67 67 52 65 73 75  eSift4(oSuggResu
3e00: 6c 74 2e 73 43 6c 65 61 6e 57 6f 72 64 5b 3a 6c  lt.sCleanWord[:l
3e10: 65 6e 28 73 43 6c 65 61 6e 4e 65 77 57 6f 72 64  en(sCleanNewWord
3e20: 29 5d 2c 20 73 43 6c 65 61 6e 4e 65 77 57 6f 72  )], sCleanNewWor
3e30: 64 29 20 3e 20 6f 53 75 67 67 52 65 73 75 6c 74  d) > oSuggResult
3e40: 2e 6e 44 69 73 74 4c 69 6d 69 74 3a 0a 20 20 20  .nDistLimit:.   
3e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74               ret
3e60: 75 72 6e 0a 20 20 20 20 20 20 20 20 69 66 20 69  urn.        if i
3e70: 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65  nt.from_bytes(se
3e80: 6c 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69  lf.byDic[iAddr:i
3e90: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
3ea0: 41 72 63 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d  Arc], byteorder=
3eb0: 27 62 69 67 27 29 20 26 20 73 65 6c 66 2e 5f 66  'big') & self._f
3ec0: 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b 3a 0a 20 20  inalNodeMask:.  
3ed0: 20 20 20 20 20 20 20 20 20 20 6f 53 75 67 67 52            oSuggR
3ee0: 65 73 75 6c 74 2e 61 64 64 53 75 67 67 28 73 4e  esult.addSugg(sN
3ef0: 65 77 57 6f 72 64 2c 20 6e 44 65 65 70 29 0a 20  ewWord, nDeep). 
3f00: 20 20 20 20 20 20 20 66 6f 72 20 63 43 68 61 72         for cChar
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 43 68 61 72 41 72 63 73 57 69 74 68  _getCharArcsWith
3f30: 50 72 69 6f 72 69 74 79 28 69 41 64 64 72 2c 20  Priority(iAddr, 
3f40: 6f 53 75 67 67 52 65 73 75 6c 74 2e 73 57 6f 72  oSuggResult.sWor
3f50: 64 5b 6e 44 65 65 70 3a 6e 44 65 65 70 2b 31 5d  d[nDeep:nDeep+1]
3f60: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  ):.            s
3f70: 65 6c 66 2e 5f 73 75 67 67 65 73 74 32 28 6f 53  elf._suggest2(oS
3f80: 75 67 67 52 65 73 75 6c 74 2c 20 6e 44 65 65 70  uggResult, nDeep
3f90: 2b 31 2c 20 6a 41 64 64 72 2c 20 73 4e 65 77 57  +1, jAddr, sNewW
3fa0: 6f 72 64 2b 63 43 68 61 72 29 0a 20 20 20 20 20  ord+cChar).     
3fb0: 20 20 20 72 65 74 75 72 6e 0a 0a 20 20 20 20 64     return..    d
3fc0: 65 66 20 5f 67 65 74 43 68 61 72 41 72 63 73 20  ef _getCharArcs 
3fd0: 28 73 65 6c 66 2c 20 69 41 64 64 72 29 3a 0a 20  (self, iAddr):. 
3fe0: 20 20 20 20 20 20 20 22 67 65 6e 65 72 61 74 6f         "generato
3ff0: 72 3a 20 79 69 65 6c 64 20 61 6c 6c 20 63 68 61  r: yield all cha
4000: 72 73 20 61 6e 64 20 61 64 64 72 65 73 73 65 73  rs and addresses
4010: 20 66 72 6f 6d 20 6e 6f 64 65 20 61 74 20 61 64   from node at ad
4020: 64 72 65 73 73 20 3c 69 41 64 64 72 3e 22 0a 20  dress <iAddr>". 
4030: 20 20 20 20 20 20 20 66 6f 72 20 6e 56 61 6c 2c         for nVal,
4040: 20 6a 41 64 64 72 20 69 6e 20 73 65 6c 66 2e 5f   jAddr in self._
4050: 67 65 74 41 72 63 73 28 69 41 64 64 72 29 3a 0a  getArcs(iAddr):.
4060: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
4070: 56 61 6c 20 3c 3d 20 73 65 6c 66 2e 6e 43 68 61  Val <= self.nCha
4080: 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r:.             
4090: 20 20 20 79 69 65 6c 64 20 28 73 65 6c 66 2e 64     yield (self.d
40a0: 43 68 61 72 56 61 6c 5b 6e 56 61 6c 5d 2c 20 6a  CharVal[nVal], j
40b0: 41 64 64 72 29 0a 0a 20 20 20 20 64 65 66 20 5f  Addr)..    def _
40c0: 67 65 74 53 69 6d 69 6c 61 72 43 68 61 72 41 72  getSimilarCharAr
40d0: 63 73 20 28 73 65 6c 66 2c 20 63 43 68 61 72 2c  cs (self, cChar,
40e0: 20 69 41 64 64 72 29 3a 0a 20 20 20 20 20 20 20   iAddr):.       
40f0: 20 22 67 65 6e 65 72 61 74 6f 72 3a 20 79 69 65   "generator: yie
4100: 6c 64 20 73 69 6d 69 6c 61 72 20 63 68 61 72 20  ld similar char 
4110: 6f 66 20 3c 63 43 68 61 72 3e 20 61 6e 64 20 61  of <cChar> and a
4120: 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 66 6f  ddress of the fo
4130: 6c 6c 6f 77 69 6e 67 20 6e 6f 64 65 22 0a 20 20  llowing node".  
4140: 20 20 20 20 20 20 66 6f 72 20 63 20 69 6e 20 63        for c in c
4150: 70 2e 64 31 74 6f 31 2e 67 65 74 28 63 43 68 61  p.d1to1.get(cCha
4160: 72 2c 20 5b 63 43 68 61 72 5d 29 3a 0a 20 20 20  r, [cChar]):.   
4170: 20 20 20 20 20 20 20 20 20 69 66 20 63 20 69 6e           if c in
4180: 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a 20 20 20   self.dChar:.   
4190: 20 20 20 20 20 20 20 20 20 20 20 20 20 6a 41 64               jAd
41a0: 64 72 20 3d 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75  dr = self._looku
41b0: 70 41 72 63 4e 6f 64 65 28 73 65 6c 66 2e 64 43  pArcNode(self.dC
41c0: 68 61 72 5b 63 5d 2c 20 69 41 64 64 72 29 0a 20  har[c], iAddr). 
41d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
41e0: 66 20 6a 41 64 64 72 3a 0a 20 20 20 20 20 20 20  f jAddr:.       
41f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65               yie
4200: 6c 64 20 28 63 2c 20 6a 41 64 64 72 29 0a 0a 20  ld (c, jAddr).. 
4210: 20 20 20 64 65 66 20 5f 67 65 74 43 68 61 72 41     def _getCharA
4220: 72 63 73 57 69 74 68 50 72 69 6f 72 69 74 79 20  rcsWithPriority 
4230: 28 73 65 6c 66 2c 20 69 41 64 64 72 2c 20 63 43  (self, iAddr, cC
4240: 68 61 72 29 3a 0a 20 20 20 20 20 20 20 20 69 66  har):.        if
4250: 20 6e 6f 74 20 63 43 68 61 72 3a 0a 20 20 20 20   not cChar:.    
4260: 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 66 72          yield fr
4270: 6f 6d 20 73 65 6c 66 2e 5f 67 65 74 43 68 61 72  om self._getChar
4280: 41 72 63 73 28 69 41 64 64 72 29 0a 20 20 20 20  Arcs(iAddr).    
4290: 20 20 20 20 6c 54 75 70 6c 65 20 3d 20 6c 69 73      lTuple = lis
42a0: 74 28 73 65 6c 66 2e 5f 67 65 74 43 68 61 72 41  t(self._getCharA
42b0: 72 63 73 28 69 41 64 64 72 29 29 0a 20 20 20 20  rcs(iAddr)).    
42c0: 20 20 20 20 6c 54 75 70 6c 65 2e 73 6f 72 74 28      lTuple.sort(
42d0: 6b 65 79 3d 6c 61 6d 62 64 61 20 74 3a 20 30 20  key=lambda t: 0 
42e0: 20 69 66 20 74 5b 30 5d 20 69 6e 20 63 70 2e 64   if t[0] in cp.d
42f0: 31 74 6f 31 2e 67 65 74 28 63 43 68 61 72 2c 20  1to1.get(cChar, 
4300: 63 43 68 61 72 29 20 20 65 6c 73 65 20 20 31 29  cChar)  else  1)
4310: 0a 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 66  .        yield f
4320: 72 6f 6d 20 6c 54 75 70 6c 65 0a 0a 20 20 20 20  rom lTuple..    
4330: 64 65 66 20 5f 67 65 74 54 61 69 6c 73 20 28 73  def _getTails (s
4340: 65 6c 66 2c 20 69 41 64 64 72 2c 20 73 54 61 69  elf, iAddr, sTai
4350: 6c 3d 22 22 2c 20 6e 3d 32 29 3a 0a 20 20 20 20  l="", n=2):.    
4360: 20 20 20 20 22 72 65 74 75 72 6e 20 61 20 6c 69      "return a li
4370: 73 74 20 6f 66 20 73 75 66 66 69 78 65 73 20 65  st of suffixes e
4380: 6e 64 69 6e 67 20 61 74 20 61 20 64 69 73 74 61  nding at a dista
4390: 6e 63 65 20 6f 66 20 3c 6e 3e 20 66 72 6f 6d 20  nce of <n> from 
43a0: 3c 69 41 64 64 72 3e 22 0a 20 20 20 20 20 20 20  <iAddr>".       
43b0: 20 61 54 61 69 6c 73 20 3d 20 73 65 74 28 29 0a   aTails = set().
43c0: 20 20 20 20 20 20 20 20 66 6f 72 20 6e 56 61 6c          for nVal
43d0: 2c 20 6a 41 64 64 72 20 69 6e 20 73 65 6c 66 2e  , jAddr in self.
43e0: 5f 67 65 74 41 72 63 73 28 69 41 64 64 72 29 3a  _getArcs(iAddr):
43f0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
4400: 6e 56 61 6c 20 3c 3d 20 73 65 6c 66 2e 6e 43 68  nVal <= self.nCh
4410: 61 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ar:.            
4420: 20 20 20 20 69 66 20 69 6e 74 2e 66 72 6f 6d 5f      if int.from_
4430: 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63  bytes(self.byDic
4440: 5b 6a 41 64 64 72 3a 6a 41 64 64 72 2b 73 65 6c  [jAddr:jAddr+sel
4450: 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20 62 79  f.nBytesArc], by
4460: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 20 26  teorder='big') &
4470: 20 73 65 6c 66 2e 5f 66 69 6e 61 6c 4e 6f 64 65   self._finalNode
4480: 4d 61 73 6b 3a 0a 20 20 20 20 20 20 20 20 20 20  Mask:.          
4490: 20 20 20 20 20 20 20 20 20 20 61 54 61 69 6c 73            aTails
44a0: 2e 61 64 64 28 73 54 61 69 6c 20 2b 20 73 65 6c  .add(sTail + sel
44b0: 66 2e 64 43 68 61 72 56 61 6c 5b 6e 56 61 6c 5d  f.dCharVal[nVal]
44c0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
44d0: 20 20 69 66 20 6e 20 61 6e 64 20 6e 6f 74 20 61    if n and not a
44e0: 54 61 69 6c 73 3a 0a 20 20 20 20 20 20 20 20 20  Tails:.         
44f0: 20 20 20 20 20 20 20 20 20 20 20 61 54 61 69 6c             aTail
4500: 73 2e 75 70 64 61 74 65 28 73 65 6c 66 2e 5f 67  s.update(self._g
4510: 65 74 54 61 69 6c 73 28 6a 41 64 64 72 2c 20 73  etTails(jAddr, s
4520: 54 61 69 6c 2b 73 65 6c 66 2e 64 43 68 61 72 56  Tail+self.dCharV
4530: 61 6c 5b 6e 56 61 6c 5d 2c 20 6e 2d 31 29 29 0a  al[nVal], n-1)).
4540: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 61          return a
4550: 54 61 69 6c 73 0a 0a 20 20 20 20 64 65 66 20 64  Tails..    def d
4560: 72 61 77 50 61 74 68 20 28 73 65 6c 66 2c 20 73  rawPath (self, s
4570: 57 6f 72 64 2c 20 69 41 64 64 72 3d 30 29 3a 0a  Word, iAddr=0):.
4580: 20 20 20 20 20 20 20 20 22 73 68 6f 77 20 74 68          "show th
4590: 65 20 70 61 74 68 20 74 61 6b 65 6e 20 62 79 20  e path taken by 
45a0: 3c 73 57 6f 72 64 3e 20 69 6e 20 74 68 65 20 67  <sWord> in the g
45b0: 72 61 70 68 22 0a 20 20 20 20 20 20 20 20 73 57  raph".        sW
45c0: 6f 72 64 20 3d 20 63 70 2e 73 70 65 6c 6c 69 6e  ord = cp.spellin
45d0: 67 4e 6f 72 6d 61 6c 69 7a 61 74 69 6f 6e 28 73  gNormalization(s
45e0: 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20 63 31  Word).        c1
45f0: 20 3d 20 73 57 6f 72 64 5b 30 3a 31 5d 20 20 69   = sWord[0:1]  i
4600: 66 20 73 57 6f 72 64 20 20 65 6c 73 65 20 22 20  f sWord  else " 
4610: 22 0a 20 20 20 20 20 20 20 20 69 50 6f 73 20 3d  ".        iPos =
4620: 20 2d 31 0a 20 20 20 20 20 20 20 20 6e 20 3d 20   -1.        n = 
4630: 30 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28  0.        print(
4640: 63 31 20 2b 20 22 3a 20 22 2c 20 65 6e 64 3d 22  c1 + ": ", end="
4650: 22 29 0a 20 20 20 20 20 20 20 20 66 6f 72 20 63  ").        for c
4660: 32 2c 20 6a 41 64 64 72 20 69 6e 20 73 65 6c 66  2, jAddr in self
4670: 2e 5f 67 65 74 43 68 61 72 41 72 63 73 28 69 41  ._getCharArcs(iA
4680: 64 64 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20  ddr):.          
4690: 20 20 70 72 69 6e 74 28 63 32 2c 20 65 6e 64 3d    print(c2, end=
46a0: 22 22 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  "").            
46b0: 69 66 20 63 32 20 3d 3d 20 73 57 6f 72 64 5b 30  if c2 == sWord[0
46c0: 3a 31 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20  :1]:.           
46d0: 20 20 20 20 20 69 4e 65 78 74 4e 6f 64 65 41 64       iNextNodeAd
46e0: 64 72 20 3d 20 6a 41 64 64 72 0a 20 20 20 20 20  dr = jAddr.     
46f0: 20 20 20 20 20 20 20 20 20 20 20 69 50 6f 73 20             iPos 
4700: 3d 20 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20  = n.            
4710: 6e 20 2b 3d 20 31 0a 20 20 20 20 20 20 20 20 69  n += 1.        i
4720: 66 20 6e 6f 74 20 73 57 6f 72 64 3a 0a 20 20 20  f not sWord:.   
4730: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 0a           return.
4740: 20 20 20 20 20 20 20 20 69 66 20 69 50 6f 73 20          if iPos 
4750: 3e 3d 20 30 3a 0a 20 20 20 20 20 20 20 20 20 20  >= 0:.          
4760: 20 20 70 72 69 6e 74 28 22 5c 6e 20 20 20 22 2b    print("\n   "+
4770: 20 22 20 22 20 2a 20 69 50 6f 73 20 2b 20 22 7c   " " * iPos + "|
4780: 22 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  ").            s
4790: 65 6c 66 2e 64 72 61 77 50 61 74 68 28 73 57 6f  elf.drawPath(sWo
47a0: 72 64 5b 31 3a 5d 2c 20 69 4e 65 78 74 4e 6f 64  rd[1:], iNextNod
47b0: 65 41 64 64 72 29 0a 0a 20 20 20 20 64 65 66 20  eAddr)..    def 
47c0: 73 65 6c 65 63 74 20 28 73 65 6c 66 2c 20 73 50  select (self, sP
47d0: 61 74 74 65 72 6e 3d 22 22 29 3a 0a 20 20 20 20  attern=""):.    
47e0: 20 20 20 20 22 67 65 6e 65 72 61 74 6f 72 3a 20      "generator: 
47f0: 72 65 74 75 72 6e 73 20 61 6c 6c 20 65 6e 74 72  returns all entr
4800: 69 65 73 20 77 68 69 63 68 20 6d 6f 72 70 68 6f  ies which morpho
4810: 6c 6f 67 79 20 66 69 74 73 20 3c 73 50 61 74 74  logy fits <sPatt
4820: 65 72 6e 3e 22 0a 20 20 20 20 20 20 20 20 7a 50  ern>".        zP
4830: 61 74 74 65 72 6e 20 3d 20 4e 6f 6e 65 0a 20 20  attern = None.  
4840: 20 20 20 20 20 20 69 66 20 73 50 61 74 74 65 72        if sPatter
4850: 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 74  n:.            t
4860: 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ry:.            
4870: 20 20 20 20 7a 50 61 74 74 65 72 6e 20 3d 20 72      zPattern = r
4880: 65 2e 63 6f 6d 70 69 6c 65 28 73 50 61 74 74 65  e.compile(sPatte
4890: 72 6e 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  rn).            
48a0: 65 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20  except:.        
48b0: 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 23          print("#
48c0: 20 45 72 72 6f 72 20 69 6e 20 72 65 67 65 78 20   Error in regex 
48d0: 70 61 74 74 65 72 6e 22 29 0a 20 20 20 20 20 20  pattern").      
48e0: 20 20 20 20 20 20 20 20 20 20 74 72 61 63 65 62            traceb
48f0: 61 63 6b 2e 70 72 69 6e 74 5f 65 78 63 28 29 0a  ack.print_exc().
4900: 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 66 72          yield fr
4910: 6f 6d 20 73 65 6c 66 2e 5f 73 65 6c 65 63 74 31  om self._select1
4920: 28 7a 50 61 74 74 65 72 6e 2c 20 30 2c 20 22 22  (zPattern, 0, ""
4930: 29 0a 0a 20 20 20 20 23 20 64 65 66 20 6d 6f 72  )..    # def mor
4940: 70 68 20 28 73 65 6c 66 2c 20 73 57 6f 72 64 29  ph (self, sWord)
4950: 3a 0a 20 20 20 20 23 20 20 20 20 20 69 73 20 64  :.    #     is d
4960: 65 66 69 6e 65 64 20 69 6e 20 5f 5f 69 6e 69 74  efined in __init
4970: 5f 5f 0a 0a 20 20 20 20 23 20 56 45 52 53 49 4f  __..    # VERSIO
4980: 4e 20 31 0a 20 20 20 20 64 65 66 20 5f 73 65 6c  N 1.    def _sel
4990: 65 63 74 31 20 28 73 65 6c 66 2c 20 7a 50 61 74  ect1 (self, zPat
49a0: 74 65 72 6e 2c 20 69 41 64 64 72 2c 20 73 57 6f  tern, iAddr, sWo
49b0: 72 64 29 3a 0a 20 20 20 20 20 20 20 20 23 20 72  rd):.        # r
49c0: 65 63 75 72 73 69 76 65 20 67 65 6e 65 72 61 74  ecursive generat
49d0: 6f 72 0a 20 20 20 20 20 20 20 20 66 6f 72 20 6e  or.        for n
49e0: 56 61 6c 2c 20 6a 41 64 64 72 20 69 6e 20 73 65  Val, jAddr in se
49f0: 6c 66 2e 5f 67 65 74 41 72 63 73 31 28 69 41 64  lf._getArcs1(iAd
4a00: 64 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  dr):.           
4a10: 20 69 66 20 6e 56 61 6c 20 3c 3d 20 73 65 6c 66   if nVal <= self
4a20: 2e 6e 43 68 61 72 3a 0a 20 20 20 20 20 20 20 20  .nChar:.        
4a30: 20 20 20 20 20 20 20 20 23 20 73 69 6d 70 6c 65          # simple
4a40: 20 63 68 61 72 61 63 74 65 72 0a 20 20 20 20 20   character.     
4a50: 20 20 20 20 20 20 20 20 20 20 20 79 69 65 6c 64             yield
4a60: 20 66 72 6f 6d 20 73 65 6c 66 2e 5f 73 65 6c 65   from self._sele
4a70: 63 74 31 28 7a 50 61 74 74 65 72 6e 2c 20 6a 41  ct1(zPattern, jA
4a80: 64 64 72 2c 20 73 57 6f 72 64 20 2b 20 73 65 6c  ddr, sWord + sel
4a90: 66 2e 6c 41 72 63 56 61 6c 5b 6e 56 61 6c 5d 29  f.lArcVal[nVal])
4aa0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73  .            els
4ab0: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
4ac0: 20 20 20 73 45 6e 74 72 79 20 3d 20 73 57 6f 72     sEntry = sWor
4ad0: 64 20 2b 20 22 5c 74 22 20 2b 20 73 65 6c 66 2e  d + "\t" + self.
4ae0: 66 75 6e 63 53 74 65 6d 6d 69 6e 67 28 73 57 6f  funcStemming(sWo
4af0: 72 64 2c 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c  rd, self.lArcVal
4b00: 5b 6e 56 61 6c 5d 29 0a 20 20 20 20 20 20 20 20  [nVal]).        
4b10: 20 20 20 20 20 20 20 20 66 6f 72 20 6e 4d 6f 72          for nMor
4b20: 70 68 56 61 6c 2c 20 5f 20 69 6e 20 73 65 6c 66  phVal, _ in self
4b30: 2e 5f 67 65 74 41 72 63 73 31 28 6a 41 64 64 72  ._getArcs1(jAddr
4b40: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
4b50: 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 7a 50         if not zP
4b60: 61 74 74 65 72 6e 20 6f 72 20 7a 50 61 74 74 65  attern or zPatte
4b70: 72 6e 2e 73 65 61 72 63 68 28 73 65 6c 66 2e 6c  rn.search(self.l
4b80: 41 72 63 56 61 6c 5b 6e 4d 6f 72 70 68 56 61 6c  ArcVal[nMorphVal
4b90: 5d 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ]):.            
4ba0: 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65 6c              yiel
4bb0: 64 20 73 45 6e 74 72 79 20 2b 20 22 5c 74 22 20  d sEntry + "\t" 
4bc0: 2b 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e  + self.lArcVal[n
4bd0: 4d 6f 72 70 68 56 61 6c 5d 0a 0a 20 20 20 20 64  MorphVal]..    d
4be0: 65 66 20 5f 6d 6f 72 70 68 31 20 28 73 65 6c 66  ef _morph1 (self
4bf0: 2c 20 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20  , sWord):.      
4c00: 20 20 22 72 65 74 75 72 6e 73 20 6d 6f 72 70 68    "returns morph
4c10: 6f 6c 6f 67 69 65 73 20 6f 66 20 3c 73 57 6f 72  ologies of <sWor
4c20: 64 3e 22 0a 20 20 20 20 20 20 20 20 69 41 64 64  d>".        iAdd
4c30: 72 20 3d 20 30 0a 20 20 20 20 20 20 20 20 66 6f  r = 0.        fo
4c40: 72 20 63 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20  r c in sWord:.  
4c50: 20 20 20 20 20 20 20 20 20 20 69 66 20 63 20 6e            if c n
4c60: 6f 74 20 69 6e 20 73 65 6c 66 2e 64 43 68 61 72  ot in self.dChar
4c70: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
4c80: 20 20 72 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20    return [].    
4c90: 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20          iAddr = 
4ca0: 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e  self._lookupArcN
4cb0: 6f 64 65 28 73 65 6c 66 2e 64 43 68 61 72 5b 63  ode(self.dChar[c
4cc0: 5d 2c 20 69 41 64 64 72 29 0a 20 20 20 20 20 20  ], iAddr).      
4cd0: 20 20 20 20 20 20 69 66 20 69 41 64 64 72 20 3d        if iAddr =
4ce0: 3d 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20  = None:.        
4cf0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b          return [
4d00: 5d 0a 20 20 20 20 20 20 20 20 69 66 20 28 69 6e  ].        if (in
4d10: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
4d20: 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 41  f.byDic[iAddr:iA
4d30: 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41  ddr+self.nBytesA
4d40: 72 63 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27  rc], byteorder='
4d50: 62 69 67 27 29 20 26 20 73 65 6c 66 2e 5f 66 69  big') & self._fi
4d60: 6e 61 6c 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20 20  nalNodeMask):.  
4d70: 20 20 20 20 20 20 20 20 20 20 6c 20 3d 20 5b 5d            l = []
4d80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e 52 61  .            nRa
4d90: 77 41 72 63 20 3d 20 30 0a 20 20 20 20 20 20 20  wArc = 0.       
4da0: 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28       while not (
4db0: 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f  nRawArc & self._
4dc0: 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20  lastArcMask):.  
4dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 45                iE
4de0: 6e 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64  ndArcAddr = iAdd
4df0: 72 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41  r + self.nBytesA
4e00: 72 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  rc.             
4e10: 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74     nRawArc = int
4e20: 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66  .from_bytes(self
4e30: 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e  .byDic[iAddr:iEn
4e40: 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f  dArcAddr], byteo
4e50: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
4e60: 20 20 20 20 20 20 20 20 20 20 20 20 6e 41 72 63              nArc
4e70: 20 3d 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c   = nRawArc & sel
4e80: 66 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20  f._arcMask.     
4e90: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 41             if nA
4ea0: 72 63 20 3e 20 73 65 6c 66 2e 6e 43 68 61 72 3a  rc > self.nChar:
4eb0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4ec0: 20 20 20 20 20 23 20 54 68 69 73 20 76 61 6c 75       # This valu
4ed0: 65 20 69 73 20 6e 6f 74 20 61 20 63 68 61 72 2c  e is not a char,
4ee0: 20 74 68 69 73 20 69 73 20 61 20 73 74 65 6d 6d   this is a stemm
4ef0: 69 6e 67 20 63 6f 64 65 20 0a 20 20 20 20 20 20  ing code .      
4f00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 53                sS
4f10: 74 65 6d 20 3d 20 22 3e 22 20 2b 20 73 65 6c 66  tem = ">" + self
4f20: 2e 66 75 6e 63 53 74 65 6d 6d 69 6e 67 28 73 57  .funcStemming(sW
4f30: 6f 72 64 2c 20 73 65 6c 66 2e 6c 41 72 63 56 61  ord, self.lArcVa
4f40: 6c 5b 6e 41 72 63 5d 29 0a 20 20 20 20 20 20 20  l[nArc]).       
4f50: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 4e               # N
4f60: 6f 77 20 2c 20 77 65 20 67 6f 20 74 6f 20 74 68  ow , we go to th
4f70: 65 20 6e 65 78 74 20 6e 6f 64 65 20 61 6e 64 20  e next node and 
4f80: 72 65 74 72 69 65 76 65 20 61 6c 6c 20 66 6f 6c  retrieve all fol
4f90: 6c 6f 77 69 6e 67 20 61 72 63 73 20 76 61 6c 75  lowing arcs valu
4fa0: 65 73 2c 20 61 6c 6c 20 6f 66 20 74 68 65 6d 20  es, all of them 
4fb0: 61 72 65 20 74 61 67 73 0a 20 20 20 20 20 20 20  are tags.       
4fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64               iAd
4fd0: 64 72 32 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62  dr2 = int.from_b
4fe0: 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b  ytes(self.byDic[
4ff0: 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e 64  iEndArcAddr:iEnd
5000: 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  ArcAddr+self.nBy
5010: 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 5d 2c  tesNodeAddress],
5020: 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27   byteorder='big'
5030: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
5040: 20 20 20 20 20 20 6e 52 61 77 41 72 63 32 20 3d        nRawArc2 =
5050: 20 30 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   0.             
5060: 20 20 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74         while not
5070: 20 28 6e 52 61 77 41 72 63 32 20 26 20 73 65 6c   (nRawArc2 & sel
5080: 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a  f._lastArcMask):
5090: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
50a0: 20 20 20 20 20 20 20 20 20 69 45 6e 64 41 72 63           iEndArc
50b0: 41 64 64 72 32 20 3d 20 69 41 64 64 72 32 20 2b  Addr2 = iAddr2 +
50c0: 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a   self.nBytesArc.
50d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
50e0: 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63 32          nRawArc2
50f0: 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65   = int.from_byte
5100: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64  s(self.byDic[iAd
5110: 64 72 32 3a 69 45 6e 64 41 72 63 41 64 64 72 32  dr2:iEndArcAddr2
5120: 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69  ], byteorder='bi
5130: 67 27 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  g').            
5140: 20 20 20 20 20 20 20 20 20 20 20 20 6c 2e 61 70              l.ap
5150: 70 65 6e 64 28 73 53 74 65 6d 20 2b 20 22 20 22  pend(sStem + " "
5160: 20 2b 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b   + self.lArcVal[
5170: 6e 52 61 77 41 72 63 32 20 26 20 73 65 6c 66 2e  nRawArc2 & self.
5180: 5f 61 72 63 4d 61 73 6b 5d 29 0a 20 20 20 20 20  _arcMask]).     
5190: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
51a0: 20 20 20 69 41 64 64 72 32 20 3d 20 69 45 6e 64     iAddr2 = iEnd
51b0: 41 72 63 41 64 64 72 32 2b 73 65 6c 66 2e 6e 42  ArcAddr2+self.nB
51c0: 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 0a  ytesNodeAddress.
51d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
51e0: 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72 63 41  iAddr = iEndArcA
51f0: 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e  ddr+self.nBytesN
5200: 6f 64 65 41 64 64 72 65 73 73 0a 20 20 20 20 20  odeAddress.     
5210: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 6c 0a         return l.
5220: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b          return [
5230: 5d 0a 0a 20 20 20 20 64 65 66 20 5f 73 74 65 6d  ]..    def _stem
5240: 31 20 28 73 65 6c 66 2c 20 73 57 6f 72 64 29 3a  1 (self, sWord):
5250: 0a 20 20 20 20 20 20 20 20 22 72 65 74 75 72 6e  .        "return
5260: 73 20 73 74 65 6d 73 20 6c 69 73 74 20 6f 66 20  s stems list of 
5270: 3c 73 57 6f 72 64 3e 22 0a 20 20 20 20 20 20 20  <sWord>".       
5280: 20 69 41 64 64 72 20 3d 20 30 0a 20 20 20 20 20   iAddr = 0.     
5290: 20 20 20 66 6f 72 20 63 20 69 6e 20 73 57 6f 72     for c in sWor
52a0: 64 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  d:.            i
52b0: 66 20 63 20 6e 6f 74 20 69 6e 20 73 65 6c 66 2e  f c not in self.
52c0: 64 43 68 61 72 3a 0a 20 20 20 20 20 20 20 20 20  dChar:.         
52d0: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d         return []
52e0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64  .            iAd
52f0: 64 72 20 3d 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75  dr = self._looku
5300: 70 41 72 63 4e 6f 64 65 28 73 65 6c 66 2e 64 43  pArcNode(self.dC
5310: 68 61 72 5b 63 5d 2c 20 69 41 64 64 72 29 0a 20  har[c], iAddr). 
5320: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 69 41             if iA
5330: 64 64 72 20 3d 3d 20 4e 6f 6e 65 3a 0a 20 20 20  ddr == None:.   
5340: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74               ret
5350: 75 72 6e 20 5b 5d 0a 20 20 20 20 20 20 20 20 69  urn [].        i
5360: 66 20 28 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65  f (int.from_byte
5370: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64  s(self.byDic[iAd
5380: 64 72 3a 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dr:iAddr+self.nB
5390: 79 74 65 73 41 72 63 5d 2c 20 62 79 74 65 6f 72  ytesArc], byteor
53a0: 64 65 72 3d 27 62 69 67 27 29 20 26 20 73 65 6c  der='big') & sel
53b0: 66 2e 5f 66 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b  f._finalNodeMask
53c0: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6c  ):.            l
53d0: 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 20 20   = [].          
53e0: 20 20 6e 52 61 77 41 72 63 20 3d 20 30 0a 20 20    nRawArc = 0.  
53f0: 20 20 20 20 20 20 20 20 20 20 77 68 69 6c 65 20            while 
5400: 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73  not (nRawArc & s
5410: 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b  elf._lastArcMask
5420: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
5430: 20 20 20 69 45 6e 64 41 72 63 41 64 64 72 20 3d     iEndArcAddr =
5440: 20 69 41 64 64 72 20 2b 20 73 65 6c 66 2e 6e 42   iAddr + self.nB
5450: 79 74 65 73 41 72 63 0a 20 20 20 20 20 20 20 20  ytesArc.        
5460: 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63 20          nRawArc 
5470: 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73  = int.from_bytes
5480: 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64 64  (self.byDic[iAdd
5490: 72 3a 69 45 6e 64 41 72 63 41 64 64 72 5d 2c 20  r:iEndArcAddr], 
54a0: 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29  byteorder='big')
54b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
54c0: 20 6e 41 72 63 20 3d 20 6e 52 61 77 41 72 63 20   nArc = nRawArc 
54d0: 26 20 73 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 0a  & self._arcMask.
54e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
54f0: 69 66 20 6e 41 72 63 20 3e 20 73 65 6c 66 2e 6e  if nArc > self.n
5500: 43 68 61 72 3a 0a 20 20 20 20 20 20 20 20 20 20  Char:.          
5510: 20 20 20 20 20 20 20 20 20 20 23 20 54 68 69 73            # This
5520: 20 76 61 6c 75 65 20 69 73 20 6e 6f 74 20 61 20   value is not a 
5530: 63 68 61 72 2c 20 74 68 69 73 20 69 73 20 61 20  char, this is a 
5540: 73 74 65 6d 6d 69 6e 67 20 63 6f 64 65 20 0a 20  stemming code . 
5550: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5560: 20 20 20 6c 2e 61 70 70 65 6e 64 28 73 65 6c 66     l.append(self
5570: 2e 66 75 6e 63 53 74 65 6d 6d 69 6e 67 28 73 57  .funcStemming(sW
5580: 6f 72 64 2c 20 73 65 6c 66 2e 6c 41 72 63 56 61  ord, self.lArcVa
5590: 6c 5b 6e 41 72 63 5d 29 29 0a 20 20 20 20 20 20  l[nArc])).      
55a0: 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20            iAddr 
55b0: 3d 20 69 45 6e 64 41 72 63 41 64 64 72 2b 73 65  = iEndArcAddr+se
55c0: 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64  lf.nBytesNodeAdd
55d0: 72 65 73 73 0a 20 20 20 20 20 20 20 20 20 20 20  ress.           
55e0: 20 72 65 74 75 72 6e 20 6c 0a 20 20 20 20 20 20   return l.      
55f0: 20 20 72 65 74 75 72 6e 20 5b 5d 0a 0a 20 20 20    return []..   
5600: 20 64 65 66 20 5f 6c 6f 6f 6b 75 70 41 72 63 4e   def _lookupArcN
5610: 6f 64 65 31 20 28 73 65 6c 66 2c 20 6e 56 61 6c  ode1 (self, nVal
5620: 2c 20 69 41 64 64 72 29 3a 0a 20 20 20 20 20 20  , iAddr):.      
5630: 20 20 22 6c 6f 6f 6b 73 20 69 66 20 3c 6e 56 61    "looks if <nVa
5640: 6c 3e 20 69 73 20 61 6e 20 61 72 63 20 61 74 20  l> is an arc at 
5650: 74 68 65 20 6e 6f 64 65 20 61 74 20 3c 69 41 64  the node at <iAd
5660: 64 72 3e 2c 20 69 66 20 79 65 73 2c 20 72 65 74  dr>, if yes, ret
5670: 75 72 6e 73 20 61 64 64 72 65 73 73 20 6f 66 20  urns address of 
5680: 6e 65 78 74 20 6e 6f 64 65 20 65 6c 73 65 20 4e  next node else N
5690: 6f 6e 65 22 0a 20 20 20 20 20 20 20 20 77 68 69  one".        whi
56a0: 6c 65 20 54 72 75 65 3a 0a 20 20 20 20 20 20 20  le True:.       
56b0: 20 20 20 20 20 69 45 6e 64 41 72 63 41 64 64 72       iEndArcAddr
56c0: 20 3d 20 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42   = iAddr+self.nB
56d0: 79 74 65 73 41 72 63 0a 20 20 20 20 20 20 20 20  ytesArc.        
56e0: 20 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e      nRawArc = in
56f0: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
5700: 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45  f.byDic[iAddr:iE
5710: 6e 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65  ndArcAddr], byte
5720: 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20  order='big').   
5730: 20 20 20 20 20 20 20 20 20 69 66 20 6e 56 61 6c           if nVal
5740: 20 3d 3d 20 28 6e 52 61 77 41 72 63 20 26 20 73   == (nRawArc & s
5750: 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 29 3a 0a 20  elf._arcMask):. 
5760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
5770: 20 74 68 65 20 76 61 6c 75 65 20 77 65 20 61 72   the value we ar
5780: 65 20 6c 6f 6f 6b 69 6e 67 20 66 6f 72 20 0a 20  e looking for . 
5790: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
57a0: 20 77 65 20 72 65 74 75 72 6e 20 74 68 65 20 61   we return the a
57b0: 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 6e 65  ddress of the ne
57c0: 78 74 20 6e 6f 64 65 0a 20 20 20 20 20 20 20 20  xt node.        
57d0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 69          return i
57e0: 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65  nt.from_bytes(se
57f0: 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41 72 63  lf.byDic[iEndArc
5800: 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72  Addr:iEndArcAddr
5810: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65  +self.nBytesNode
5820: 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65 6f 72  Address], byteor
5830: 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20  der='big').     
5840: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
5850: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 76               # v
5860: 61 6c 75 65 20 6e 6f 74 20 66 6f 75 6e 64 0a 20  alue not found. 
5870: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
5880: 66 20 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c  f (nRawArc & sel
5890: 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a  f._lastArcMask):
58a0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
58b0: 20 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e 65       return None
58c0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
58d0: 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72 63   iAddr = iEndArc
58e0: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
58f0: 4e 6f 64 65 41 64 64 72 65 73 73 0a 0a 20 20 20  NodeAddress..   
5900: 20 64 65 66 20 5f 67 65 74 41 72 63 73 31 20 28   def _getArcs1 (
5910: 73 65 6c 66 2c 20 69 41 64 64 72 29 3a 0a 20 20  self, iAddr):.  
5920: 20 20 20 20 20 20 22 67 65 6e 65 72 61 74 6f 72        "generator
5930: 3a 20 72 65 74 75 72 6e 20 61 6c 6c 20 61 72 63  : return all arc
5940: 73 20 61 74 20 3c 69 41 64 64 72 3e 20 61 73 20  s at <iAddr> as 
5950: 74 75 70 6c 65 73 20 6f 66 20 28 6e 56 61 6c 2c  tuples of (nVal,
5960: 20 69 41 64 64 72 29 22 0a 20 20 20 20 20 20 20   iAddr)".       
5970: 20 77 68 69 6c 65 20 54 72 75 65 3a 0a 20 20 20   while True:.   
5980: 20 20 20 20 20 20 20 20 20 69 45 6e 64 41 72 63           iEndArc
5990: 41 64 64 72 20 3d 20 69 41 64 64 72 2b 73 65 6c  Addr = iAddr+sel
59a0: 66 2e 6e 42 79 74 65 73 41 72 63 0a 20 20 20 20  f.nBytesArc.    
59b0: 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63 20          nRawArc 
59c0: 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73  = int.from_bytes
59d0: 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64 64  (self.byDic[iAdd
59e0: 72 3a 69 45 6e 64 41 72 63 41 64 64 72 5d 2c 20  r:iEndArcAddr], 
59f0: 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29  byteorder='big')
5a00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65  .            yie
5a10: 6c 64 20 28 6e 52 61 77 41 72 63 20 26 20 73 65  ld (nRawArc & se
5a20: 6c 66 2e 5f 61 72 63 4d 61 73 6b 2c 20 69 6e 74  lf._arcMask, int
5a30: 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66  .from_bytes(self
5a40: 2e 62 79 44 69 63 5b 69 45 6e 64 41 72 63 41 64  .byDic[iEndArcAd
5a50: 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72 2b 73  dr:iEndArcAddr+s
5a60: 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64  elf.nBytesNodeAd
5a70: 64 72 65 73 73 5d 2c 20 62 79 74 65 6f 72 64 65  dress], byteorde
5a80: 72 3d 27 62 69 67 27 29 29 0a 20 20 20 20 20 20  r='big')).      
5a90: 20 20 20 20 20 20 69 66 20 28 6e 52 61 77 41 72        if (nRawAr
5aa0: 63 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72  c & self._lastAr
5ab0: 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20 20  cMask):.        
5ac0: 20 20 20 20 20 20 20 20 62 72 65 61 6b 0a 20 20          break.  
5ad0: 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20            iAddr 
5ae0: 3d 20 69 45 6e 64 41 72 63 41 64 64 72 2b 73 65  = iEndArcAddr+se
5af0: 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64  lf.nBytesNodeAdd
5b00: 72 65 73 73 0a 0a 20 20 20 20 64 65 66 20 5f 77  ress..    def _w
5b10: 72 69 74 65 4e 6f 64 65 73 31 20 28 73 65 6c 66  riteNodes1 (self
5b20: 2c 20 73 70 66 44 65 73 74 29 3a 0a 20 20 20 20  , spfDest):.    
5b30: 20 20 20 20 22 66 6f 72 20 64 65 62 75 67 67 69      "for debuggi
5b40: 6e 67 20 6f 6e 6c 79 22 0a 20 20 20 20 20 20 20  ng only".       
5b50: 20 70 72 69 6e 74 28 22 20 3e 20 57 72 69 74 65   print(" > Write
5b60: 20 62 69 6e 61 72 79 20 6e 6f 64 65 73 22 29 0a   binary nodes").
5b70: 20 20 20 20 20 20 20 20 77 69 74 68 20 63 6f 64          with cod
5b80: 65 63 73 2e 6f 70 65 6e 28 73 70 66 44 65 73 74  ecs.open(spfDest
5b90: 2c 20 27 77 27 2c 20 27 75 74 66 2d 38 27 2c 20  , 'w', 'utf-8', 
5ba0: 6e 65 77 6c 69 6e 65 3d 22 5c 6e 22 29 20 61 73  newline="\n") as
5bb0: 20 68 44 73 74 3a 0a 20 20 20 20 20 20 20 20 20   hDst:.         
5bc0: 20 20 20 69 41 64 64 72 20 3d 20 30 0a 20 20 20     iAddr = 0.   
5bd0: 20 20 20 20 20 20 20 20 20 68 44 73 74 2e 77 72           hDst.wr
5be0: 69 74 65 28 22 69 7b 3a 5f 3e 31 30 7d 20 2d 2d  ite("i{:_>10} --
5bf0: 20 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72   #{:_>10}\n".for
5c00: 6d 61 74 28 22 30 22 2c 20 69 41 64 64 72 29 29  mat("0", iAddr))
5c10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 77 68 69  .            whi
5c20: 6c 65 20 69 41 64 64 72 20 3c 20 6c 65 6e 28 73  le iAddr < len(s
5c30: 65 6c 66 2e 62 79 44 69 63 29 3a 0a 20 20 20 20  elf.byDic):.    
5c40: 20 20 20 20 20 20 20 20 20 20 20 20 69 45 6e 64              iEnd
5c50: 41 72 63 41 64 64 72 20 3d 20 69 41 64 64 72 2b  ArcAddr = iAddr+
5c60: 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a 20  self.nBytesArc. 
5c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e                 n
5c80: 52 61 77 41 72 63 20 3d 20 69 6e 74 2e 66 72 6f  RawArc = int.fro
5c90: 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44  m_bytes(self.byD
5ca0: 69 63 5b 69 41 64 64 72 3a 69 45 6e 64 41 72 63  ic[iAddr:iEndArc
5cb0: 41 64 64 72 5d 2c 20 62 79 74 65 6f 72 64 65 72  Addr], byteorder
5cc0: 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20 20 20  ='big').        
5cd0: 20 20 20 20 20 20 20 20 6e 41 72 63 20 3d 20 6e          nArc = n
5ce0: 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61  RawArc & self._a
5cf0: 72 63 4d 61 73 6b 0a 20 20 20 20 20 20 20 20 20  rcMask.         
5d00: 20 20 20 20 20 20 20 68 44 73 74 2e 77 72 69 74         hDst.writ
5d10: 65 28 22 20 20 7b 3a 3c 32 30 7d 20 20 7b 3a 30  e("  {:<20}  {:0
5d20: 3e 31 36 7d 20 20 69 7b 3a 3e 31 30 7d 20 20 20  >16}  i{:>10}   
5d30: 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d  #{:_>10}\n".form
5d40: 61 74 28 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b  at(self.lArcVal[
5d50: 6e 41 72 63 5d 2c 20 62 69 6e 28 6e 52 61 77 41  nArc], bin(nRawA
5d60: 72 63 29 5b 32 3a 5d 2c 20 22 3f 22 2c 20 5c 0a  rc)[2:], "?", \.
5d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5d90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5da0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5db0: 20 20 20 20 20 20 20 20 20 20 20 20 69 6e 74 2e              int.
5dc0: 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e  from_bytes(self.
5dd0: 62 79 44 69 63 5b 69 45 6e 64 41 72 63 41 64 64  byDic[iEndArcAdd
5de0: 72 3a 69 45 6e 64 41 72 63 41 64 64 72 2b 73 65  r:iEndArcAddr+se
5df0: 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64  lf.nBytesNodeAdd
5e00: 72 65 73 73 5d 2c 20 5c 0a 20 20 20 20 20 20 20  ress], \.       
5e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e60: 20 20 20 20 62 79 74 65 6f 72 64 65 72 3d 27 62      byteorder='b
5e70: 69 67 27 29 29 29 0a 20 20 20 20 20 20 20 20 20  ig'))).         
5e80: 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 69         iAddr = i
5e90: 45 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e  EndArcAddr+self.
5ea0: 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73  nBytesNodeAddres
5eb0: 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  s.              
5ec0: 20 20 69 66 20 28 6e 52 61 77 41 72 63 20 26 20    if (nRawArc & 
5ed0: 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73  self._lastArcMas
5ee0: 6b 29 20 61 6e 64 20 69 41 64 64 72 20 3c 20 6c  k) and iAddr < l
5ef0: 65 6e 28 73 65 6c 66 2e 62 79 44 69 63 29 3a 0a  en(self.byDic):.
5f00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5f10: 20 20 20 20 68 44 73 74 2e 77 72 69 74 65 28 22      hDst.write("
5f20: 5c 6e 69 7b 3a 5f 3e 31 30 7d 20 2d 2d 20 23 7b  \ni{:_>10} -- #{
5f30: 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d 61 74  :_>10}\n".format
5f40: 28 22 3f 22 2c 20 69 41 64 64 72 29 29 0a 20 20  ("?", iAddr)).  
5f50: 20 20 20 20 20 20 20 20 20 20 68 44 73 74 2e 63            hDst.c
5f60: 6c 6f 73 65 28 29 0a 0a 20 20 20 20 23 20 56 45  lose()..    # VE
5f70: 52 53 49 4f 4e 20 32 0a 20 20 20 20 64 65 66 20  RSION 2.    def 
5f80: 5f 6d 6f 72 70 68 32 20 28 73 65 6c 66 2c 20 73  _morph2 (self, s
5f90: 57 6f 72 64 29 3a 0a 20 20 20 20 20 20 20 20 22  Word):.        "
5fa0: 72 65 74 75 72 6e 73 20 6d 6f 72 70 68 6f 6c 6f  returns morpholo
5fb0: 67 69 65 73 20 6f 66 20 3c 73 57 6f 72 64 3e 22  gies of <sWord>"
5fc0: 0a 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d  .        iAddr =
5fd0: 20 30 0a 20 20 20 20 20 20 20 20 66 6f 72 20 63   0.        for c
5fe0: 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20 20 20 20   in sWord:.     
5ff0: 20 20 20 20 20 20 20 69 66 20 63 20 6e 6f 74 20         if c not 
6000: 69 6e 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a 20  in self.dChar:. 
6010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72                 r
6020: 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20 20 20 20  eturn [].       
6030: 20 20 20 20 20 69 41 64 64 72 20 3d 20 73 65 6c       iAddr = sel
6040: 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64 65  f._lookupArcNode
6050: 28 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d 2c 20  (self.dChar[c], 
6060: 69 41 64 64 72 29 0a 20 20 20 20 20 20 20 20 20  iAddr).         
6070: 20 20 20 69 66 20 69 41 64 64 72 20 3d 3d 20 4e     if iAddr == N
6080: 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  one:.           
6090: 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 20       return []. 
60a0: 20 20 20 20 20 20 20 69 66 20 28 69 6e 74 2e 66         if (int.f
60b0: 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62  rom_bytes(self.b
60c0: 79 44 69 63 5b 69 41 64 64 72 3a 69 41 64 64 72  yDic[iAddr:iAddr
60d0: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 5d  +self.nBytesArc]
60e0: 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67  , byteorder='big
60f0: 27 29 20 26 20 73 65 6c 66 2e 5f 66 69 6e 61 6c  ') & self._final
6100: 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20 20 20 20 20  NodeMask):.     
6110: 20 20 20 20 20 20 20 6c 20 3d 20 5b 5d 0a 20 20         l = [].  
6120: 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72            nRawAr
6130: 63 20 3d 20 30 0a 20 20 20 20 20 20 20 20 20 20  c = 0.          
6140: 20 20 77 68 69 6c 65 20 6e 6f 74 20 28 6e 52 61    while not (nRa
6150: 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 6c 61 73  wArc & self._las
6160: 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20  tArcMask):.     
6170: 20 20 20 20 20 20 20 20 20 20 20 69 45 6e 64 41             iEndA
6180: 72 63 41 64 64 72 20 3d 20 69 41 64 64 72 20 2b  rcAddr = iAddr +
6190: 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a   self.nBytesArc.
61a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
61b0: 6e 52 61 77 41 72 63 20 3d 20 69 6e 74 2e 66 72  nRawArc = int.fr
61c0: 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79  om_bytes(self.by
61d0: 44 69 63 5b 69 41 64 64 72 3a 69 45 6e 64 41 72  Dic[iAddr:iEndAr
61e0: 63 41 64 64 72 5d 2c 20 62 79 74 65 6f 72 64 65  cAddr], byteorde
61f0: 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20 20  r='big').       
6200: 20 20 20 20 20 20 20 20 20 6e 41 72 63 20 3d 20           nArc = 
6210: 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f  nRawArc & self._
6220: 61 72 63 4d 61 73 6b 0a 20 20 20 20 20 20 20 20  arcMask.        
6230: 20 20 20 20 20 20 20 20 69 66 20 6e 41 72 63 20          if nArc 
6240: 3e 20 73 65 6c 66 2e 6e 43 68 61 72 3a 0a 20 20  > self.nChar:.  
6250: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6260: 20 20 23 20 54 68 69 73 20 76 61 6c 75 65 20 69    # This value i
6270: 73 20 6e 6f 74 20 61 20 63 68 61 72 2c 20 74 68  s not a char, th
6280: 69 73 20 69 73 20 61 20 73 74 65 6d 6d 69 6e 67  is is a stemming
6290: 20 63 6f 64 65 20 0a 20 20 20 20 20 20 20 20 20   code .         
62a0: 20 20 20 20 20 20 20 20 20 20 20 73 53 74 65 6d             sStem
62b0: 20 3d 20 22 3e 22 20 2b 20 73 65 6c 66 2e 66 75   = ">" + self.fu
62c0: 6e 63 53 74 65 6d 6d 69 6e 67 28 73 57 6f 72 64  ncStemming(sWord
62d0: 2c 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e  , self.lArcVal[n
62e0: 41 72 63 5d 29 0a 20 20 20 20 20 20 20 20 20 20  Arc]).          
62f0: 20 20 20 20 20 20 20 20 20 20 23 20 4e 6f 77 20            # Now 
6300: 2c 20 77 65 20 67 6f 20 74 6f 20 74 68 65 20 6e  , we go to the n
6310: 65 78 74 20 6e 6f 64 65 20 61 6e 64 20 72 65 74  ext node and ret
6320: 72 69 65 76 65 20 61 6c 6c 20 66 6f 6c 6c 6f 77  rieve all follow
6330: 69 6e 67 20 61 72 63 73 20 76 61 6c 75 65 73 2c  ing arcs values,
6340: 20 61 6c 6c 20 6f 66 20 74 68 65 6d 20 61 72 65   all of them are
6350: 20 74 61 67 73 0a 20 20 20 20 20 20 20 20 20 20   tags.          
6360: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74            if not
6370: 20 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66   (nRawArc & self
6380: 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 3a 0a  ._addrBitMask):.
6390: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
63a0: 20 20 20 20 20 20 20 20 69 41 64 64 72 32 20 3d          iAddr2 =
63b0: 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28   int.from_bytes(
63c0: 73 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41  self.byDic[iEndA
63d0: 72 63 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64  rcAddr:iEndArcAd
63e0: 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f  dr+self.nBytesNo
63f0: 64 65 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65  deAddress], byte
6400: 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20  order='big').   
6410: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6420: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
6430: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
6440: 20 77 65 20 67 6f 20 74 6f 20 74 68 65 20 65 6e   we go to the en
6450: 64 20 6f 66 20 74 68 65 20 6e 6f 64 65 0a 20 20  d of the node.  
6460: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6470: 20 20 20 20 20 20 69 41 64 64 72 32 20 3d 20 69        iAddr2 = i
6480: 45 6e 64 41 72 63 41 64 64 72 0a 20 20 20 20 20  EndArcAddr.     
6490: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
64a0: 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28 6e 52     while not (nR
64b0: 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 6c 61  awArc & self._la
64c0: 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20  stArcMask):.    
64d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
64e0: 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63 20          nRawArc 
64f0: 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73  = int.from_bytes
6500: 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64 64  (self.byDic[iAdd
6510: 72 32 3a 69 41 64 64 72 32 2b 73 65 6c 66 2e 6e  r2:iAddr2+self.n
6520: 42 79 74 65 73 41 72 63 5d 2c 20 62 79 74 65 6f  BytesArc], byteo
6530: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
6540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6550: 20 20 20 20 20 20 20 20 69 41 64 64 72 32 20 2b          iAddr2 +
6560: 3d 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63  = self.nBytesArc
6570: 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f   + self.nBytesNo
6580: 64 65 41 64 64 72 65 73 73 0a 20 20 20 20 20 20  deAddress.      
6590: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 52                nR
65a0: 61 77 41 72 63 32 20 3d 20 30 0a 20 20 20 20 20  awArc2 = 0.     
65b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 77                 w
65c0: 68 69 6c 65 20 6e 6f 74 20 28 6e 52 61 77 41 72  hile not (nRawAr
65d0: 63 32 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41  c2 & self._lastA
65e0: 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20  rcMask):.       
65f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6600: 20 69 45 6e 64 41 72 63 41 64 64 72 32 20 3d 20   iEndArcAddr2 = 
6610: 69 41 64 64 72 32 20 2b 20 73 65 6c 66 2e 6e 42  iAddr2 + self.nB
6620: 79 74 65 73 41 72 63 0a 20 20 20 20 20 20 20 20  ytesArc.        
6630: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6640: 6e 52 61 77 41 72 63 32 20 3d 20 69 6e 74 2e 66  nRawArc2 = int.f
6650: 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62  rom_bytes(self.b
6660: 79 44 69 63 5b 69 41 64 64 72 32 3a 69 45 6e 64  yDic[iAddr2:iEnd
6670: 41 72 63 41 64 64 72 32 5d 2c 20 62 79 74 65 6f  ArcAddr2], byteo
6680: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
6690: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
66a0: 20 20 20 20 6c 2e 61 70 70 65 6e 64 28 73 53 74      l.append(sSt
66b0: 65 6d 20 2b 20 22 20 22 20 2b 20 73 65 6c 66 2e  em + " " + self.
66c0: 6c 41 72 63 56 61 6c 5b 6e 52 61 77 41 72 63 32  lArcVal[nRawArc2
66d0: 20 26 20 73 65 6c 66 2e 5f 61 72 63 4d 61 73 6b   & self._arcMask
66e0: 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]).             
66f0: 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72             iAddr
6700: 32 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72 32  2 = iEndArcAddr2
6710: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65  +self.nBytesNode
6720: 41 64 64 72 65 73 73 20 20 69 66 20 6e 6f 74 20  Address  if not 
6730: 28 6e 52 61 77 41 72 63 32 20 26 20 73 65 6c 66  (nRawArc2 & self
6740: 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 20 65  ._addrBitMask) e
6750: 6c 73 65 20 69 45 6e 64 41 72 63 41 64 64 72 32  lse iEndArcAddr2
6760: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6770: 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72 63   iAddr = iEndArc
6780: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
6790: 4e 6f 64 65 41 64 64 72 65 73 73 20 20 69 66 20  NodeAddress  if 
67a0: 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73  not (nRawArc & s
67b0: 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b  elf._addrBitMask
67c0: 29 20 20 65 6c 73 65 20 69 45 6e 64 41 72 63 41  )  else iEndArcA
67d0: 64 64 72 0a 20 20 20 20 20 20 20 20 20 20 20 20  ddr.            
67e0: 72 65 74 75 72 6e 20 6c 0a 20 20 20 20 20 20 20  return l.       
67f0: 20 72 65 74 75 72 6e 20 5b 5d 0a 0a 20 20 20 20   return []..    
6800: 64 65 66 20 5f 73 74 65 6d 32 20 28 73 65 6c 66  def _stem2 (self
6810: 2c 20 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20  , sWord):.      
6820: 20 20 22 72 65 74 75 72 6e 73 20 73 74 65 6d 73    "returns stems
6830: 20 6c 69 73 74 20 6f 66 20 3c 73 57 6f 72 64 3e   list of <sWord>
6840: 22 0a 20 20 20 20 20 20 20 20 69 41 64 64 72 20  ".        iAddr 
6850: 3d 20 30 0a 20 20 20 20 20 20 20 20 66 6f 72 20  = 0.        for 
6860: 63 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20 20 20  c in sWord:.    
6870: 20 20 20 20 20 20 20 20 69 66 20 63 20 6e 6f 74          if c not
6880: 20 69 6e 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a   in self.dChar:.
6890: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
68a0: 72 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20 20 20  return [].      
68b0: 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 73 65        iAddr = se
68c0: 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64  lf._lookupArcNod
68d0: 65 28 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d 2c  e(self.dChar[c],
68e0: 20 69 41 64 64 72 29 0a 20 20 20 20 20 20 20 20   iAddr).        
68f0: 20 20 20 20 69 66 20 69 41 64 64 72 20 3d 3d 20      if iAddr == 
6900: 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 20 20  None:.          
6910: 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a        return [].
6920: 20 20 20 20 20 20 20 20 69 66 20 28 69 6e 74 2e          if (int.
6930: 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e  from_bytes(self.
6940: 62 79 44 69 63 5b 69 41 64 64 72 3a 69 41 64 64  byDic[iAddr:iAdd
6950: 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63  r+self.nBytesArc
6960: 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69  ], byteorder='bi
6970: 67 27 29 20 26 20 73 65 6c 66 2e 5f 66 69 6e 61  g') & self._fina
6980: 6c 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20 20 20 20  lNodeMask):.    
6990: 20 20 20 20 20 20 20 20 6c 20 3d 20 5b 5d 0a 20          l = []. 
69a0: 20 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41             nRawA
69b0: 72 63 20 3d 20 30 0a 20 20 20 20 20 20 20 20 20  rc = 0.         
69c0: 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28 6e 52     while not (nR
69d0: 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 6c 61  awArc & self._la
69e0: 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20  stArcMask):.    
69f0: 20 20 20 20 20 20 20 20 20 20 20 20 69 45 6e 64              iEnd
6a00: 41 72 63 41 64 64 72 20 3d 20 69 41 64 64 72 20  ArcAddr = iAddr 
6a10: 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63  + self.nBytesArc
6a20: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6a30: 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74 2e 66   nRawArc = int.f
6a40: 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62  rom_bytes(self.b
6a50: 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e 64 41  yDic[iAddr:iEndA
6a60: 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f 72 64  rcAddr], byteord
6a70: 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20  er='big').      
6a80: 20 20 20 20 20 20 20 20 20 20 6e 41 72 63 20 3d            nArc =
6a90: 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e   nRawArc & self.
6aa0: 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20 20 20  _arcMask.       
6ab0: 20 20 20 20 20 20 20 20 20 69 66 20 6e 41 72 63           if nArc
6ac0: 20 3e 20 73 65 6c 66 2e 6e 43 68 61 72 3a 0a 20   > self.nChar:. 
6ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ae0: 20 20 20 23 20 54 68 69 73 20 76 61 6c 75 65 20     # This value 
6af0: 69 73 20 6e 6f 74 20 61 20 63 68 61 72 2c 20 74  is not a char, t
6b00: 68 69 73 20 69 73 20 61 20 73 74 65 6d 6d 69 6e  his is a stemmin
6b10: 67 20 63 6f 64 65 20 0a 20 20 20 20 20 20 20 20  g code .        
6b20: 20 20 20 20 20 20 20 20 20 20 20 20 6c 2e 61 70              l.ap
6b30: 70 65 6e 64 28 73 65 6c 66 2e 66 75 6e 63 53 74  pend(self.funcSt
6b40: 65 6d 6d 69 6e 67 28 73 57 6f 72 64 2c 20 73 65  emming(sWord, se
6b50: 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 41 72 63 5d  lf.lArcVal[nArc]
6b60: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  )).             
6b70: 20 20 20 20 20 20 20 23 20 4e 6f 77 20 2c 20 77         # Now , w
6b80: 65 20 67 6f 20 74 6f 20 74 68 65 20 6e 65 78 74  e go to the next
6b90: 20 6e 6f 64 65 0a 20 20 20 20 20 20 20 20 20 20   node.          
6ba0: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74            if not
6bb0: 20 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66   (nRawArc & self
6bc0: 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 3a 0a  ._addrBitMask):.
6bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6be0: 20 20 20 20 20 20 20 20 69 41 64 64 72 32 20 3d          iAddr2 =
6bf0: 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28   int.from_bytes(
6c00: 73 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41  self.byDic[iEndA
6c10: 72 63 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64  rcAddr:iEndArcAd
6c20: 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f  dr+self.nBytesNo
6c30: 64 65 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65  deAddress], byte
6c40: 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20  order='big').   
6c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c60: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
6c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
6c80: 20 77 65 20 67 6f 20 74 6f 20 74 68 65 20 65 6e   we go to the en
6c90: 64 20 6f 66 20 74 68 65 20 6e 6f 64 65 0a 20 20  d of the node.  
6ca0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6cb0: 20 20 20 20 20 20 69 41 64 64 72 32 20 3d 20 69        iAddr2 = i
6cc0: 45 6e 64 41 72 63 41 64 64 72 0a 20 20 20 20 20  EndArcAddr.     
6cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ce0: 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28 6e 52     while not (nR
6cf0: 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 6c 61  awArc & self._la
6d00: 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20  stArcMask):.    
6d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6d20: 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63 20          nRawArc 
6d30: 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73  = int.from_bytes
6d40: 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64 64  (self.byDic[iAdd
6d50: 72 32 3a 69 41 64 64 72 32 2b 73 65 6c 66 2e 6e  r2:iAddr2+self.n
6d60: 42 79 74 65 73 41 72 63 5d 2c 20 62 79 74 65 6f  BytesArc], byteo
6d70: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
6d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6d90: 20 20 20 20 20 20 20 20 69 41 64 64 72 32 20 2b          iAddr2 +
6da0: 3d 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63  = self.nBytesArc
6db0: 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f   + self.nBytesNo
6dc0: 64 65 41 64 64 72 65 73 73 0a 20 20 20 20 20 20  deAddress.      
6dd0: 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20            iAddr 
6de0: 3d 20 69 45 6e 64 41 72 63 41 64 64 72 2b 73 65  = iEndArcAddr+se
6df0: 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64  lf.nBytesNodeAdd
6e00: 72 65 73 73 20 20 69 66 20 6e 6f 74 20 28 6e 52  ress  if not (nR
6e10: 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61 64  awArc & self._ad
6e20: 64 72 42 69 74 4d 61 73 6b 29 20 20 65 6c 73 65  drBitMask)  else
6e30: 20 69 45 6e 64 41 72 63 41 64 64 72 0a 20 20 20   iEndArcAddr.   
6e40: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
6e50: 6c 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  l.        return
6e60: 20 5b 5d 0a 0a 20 20 20 20 64 65 66 20 5f 6c 6f   []..    def _lo
6e70: 6f 6b 75 70 41 72 63 4e 6f 64 65 32 20 28 73 65  okupArcNode2 (se
6e80: 6c 66 2c 20 6e 56 61 6c 2c 20 69 41 64 64 72 29  lf, nVal, iAddr)
6e90: 3a 0a 20 20 20 20 20 20 20 20 22 6c 6f 6f 6b 73  :.        "looks
6ea0: 20 69 66 20 3c 6e 56 61 6c 3e 20 69 73 20 61 6e   if <nVal> is an
6eb0: 20 61 72 63 20 61 74 20 74 68 65 20 6e 6f 64 65   arc at the node
6ec0: 20 61 74 20 3c 69 41 64 64 72 3e 2c 20 69 66 20   at <iAddr>, if 
6ed0: 79 65 73 2c 20 72 65 74 75 72 6e 73 20 61 64 64  yes, returns add
6ee0: 72 65 73 73 20 6f 66 20 6e 65 78 74 20 6e 6f 64  ress of next nod
6ef0: 65 20 65 6c 73 65 20 4e 6f 6e 65 22 0a 20 20 20  e else None".   
6f00: 20 20 20 20 20 77 68 69 6c 65 20 54 72 75 65 3a       while True:
6f10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 45 6e  .            iEn
6f20: 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64 72  dArcAddr = iAddr
6f30: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a  +self.nBytesArc.
6f40: 20 20 20 20 20 20 20 20 20 20 20 20 6e 52 61 77              nRaw
6f50: 41 72 63 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62  Arc = int.from_b
6f60: 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b  ytes(self.byDic[
6f70: 69 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64  iAddr:iEndArcAdd
6f80: 72 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62  r], byteorder='b
6f90: 69 67 27 29 0a 20 20 20 20 20 20 20 20 20 20 20  ig').           
6fa0: 20 69 66 20 6e 56 61 6c 20 3d 3d 20 28 6e 52 61   if nVal == (nRa
6fb0: 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61 72 63  wArc & self._arc
6fc0: 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20 20 20  Mask):.         
6fd0: 20 20 20 20 20 20 20 23 20 74 68 65 20 76 61 6c         # the val
6fe0: 75 65 20 77 65 20 61 72 65 20 6c 6f 6f 6b 69 6e  ue we are lookin
6ff0: 67 20 66 6f 72 20 0a 20 20 20 20 20 20 20 20 20  g for .         
7000: 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 28 6e         if not (n
7010: 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61  RawArc & self._a
7020: 64 64 72 42 69 74 4d 61 73 6b 29 3a 0a 20 20 20  ddrBitMask):.   
7030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7040: 20 23 20 77 65 20 72 65 74 75 72 6e 20 74 68 65   # we return the
7050: 20 61 64 64 72 65 73 73 20 6f 66 20 74 68 65 20   address of the 
7060: 6e 65 78 74 20 6e 6f 64 65 0a 20 20 20 20 20 20  next node.      
7070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
7080: 74 75 72 6e 20 69 6e 74 2e 66 72 6f 6d 5f 62 79  turn int.from_by
7090: 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69  tes(self.byDic[i
70a0: 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e 64 41  EndArcAddr:iEndA
70b0: 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74  rcAddr+self.nByt
70c0: 65 73 4e 6f 64 65 41 64 64 72 65 73 73 5d 2c 20  esNodeAddress], 
70d0: 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29  byteorder='big')
70e0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
70f0: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
7100: 20 20 20 20 20 20 20 20 20 20 20 23 20 77 65 20             # we 
7110: 67 6f 20 74 6f 20 74 68 65 20 65 6e 64 20 6f 66  go to the end of
7120: 20 74 68 65 20 6e 6f 64 65 0a 20 20 20 20 20 20   the node.      
7130: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41                iA
7140: 64 64 72 20 3d 20 69 45 6e 64 41 72 63 41 64 64  ddr = iEndArcAdd
7150: 72 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  r.              
7160: 20 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20        while not 
7170: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
7180: 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20  _lastArcMask):. 
7190: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
71a0: 20 20 20 20 20 20 20 6e 52 61 77 41 72 63 20 3d         nRawArc =
71b0: 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28   int.from_bytes(
71c0: 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64 64 72  self.byDic[iAddr
71d0: 3a 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74  :iAddr+self.nByt
71e0: 65 73 41 72 63 5d 2c 20 62 79 74 65 6f 72 64 65  esArc], byteorde
71f0: 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20 20  r='big').       
7200: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7210: 20 69 41 64 64 72 20 2b 3d 20 73 65 6c 66 2e 6e   iAddr += self.n
7220: 42 79 74 65 73 41 72 63 20 2b 20 73 65 6c 66 2e  BytesArc + self.
7230: 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73  nBytesNodeAddres
7240: 73 20 20 69 66 20 6e 6f 74 20 28 6e 52 61 77 41  s  if not (nRawA
7250: 72 63 20 26 20 73 65 6c 66 2e 5f 61 64 64 72 42  rc & self._addrB
7260: 69 74 4d 61 73 6b 29 20 20 65 6c 73 65 20 73 65  itMask)  else se
7270: 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a 20 20 20  lf.nBytesArc.   
7280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7290: 20 72 65 74 75 72 6e 20 69 41 64 64 72 0a 20 20   return iAddr.  
72a0: 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a            else:.
72b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
72c0: 23 20 76 61 6c 75 65 20 6e 6f 74 20 66 6f 75 6e  # value not foun
72d0: 64 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  d.              
72e0: 20 20 69 66 20 28 6e 52 61 77 41 72 63 20 26 20    if (nRawArc & 
72f0: 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73  self._lastArcMas
7300: 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  k):.            
7310: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 4e          return N
7320: 6f 6e 65 0a 20 20 20 20 20 20 20 20 20 20 20 20  one.            
7330: 20 20 20 20 69 41 64 64 72 20 3d 20 69 45 6e 64      iAddr = iEnd
7340: 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  ArcAddr+self.nBy
7350: 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 20 20  tesNodeAddress  
7360: 69 66 20 6e 6f 74 20 28 6e 52 61 77 41 72 63 20  if not (nRawArc 
7370: 26 20 73 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d  & self._addrBitM
7380: 61 73 6b 29 20 20 65 6c 73 65 20 69 45 6e 64 41  ask)  else iEndA
7390: 72 63 41 64 64 72 0a 0a 20 20 20 20 64 65 66 20  rcAddr..    def 
73a0: 5f 77 72 69 74 65 4e 6f 64 65 73 32 20 28 73 65  _writeNodes2 (se
73b0: 6c 66 2c 20 73 70 66 44 65 73 74 29 3a 0a 20 20  lf, spfDest):.  
73c0: 20 20 20 20 20 20 22 66 6f 72 20 64 65 62 75 67        "for debug
73d0: 67 69 6e 67 20 6f 6e 6c 79 22 0a 20 20 20 20 20  ging only".     
73e0: 20 20 20 70 72 69 6e 74 28 22 20 3e 20 57 72 69     print(" > Wri
73f0: 74 65 20 62 69 6e 61 72 79 20 6e 6f 64 65 73 22  te binary nodes"
7400: 29 0a 20 20 20 20 20 20 20 20 77 69 74 68 20 63  ).        with c
7410: 6f 64 65 63 73 2e 6f 70 65 6e 28 73 70 66 44 65  odecs.open(spfDe
7420: 73 74 2c 20 27 77 27 2c 20 27 75 74 66 2d 38 27  st, 'w', 'utf-8'
7430: 2c 20 6e 65 77 6c 69 6e 65 3d 22 5c 6e 22 29 20  , newline="\n") 
7440: 61 73 20 68 44 73 74 3a 0a 20 20 20 20 20 20 20  as hDst:.       
7450: 20 20 20 20 20 69 41 64 64 72 20 3d 20 30 0a 20       iAddr = 0. 
7460: 20 20 20 20 20 20 20 20 20 20 20 68 44 73 74 2e             hDst.
7470: 77 72 69 74 65 28 22 69 7b 3a 5f 3e 31 30 7d 20  write("i{:_>10} 
7480: 2d 2d 20 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66  -- #{:_>10}\n".f
7490: 6f 72 6d 61 74 28 22 30 22 2c 20 69 41 64 64 72  ormat("0", iAddr
74a0: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 77  )).            w
74b0: 68 69 6c 65 20 69 41 64 64 72 20 3c 20 6c 65 6e  hile iAddr < len
74c0: 28 73 65 6c 66 2e 62 79 44 69 63 29 3a 0a 20 20  (self.byDic):.  
74d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 45                iE
74e0: 6e 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64  ndArcAddr = iAdd
74f0: 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63  r+self.nBytesArc
7500: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
7510: 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74 2e 66   nRawArc = int.f
7520: 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62  rom_bytes(self.b
7530: 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e 64 41  yDic[iAddr:iEndA
7540: 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f 72 64  rcAddr], byteord
7550: 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20  er='big').      
7560: 20 20 20 20 20 20 20 20 20 20 6e 41 72 63 20 3d            nArc =
7570: 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e   nRawArc & self.
7580: 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20 20 20  _arcMask.       
7590: 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20           if not 
75a0: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
75b0: 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 3a 0a 20  _addrBitMask):. 
75c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
75d0: 20 20 20 69 4e 65 78 74 4e 6f 64 65 41 64 64 72     iNextNodeAddr
75e0: 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65   = int.from_byte
75f0: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e  s(self.byDic[iEn
7600: 64 41 72 63 41 64 64 72 3a 69 45 6e 64 41 72 63  dArcAddr:iEndArc
7610: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
7620: 4e 6f 64 65 41 64 64 72 65 73 73 5d 2c 20 62 79  NodeAddress], by
7630: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20  teorder='big'). 
7640: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7650: 20 20 20 68 44 73 74 2e 77 72 69 74 65 28 22 20     hDst.write(" 
7660: 20 7b 3a 3c 32 30 7d 20 20 7b 3a 30 3e 31 36 7d   {:<20}  {:0>16}
7670: 20 20 69 7b 3a 3e 31 30 7d 20 20 20 23 7b 3a 5f    i{:>10}   #{:_
7680: 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d 61 74 28 73  >10}\n".format(s
7690: 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 41 72 63  elf.lArcVal[nArc
76a0: 5d 2c 20 62 69 6e 28 6e 52 61 77 41 72 63 29 5b  ], bin(nRawArc)[
76b0: 32 3a 5d 2c 20 22 3f 22 2c 20 69 4e 65 78 74 4e  2:], "?", iNextN
76c0: 6f 64 65 41 64 64 72 29 29 0a 20 20 20 20 20 20  odeAddr)).      
76d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41                iA
76e0: 64 64 72 20 3d 20 69 45 6e 64 41 72 63 41 64 64  ddr = iEndArcAdd
76f0: 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64  r+self.nBytesNod
7700: 65 41 64 64 72 65 73 73 0a 20 20 20 20 20 20 20  eAddress.       
7710: 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20           else:. 
7720: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7730: 20 20 20 68 44 73 74 2e 77 72 69 74 65 28 22 20     hDst.write(" 
7740: 20 7b 3a 3c 32 30 7d 20 20 7b 3a 30 3e 31 36 7d   {:<20}  {:0>16}
7750: 5c 6e 22 2e 66 6f 72 6d 61 74 28 73 65 6c 66 2e  \n".format(self.
7760: 6c 41 72 63 56 61 6c 5b 6e 41 72 63 5d 2c 20 62  lArcVal[nArc], b
7770: 69 6e 28 6e 52 61 77 41 72 63 29 5b 32 3a 5d 29  in(nRawArc)[2:])
7780: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
7790: 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 69 45        iAddr = iE
77a0: 6e 64 41 72 63 41 64 64 72 0a 20 20 20 20 20 20  ndArcAddr.      
77b0: 20 20 20 20 20 20 20 20 20 20 69 66 20 28 6e 52            if (nR
77c0: 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 6c 61  awArc & self._la
77d0: 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20  stArcMask):.    
77e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
77f0: 68 44 73 74 2e 77 72 69 74 65 28 22 5c 6e 69 7b  hDst.write("\ni{
7800: 3a 5f 3e 31 30 7d 20 2d 2d 20 23 7b 3a 5f 3e 31  :_>10} -- #{:_>1
7810: 30 7d 5c 6e 22 2e 66 6f 72 6d 61 74 28 22 3f 22  0}\n".format("?"
7820: 2c 20 69 41 64 64 72 29 29 0a 20 20 20 20 20 20  , iAddr)).      
7830: 20 20 20 20 20 20 68 44 73 74 2e 63 6c 6f 73 65        hDst.close
7840: 28 29 0a 0a 20 20 20 20 23 20 56 45 52 53 49 4f  ()..    # VERSIO
7850: 4e 20 33 0a 20 20 20 20 64 65 66 20 5f 6d 6f 72  N 3.    def _mor
7860: 70 68 33 20 28 73 65 6c 66 2c 20 73 57 6f 72 64  ph3 (self, sWord
7870: 29 3a 0a 20 20 20 20 20 20 20 20 22 72 65 74 75  ):.        "retu
7880: 72 6e 73 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73  rns morphologies
7890: 20 6f 66 20 3c 73 57 6f 72 64 3e 22 0a 20 20 20   of <sWord>".   
78a0: 20 20 20 20 20 69 41 64 64 72 20 3d 20 30 0a 20       iAddr = 0. 
78b0: 20 20 20 20 20 20 20 66 6f 72 20 63 20 69 6e 20         for c in 
78c0: 73 57 6f 72 64 3a 0a 20 20 20 20 20 20 20 20 20  sWord:.         
78d0: 20 20 20 69 66 20 63 20 6e 6f 74 20 69 6e 20 73     if c not in s
78e0: 65 6c 66 2e 64 43 68 61 72 3a 0a 20 20 20 20 20  elf.dChar:.     
78f0: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
7900: 6e 20 5b 5d 0a 20 20 20 20 20 20 20 20 20 20 20  n [].           
7910: 20 69 41 64 64 72 20 3d 20 73 65 6c 66 2e 5f 6c   iAddr = self._l
7920: 6f 6f 6b 75 70 41 72 63 4e 6f 64 65 28 73 65 6c  ookupArcNode(sel
7930: 66 2e 64 43 68 61 72 5b 63 5d 2c 20 69 41 64 64  f.dChar[c], iAdd
7940: 72 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  r).            i
7950: 66 20 69 41 64 64 72 20 3d 3d 20 4e 6f 6e 65 3a  f iAddr == None:
7960: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
7970: 20 72 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20 20   return [].     
7980: 20 20 20 69 66 20 28 69 6e 74 2e 66 72 6f 6d 5f     if (int.from_
7990: 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63  bytes(self.byDic
79a0: 5b 69 41 64 64 72 3a 69 41 64 64 72 2b 73 65 6c  [iAddr:iAddr+sel
79b0: 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20 62 79  f.nBytesArc], by
79c0: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 20 26  teorder='big') &
79d0: 20 73 65 6c 66 2e 5f 66 69 6e 61 6c 4e 6f 64 65   self._finalNode
79e0: 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20 20 20  Mask):.         
79f0: 20 20 20 6c 20 3d 20 5b 5d 0a 20 20 20 20 20 20     l = [].      
7a00: 20 20 20 20 20 20 6e 52 61 77 41 72 63 20 3d 20        nRawArc = 
7a10: 30 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 41  0.            iA
7a20: 64 64 72 4e 6f 64 65 20 3d 20 69 41 64 64 72 0a  ddrNode = iAddr.
7a30: 20 20 20 20 20 20 20 20 20 20 20 20 77 68 69 6c              whil
7a40: 65 20 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26  e not (nRawArc &
7a50: 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61   self._lastArcMa
7a60: 73 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  sk):.           
7a70: 20 20 20 20 20 69 45 6e 64 41 72 63 41 64 64 72       iEndArcAddr
7a80: 20 3d 20 69 41 64 64 72 20 2b 20 73 65 6c 66 2e   = iAddr + self.
7a90: 6e 42 79 74 65 73 41 72 63 0a 20 20 20 20 20 20  nBytesArc.      
7aa0: 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72            nRawAr
7ab0: 63 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74  c = int.from_byt
7ac0: 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41  es(self.byDic[iA
7ad0: 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72 5d  ddr:iEndArcAddr]
7ae0: 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67  , byteorder='big
7af0: 27 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ').             
7b00: 20 20 20 6e 41 72 63 20 3d 20 6e 52 61 77 41 72     nArc = nRawAr
7b10: 63 20 26 20 73 65 6c 66 2e 5f 61 72 63 4d 61 73  c & self._arcMas
7b20: 6b 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  k.              
7b30: 20 20 69 66 20 6e 41 72 63 20 3e 20 73 65 6c 66    if nArc > self
7b40: 2e 6e 43 68 61 72 3a 0a 20 20 20 20 20 20 20 20  .nChar:.        
7b50: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 54 68              # Th
7b60: 69 73 20 76 61 6c 75 65 20 69 73 20 6e 6f 74 20  is value is not 
7b70: 61 20 63 68 61 72 2c 20 74 68 69 73 20 69 73 20  a char, this is 
7b80: 61 20 73 74 65 6d 6d 69 6e 67 20 63 6f 64 65 20  a stemming code 
7b90: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
7ba0: 20 20 20 20 20 73 53 74 65 6d 20 3d 20 22 3e 22       sStem = ">"
7bb0: 20 2b 20 73 65 6c 66 2e 66 75 6e 63 53 74 65 6d   + self.funcStem
7bc0: 6d 69 6e 67 28 73 57 6f 72 64 2c 20 73 65 6c 66  ming(sWord, self
7bd0: 2e 6c 41 72 63 56 61 6c 5b 6e 41 72 63 5d 29 0a  .lArcVal[nArc]).
7be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7bf0: 20 20 20 20 23 20 4e 6f 77 20 2c 20 77 65 20 67      # Now , we g
7c00: 6f 20 74 6f 20 74 68 65 20 6e 65 78 74 20 6e 6f  o to the next no
7c10: 64 65 20 61 6e 64 20 72 65 74 72 69 65 76 65 20  de and retrieve 
7c20: 61 6c 6c 20 66 6f 6c 6c 6f 77 69 6e 67 20 61 72  all following ar
7c30: 63 73 20 76 61 6c 75 65 73 2c 20 61 6c 6c 20 6f  cs values, all o
7c40: 66 20 74 68 65 6d 20 61 72 65 20 74 61 67 73 0a  f them are tags.
7c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7c60: 20 20 20 20 69 66 20 6e 6f 74 20 28 6e 52 61 77      if not (nRaw
7c70: 41 72 63 20 26 20 73 65 6c 66 2e 5f 61 64 64 72  Arc & self._addr
7c80: 42 69 74 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20  BitMask):.      
7c90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7ca0: 20 20 69 41 64 64 72 32 20 3d 20 69 6e 74 2e 66    iAddr2 = int.f
7cb0: 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62  rom_bytes(self.b
7cc0: 79 44 69 63 5b 69 45 6e 64 41 72 63 41 64 64 72  yDic[iEndArcAddr
7cd0: 3a 69 45 6e 64 41 72 63 41 64 64 72 2b 73 65 6c  :iEndArcAddr+sel
7ce0: 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72  f.nBytesNodeAddr
7cf0: 65 73 73 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d  ess], byteorder=
7d00: 27 62 69 67 27 29 0a 20 20 20 20 20 20 20 20 20  'big').         
7d10: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
7d20: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
7d30: 20 20 20 20 20 20 20 20 20 69 41 64 64 72 32 20           iAddr2 
7d40: 3d 20 69 41 64 64 72 4e 6f 64 65 20 2b 20 69 6e  = iAddrNode + in
7d50: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
7d60: 66 2e 62 79 44 69 63 5b 69 45 6e 64 41 72 63 41  f.byDic[iEndArcA
7d70: 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72 2b  ddr:iEndArcAddr+
7d80: 73 65 6c 66 2e 6e 42 79 74 65 73 4f 66 66 73 65  self.nBytesOffse
7d90: 74 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62  t], byteorder='b
7da0: 69 67 27 29 0a 20 20 20 20 20 20 20 20 20 20 20  ig').           
7db0: 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63           nRawArc
7dc0: 32 20 3d 20 30 0a 20 20 20 20 20 20 20 20 20 20  2 = 0.          
7dd0: 20 20 20 20 20 20 20 20 20 20 77 68 69 6c 65 20            while 
7de0: 6e 6f 74 20 28 6e 52 61 77 41 72 63 32 20 26 20  not (nRawArc2 & 
7df0: 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73  self._lastArcMas
7e00: 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  k):.            
7e10: 20 20 20 20 20 20 20 20 20 20 20 20 69 45 6e 64              iEnd
7e20: 41 72 63 41 64 64 72 32 20 3d 20 69 41 64 64 72  ArcAddr2 = iAddr
7e30: 32 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41  2 + self.nBytesA
7e40: 72 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  rc.             
7e50: 20 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41             nRawA
7e60: 72 63 32 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62  rc2 = int.from_b
7e70: 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b  ytes(self.byDic[
7e80: 69 41 64 64 72 32 3a 69 45 6e 64 41 72 63 41 64  iAddr2:iEndArcAd
7e90: 64 72 32 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d  dr2], byteorder=
7ea0: 27 62 69 67 27 29 0a 20 20 20 20 20 20 20 20 20  'big').         
7eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c                 l
7ec0: 2e 61 70 70 65 6e 64 28 73 53 74 65 6d 20 2b 20  .append(sStem + 
7ed0: 22 20 22 20 2b 20 73 65 6c 66 2e 6c 41 72 63 56  " " + self.lArcV
7ee0: 61 6c 5b 6e 52 61 77 41 72 63 32 20 26 20 73 65  al[nRawArc2 & se
7ef0: 6c 66 2e 5f 61 72 63 4d 61 73 6b 5d 29 0a 20 20  lf._arcMask]).  
7f00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7f10: 20 20 20 20 20 20 69 41 64 64 72 32 20 3d 20 69        iAddr2 = i
7f20: 45 6e 64 41 72 63 41 64 64 72 32 2b 73 65 6c 66  EndArcAddr2+self
7f30: 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65  .nBytesNodeAddre
7f40: 73 73 20 20 69 66 20 6e 6f 74 20 28 6e 52 61 77  ss  if not (nRaw
7f50: 41 72 63 32 20 26 20 73 65 6c 66 2e 5f 61 64 64  Arc2 & self._add
7f60: 72 42 69 74 4d 61 73 6b 29 20 65 6c 73 65 20 69  rBitMask) else i
7f70: 45 6e 64 41 72 63 41 64 64 72 32 2b 73 65 6c 66  EndArcAddr2+self
7f80: 2e 6e 42 79 74 65 73 4f 66 66 73 65 74 0a 20 20  .nBytesOffset.  
7f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41                iA
7fa0: 64 64 72 20 3d 20 69 45 6e 64 41 72 63 41 64 64  ddr = iEndArcAdd
7fb0: 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64  r+self.nBytesNod
7fc0: 65 41 64 64 72 65 73 73 20 20 69 66 20 6e 6f 74  eAddress  if not
7fd0: 20 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66   (nRawArc & self
7fe0: 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 20 20  ._addrBitMask)  
7ff0: 65 6c 73 65 20 69 45 6e 64 41 72 63 41 64 64 72  else iEndArcAddr
8000: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4f 66 66 73  +self.nBytesOffs
8010: 65 74 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  et.            r
8020: 65 74 75 72 6e 20 6c 0a 20 20 20 20 20 20 20 20  eturn l.        
8030: 72 65 74 75 72 6e 20 5b 5d 0a 0a 20 20 20 20 64  return []..    d
8040: 65 66 20 5f 73 74 65 6d 33 20 28 73 65 6c 66 2c  ef _stem3 (self,
8050: 20 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20 20   sWord):.       
8060: 20 22 72 65 74 75 72 6e 73 20 73 74 65 6d 73 20   "returns stems 
8070: 6c 69 73 74 20 6f 66 20 3c 73 57 6f 72 64 3e 22  list of <sWord>"
8080: 0a 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d  .        iAddr =
8090: 20 30 0a 20 20 20 20 20 20 20 20 66 6f 72 20 63   0.        for c
80a0: 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20 20 20 20   in sWord:.     
80b0: 20 20 20 20 20 20 20 69 66 20 63 20 6e 6f 74 20         if c not 
80c0: 69 6e 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a 20  in self.dChar:. 
80d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72                 r
80e0: 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20 20 20 20  eturn [].       
80f0: 20 20 20 20 20 69 41 64 64 72 20 3d 20 73 65 6c       iAddr = sel
8100: 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64 65  f._lookupArcNode
8110: 28 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d 2c 20  (self.dChar[c], 
8120: 69 41 64 64 72 29 0a 20 20 20 20 20 20 20 20 20  iAddr).         
8130: 20 20 20 69 66 20 69 41 64 64 72 20 3d 3d 20 4e     if iAddr == N
8140: 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  one:.           
8150: 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 20       return []. 
8160: 20 20 20 20 20 20 20 69 66 20 28 69 6e 74 2e 66         if (int.f
8170: 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62  rom_bytes(self.b
8180: 79 44 69 63 5b 69 41 64 64 72 3a 69 41 64 64 72  yDic[iAddr:iAddr
8190: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 5d  +self.nBytesArc]
81a0: 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67  , byteorder='big
81b0: 27 29 20 26 20 73 65 6c 66 2e 5f 66 69 6e 61 6c  ') & self._final
81c0: 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20 20 20 20 20  NodeMask):.     
81d0: 20 20 20 20 20 20 20 6c 20 3d 20 5b 5d 0a 20 20         l = [].  
81e0: 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72            nRawAr
81f0: 63 20 3d 20 30 0a 20 20 20 20 20 20 20 20 20 20  c = 0.          
8200: 20 20 69 41 64 64 72 4e 6f 64 65 20 3d 20 69 41    iAddrNode = iA
8210: 64 64 72 0a 20 20 20 20 20 20 20 20 20 20 20 20  ddr.            
8220: 77 68 69 6c 65 20 6e 6f 74 20 28 6e 52 61 77 41  while not (nRawA
8230: 72 63 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41  rc & self._lastA
8240: 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20  rcMask):.       
8250: 20 20 20 20 20 20 20 20 20 69 45 6e 64 41 72 63           iEndArc
8260: 41 64 64 72 20 3d 20 69 41 64 64 72 20 2b 20 73  Addr = iAddr + s
8270: 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a 20 20  elf.nBytesArc.  
8280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 52                nR
8290: 61 77 41 72 63 20 3d 20 69 6e 74 2e 66 72 6f 6d  awArc = int.from
82a0: 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69  _bytes(self.byDi
82b0: 63 5b 69 41 64 64 72 3a 69 45 6e 64 41 72 63 41  c[iAddr:iEndArcA
82c0: 64 64 72 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d  ddr], byteorder=
82d0: 27 62 69 67 27 29 0a 20 20 20 20 20 20 20 20 20  'big').         
82e0: 20 20 20 20 20 20 20 6e 41 72 63 20 3d 20 6e 52         nArc = nR
82f0: 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61 72  awArc & self._ar
8300: 63 4d 61 73 6b 0a 20 20 20 20 20 20 20 20 20 20  cMask.          
8310: 20 20 20 20 20 20 69 66 20 6e 41 72 63 20 3e 20        if nArc > 
8320: 73 65 6c 66 2e 6e 43 68 61 72 3a 0a 20 20 20 20  self.nChar:.    
8330: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8340: 23 20 54 68 69 73 20 76 61 6c 75 65 20 69 73 20  # This value is 
8350: 6e 6f 74 20 61 20 63 68 61 72 2c 20 74 68 69 73  not a char, this
8360: 20 69 73 20 61 20 73 74 65 6d 6d 69 6e 67 20 63   is a stemming c
8370: 6f 64 65 20 0a 20 20 20 20 20 20 20 20 20 20 20  ode .           
8380: 20 20 20 20 20 20 20 20 20 6c 2e 61 70 70 65 6e           l.appen
8390: 64 28 73 65 6c 66 2e 66 75 6e 63 53 74 65 6d 6d  d(self.funcStemm
83a0: 69 6e 67 28 73 57 6f 72 64 2c 20 73 65 6c 66 2e  ing(sWord, self.
83b0: 6c 41 72 63 56 61 6c 5b 6e 41 72 63 5d 29 29 0a  lArcVal[nArc])).
83c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
83d0: 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72 63 41  iAddr = iEndArcA
83e0: 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e  ddr+self.nBytesN
83f0: 6f 64 65 41 64 64 72 65 73 73 20 20 69 66 20 6e  odeAddress  if n
8400: 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73 65  ot (nRawArc & se
8410: 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29  lf._addrBitMask)
8420: 20 20 65 6c 73 65 20 69 45 6e 64 41 72 63 41 64    else iEndArcAd
8430: 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4f 66  dr+self.nBytesOf
8440: 66 73 65 74 0a 20 20 20 20 20 20 20 20 20 20 20  fset.           
8450: 20 72 65 74 75 72 6e 20 6c 0a 20 20 20 20 20 20   return l.      
8460: 20 20 72 65 74 75 72 6e 20 5b 5d 0a 0a 20 20 20    return []..   
8470: 20 64 65 66 20 5f 6c 6f 6f 6b 75 70 41 72 63 4e   def _lookupArcN
8480: 6f 64 65 33 20 28 73 65 6c 66 2c 20 6e 56 61 6c  ode3 (self, nVal
8490: 2c 20 69 41 64 64 72 29 3a 0a 20 20 20 20 20 20  , iAddr):.      
84a0: 20 20 22 6c 6f 6f 6b 73 20 69 66 20 3c 6e 56 61    "looks if <nVa
84b0: 6c 3e 20 69 73 20 61 6e 20 61 72 63 20 61 74 20  l> is an arc at 
84c0: 74 68 65 20 6e 6f 64 65 20 61 74 20 3c 69 41 64  the node at <iAd
84d0: 64 72 3e 2c 20 69 66 20 79 65 73 2c 20 72 65 74  dr>, if yes, ret
84e0: 75 72 6e 73 20 61 64 64 72 65 73 73 20 6f 66 20  urns address of 
84f0: 6e 65 78 74 20 6e 6f 64 65 20 65 6c 73 65 20 4e  next node else N
8500: 6f 6e 65 22 0a 20 20 20 20 20 20 20 20 69 41 64  one".        iAd
8510: 64 72 4e 6f 64 65 20 3d 20 69 41 64 64 72 0a 20  drNode = iAddr. 
8520: 20 20 20 20 20 20 20 77 68 69 6c 65 20 54 72 75         while Tru
8530: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  e:.            i
8540: 45 6e 64 41 72 63 41 64 64 72 20 3d 20 69 41 64  EndArcAddr = iAd
8550: 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72  dr+self.nBytesAr
8560: 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e 52  c.            nR
8570: 61 77 41 72 63 20 3d 20 69 6e 74 2e 66 72 6f 6d  awArc = int.from
8580: 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69  _bytes(self.byDi
8590: 63 5b 69 41 64 64 72 3a 69 45 6e 64 41 72 63 41  c[iAddr:iEndArcA
85a0: 64 64 72 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d  ddr], byteorder=
85b0: 27 62 69 67 27 29 0a 20 20 20 20 20 20 20 20 20  'big').         
85c0: 20 20 20 69 66 20 6e 56 61 6c 20 3d 3d 20 28 6e     if nVal == (n
85d0: 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61  RawArc & self._a
85e0: 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20  rcMask):.       
85f0: 20 20 20 20 20 20 20 20 20 23 20 74 68 65 20 76           # the v
8600: 61 6c 75 65 20 77 65 20 61 72 65 20 6c 6f 6f 6b  alue we are look
8610: 69 6e 67 20 66 6f 72 20 0a 20 20 20 20 20 20 20  ing for .       
8620: 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20           if not 
8630: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
8640: 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 3a 0a 20  _addrBitMask):. 
8650: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8660: 20 20 20 72 65 74 75 72 6e 20 69 6e 74 2e 66 72     return int.fr
8670: 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79  om_bytes(self.by
8680: 44 69 63 5b 69 45 6e 64 41 72 63 41 64 64 72 3a  Dic[iEndArcAddr:
8690: 69 45 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66  iEndArcAddr+self
86a0: 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65  .nBytesNodeAddre
86b0: 73 73 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27  ss], byteorder='
86c0: 62 69 67 27 29 0a 20 20 20 20 20 20 20 20 20 20  big').          
86d0: 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20        else:.    
86e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
86f0: 72 65 74 75 72 6e 20 69 41 64 64 72 4e 6f 64 65  return iAddrNode
8700: 20 2b 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65   + int.from_byte
8710: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e  s(self.byDic[iEn
8720: 64 41 72 63 41 64 64 72 3a 69 45 6e 64 41 72 63  dArcAddr:iEndArc
8730: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
8740: 4f 66 66 73 65 74 5d 2c 20 62 79 74 65 6f 72 64  Offset], byteord
8750: 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20  er='big').      
8760: 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20        else:.    
8770: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 76 61              # va
8780: 6c 75 65 20 6e 6f 74 20 66 6f 75 6e 64 0a 20 20  lue not found.  
8790: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
87a0: 20 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66   (nRawArc & self
87b0: 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a  ._lastArcMask):.
87c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
87d0: 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e 65 0a      return None.
87e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
87f0: 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72 63 41  iAddr = iEndArcA
8800: 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e  ddr+self.nBytesN
8810: 6f 64 65 41 64 64 72 65 73 73 20 20 69 66 20 6e  odeAddress  if n
8820: 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73 65  ot (nRawArc & se
8830: 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29  lf._addrBitMask)
8840: 20 20 65 6c 73 65 20 69 45 6e 64 41 72 63 41 64    else iEndArcAd
8850: 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4f 66  dr+self.nBytesOf
8860: 66 73 65 74 0a 0a 20 20 20 20 64 65 66 20 5f 77  fset..    def _w
8870: 72 69 74 65 4e 6f 64 65 73 33 20 28 73 65 6c 66  riteNodes3 (self
8880: 2c 20 73 70 66 44 65 73 74 29 3a 0a 20 20 20 20  , spfDest):.    
8890: 20 20 20 20 22 66 6f 72 20 64 65 62 75 67 67 69      "for debuggi
88a0: 6e 67 20 6f 6e 6c 79 22 0a 20 20 20 20 20 20 20  ng only".       
88b0: 20 70 72 69 6e 74 28 22 20 3e 20 57 72 69 74 65   print(" > Write
88c0: 20 62 69 6e 61 72 79 20 6e 6f 64 65 73 22 29 0a   binary nodes").
88d0: 20 20 20 20 20 20 20 20 77 69 74 68 20 63 6f 64          with cod
88e0: 65 63 73 2e 6f 70 65 6e 28 73 70 66 44 65 73 74  ecs.open(spfDest
88f0: 2c 20 27 77 27 2c 20 27 75 74 66 2d 38 27 2c 20  , 'w', 'utf-8', 
8900: 6e 65 77 6c 69 6e 65 3d 22 5c 6e 22 29 20 61 73  newline="\n") as
8910: 20 68 44 73 74 3a 0a 20 20 20 20 20 20 20 20 20   hDst:.         
8920: 20 20 20 69 41 64 64 72 20 3d 20 30 0a 20 20 20     iAddr = 0.   
8930: 20 20 20 20 20 20 20 20 20 68 44 73 74 2e 77 72           hDst.wr
8940: 69 74 65 28 22 69 7b 3a 5f 3e 31 30 7d 20 2d 2d  ite("i{:_>10} --
8950: 20 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72   #{:_>10}\n".for
8960: 6d 61 74 28 22 30 22 2c 20 69 41 64 64 72 29 29  mat("0", iAddr))
8970: 0a 20 20 20 20 20 20 20 20 20 20 20 20 77 68 69  .            whi
8980: 6c 65 20 69 41 64 64 72 20 3c 20 6c 65 6e 28 73  le iAddr < len(s
8990: 65 6c 66 2e 62 79 44 69 63 29 3a 0a 20 20 20 20  elf.byDic):.    
89a0: 20 20 20 20 20 20 20 20 20 20 20 20 69 45 6e 64              iEnd
89b0: 41 72 63 41 64 64 72 20 3d 20 69 41 64 64 72 2b  ArcAddr = iAddr+
89c0: 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a 20  self.nBytesArc. 
89d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e                 n
89e0: 52 61 77 41 72 63 20 3d 20 69 6e 74 2e 66 72 6f  RawArc = int.fro
89f0: 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44  m_bytes(self.byD
8a00: 69 63 5b 69 41 64 64 72 3a 69 45 6e 64 41 72 63  ic[iAddr:iEndArc
8a10: 41 64 64 72 5d 2c 20 62 79 74 65 6f 72 64 65 72  Addr], byteorder
8a20: 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20 20 20  ='big').        
8a30: 20 20 20 20 20 20 20 20 6e 41 72 63 20 3d 20 6e          nArc = n
8a40: 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61  RawArc & self._a
8a50: 72 63 4d 61 73 6b 0a 20 20 20 20 20 20 20 20 20  rcMask.         
8a60: 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 28 6e         if not (n
8a70: 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61  RawArc & self._a
8a80: 64 64 72 42 69 74 4d 61 73 6b 29 3a 0a 20 20 20  ddrBitMask):.   
8a90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8aa0: 20 69 4e 65 78 74 4e 6f 64 65 41 64 64 72 20 3d   iNextNodeAddr =
8ab0: 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28   int.from_bytes(
8ac0: 73 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41  self.byDic[iEndA
8ad0: 72 63 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64  rcAddr:iEndArcAd
8ae0: 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f  dr+self.nBytesNo
8af0: 64 65 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65  deAddress], 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 23 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 4e 6f 64 65 41  self.nBytesNodeA
8bd0: 64 64 72 65 73 73 0a 20 20 20 20 20 20 20 20 20  ddress.         
8be0: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
8bf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8c00: 20 69 4e 65 78 74 4e 6f 64 65 41 64 64 72 20 3d   iNextNodeAddr =
8c10: 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28   int.from_bytes(
8c20: 73 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41  self.byDic[iEndA
8c30: 72 63 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64  rcAddr:iEndArcAd
8c40: 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4f 66  dr+self.nBytesOf
8c50: 66 73 65 74 5d 2c 20 62 79 74 65 6f 72 64 65 72  fset], byteorder
8c60: 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20 20 20  ='big').        
8c70: 20 20 20 20 20 20 20 20 20 20 20 20 68 44 73 74              hDst
8c80: 2e 77 72 69 74 65 28 22 20 20 7b 3a 3c 32 30 7d  .write("  {:<20}
8c90: 20 20 7b 3a 30 3e 31 36 7d 20 20 69 7b 3a 3e 31    {:0>16}  i{:>1
8ca0: 30 7d 20 20 20 2b 7b 3a 5f 3e 31 30 7d 5c 6e 22  0}   +{:_>10}\n"
8cb0: 2e 66 6f 72 6d 61 74 28 73 65 6c 66 2e 6c 41 72  .format(self.lAr
8cc0: 63 56 61 6c 5b 6e 41 72 63 5d 2c 20 62 69 6e 28  cVal[nArc], bin(
8cd0: 6e 52 61 77 41 72 63 29 5b 32 3a 5d 2c 20 22 3f  nRawArc)[2:], "?
8ce0: 22 2c 20 69 4e 65 78 74 4e 6f 64 65 41 64 64 72  ", iNextNodeAddr
8cf0: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  )).             
8d00: 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 69         iAddr = i
8d10: 45 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e  EndArcAddr+self.
8d20: 6e 42 79 74 65 73 4f 66 66 73 65 74 0a 20 20 20  nBytesOffset.   
8d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
8d40: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
8d50: 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20  _lastArcMask):. 
8d60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8d70: 20 20 20 68 44 73 74 2e 77 72 69 74 65 28 22 5c     hDst.write("\
8d80: 6e 69 7b 3a 5f 3e 31 30 7d 20 2d 2d 20 23 7b 3a  ni{:_>10} -- #{:
8d90: 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d 61 74 28  _>10}\n".format(
8da0: 22 3f 22 2c 20 69 41 64 64 72 29 29 0a 20 20 20  "?", iAddr)).   
8db0: 20 20 20 20 20 20 20 20 20 68 44 73 74 2e 63 6c           hDst.cl
8dc0: 6f 73 65 28 29 0a                                ose().