Grammalecte  Hex Artifact Content

Artifact 8db71f38abef63344aee6271aa87eaae69c4d9a0badb817d02d048eaeaf16330:


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 69 74 65 72 74 6f 6f 6c 73 20 69 6d  rom itertools im
0050: 70 6f 72 74 20 63 68 61 69 6e 0a 66 72 6f 6d 20  port chain.from 
0060: 66 75 6e 63 74 6f 6f 6c 73 20 69 6d 70 6f 72 74  functools import
0070: 20 77 72 61 70 73 0a 69 6d 70 6f 72 74 20 74 69   wraps.import ti
0080: 6d 65 0a 0a 69 6d 70 6f 72 74 20 6c 6f 67 67 69  me..import loggi
0090: 6e 67 0a 6c 6f 67 67 69 6e 67 2e 62 61 73 69 63  ng.logging.basic
00a0: 43 6f 6e 66 69 67 28 66 69 6c 65 6e 61 6d 65 3d  Config(filename=
00b0: 22 73 75 67 67 65 73 74 69 6f 6e 73 2e 6c 6f 67  "suggestions.log
00c0: 22 2c 20 6c 65 76 65 6c 3d 6c 6f 67 67 69 6e 67  ", level=logging
00d0: 2e 44 45 42 55 47 29 0a 0a 66 72 6f 6d 20 2e 20  .DEBUG)..from . 
00e0: 69 6d 70 6f 72 74 20 73 74 72 5f 74 72 61 6e 73  import str_trans
00f0: 66 6f 72 6d 20 61 73 20 73 74 0a 66 72 6f 6d 20  form as st.from 
0100: 2e 20 69 6d 70 6f 72 74 20 63 68 61 72 5f 70 6c  . import char_pl
0110: 61 79 65 72 20 61 73 20 63 70 0a 66 72 6f 6d 20  ayer as cp.from 
0120: 2e 65 63 68 6f 20 69 6d 70 6f 72 74 20 65 63 68  .echo import ech
0130: 6f 0a 0a 0a 64 65 66 20 74 69 6d 65 74 68 69 73  o...def timethis
0140: 20 28 66 75 6e 63 29 3a 0a 20 20 20 20 22 64 65   (func):.    "de
0150: 63 6f 72 61 74 6f 72 20 66 6f 72 20 74 68 65 20  corator for the 
0160: 65 78 65 63 75 74 69 6f 6e 20 74 69 6d 65 22 0a  execution time".
0170: 20 20 20 20 40 77 72 61 70 73 28 66 75 6e 63 29      @wraps(func)
0180: 0a 20 20 20 20 64 65 66 20 77 72 61 70 70 65 72  .    def wrapper
0190: 20 28 2a 61 72 67 73 2c 20 2a 2a 6b 77 61 72 67   (*args, **kwarg
01a0: 73 29 3a 0a 20 20 20 20 20 20 20 20 66 53 74 61  s):.        fSta
01b0: 72 74 20 3d 20 74 69 6d 65 2e 74 69 6d 65 28 29  rt = time.time()
01c0: 0a 20 20 20 20 20 20 20 20 72 65 73 75 6c 74 20  .        result 
01d0: 3d 20 66 75 6e 63 28 2a 61 72 67 73 2c 20 2a 2a  = func(*args, **
01e0: 6b 77 61 72 67 73 29 0a 20 20 20 20 20 20 20 20  kwargs).        
01f0: 66 45 6e 64 20 3d 20 74 69 6d 65 2e 74 69 6d 65  fEnd = time.time
0200: 28 29 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74  ().        print
0210: 28 66 75 6e 63 2e 5f 5f 6e 61 6d 65 5f 5f 2c 20  (func.__name__, 
0220: 66 45 6e 64 20 2d 20 66 53 74 61 72 74 29 0a 20  fEnd - fStart). 
0230: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 72 65         return re
0240: 73 75 6c 74 0a 20 20 20 20 72 65 74 75 72 6e 20  sult.    return 
0250: 77 72 61 70 70 65 72 0a 0a 0a 63 6c 61 73 73 20  wrapper...class 
0260: 53 75 67 67 52 65 73 75 6c 74 3a 0a 0a 20 20 20  SuggResult:..   
0270: 20 64 65 66 20 5f 5f 69 6e 69 74 5f 5f 20 28 73   def __init__ (s
0280: 65 6c 66 2c 20 73 57 6f 72 64 2c 20 6e 44 69 73  elf, sWord, nDis
0290: 74 4c 69 6d 69 74 3d 2d 31 29 3a 0a 20 20 20 20  tLimit=-1):.    
02a0: 20 20 20 20 73 65 6c 66 2e 73 57 6f 72 64 20 3d      self.sWord =
02b0: 20 73 57 6f 72 64 0a 20 20 20 20 20 20 20 20 73   sWord.        s
02c0: 65 6c 66 2e 73 43 6c 65 61 6e 57 6f 72 64 20 3d  elf.sCleanWord =
02d0: 20 63 70 2e 63 6c 65 61 6e 57 6f 72 64 28 73 57   cp.cleanWord(sW
02e0: 6f 72 64 29 0a 20 20 20 20 20 20 20 20 73 65 6c  ord).        sel
02f0: 66 2e 6e 44 69 73 74 4c 69 6d 69 74 20 3d 20 6e  f.nDistLimit = n
0300: 44 69 73 74 4c 69 6d 69 74 20 20 69 66 20 6e 44  DistLimit  if nD
0310: 69 73 74 4c 69 6d 69 74 20 3e 3d 20 30 20 20 65  istLimit >= 0  e
0320: 6c 73 65 20 20 28 6c 65 6e 28 73 57 6f 72 64 29  lse  (len(sWord)
0330: 20 2f 2f 20 33 29 20 2b 20 31 0a 20 20 20 20 20   // 3) + 1.     
0340: 20 20 20 73 65 6c 66 2e 6e 4d 69 6e 44 69 73 74     self.nMinDist
0350: 20 3d 20 31 30 30 30 0a 20 20 20 20 20 20 20 20   = 1000.        
0360: 73 65 6c 66 2e 61 53 75 67 67 20 3d 20 73 65 74  self.aSugg = set
0370: 28 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e  ().        self.
0380: 64 53 75 67 67 20 3d 20 7b 20 30 3a 20 5b 5d 2c  dSugg = { 0: [],
0390: 20 20 31 3a 20 5b 5d 2c 20 20 32 3a 20 5b 5d 20    1: [],  2: [] 
03a0: 7d 0a 0a 20 20 20 20 64 65 66 20 61 64 64 53 75  }..    def addSu
03b0: 67 67 20 28 73 65 6c 66 2c 20 73 53 75 67 67 2c  gg (self, sSugg,
03c0: 20 6e 44 65 65 70 3d 30 29 3a 0a 20 20 20 20 20   nDeep=0):.     
03d0: 20 20 20 22 61 64 64 20 61 20 73 75 67 67 65 73     "add a sugges
03e0: 74 69 6f 6e 22 0a 20 20 20 20 20 20 20 20 69 66  tion".        if
03f0: 20 73 53 75 67 67 20 6e 6f 74 20 69 6e 20 73 65   sSugg not in se
0400: 6c 66 2e 61 53 75 67 67 3a 0a 20 20 20 20 20 20  lf.aSugg:.      
0410: 20 20 20 20 20 20 6e 44 69 73 74 20 3d 20 73 74        nDist = st
0420: 2e 64 69 73 74 61 6e 63 65 44 61 6d 65 72 61 75  .distanceDamerau
0430: 4c 65 76 65 6e 73 68 74 65 69 6e 28 73 65 6c 66  Levenshtein(self
0440: 2e 73 43 6c 65 61 6e 57 6f 72 64 2c 20 63 70 2e  .sCleanWord, cp.
0450: 63 6c 65 61 6e 57 6f 72 64 28 73 53 75 67 67 29  cleanWord(sSugg)
0460: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  ).            if
0470: 20 6e 44 69 73 74 20 3c 3d 20 73 65 6c 66 2e 6e   nDist <= self.n
0480: 44 69 73 74 4c 69 6d 69 74 3a 0a 20 20 20 20 20  DistLimit:.     
0490: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 44             if nD
04a0: 69 73 74 20 6e 6f 74 20 69 6e 20 73 65 6c 66 2e  ist not in self.
04b0: 64 53 75 67 67 3a 0a 20 20 20 20 20 20 20 20 20  dSugg:.         
04c0: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
04d0: 64 53 75 67 67 5b 6e 44 69 73 74 5d 20 3d 20 5b  dSugg[nDist] = [
04e0: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ].              
04f0: 20 20 73 65 6c 66 2e 64 53 75 67 67 5b 6e 44 69    self.dSugg[nDi
0500: 73 74 5d 2e 61 70 70 65 6e 64 28 73 53 75 67 67  st].append(sSugg
0510: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
0520: 20 20 6c 6f 67 67 69 6e 67 2e 69 6e 66 6f 28 28    logging.info((
0530: 6e 44 65 65 70 20 2a 20 22 20 20 22 29 20 2b 20  nDeep * "  ") + 
0540: 22 5f 5f 22 20 2b 20 73 53 75 67 67 20 2b 20 22  "__" + sSugg + "
0550: 5f 5f 22 29 0a 20 20 20 20 20 20 20 20 20 20 20  __").           
0560: 20 20 20 20 20 69 66 20 6e 44 69 73 74 20 3c 20       if nDist < 
0570: 73 65 6c 66 2e 6e 4d 69 6e 44 69 73 74 3a 0a 20  self.nMinDist:. 
0580: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0590: 20 20 20 73 65 6c 66 2e 6e 4d 69 6e 44 69 73 74     self.nMinDist
05a0: 20 3d 20 6e 44 69 73 74 0a 20 20 20 20 20 20 20   = nDist.       
05b0: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6e 44           self.nD
05c0: 69 73 74 4c 69 6d 69 74 20 3d 20 6d 69 6e 28 73  istLimit = min(s
05d0: 65 6c 66 2e 6e 44 69 73 74 4c 69 6d 69 74 2c 20  elf.nDistLimit, 
05e0: 73 65 6c 66 2e 6e 4d 69 6e 44 69 73 74 2b 32 29  self.nMinDist+2)
05f0: 0a 0a 20 20 20 20 64 65 66 20 67 65 74 53 75 67  ..    def getSug
0600: 67 65 73 74 69 6f 6e 73 20 28 73 65 6c 66 2c 20  gestions (self, 
0610: 6e 53 75 67 67 4c 69 6d 69 74 3d 31 30 2c 20 6e  nSuggLimit=10, n
0620: 44 69 73 74 4c 69 6d 69 74 3d 2d 31 29 3a 0a 20  DistLimit=-1):. 
0630: 20 20 20 20 20 20 20 22 72 65 74 75 72 6e 20 61         "return a
0640: 20 6c 69 73 74 20 6f 66 20 73 75 67 67 65 73 74   list of suggest
0650: 69 6f 6e 73 22 0a 20 20 20 20 20 20 20 20 6c 52  ions".        lR
0660: 65 73 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20  es = [].        
0670: 66 6f 72 20 6c 53 75 67 67 20 69 6e 20 73 65 6c  for lSugg in sel
0680: 66 2e 64 53 75 67 67 2e 76 61 6c 75 65 73 28 29  f.dSugg.values()
0690: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6c 52  :.            lR
06a0: 65 73 2e 65 78 74 65 6e 64 28 6c 53 75 67 67 29  es.extend(lSugg)
06b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
06c0: 6c 65 6e 28 6c 52 65 73 29 20 3e 20 6e 53 75 67  len(lRes) > nSug
06d0: 67 4c 69 6d 69 74 3a 0a 20 20 20 20 20 20 20 20  gLimit:.        
06e0: 20 20 20 20 20 20 20 20 62 72 65 61 6b 0a 20 20          break.  
06f0: 20 20 20 20 20 20 6c 52 65 73 20 3d 20 6c 69 73        lRes = lis
0700: 74 28 63 70 2e 66 69 6c 74 65 72 53 75 67 67 28  t(cp.filterSugg(
0710: 6c 52 65 73 29 29 0a 20 20 20 20 20 20 20 20 69  lRes)).        i
0720: 66 20 73 65 6c 66 2e 73 57 6f 72 64 2e 69 73 74  f self.sWord.ist
0730: 69 74 6c 65 28 29 3a 0a 20 20 20 20 20 20 20 20  itle():.        
0740: 20 20 20 20 6c 52 65 73 20 3d 20 6c 69 73 74 28      lRes = list(
0750: 6d 61 70 28 6c 61 6d 62 64 61 20 73 53 75 67 67  map(lambda sSugg
0760: 3a 20 73 53 75 67 67 2e 74 69 74 6c 65 28 29 2c  : sSugg.title(),
0770: 20 6c 52 65 73 29 29 0a 20 20 20 20 20 20 20 20   lRes)).        
0780: 72 65 74 75 72 6e 20 6c 52 65 73 5b 3a 6e 53 75  return lRes[:nSu
0790: 67 67 4c 69 6d 69 74 5d 0a 0a 0a 63 6c 61 73 73  ggLimit]...class
07a0: 20 49 42 44 41 57 47 3a 0a 20 20 20 20 22 22 22   IBDAWG:.    """
07b0: 49 4e 44 45 58 41 42 4c 45 20 42 49 4e 41 52 59  INDEXABLE BINARY
07c0: 20 44 49 52 45 43 54 20 41 43 59 43 4c 49 43 20   DIRECT ACYCLIC 
07d0: 57 4f 52 44 20 47 52 41 50 48 22 22 22 0a 0a 20  WORD GRAPH""".. 
07e0: 20 20 20 64 65 66 20 5f 5f 69 6e 69 74 5f 5f 20     def __init__ 
07f0: 28 73 65 6c 66 2c 20 73 44 69 63 4e 61 6d 65 29  (self, sDicName)
0800: 3a 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 62  :.        self.b
0810: 79 20 3d 20 70 6b 67 75 74 69 6c 2e 67 65 74 5f  y = pkgutil.get_
0820: 64 61 74 61 28 5f 5f 70 61 63 6b 61 67 65 5f 5f  data(__package__
0830: 2c 20 22 5f 64 69 63 74 69 6f 6e 61 72 69 65 73  , "_dictionaries
0840: 2f 22 20 2b 20 73 44 69 63 4e 61 6d 65 29 0a 20  /" + sDicName). 
0850: 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 73 65         if not se
0860: 6c 66 2e 62 79 3a 0a 20 20 20 20 20 20 20 20 20  lf.by:.         
0870: 20 20 20 72 61 69 73 65 20 4f 53 45 72 72 6f 72     raise OSError
0880: 28 22 23 20 45 72 72 6f 72 2e 20 46 69 6c 65 20  ("# Error. File 
0890: 6e 6f 74 20 66 6f 75 6e 64 20 6f 72 20 6e 6f 74  not found or not
08a0: 20 6c 6f 61 64 61 62 6c 65 3a 20 22 2b 73 44 69   loadable: "+sDi
08b0: 63 4e 61 6d 65 29 0a 0a 20 20 20 20 20 20 20 20  cName)..        
08c0: 69 66 20 73 65 6c 66 2e 62 79 5b 30 3a 37 5d 20  if self.by[0:7] 
08d0: 21 3d 20 62 22 2f 70 79 66 73 61 2f 22 3a 0a 20  != b"/pyfsa/":. 
08e0: 20 20 20 20 20 20 20 20 20 20 20 72 61 69 73 65             raise
08f0: 20 54 79 70 65 45 72 72 6f 72 28 22 23 20 45 72   TypeError("# Er
0900: 72 6f 72 2e 20 4e 6f 74 20 61 20 70 79 66 73 61  ror. Not a pyfsa
0910: 20 62 69 6e 61 72 79 20 64 69 63 74 69 6f 6e 61   binary dictiona
0920: 72 79 2e 20 48 65 61 64 65 72 3a 20 7b 7d 22 2e  ry. Header: {}".
0930: 66 6f 72 6d 61 74 28 73 65 6c 66 2e 62 79 5b 30  format(self.by[0
0940: 3a 39 5d 29 29 0a 20 20 20 20 20 20 20 20 69 66  :9])).        if
0950: 20 6e 6f 74 28 73 65 6c 66 2e 62 79 5b 37 3a 38   not(self.by[7:8
0960: 5d 20 3d 3d 20 62 22 31 22 20 6f 72 20 73 65 6c  ] == b"1" or sel
0970: 66 2e 62 79 5b 37 3a 38 5d 20 3d 3d 20 62 22 32  f.by[7:8] == b"2
0980: 22 20 6f 72 20 73 65 6c 66 2e 62 79 5b 37 3a 38  " or self.by[7:8
0990: 5d 20 3d 3d 20 62 22 33 22 29 3a 0a 20 20 20 20  ] == b"3"):.    
09a0: 20 20 20 20 20 20 20 20 72 61 69 73 65 20 56 61          raise Va
09b0: 6c 75 65 45 72 72 6f 72 28 22 23 20 45 72 72 6f  lueError("# Erro
09c0: 72 2e 20 55 6e 6b 6e 6f 77 6e 20 64 69 63 74 69  r. Unknown dicti
09d0: 6f 6e 61 72 79 20 76 65 72 73 69 6f 6e 3a 20 7b  onary version: {
09e0: 7d 22 2e 66 6f 72 6d 61 74 28 73 65 6c 66 2e 62  }".format(self.b
09f0: 79 5b 37 3a 38 5d 29 29 0a 20 20 20 20 20 20 20  y[7:8])).       
0a00: 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20   try:.          
0a10: 20 20 68 65 61 64 65 72 2c 20 69 6e 66 6f 2c 20    header, info, 
0a20: 76 61 6c 75 65 73 2c 20 62 64 69 63 20 3d 20 73  values, bdic = s
0a30: 65 6c 66 2e 62 79 2e 73 70 6c 69 74 28 62 22 5c  elf.by.split(b"\
0a40: 30 5c 30 5c 30 5c 30 22 2c 20 33 29 0a 20 20 20  0\0\0\0", 3).   
0a50: 20 20 20 20 20 65 78 63 65 70 74 20 45 78 63 65       except Exce
0a60: 70 74 69 6f 6e 3a 0a 20 20 20 20 20 20 20 20 20  ption:.         
0a70: 20 20 20 72 61 69 73 65 20 45 78 63 65 70 74 69     raise Excepti
0a80: 6f 6e 0a 0a 20 20 20 20 20 20 20 20 73 65 6c 66  on..        self
0a90: 2e 73 4e 61 6d 65 20 3d 20 73 44 69 63 4e 61 6d  .sName = sDicNam
0aa0: 65 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6e  e.        self.n
0ab0: 56 65 72 73 69 6f 6e 20 3d 20 69 6e 74 28 73 65  Version = int(se
0ac0: 6c 66 2e 62 79 5b 37 3a 38 5d 2e 64 65 63 6f 64  lf.by[7:8].decod
0ad0: 65 28 22 75 74 66 2d 38 22 29 29 0a 20 20 20 20  e("utf-8")).    
0ae0: 20 20 20 20 73 65 6c 66 2e 73 48 65 61 64 65 72      self.sHeader
0af0: 20 3d 20 68 65 61 64 65 72 2e 64 65 63 6f 64 65   = header.decode
0b00: 28 22 75 74 66 2d 38 22 29 0a 20 20 20 20 20 20  ("utf-8").      
0b10: 20 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 20 3d    self.lArcVal =
0b20: 20 76 61 6c 75 65 73 2e 64 65 63 6f 64 65 28 22   values.decode("
0b30: 75 74 66 2d 38 22 29 2e 73 70 6c 69 74 28 22 5c  utf-8").split("\
0b40: 74 22 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66  t").        self
0b50: 2e 6e 41 72 63 56 61 6c 20 3d 20 6c 65 6e 28 73  .nArcVal = len(s
0b60: 65 6c 66 2e 6c 41 72 63 56 61 6c 29 0a 20 20 20  elf.lArcVal).   
0b70: 20 20 20 20 20 73 65 6c 66 2e 62 79 44 69 63 20       self.byDic 
0b80: 3d 20 62 64 69 63 0a 0a 20 20 20 20 20 20 20 20  = bdic..        
0b90: 6c 20 3d 20 69 6e 66 6f 2e 64 65 63 6f 64 65 28  l = info.decode(
0ba0: 22 75 74 66 2d 38 22 29 2e 73 70 6c 69 74 28 22  "utf-8").split("
0bb0: 2f 22 29 0a 20 20 20 20 20 20 20 20 73 65 6c 66  /").        self
0bc0: 2e 73 4c 61 6e 67 20 3d 20 6c 5b 30 5d 0a 20 20  .sLang = l[0].  
0bd0: 20 20 20 20 20 20 73 65 6c 66 2e 6e 43 68 61 72        self.nChar
0be0: 20 3d 20 69 6e 74 28 6c 5b 31 5d 29 0a 20 20 20   = int(l[1]).   
0bf0: 20 20 20 20 20 73 65 6c 66 2e 6e 42 79 74 65 73       self.nBytes
0c00: 41 72 63 20 3d 20 69 6e 74 28 6c 5b 32 5d 29 0a  Arc = int(l[2]).
0c10: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6e 42 79          self.nBy
0c20: 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 20 3d  tesNodeAddress =
0c30: 20 69 6e 74 28 6c 5b 33 5d 29 0a 20 20 20 20 20   int(l[3]).     
0c40: 20 20 20 73 65 6c 66 2e 6e 45 6e 74 72 69 65 73     self.nEntries
0c50: 20 3d 20 69 6e 74 28 6c 5b 34 5d 29 0a 20 20 20   = int(l[4]).   
0c60: 20 20 20 20 20 73 65 6c 66 2e 6e 4e 6f 64 65 20       self.nNode 
0c70: 3d 20 69 6e 74 28 6c 5b 35 5d 29 0a 20 20 20 20  = int(l[5]).    
0c80: 20 20 20 20 73 65 6c 66 2e 6e 41 72 63 20 3d 20      self.nArc = 
0c90: 69 6e 74 28 6c 5b 36 5d 29 0a 20 20 20 20 20 20  int(l[6]).      
0ca0: 20 20 73 65 6c 66 2e 6e 41 66 66 20 3d 20 69 6e    self.nAff = in
0cb0: 74 28 6c 5b 37 5d 29 0a 20 20 20 20 20 20 20 20  t(l[7]).        
0cc0: 73 65 6c 66 2e 63 53 74 65 6d 6d 69 6e 67 20 3d  self.cStemming =
0cd0: 20 6c 5b 38 5d 0a 20 20 20 20 20 20 20 20 69 66   l[8].        if
0ce0: 20 73 65 6c 66 2e 63 53 74 65 6d 6d 69 6e 67 20   self.cStemming 
0cf0: 3d 3d 20 22 53 22 3a 0a 20 20 20 20 20 20 20 20  == "S":.        
0d00: 20 20 20 20 73 65 6c 66 2e 66 75 6e 63 53 74 65      self.funcSte
0d10: 6d 6d 69 6e 67 20 3d 20 73 74 2e 63 68 61 6e 67  mming = st.chang
0d20: 65 57 6f 72 64 57 69 74 68 53 75 66 66 69 78 43  eWordWithSuffixC
0d30: 6f 64 65 0a 20 20 20 20 20 20 20 20 65 6c 69 66  ode.        elif
0d40: 20 73 65 6c 66 2e 63 53 74 65 6d 6d 69 6e 67 20   self.cStemming 
0d50: 3d 3d 20 22 41 22 3a 0a 20 20 20 20 20 20 20 20  == "A":.        
0d60: 20 20 20 20 73 65 6c 66 2e 66 75 6e 63 53 74 65      self.funcSte
0d70: 6d 6d 69 6e 67 20 3d 20 73 74 2e 63 68 61 6e 67  mming = st.chang
0d80: 65 57 6f 72 64 57 69 74 68 41 66 66 69 78 43 6f  eWordWithAffixCo
0d90: 64 65 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a  de.        else:
0da0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c  .            sel
0db0: 66 2e 66 75 6e 63 53 74 65 6d 6d 69 6e 67 20 3d  f.funcStemming =
0dc0: 20 73 74 2e 6e 6f 53 74 65 6d 6d 69 6e 67 0a 20   st.noStemming. 
0dd0: 20 20 20 20 20 20 20 73 65 6c 66 2e 6e 54 61 67         self.nTag
0de0: 20 3d 20 73 65 6c 66 2e 6e 41 72 63 56 61 6c 20   = self.nArcVal 
0df0: 2d 20 73 65 6c 66 2e 6e 43 68 61 72 20 2d 20 73  - self.nChar - s
0e00: 65 6c 66 2e 6e 41 66 66 0a 20 20 20 20 20 20 20  elf.nAff.       
0e10: 20 23 20 3c 64 43 68 61 72 3e 20 74 6f 20 67 65   # <dChar> to ge
0e20: 74 20 74 68 65 20 76 61 6c 75 65 20 6f 66 20 61  t the value of a
0e30: 6e 20 61 72 63 2c 20 3c 64 43 68 61 72 56 61 6c  n arc, <dCharVal
0e40: 3e 20 74 6f 20 67 65 74 20 74 68 65 20 63 68 61  > to get the cha
0e50: 72 20 6f 66 20 61 6e 20 61 72 63 20 77 69 74 68  r of an arc with
0e60: 20 69 74 73 20 76 61 6c 75 65 0a 20 20 20 20 20   its value.     
0e70: 20 20 20 73 65 6c 66 2e 64 43 68 61 72 20 3d 20     self.dChar = 
0e80: 7b 7d 0a 20 20 20 20 20 20 20 20 66 6f 72 20 69  {}.        for i
0e90: 20 69 6e 20 72 61 6e 67 65 28 31 2c 20 73 65 6c   in range(1, sel
0ea0: 66 2e 6e 43 68 61 72 29 3a 0a 20 20 20 20 20 20  f.nChar):.      
0eb0: 20 20 20 20 20 20 73 65 6c 66 2e 64 43 68 61 72        self.dChar
0ec0: 5b 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 69 5d  [self.lArcVal[i]
0ed0: 5d 20 3d 20 69 0a 20 20 20 20 20 20 20 20 73 65  ] = i.        se
0ee0: 6c 66 2e 64 43 68 61 72 56 61 6c 20 3d 20 7b 20  lf.dCharVal = { 
0ef0: 76 3a 20 6b 20 20 66 6f 72 20 6b 2c 20 76 20 69  v: k  for k, v i
0f00: 6e 20 73 65 6c 66 2e 64 43 68 61 72 2e 69 74 65  n self.dChar.ite
0f10: 6d 73 28 29 20 7d 0a 20 20 20 20 20 20 20 20 20  ms() }.         
0f20: 20 20 20 0a 20 20 20 20 20 20 20 20 73 65 6c 66     .        self
0f30: 2e 5f 61 72 63 4d 61 73 6b 20 3d 20 28 32 20 2a  ._arcMask = (2 *
0f40: 2a 20 28 28 73 65 6c 66 2e 6e 42 79 74 65 73 41  * ((self.nBytesA
0f50: 72 63 20 2a 20 38 29 20 2d 20 33 29 29 20 2d 20  rc * 8) - 3)) - 
0f60: 31 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f  1.        self._
0f70: 66 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b 20 3d 20  finalNodeMask = 
0f80: 31 20 3c 3c 20 28 28 73 65 6c 66 2e 6e 42 79 74  1 << ((self.nByt
0f90: 65 73 41 72 63 20 2a 20 38 29 20 2d 20 31 29 0a  esArc * 8) - 1).
0fa0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 6c 61          self._la
0fb0: 73 74 41 72 63 4d 61 73 6b 20 3d 20 31 20 3c 3c  stArcMask = 1 <<
0fc0: 20 28 28 73 65 6c 66 2e 6e 42 79 74 65 73 41 72   ((self.nBytesAr
0fd0: 63 20 2a 20 38 29 20 2d 20 32 29 0a 20 20 20 20  c * 8) - 2).    
0fe0: 20 20 20 20 73 65 6c 66 2e 5f 61 64 64 72 42 69      self._addrBi
0ff0: 74 4d 61 73 6b 20 3d 20 31 20 3c 3c 20 28 28 73  tMask = 1 << ((s
1000: 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 20 2a 20  elf.nBytesArc * 
1010: 38 29 20 2d 20 33 29 20 20 23 20 76 65 72 73 69  8) - 3)  # versi
1020: 6f 6e 20 32 0a 0a 20 20 20 20 20 20 20 20 73 65  on 2..        se
1030: 6c 66 2e 6e 42 79 74 65 73 4f 66 66 73 65 74 20  lf.nBytesOffset 
1040: 3d 20 31 20 23 20 76 65 72 73 69 6f 6e 20 33 0a  = 1 # version 3.
1050: 0a 20 20 20 20 20 20 20 20 23 20 43 6f 6e 66 69  .        # Confi
1060: 67 75 72 69 6e 67 20 44 41 57 47 20 66 75 6e 63  guring DAWG func
1070: 74 69 6f 6e 73 20 61 63 63 6f 72 64 69 6e 67 20  tions according 
1080: 74 6f 20 6e 56 65 72 73 69 6f 6e 0a 20 20 20 20  to nVersion.    
1090: 20 20 20 20 69 66 20 73 65 6c 66 2e 6e 56 65 72      if self.nVer
10a0: 73 69 6f 6e 20 3d 3d 20 31 3a 0a 20 20 20 20 20  sion == 1:.     
10b0: 20 20 20 20 20 20 20 73 65 6c 66 2e 6d 6f 72 70         self.morp
10c0: 68 20 3d 20 73 65 6c 66 2e 5f 6d 6f 72 70 68 31  h = self._morph1
10d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c  .            sel
10e0: 66 2e 73 74 65 6d 20 3d 20 73 65 6c 66 2e 5f 73  f.stem = self._s
10f0: 74 65 6d 31 0a 20 20 20 20 20 20 20 20 20 20 20  tem1.           
1100: 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63   self._lookupArc
1110: 4e 6f 64 65 20 3d 20 73 65 6c 66 2e 5f 6c 6f 6f  Node = self._loo
1120: 6b 75 70 41 72 63 4e 6f 64 65 31 0a 20 20 20 20  kupArcNode1.    
1130: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 67 65          self._ge
1140: 74 41 72 63 73 20 3d 20 73 65 6c 66 2e 5f 67 65  tArcs = self._ge
1150: 74 41 72 63 73 31 0a 20 20 20 20 20 20 20 20 20  tArcs1.         
1160: 20 20 20 73 65 6c 66 2e 5f 77 72 69 74 65 4e 6f     self._writeNo
1170: 64 65 73 20 3d 20 73 65 6c 66 2e 5f 77 72 69 74  des = self._writ
1180: 65 4e 6f 64 65 73 31 0a 20 20 20 20 20 20 20 20  eNodes1.        
1190: 65 6c 69 66 20 73 65 6c 66 2e 6e 56 65 72 73 69  elif self.nVersi
11a0: 6f 6e 20 3d 3d 20 32 3a 0a 20 20 20 20 20 20 20  on == 2:.       
11b0: 20 20 20 20 20 73 65 6c 66 2e 6d 6f 72 70 68 20       self.morph 
11c0: 3d 20 73 65 6c 66 2e 5f 6d 6f 72 70 68 32 0a 20  = self._morph2. 
11d0: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
11e0: 73 74 65 6d 20 3d 20 73 65 6c 66 2e 5f 73 74 65  stem = self._ste
11f0: 6d 32 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  m2.            s
1200: 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f  elf._lookupArcNo
1210: 64 65 20 3d 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75  de = self._looku
1220: 70 41 72 63 4e 6f 64 65 32 0a 20 20 20 20 20 20  pArcNode2.      
1230: 20 20 20 20 20 20 73 65 6c 66 2e 5f 67 65 74 41        self._getA
1240: 72 63 73 20 3d 20 73 65 6c 66 2e 5f 67 65 74 41  rcs = self._getA
1250: 72 63 73 32 0a 20 20 20 20 20 20 20 20 20 20 20  rcs2.           
1260: 20 73 65 6c 66 2e 5f 77 72 69 74 65 4e 6f 64 65   self._writeNode
1270: 73 20 3d 20 73 65 6c 66 2e 5f 77 72 69 74 65 4e  s = self._writeN
1280: 6f 64 65 73 32 0a 20 20 20 20 20 20 20 20 65 6c  odes2.        el
1290: 69 66 20 73 65 6c 66 2e 6e 56 65 72 73 69 6f 6e  if self.nVersion
12a0: 20 3d 3d 20 33 3a 0a 20 20 20 20 20 20 20 20 20   == 3:.         
12b0: 20 20 20 73 65 6c 66 2e 6d 6f 72 70 68 20 3d 20     self.morph = 
12c0: 73 65 6c 66 2e 5f 6d 6f 72 70 68 33 0a 20 20 20  self._morph3.   
12d0: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73 74           self.st
12e0: 65 6d 20 3d 20 73 65 6c 66 2e 5f 73 74 65 6d 33  em = self._stem3
12f0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c  .            sel
1300: 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64 65  f._lookupArcNode
1310: 20 3d 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41   = self._lookupA
1320: 72 63 4e 6f 64 65 33 0a 20 20 20 20 20 20 20 20  rcNode3.        
1330: 20 20 20 20 73 65 6c 66 2e 5f 67 65 74 41 72 63      self._getArc
1340: 73 20 3d 20 73 65 6c 66 2e 5f 67 65 74 41 72 63  s = self._getArc
1350: 73 33 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  s3.            s
1360: 65 6c 66 2e 5f 77 72 69 74 65 4e 6f 64 65 73 20  elf._writeNodes 
1370: 3d 20 73 65 6c 66 2e 5f 77 72 69 74 65 4e 6f 64  = self._writeNod
1380: 65 73 33 0a 20 20 20 20 20 20 20 20 65 6c 73 65  es3.        else
1390: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 61  :.            ra
13a0: 69 73 65 20 56 61 6c 75 65 45 72 72 6f 72 28 22  ise ValueError("
13b0: 20 20 23 20 45 72 72 6f 72 3a 20 75 6e 6b 6e 6f    # Error: unkno
13c0: 77 6e 20 63 6f 64 65 3a 20 7b 7d 22 2e 66 6f 72  wn code: {}".for
13d0: 6d 61 74 28 73 65 6c 66 2e 6e 56 65 72 73 69 6f  mat(self.nVersio
13e0: 6e 29 29 0a 0a 20 20 20 20 20 20 20 20 73 65 6c  n))..        sel
13f0: 66 2e 62 4f 70 74 4e 75 6d 53 69 67 6c 65 20 3d  f.bOptNumSigle =
1400: 20 46 61 6c 73 65 0a 20 20 20 20 20 20 20 20 73   False.        s
1410: 65 6c 66 2e 62 4f 70 74 4e 75 6d 41 74 4c 61 73  elf.bOptNumAtLas
1420: 74 20 3d 20 46 61 6c 73 65 0a 0a 20 20 20 20 64  t = False..    d
1430: 65 66 20 67 65 74 49 6e 66 6f 20 28 73 65 6c 66  ef getInfo (self
1440: 29 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  ):.        retur
1450: 6e 20 20 22 20 20 4c 61 6e 67 75 61 67 65 3a 20  n  "  Language: 
1460: 7b 30 2e 73 4c 61 6e 67 3a 3e 31 30 7d 20 20 20  {0.sLang:>10}   
1470: 20 20 20 56 65 72 73 69 6f 6e 3a 20 7b 30 2e 6e     Version: {0.n
1480: 56 65 72 73 69 6f 6e 3a 3e 32 7d 20 20 20 20 20  Version:>2}     
1490: 20 53 74 65 6d 6d 69 6e 67 3a 20 7b 30 2e 63 53   Stemming: {0.cS
14a0: 74 65 6d 6d 69 6e 67 7d 46 58 5c 6e 22 20 5c 0a  temming}FX\n" \.
14b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
14c0: 22 20 20 41 72 63 73 20 76 61 6c 75 65 73 3a 20  "  Arcs values: 
14d0: 20 7b 30 2e 6e 41 72 63 56 61 6c 3a 3e 31 30 2c   {0.nArcVal:>10,
14e0: 7d 20 3d 20 7b 30 2e 6e 43 68 61 72 3a 3e 35 2c  } = {0.nChar:>5,
14f0: 7d 20 63 68 61 72 61 63 74 65 72 73 2c 20 20 7b  } characters,  {
1500: 30 2e 6e 41 66 66 3a 3e 36 2c 7d 20 61 66 66 69  0.nAff:>6,} affi
1510: 78 65 73 2c 20 20 7b 30 2e 6e 54 61 67 3a 3e 36  xes,  {0.nTag:>6
1520: 2c 7d 20 74 61 67 73 5c 6e 22 20 5c 0a 20 20 20  ,} tags\n" \.   
1530: 20 20 20 20 20 20 20 20 20 20 20 20 20 22 20 20               "  
1540: 44 69 63 74 69 6f 6e 61 72 79 3a 20 7b 30 2e 6e  Dictionary: {0.n
1550: 45 6e 74 72 69 65 73 3a 3e 31 32 2c 7d 20 65 6e  Entries:>12,} en
1560: 74 72 69 65 73 2c 20 20 20 20 7b 30 2e 6e 4e 6f  tries,    {0.nNo
1570: 64 65 3a 3e 31 31 2c 7d 20 6e 6f 64 65 73 2c 20  de:>11,} nodes, 
1580: 20 20 7b 30 2e 6e 41 72 63 3a 3e 31 31 2c 7d 20    {0.nArc:>11,} 
1590: 61 72 63 73 5c 6e 22 20 5c 0a 20 20 20 20 20 20  arcs\n" \.      
15a0: 20 20 20 20 20 20 20 20 20 20 22 20 20 41 64 64            "  Add
15b0: 72 65 73 73 20 73 69 7a 65 3a 20 7b 30 2e 6e 42  ress size: {0.nB
15c0: 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 3a  ytesNodeAddress:
15d0: 3e 31 7d 20 62 79 74 65 73 2c 20 20 41 72 63 20  >1} bytes,  Arc 
15e0: 73 69 7a 65 3a 20 7b 30 2e 6e 42 79 74 65 73 41  size: {0.nBytesA
15f0: 72 63 3a 3e 31 7d 20 62 79 74 65 73 5c 6e 22 2e  rc:>1} bytes\n".
1600: 66 6f 72 6d 61 74 28 73 65 6c 66 29 0a 0a 20 20  format(self)..  
1610: 20 20 64 65 66 20 77 72 69 74 65 41 73 4a 53 4f    def writeAsJSO
1620: 62 6a 65 63 74 20 28 73 65 6c 66 2c 20 73 70 66  bject (self, spf
1630: 44 65 73 74 2c 20 62 49 6e 4a 53 4d 6f 64 75 6c  Dest, bInJSModul
1640: 65 3d 46 61 6c 73 65 2c 20 62 42 69 6e 61 72 79  e=False, bBinary
1650: 44 69 63 74 41 73 48 65 78 53 74 72 69 6e 67 3d  DictAsHexString=
1660: 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20 20  False):.        
1670: 22 77 72 69 74 65 20 49 42 44 41 57 47 20 61 73  "write IBDAWG as
1680: 20 61 20 4a 61 76 61 53 63 72 69 70 74 20 6f 62   a JavaScript ob
1690: 6a 65 63 74 20 69 6e 20 61 20 4a 61 76 61 53 63  ject in a JavaSc
16a0: 72 69 70 74 20 6d 6f 64 75 6c 65 22 0a 20 20 20  ript module".   
16b0: 20 20 20 20 20 69 6d 70 6f 72 74 20 6a 73 6f 6e       import json
16c0: 0a 20 20 20 20 20 20 20 20 77 69 74 68 20 6f 70  .        with op
16d0: 65 6e 28 73 70 66 44 65 73 74 2c 20 22 77 22 2c  en(spfDest, "w",
16e0: 20 65 6e 63 6f 64 69 6e 67 3d 22 75 74 66 2d 38   encoding="utf-8
16f0: 22 2c 20 6e 65 77 6c 69 6e 65 3d 22 5c 6e 22 29  ", newline="\n")
1700: 20 61 73 20 68 44 73 74 3a 0a 20 20 20 20 20 20   as hDst:.      
1710: 20 20 20 20 20 20 69 66 20 62 49 6e 4a 53 4d 6f        if bInJSMo
1720: 64 75 6c 65 3a 0a 20 20 20 20 20 20 20 20 20 20  dule:.          
1730: 20 20 20 20 20 20 68 44 73 74 2e 77 72 69 74 65        hDst.write
1740: 28 27 2f 2f 20 4a 61 76 61 53 63 72 69 70 74 5c  ('// JavaScript\
1750: 6e 2f 2f 20 47 65 6e 65 72 61 74 65 64 20 64 61  n// Generated da
1760: 74 61 20 28 64 6f 20 6e 6f 74 20 65 64 69 74 29  ta (do not edit)
1770: 5c 6e 5c 6e 22 75 73 65 20 73 74 72 69 63 74 22  \n\n"use strict"
1780: 3b 5c 6e 5c 6e 63 6f 6e 73 74 20 64 69 63 74 69  ;\n\nconst dicti
1790: 6f 6e 61 72 79 20 3d 20 27 29 0a 20 20 20 20 20  onary = ').     
17a0: 20 20 20 20 20 20 20 68 44 73 74 2e 77 72 69 74         hDst.writ
17b0: 65 28 6a 73 6f 6e 2e 64 75 6d 70 73 28 7b 0a 20  e(json.dumps({. 
17c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
17d0: 20 20 20 20 20 20 20 20 20 20 20 22 73 4e 61 6d             "sNam
17e0: 65 22 3a 20 73 65 6c 66 2e 73 4e 61 6d 65 2c 0a  e": self.sName,.
17f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1800: 20 20 20 20 20 20 20 20 20 20 20 20 22 6e 56 65              "nVe
1810: 72 73 69 6f 6e 22 3a 20 73 65 6c 66 2e 6e 56 65  rsion": self.nVe
1820: 72 73 69 6f 6e 2c 0a 20 20 20 20 20 20 20 20 20  rsion,.         
1830: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1840: 20 20 20 22 73 48 65 61 64 65 72 22 3a 20 73 65     "sHeader": se
1850: 6c 66 2e 73 48 65 61 64 65 72 2c 0a 20 20 20 20  lf.sHeader,.    
1860: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1870: 20 20 20 20 20 20 20 20 22 6c 41 72 63 56 61 6c          "lArcVal
1880: 22 3a 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 2c  ": self.lArcVal,
1890: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
18a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 22 6e 41               "nA
18b0: 72 63 56 61 6c 22 3a 20 73 65 6c 66 2e 6e 41 72  rcVal": self.nAr
18c0: 63 56 61 6c 2c 0a 20 20 20 20 20 20 20 20 20 20  cVal,.          
18d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
18e0: 20 20 23 20 4a 61 76 61 53 63 72 69 70 74 20 69    # JavaScript i
18f0: 73 20 61 20 70 69 6c 65 20 6f 66 20 73 68 69 74  s a pile of shit
1900: 2c 20 73 6f 20 4d 6f 7a 69 6c 6c 61 e2 80 99 73  , so Mozilla...s
1910: 20 4a 53 20 70 61 72 73 65 72 20 64 6f 6e e2 80   JS parser don..
1920: 99 74 20 6c 69 6b 65 20 66 69 6c 65 20 62 69 67  .t like file big
1930: 67 65 72 20 74 68 61 6e 20 34 20 4d 62 21 0a 20  ger than 4 Mb!. 
1940: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1950: 20 20 20 20 20 20 20 20 20 20 20 23 20 53 6f 2c             # So,
1960: 20 69 66 20 6e 65 63 65 73 73 61 72 79 2c 20 77   if necessary, w
1970: 65 20 75 73 65 20 61 6e 20 68 65 78 61 64 65 63  e use an hexadec
1980: 69 6d 61 6c 20 73 74 72 69 6e 67 2c 20 74 68 61  imal string, tha
1990: 74 20 77 65 20 77 69 6c 6c 20 63 6f 6e 76 65 72  t we will conver
19a0: 74 20 6c 61 74 65 72 20 69 6e 20 46 69 72 65 66  t later in Firef
19b0: 6f 78 e2 80 99 73 20 65 78 74 65 6e 73 69 6f 6e  ox...s extension
19c0: 2e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ..              
19d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
19e0: 68 74 74 70 73 3a 2f 2f 67 69 74 68 75 62 2e 63  https://github.c
19f0: 6f 6d 2f 6d 6f 7a 69 6c 6c 61 2f 61 64 64 6f 6e  om/mozilla/addon
1a00: 73 2d 6c 69 6e 74 65 72 2f 69 73 73 75 65 73 2f  s-linter/issues/
1a10: 31 33 36 31 0a 20 20 20 20 20 20 20 20 20 20 20  1361.           
1a20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1a30: 20 22 62 79 44 69 63 22 3a 20 73 65 6c 66 2e 62   "byDic": self.b
1a40: 79 44 69 63 2e 68 65 78 28 29 20 20 69 66 20 62  yDic.hex()  if b
1a50: 42 69 6e 61 72 79 44 69 63 74 41 73 48 65 78 53  BinaryDictAsHexS
1a60: 74 72 69 6e 67 20 20 65 6c 73 65 20 5b 20 65 20  tring  else [ e 
1a70: 20 66 6f 72 20 65 20 69 6e 20 73 65 6c 66 2e 62   for e in self.b
1a80: 79 44 69 63 20 5d 2c 0a 20 20 20 20 20 20 20 20  yDic ],.        
1a90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1aa0: 20 20 20 20 22 73 4c 61 6e 67 22 3a 20 73 65 6c      "sLang": sel
1ab0: 66 2e 73 4c 61 6e 67 2c 0a 20 20 20 20 20 20 20  f.sLang,.       
1ac0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ad0: 20 20 20 20 20 22 6e 43 68 61 72 22 3a 20 73 65       "nChar": se
1ae0: 6c 66 2e 6e 43 68 61 72 2c 0a 20 20 20 20 20 20  lf.nChar,.      
1af0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b00: 20 20 20 20 20 20 22 6e 42 79 74 65 73 41 72 63        "nBytesArc
1b10: 22 3a 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72  ": self.nBytesAr
1b20: 63 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  c,.             
1b30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22                 "
1b40: 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73  nBytesNodeAddres
1b50: 73 22 3a 20 73 65 6c 66 2e 6e 42 79 74 65 73 4e  s": self.nBytesN
1b60: 6f 64 65 41 64 64 72 65 73 73 2c 0a 20 20 20 20  odeAddress,.    
1b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b80: 20 20 20 20 20 20 20 20 22 6e 45 6e 74 72 69 65          "nEntrie
1b90: 73 22 3a 20 73 65 6c 66 2e 6e 45 6e 74 72 69 65  s": self.nEntrie
1ba0: 73 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  s,.             
1bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22                 "
1bc0: 6e 4e 6f 64 65 22 3a 20 73 65 6c 66 2e 6e 4e 6f  nNode": self.nNo
1bd0: 64 65 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  de,.            
1be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1bf0: 22 6e 41 72 63 22 3a 20 73 65 6c 66 2e 6e 41 72  "nArc": self.nAr
1c00: 63 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  c,.             
1c10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22                 "
1c20: 6e 41 66 66 22 3a 20 73 65 6c 66 2e 6e 41 66 66  nAff": self.nAff
1c30: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
1c40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 63                "c
1c50: 53 74 65 6d 6d 69 6e 67 22 3a 20 73 65 6c 66 2e  Stemming": self.
1c60: 63 53 74 65 6d 6d 69 6e 67 2c 0a 20 20 20 20 20  cStemming,.     
1c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c80: 20 20 20 20 20 20 20 22 6e 54 61 67 22 3a 20 73         "nTag": s
1c90: 65 6c 66 2e 6e 54 61 67 2c 0a 20 20 20 20 20 20  elf.nTag,.      
1ca0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1cb0: 20 20 20 20 20 20 22 64 43 68 61 72 22 3a 20 73        "dChar": s
1cc0: 65 6c 66 2e 64 43 68 61 72 2c 0a 20 20 20 20 20  elf.dChar,.     
1cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ce0: 20 20 20 20 20 20 20 22 5f 61 72 63 4d 61 73 6b         "_arcMask
1cf0: 22 3a 20 73 65 6c 66 2e 5f 61 72 63 4d 61 73 6b  ": self._arcMask
1d00: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
1d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 5f                "_
1d20: 66 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b 22 3a 20  finalNodeMask": 
1d30: 73 65 6c 66 2e 5f 66 69 6e 61 6c 4e 6f 64 65 4d  self._finalNodeM
1d40: 61 73 6b 2c 0a 20 20 20 20 20 20 20 20 20 20 20  ask,.           
1d50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d60: 20 22 5f 6c 61 73 74 41 72 63 4d 61 73 6b 22 3a   "_lastArcMask":
1d70: 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61   self._lastArcMa
1d80: 73 6b 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  sk,.            
1d90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1da0: 22 5f 61 64 64 72 42 69 74 4d 61 73 6b 22 3a 20  "_addrBitMask": 
1db0: 73 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73  self._addrBitMas
1dc0: 6b 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  k,.             
1dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22                 "
1de0: 6e 42 79 74 65 73 4f 66 66 73 65 74 22 3a 20 73  nBytesOffset": s
1df0: 65 6c 66 2e 6e 42 79 74 65 73 4f 66 66 73 65 74  elf.nBytesOffset
1e00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1e10: 20 20 20 20 20 20 20 20 20 7d 2c 20 65 6e 73 75           }, ensu
1e20: 72 65 5f 61 73 63 69 69 3d 46 61 6c 73 65 29 29  re_ascii=False))
1e30: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
1e40: 62 49 6e 4a 53 4d 6f 64 75 6c 65 3a 0a 20 20 20  bInJSModule:.   
1e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 68 44 73               hDs
1e60: 74 2e 77 72 69 74 65 28 22 3b 5c 6e 5c 6e 65 78  t.write(";\n\nex
1e70: 70 6f 72 74 73 2e 64 69 63 74 69 6f 6e 61 72 79  ports.dictionary
1e80: 20 3d 20 64 69 63 74 69 6f 6e 61 72 79 3b 5c 6e   = dictionary;\n
1e90: 22 29 0a 0a 20 20 20 20 64 65 66 20 69 73 56 61  ")..    def isVa
1ea0: 6c 69 64 54 6f 6b 65 6e 20 28 73 65 6c 66 2c 20  lidToken (self, 
1eb0: 73 54 6f 6b 65 6e 29 3a 0a 20 20 20 20 20 20 20  sToken):.       
1ec0: 20 22 63 68 65 63 6b 73 20 69 66 20 3c 73 54 6f   "checks if <sTo
1ed0: 6b 65 6e 3e 20 69 73 20 76 61 6c 69 64 20 28 69  ken> is valid (i
1ee0: 66 20 74 68 65 72 65 20 69 73 20 68 79 70 68 65  f there is hyphe
1ef0: 6e 73 20 69 6e 20 3c 73 54 6f 6b 65 6e 3e 2c 20  ns in <sToken>, 
1f00: 3c 73 54 6f 6b 65 6e 3e 20 69 73 20 73 70 6c 69  <sToken> is spli
1f10: 74 2c 20 65 61 63 68 20 70 61 72 74 20 69 73 20  t, each part is 
1f20: 63 68 65 63 6b 65 64 29 22 0a 20 20 20 20 20 20  checked)".      
1f30: 20 20 69 66 20 73 65 6c 66 2e 69 73 56 61 6c 69    if self.isVali
1f40: 64 28 73 54 6f 6b 65 6e 29 3a 0a 20 20 20 20 20  d(sToken):.     
1f50: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54 72         return Tr
1f60: 75 65 0a 20 20 20 20 20 20 20 20 69 66 20 22 2d  ue.        if "-
1f70: 22 20 69 6e 20 73 54 6f 6b 65 6e 3a 0a 20 20 20  " in sToken:.   
1f80: 20 20 20 20 20 20 20 20 20 69 66 20 73 54 6f 6b           if sTok
1f90: 65 6e 2e 63 6f 75 6e 74 28 22 2d 22 29 20 3e 20  en.count("-") > 
1fa0: 34 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  4:.             
1fb0: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
1fc0: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
1fd0: 6e 20 61 6c 6c 28 73 65 6c 66 2e 69 73 56 61 6c  n all(self.isVal
1fe0: 69 64 28 73 57 6f 72 64 29 20 20 66 6f 72 20 73  id(sWord)  for s
1ff0: 57 6f 72 64 20 69 6e 20 73 54 6f 6b 65 6e 2e 73  Word in sToken.s
2000: 70 6c 69 74 28 22 2d 22 29 29 0a 20 20 20 20 20  plit("-")).     
2010: 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a     return False.
2020: 0a 20 20 20 20 64 65 66 20 69 73 56 61 6c 69 64  .    def isValid
2030: 20 28 73 65 6c 66 2c 20 73 57 6f 72 64 29 3a 0a   (self, sWord):.
2040: 20 20 20 20 20 20 20 20 22 63 68 65 63 6b 73 20          "checks 
2050: 69 66 20 3c 73 57 6f 72 64 3e 20 69 73 20 76 61  if <sWord> is va
2060: 6c 69 64 20 28 64 69 66 66 65 72 65 6e 74 20 63  lid (different c
2070: 61 73 69 6e 67 20 74 65 73 74 65 64 20 69 66 20  asing tested if 
2080: 74 68 65 20 66 69 72 73 74 20 6c 65 74 74 65 72  the first letter
2090: 20 69 73 20 61 20 63 61 70 69 74 61 6c 29 22 0a   is a capital)".
20a0: 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 73          if not s
20b0: 57 6f 72 64 3a 0a 20 20 20 20 20 20 20 20 20 20  Word:.          
20c0: 20 20 72 65 74 75 72 6e 20 4e 6f 6e 65 0a 20 20    return None.  
20d0: 20 20 20 20 20 20 69 66 20 22 e2 80 99 22 20 69        if "..." i
20e0: 6e 20 73 57 6f 72 64 3a 20 23 20 75 67 6c 79 20  n sWord: # ugly 
20f0: 68 61 63 6b 0a 20 20 20 20 20 20 20 20 20 20 20  hack.           
2100: 20 73 57 6f 72 64 20 3d 20 73 57 6f 72 64 2e 72   sWord = sWord.r
2110: 65 70 6c 61 63 65 28 22 e2 80 99 22 2c 20 22 27  eplace("...", "'
2120: 22 29 0a 20 20 20 20 20 20 20 20 69 66 20 73 65  ").        if se
2130: 6c 66 2e 6c 6f 6f 6b 75 70 28 73 57 6f 72 64 29  lf.lookup(sWord)
2140: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  :.            re
2150: 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 20 20  turn True.      
2160: 20 20 69 66 20 73 57 6f 72 64 5b 30 3a 31 5d 2e    if sWord[0:1].
2170: 69 73 75 70 70 65 72 28 29 3a 0a 20 20 20 20 20  isupper():.     
2180: 20 20 20 20 20 20 20 69 66 20 6c 65 6e 28 73 57         if len(sW
2190: 6f 72 64 29 20 3e 20 31 3a 0a 20 20 20 20 20 20  ord) > 1:.      
21a0: 20 20 20 20 20 20 20 20 20 20 69 66 20 73 57 6f            if sWo
21b0: 72 64 2e 69 73 74 69 74 6c 65 28 29 3a 0a 20 20  rd.istitle():.  
21c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
21d0: 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 6c 6f    return self.lo
21e0: 6f 6b 75 70 28 73 57 6f 72 64 2e 6c 6f 77 65 72  okup(sWord.lower
21f0: 28 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ()).            
2200: 20 20 20 20 69 66 20 73 57 6f 72 64 2e 69 73 75      if sWord.isu
2210: 70 70 65 72 28 29 3a 0a 20 20 20 20 20 20 20 20  pper():.        
2220: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73              if s
2230: 65 6c 66 2e 62 4f 70 74 4e 75 6d 53 69 67 6c 65  elf.bOptNumSigle
2240: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
2250: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
2260: 20 54 72 75 65 0a 20 20 20 20 20 20 20 20 20 20   True.          
2270: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
2280: 20 73 65 6c 66 2e 6c 6f 6f 6b 75 70 28 73 57 6f   self.lookup(sWo
2290: 72 64 2e 6c 6f 77 65 72 28 29 29 20 6f 72 20 73  rd.lower()) or s
22a0: 65 6c 66 2e 6c 6f 6f 6b 75 70 28 73 57 6f 72 64  elf.lookup(sWord
22b0: 2e 63 61 70 69 74 61 6c 69 7a 65 28 29 29 0a 20  .capitalize()). 
22c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72                 r
22d0: 65 74 75 72 6e 20 73 65 6c 66 2e 6c 6f 6f 6b 75  eturn self.looku
22e0: 70 28 73 57 6f 72 64 5b 3a 31 5d 2e 6c 6f 77 65  p(sWord[:1].lowe
22f0: 72 28 29 20 2b 20 73 57 6f 72 64 5b 31 3a 5d 29  r() + sWord[1:])
2300: 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73  .            els
2310: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
2320: 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 6c     return self.l
2330: 6f 6f 6b 75 70 28 73 57 6f 72 64 2e 6c 6f 77 65  ookup(sWord.lowe
2340: 72 28 29 29 0a 20 20 20 20 20 20 20 20 72 65 74  r()).        ret
2350: 75 72 6e 20 46 61 6c 73 65 0a 0a 20 20 20 20 64  urn False..    d
2360: 65 66 20 6c 6f 6f 6b 75 70 20 28 73 65 6c 66 2c  ef lookup (self,
2370: 20 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20 20   sWord):.       
2380: 20 22 72 65 74 75 72 6e 73 20 54 72 75 65 20 69   "returns True i
2390: 66 20 3c 73 57 6f 72 64 3e 20 69 6e 20 64 69 63  f <sWord> in dic
23a0: 74 69 6f 6e 61 72 79 20 28 73 74 72 69 63 74 20  tionary (strict 
23b0: 76 65 72 69 66 69 63 61 74 69 6f 6e 29 22 0a 20  verification)". 
23c0: 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 30         iAddr = 0
23d0: 0a 20 20 20 20 20 20 20 20 66 6f 72 20 63 20 69  .        for c i
23e0: 6e 20 73 57 6f 72 64 3a 0a 20 20 20 20 20 20 20  n sWord:.       
23f0: 20 20 20 20 20 69 66 20 63 20 6e 6f 74 20 69 6e       if c not in
2400: 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a 20 20 20   self.dChar:.   
2410: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74               ret
2420: 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 20 20  urn False.      
2430: 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 73 65        iAddr = se
2440: 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64  lf._lookupArcNod
2450: 65 28 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d 2c  e(self.dChar[c],
2460: 20 69 41 64 64 72 29 0a 20 20 20 20 20 20 20 20   iAddr).        
2470: 20 20 20 20 69 66 20 69 41 64 64 72 20 3d 3d 20      if iAddr == 
2480: 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 20 20  None:.          
2490: 20 20 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c        return Fal
24a0: 73 65 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  se.        retur
24b0: 6e 20 62 6f 6f 6c 28 69 6e 74 2e 66 72 6f 6d 5f  n bool(int.from_
24c0: 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63  bytes(self.byDic
24d0: 5b 69 41 64 64 72 3a 69 41 64 64 72 2b 73 65 6c  [iAddr:iAddr+sel
24e0: 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20 62 79  f.nBytesArc], by
24f0: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 20 26  teorder='big') &
2500: 20 73 65 6c 66 2e 5f 66 69 6e 61 6c 4e 6f 64 65   self._finalNode
2510: 4d 61 73 6b 29 0a 0a 20 20 20 20 64 65 66 20 67  Mask)..    def g
2520: 65 74 4d 6f 72 70 68 20 28 73 65 6c 66 2c 20 73  etMorph (self, s
2530: 57 6f 72 64 29 3a 0a 20 20 20 20 20 20 20 20 22  Word):.        "
2540: 72 65 74 72 69 65 76 65 73 20 6d 6f 72 70 68 6f  retrieves morpho
2550: 6c 6f 67 69 65 73 20 6c 69 73 74 2c 20 64 69 66  logies list, dif
2560: 66 65 72 65 6e 74 20 63 61 73 69 6e 67 20 61 6c  ferent casing al
2570: 6c 6f 77 65 64 22 0a 20 20 20 20 20 20 20 20 6c  lowed".        l
2580: 20 3d 20 73 65 6c 66 2e 6d 6f 72 70 68 28 73 57   = self.morph(sW
2590: 6f 72 64 29 0a 20 20 20 20 20 20 20 20 69 66 20  ord).        if 
25a0: 73 57 6f 72 64 5b 30 3a 31 5d 2e 69 73 75 70 70  sWord[0:1].isupp
25b0: 65 72 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20  er():.          
25c0: 20 20 6c 2e 65 78 74 65 6e 64 28 73 65 6c 66 2e    l.extend(self.
25d0: 6d 6f 72 70 68 28 73 57 6f 72 64 2e 6c 6f 77 65  morph(sWord.lowe
25e0: 72 28 29 29 29 0a 20 20 20 20 20 20 20 20 20 20  r())).          
25f0: 20 20 69 66 20 73 57 6f 72 64 2e 69 73 75 70 70    if sWord.isupp
2600: 65 72 28 29 20 61 6e 64 20 6c 65 6e 28 73 57 6f  er() and len(sWo
2610: 72 64 29 20 3e 20 31 3a 0a 20 20 20 20 20 20 20  rd) > 1:.       
2620: 20 20 20 20 20 20 20 20 20 6c 2e 65 78 74 65 6e           l.exten
2630: 64 28 73 65 6c 66 2e 6d 6f 72 70 68 28 73 57 6f  d(self.morph(sWo
2640: 72 64 2e 63 61 70 69 74 61 6c 69 7a 65 28 29 29  rd.capitalize())
2650: 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ).        return
2660: 20 6c 0a 0a 20 20 20 20 40 74 69 6d 65 74 68 69   l..    @timethi
2670: 73 0a 20 20 20 20 64 65 66 20 73 75 67 67 65 73  s.    def sugges
2680: 74 20 28 73 65 6c 66 2c 20 73 57 6f 72 64 2c 20  t (self, sWord, 
2690: 6e 4d 61 78 53 75 67 67 3d 31 30 29 3a 0a 20 20  nMaxSugg=10):.  
26a0: 20 20 20 20 20 20 22 72 65 74 75 72 6e 73 20 61        "returns a
26b0: 20 73 65 74 20 6f 66 20 73 75 67 67 65 73 74 69   set of suggesti
26c0: 6f 6e 73 20 66 6f 72 20 3c 73 57 6f 72 64 3e 22  ons for <sWord>"
26d0: 0a 20 20 20 20 20 20 20 20 73 50 66 78 2c 20 73  .        sPfx, s
26e0: 57 6f 72 64 2c 20 73 53 66 78 20 3d 20 63 70 2e  Word, sSfx = cp.
26f0: 63 75 74 28 73 57 6f 72 64 29 0a 20 20 20 20 20  cut(sWord).     
2700: 20 20 20 6e 4d 61 78 44 65 6c 20 3d 20 6c 65 6e     nMaxDel = len
2710: 28 73 57 6f 72 64 29 20 2f 2f 20 35 0a 20 20 20  (sWord) // 5.   
2720: 20 20 20 20 20 6e 4d 61 78 48 61 72 64 52 65 70       nMaxHardRep
2730: 6c 20 3d 20 6d 61 78 28 28 6c 65 6e 28 73 57 6f  l = max((len(sWo
2740: 72 64 29 20 2d 20 35 29 20 2f 2f 20 34 2c 20 31  rd) - 5) // 4, 1
2750: 29 0a 20 20 20 20 20 20 20 20 6f 53 75 67 67 52  ).        oSuggR
2760: 65 73 75 6c 74 20 3d 20 53 75 67 67 52 65 73 75  esult = SuggResu
2770: 6c 74 28 73 57 6f 72 64 29 0a 20 20 20 20 20 20  lt(sWord).      
2780: 20 20 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28    self._suggest(
2790: 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 73 57 6f  oSuggResult, sWo
27a0: 72 64 2c 20 6e 4d 61 78 44 65 6c 3d 6e 4d 61 78  rd, nMaxDel=nMax
27b0: 44 65 6c 2c 20 6e 4d 61 78 48 61 72 64 52 65 70  Del, nMaxHardRep
27c0: 6c 3d 6e 4d 61 78 48 61 72 64 52 65 70 6c 29 0a  l=nMaxHardRepl).
27d0: 20 20 20 20 20 20 20 20 69 66 20 73 57 6f 72 64          if sWord
27e0: 2e 69 73 74 69 74 6c 65 28 29 3a 0a 20 20 20 20  .istitle():.    
27f0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73 75          self._su
2800: 67 67 65 73 74 28 6f 53 75 67 67 52 65 73 75 6c  ggest(oSuggResul
2810: 74 2c 20 73 57 6f 72 64 2e 6c 6f 77 65 72 28 29  t, sWord.lower()
2820: 2c 20 6e 4d 61 78 44 65 6c 3d 6e 4d 61 78 44 65  , nMaxDel=nMaxDe
2830: 6c 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 3d  l, nMaxHardRepl=
2840: 6e 4d 61 78 48 61 72 64 52 65 70 6c 29 0a 20 20  nMaxHardRepl).  
2850: 20 20 20 20 20 20 65 6c 69 66 20 73 57 6f 72 64        elif sWord
2860: 2e 69 73 6c 6f 77 65 72 28 29 3a 0a 20 20 20 20  .islower():.    
2870: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73 75          self._su
2880: 67 67 65 73 74 28 6f 53 75 67 67 52 65 73 75 6c  ggest(oSuggResul
2890: 74 2c 20 73 57 6f 72 64 2e 74 69 74 6c 65 28 29  t, sWord.title()
28a0: 2c 20 6e 4d 61 78 44 65 6c 3d 6e 4d 61 78 44 65  , nMaxDel=nMaxDe
28b0: 6c 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 3d  l, nMaxHardRepl=
28c0: 6e 4d 61 78 48 61 72 64 52 65 70 6c 29 0a 20 20  nMaxHardRepl).  
28d0: 20 20 20 20 20 20 61 53 75 67 67 20 3d 20 6f 53        aSugg = oS
28e0: 75 67 67 52 65 73 75 6c 74 2e 67 65 74 53 75 67  uggResult.getSug
28f0: 67 65 73 74 69 6f 6e 73 28 29 0a 20 20 20 20 20  gestions().     
2900: 20 20 20 69 66 20 73 53 66 78 20 6f 72 20 73 50     if sSfx or sP
2910: 66 78 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  fx:.            
2920: 23 20 77 65 20 61 64 64 20 77 68 61 74 20 77 65  # we add what we
2930: 20 72 65 6d 6f 76 65 64 0a 20 20 20 20 20 20 20   removed.       
2940: 20 20 20 20 20 72 65 74 75 72 6e 20 6c 69 73 74       return list
2950: 28 6d 61 70 28 6c 61 6d 62 64 61 20 73 53 75 67  (map(lambda sSug
2960: 3a 20 73 50 66 78 20 2b 20 73 53 75 67 20 2b 20  : sPfx + sSug + 
2970: 73 53 66 78 2c 20 61 53 75 67 67 29 29 0a 20 20  sSfx, aSugg)).  
2980: 20 20 20 20 20 20 72 65 74 75 72 6e 20 61 53 75        return aSu
2990: 67 67 0a 0a 20 20 20 20 64 65 66 20 5f 73 75 67  gg..    def _sug
29a0: 67 65 73 74 20 28 73 65 6c 66 2c 20 6f 53 75 67  gest (self, oSug
29b0: 67 52 65 73 75 6c 74 2c 20 73 52 65 6d 61 69 6e  gResult, sRemain
29c0: 2c 20 6e 4d 61 78 44 65 6c 3d 30 2c 20 6e 4d 61  , nMaxDel=0, nMa
29d0: 78 48 61 72 64 52 65 70 6c 3d 30 2c 20 6e 44 65  xHardRepl=0, nDe
29e0: 65 70 3d 30 2c 20 69 41 64 64 72 3d 30 2c 20 73  ep=0, iAddr=0, s
29f0: 4e 65 77 57 6f 72 64 3d 22 22 2c 20 73 41 63 74  NewWord="", sAct
2a00: 69 6f 6e 3d 22 22 2c 20 62 41 76 6f 69 64 4c 6f  ion="", bAvoidLo
2a10: 6f 70 3d 46 61 6c 73 65 29 3a 0a 20 20 20 20 20  op=False):.     
2a20: 20 20 20 22 72 65 74 75 72 6e 73 20 61 20 73 65     "returns a se
2a30: 74 20 6f 66 20 73 75 67 67 65 73 74 69 6f 6e 73  t of suggestions
2a40: 22 0a 20 20 20 20 20 20 20 20 23 20 72 65 63 75  ".        # recu
2a50: 72 73 69 76 65 20 66 75 6e 63 74 69 6f 6e 0a 20  rsive function. 
2a60: 20 20 20 20 20 20 20 23 6c 6f 67 67 69 6e 67 2e         #logging.
2a70: 69 6e 66 6f 28 28 6e 44 65 65 70 20 2a 20 22 20  info((nDeep * " 
2a80: 20 22 29 20 2b 20 73 4e 65 77 57 6f 72 64 20 2b   ") + sNewWord +
2a90: 20 22 3a 22 20 2b 20 73 52 65 6d 61 69 6e 20 2b   ":" + sRemain +
2aa0: 20 22 20 c2 b7 20 22 20 2b 20 73 41 63 74 69 6f   " .. " + sActio
2ab0: 6e 29 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f  n).        if no
2ac0: 74 20 73 52 65 6d 61 69 6e 3a 0a 20 20 20 20 20  t sRemain:.     
2ad0: 20 20 20 20 20 20 20 69 66 20 69 6e 74 2e 66 72         if int.fr
2ae0: 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79  om_bytes(self.by
2af0: 44 69 63 5b 69 41 64 64 72 3a 69 41 64 64 72 2b  Dic[iAddr:iAddr+
2b00: 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c  self.nBytesArc],
2b10: 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27   byteorder='big'
2b20: 29 20 26 20 73 65 6c 66 2e 5f 66 69 6e 61 6c 4e  ) & self._finalN
2b30: 6f 64 65 4d 61 73 6b 3a 0a 20 20 20 20 20 20 20  odeMask:.       
2b40: 20 20 20 20 20 20 20 20 20 23 6c 6f 67 67 69 6e           #loggin
2b50: 67 2e 69 6e 66 6f 28 28 6e 44 65 65 70 20 2a 20  g.info((nDeep * 
2b60: 22 20 20 22 29 20 2b 20 22 5f 5f 22 20 2b 20 73  "  ") + "__" + s
2b70: 4e 65 77 57 6f 72 64 20 2b 20 22 5f 5f 22 29 0a  NewWord + "__").
2b80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2b90: 6f 53 75 67 67 52 65 73 75 6c 74 2e 61 64 64 53  oSuggResult.addS
2ba0: 75 67 67 28 73 4e 65 77 57 6f 72 64 29 0a 20 20  ugg(sNewWord).  
2bb0: 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 73 54            for sT
2bc0: 61 69 6c 20 69 6e 20 73 65 6c 66 2e 5f 67 65 74  ail in self._get
2bd0: 54 61 69 6c 73 28 69 41 64 64 72 29 3a 0a 20 20  Tails(iAddr):.  
2be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 6c                #l
2bf0: 6f 67 67 69 6e 67 2e 69 6e 66 6f 28 28 6e 44 65  ogging.info((nDe
2c00: 65 70 20 2a 20 22 20 20 22 29 20 2b 20 22 5f 5f  ep * "  ") + "__
2c10: 22 20 2b 20 73 4e 65 77 57 6f 72 64 2b 73 54 61  " + sNewWord+sTa
2c20: 69 6c 20 2b 20 22 5f 5f 22 29 0a 20 20 20 20 20  il + "__").     
2c30: 20 20 20 20 20 20 20 20 20 20 20 6f 53 75 67 67             oSugg
2c40: 52 65 73 75 6c 74 2e 61 64 64 53 75 67 67 28 73  Result.addSugg(s
2c50: 4e 65 77 57 6f 72 64 2b 73 54 61 69 6c 29 0a 20  NewWord+sTail). 
2c60: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
2c70: 6e 0a 20 20 20 20 20 20 20 20 63 43 75 72 72 65  n.        cCurre
2c80: 6e 74 20 3d 20 73 52 65 6d 61 69 6e 5b 30 3a 31  nt = sRemain[0:1
2c90: 5d 0a 20 20 20 20 20 20 20 20 66 6f 72 20 63 43  ].        for cC
2ca0: 68 61 72 2c 20 6a 41 64 64 72 20 69 6e 20 73 65  har, jAddr in se
2cb0: 6c 66 2e 5f 67 65 74 53 69 6d 69 6c 61 72 41 72  lf._getSimilarAr
2cc0: 63 73 28 63 43 75 72 72 65 6e 74 2c 20 69 41 64  cs(cCurrent, iAd
2cd0: 64 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  dr):.           
2ce0: 20 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28 6f   self._suggest(o
2cf0: 53 75 67 67 52 65 73 75 6c 74 2c 20 73 52 65 6d  SuggResult, sRem
2d00: 61 69 6e 5b 31 3a 5d 2c 20 6e 4d 61 78 44 65 6c  ain[1:], nMaxDel
2d10: 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 2c 20  , nMaxHardRepl, 
2d20: 6e 44 65 65 70 2b 31 2c 20 6a 41 64 64 72 2c 20  nDeep+1, jAddr, 
2d30: 73 4e 65 77 57 6f 72 64 2b 63 43 68 61 72 2c 20  sNewWord+cChar, 
2d40: 22 2a 22 29 0a 20 20 20 20 20 20 20 20 69 66 20  "*").        if 
2d50: 6e 6f 74 20 62 41 76 6f 69 64 4c 6f 6f 70 3a 20  not bAvoidLoop: 
2d60: 23 20 61 76 6f 69 64 20 69 6e 66 69 6e 69 74 65  # avoid infinite
2d70: 20 6c 6f 6f 70 0a 20 20 20 20 20 20 20 20 20 20   loop.          
2d80: 20 20 69 66 20 63 43 75 72 72 65 6e 74 20 3d 3d    if cCurrent ==
2d90: 20 73 52 65 6d 61 69 6e 5b 31 3a 32 5d 3a 0a 20   sRemain[1:2]:. 
2da0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
2db0: 20 73 61 6d 65 20 63 68 61 72 2c 20 77 65 20 72   same char, we r
2dc0: 65 6d 6f 76 65 20 31 20 63 68 61 72 20 77 69 74  emove 1 char wit
2dd0: 68 6f 75 74 20 61 64 64 69 6e 67 20 31 20 74 6f  hout adding 1 to
2de0: 20 3c 73 4e 65 77 57 6f 72 64 3e 0a 20 20 20 20   <sNewWord>.    
2df0: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
2e00: 2e 5f 73 75 67 67 65 73 74 28 6f 53 75 67 67 52  ._suggest(oSuggR
2e10: 65 73 75 6c 74 2c 20 73 52 65 6d 61 69 6e 5b 31  esult, sRemain[1
2e20: 3a 5d 2c 20 6e 4d 61 78 44 65 6c 2c 20 6e 4d 61  :], nMaxDel, nMa
2e30: 78 48 61 72 64 52 65 70 6c 2c 20 6e 44 65 65 70  xHardRepl, nDeep
2e40: 2b 31 2c 20 69 41 64 64 72 2c 20 73 4e 65 77 57  +1, iAddr, sNewW
2e50: 6f 72 64 2c 20 63 43 75 72 72 65 6e 74 2b 22 2f  ord, cCurrent+"/
2e60: 32 22 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  2").            
2e70: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
2e80: 20 20 20 20 20 20 23 20 73 77 69 74 63 68 69 6e        # switchin
2e90: 67 20 63 68 61 72 73 0a 20 20 20 20 20 20 20 20  g chars.        
2ea0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73 75          self._su
2eb0: 67 67 65 73 74 28 6f 53 75 67 67 52 65 73 75 6c  ggest(oSuggResul
2ec0: 74 2c 20 73 52 65 6d 61 69 6e 5b 31 3a 32 5d 2b  t, sRemain[1:2]+
2ed0: 73 52 65 6d 61 69 6e 5b 30 3a 31 5d 2b 73 52 65  sRemain[0:1]+sRe
2ee0: 6d 61 69 6e 5b 32 3a 5d 2c 20 6e 4d 61 78 44 65  main[2:], nMaxDe
2ef0: 6c 2c 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 2c  l, nMaxHardRepl,
2f00: 20 6e 44 65 65 70 2b 31 2c 20 69 41 64 64 72 2c   nDeep+1, iAddr,
2f10: 20 73 4e 65 77 57 6f 72 64 2c 20 22 3e 3c 22 2c   sNewWord, "><",
2f20: 54 72 75 65 29 0a 20 20 20 20 20 20 20 20 20 20  True).          
2f30: 20 20 20 20 20 20 23 20 64 65 6c 65 74 65 20 63        # delete c
2f40: 68 61 72 0a 20 20 20 20 20 20 20 20 20 20 20 20  har.            
2f50: 20 20 20 20 69 66 20 6e 4d 61 78 44 65 6c 20 3e      if nMaxDel >
2f60: 20 30 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20   0:.            
2f70: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73 75          self._su
2f80: 67 67 65 73 74 28 6f 53 75 67 67 52 65 73 75 6c  ggest(oSuggResul
2f90: 74 2c 20 73 52 65 6d 61 69 6e 5b 31 3a 5d 2c 20  t, sRemain[1:], 
2fa0: 6e 4d 61 78 44 65 6c 2d 31 2c 20 6e 4d 61 78 48  nMaxDel-1, nMaxH
2fb0: 61 72 64 52 65 70 6c 2c 20 6e 44 65 65 70 2b 31  ardRepl, nDeep+1
2fc0: 2c 20 69 41 64 64 72 2c 20 73 4e 65 77 57 6f 72  , iAddr, sNewWor
2fd0: 64 2c 20 22 2d 22 2b 63 43 75 72 72 65 6e 74 2c  d, "-"+cCurrent,
2fe0: 20 54 72 75 65 29 0a 20 20 20 20 20 20 20 20 20   True).         
2ff0: 20 20 20 23 20 50 68 6f 6e 65 74 69 63 20 72 65     # Phonetic re
3000: 70 6c 61 63 65 6d 65 6e 74 73 0a 20 20 20 20 20  placements.     
3010: 20 20 20 20 20 20 20 66 6f 72 20 73 52 65 70 6c         for sRepl
3020: 20 69 6e 20 63 70 2e 64 31 74 6f 58 2e 67 65 74   in cp.d1toX.get
3030: 28 63 43 75 72 72 65 6e 74 2c 20 28 29 29 3a 0a  (cCurrent, ()):.
3040: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3050: 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28 6f 53  self._suggest(oS
3060: 75 67 67 52 65 73 75 6c 74 2c 20 73 52 65 70 6c  uggResult, sRepl
3070: 20 2b 20 73 52 65 6d 61 69 6e 5b 31 3a 5d 2c 20   + sRemain[1:], 
3080: 6e 4d 61 78 44 65 6c 2c 20 6e 4d 61 78 48 61 72  nMaxDel, nMaxHar
3090: 64 52 65 70 6c 2c 20 6e 44 65 65 70 2b 31 2c 20  dRepl, nDeep+1, 
30a0: 69 41 64 64 72 2c 20 73 4e 65 77 57 6f 72 64 2c  iAddr, sNewWord,
30b0: 20 63 43 75 72 72 65 6e 74 2b 22 3e 22 2b 73 52   cCurrent+">"+sR
30c0: 65 70 6c 2c 20 54 72 75 65 29 0a 20 20 20 20 20  epl, True).     
30d0: 20 20 20 20 20 20 20 66 6f 72 20 73 52 65 70 6c         for sRepl
30e0: 20 69 6e 20 63 70 2e 64 32 74 6f 58 2e 67 65 74   in cp.d2toX.get
30f0: 28 73 52 65 6d 61 69 6e 5b 30 3a 32 5d 2c 20 28  (sRemain[0:2], (
3100: 29 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  )):.            
3110: 20 20 20 20 73 65 6c 66 2e 5f 73 75 67 67 65 73      self._sugges
3120: 74 28 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 73  t(oSuggResult, s
3130: 52 65 70 6c 20 2b 20 73 52 65 6d 61 69 6e 5b 32  Repl + sRemain[2
3140: 3a 5d 2c 20 6e 4d 61 78 44 65 6c 2c 20 6e 4d 61  :], nMaxDel, nMa
3150: 78 48 61 72 64 52 65 70 6c 2c 20 6e 44 65 65 70  xHardRepl, nDeep
3160: 2b 31 2c 20 69 41 64 64 72 2c 20 73 4e 65 77 57  +1, iAddr, sNewW
3170: 6f 72 64 2c 20 73 52 65 6d 61 69 6e 5b 30 3a 32  ord, sRemain[0:2
3180: 5d 2b 22 3e 22 2b 73 52 65 70 6c 2c 20 54 72 75  ]+">"+sRepl, Tru
3190: 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 23  e).            #
31a0: 20 48 61 72 64 20 72 65 70 6c 61 63 65 6d 65 6e   Hard replacemen
31b0: 74 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  ts.            i
31c0: 66 20 6e 44 65 65 70 20 3e 20 33 20 61 6e 64 20  f nDeep > 3 and 
31d0: 6e 4d 61 78 48 61 72 64 52 65 70 6c 20 61 6e 64  nMaxHardRepl and
31e0: 20 6c 65 6e 28 73 52 65 6d 61 69 6e 29 20 3e 3d   len(sRemain) >=
31f0: 20 32 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20   2:.            
3200: 20 20 20 20 66 6f 72 20 6e 56 61 6c 2c 20 6b 41      for nVal, kA
3210: 64 64 72 20 69 6e 20 73 65 6c 66 2e 5f 67 65 74  ddr in self._get
3220: 41 72 63 73 31 28 69 41 64 64 72 29 3a 0a 20 20  Arcs1(iAddr):.  
3230: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3240: 20 20 69 66 20 6e 56 61 6c 20 69 6e 20 73 65 6c    if nVal in sel
3250: 66 2e 64 43 68 61 72 56 61 6c 3a 0a 20 20 20 20  f.dCharVal:.    
3260: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3270: 20 20 20 20 63 43 68 61 72 20 3d 20 73 65 6c 66      cChar = self
3280: 2e 64 43 68 61 72 56 61 6c 5b 6e 56 61 6c 5d 0a  .dCharVal[nVal].
3290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
32a0: 20 20 20 20 20 20 20 20 69 66 20 63 43 68 61 72          if cChar
32b0: 20 6e 6f 74 20 69 6e 20 63 70 2e 64 31 74 6f 31   not in cp.d1to1
32c0: 2e 67 65 74 28 63 43 75 72 72 65 6e 74 2c 20 22  .get(cCurrent, "
32d0: 22 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  "):.            
32e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
32f0: 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28 6f 53  self._suggest(oS
3300: 75 67 67 52 65 73 75 6c 74 2c 20 73 52 65 6d 61  uggResult, sRema
3310: 69 6e 5b 31 3a 5d 2c 20 6e 4d 61 78 44 65 6c 2c  in[1:], nMaxDel,
3320: 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 2d 31 2c   nMaxHardRepl-1,
3330: 20 6e 44 65 65 70 2b 31 2c 20 6b 41 64 64 72 2c   nDeep+1, kAddr,
3340: 20 73 4e 65 77 57 6f 72 64 2b 63 43 68 61 72 2c   sNewWord+cChar,
3350: 20 22 5b 5b 22 2b 63 43 68 61 72 2b 22 5d 5d 22   "[["+cChar+"]]"
3360: 2c 20 54 72 75 65 29 0a 20 20 20 20 20 20 20 20  , True).        
3370: 20 20 20 20 23 20 65 6e 64 20 6f 66 20 77 6f 72      # end of wor
3380: 64 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  d.            if
3390: 20 6c 65 6e 28 73 52 65 6d 61 69 6e 29 20 3d 3d   len(sRemain) ==
33a0: 20 32 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20   2:.            
33b0: 20 20 20 20 66 6f 72 20 73 52 65 70 6c 20 69 6e      for sRepl in
33c0: 20 63 70 2e 64 46 69 6e 61 6c 32 2e 67 65 74 28   cp.dFinal2.get(
33d0: 73 52 65 6d 61 69 6e 2c 20 28 29 29 3a 0a 20 20  sRemain, ()):.  
33e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
33f0: 20 20 73 65 6c 66 2e 5f 73 75 67 67 65 73 74 28    self._suggest(
3400: 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 73 52 65  oSuggResult, sRe
3410: 70 6c 2c 20 6e 4d 61 78 44 65 6c 2c 20 6e 4d 61  pl, nMaxDel, nMa
3420: 78 48 61 72 64 52 65 70 6c 2c 20 6e 44 65 65 70  xHardRepl, nDeep
3430: 2b 31 2c 20 69 41 64 64 72 2c 20 73 4e 65 77 57  +1, iAddr, sNewW
3440: 6f 72 64 2c 20 73 52 65 6d 61 69 6e 20 2b 20 22  ord, sRemain + "
3450: 20 3e 3e 20 22 20 2b 20 73 52 65 70 6c 2c 20 54   >> " + sRepl, T
3460: 72 75 65 29 0a 20 20 20 20 20 20 20 20 20 20 20  rue).           
3470: 20 65 6c 69 66 20 6c 65 6e 28 73 52 65 6d 61 69   elif len(sRemai
3480: 6e 29 20 3d 3d 20 31 3a 0a 20 20 20 20 20 20 20  n) == 1:.       
3490: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73           self._s
34a0: 75 67 67 65 73 74 28 6f 53 75 67 67 52 65 73 75  uggest(oSuggResu
34b0: 6c 74 2c 20 22 22 2c 20 6e 4d 61 78 44 65 6c 2c  lt, "", nMaxDel,
34c0: 20 6e 4d 61 78 48 61 72 64 52 65 70 6c 2c 20 6e   nMaxHardRepl, n
34d0: 44 65 65 70 2b 31 2c 20 69 41 64 64 72 2c 20 73  Deep+1, iAddr, s
34e0: 4e 65 77 57 6f 72 64 2c 20 73 52 65 6d 61 69 6e  NewWord, sRemain
34f0: 20 2b 20 22 20 5b 6c 61 73 74 20 63 68 61 72 20   + " [last char 
3500: 72 65 6d 6f 76 65 64 5d 20 22 2c 20 54 72 75 65  removed] ", True
3510: 29 20 23 20 72 65 6d 6f 76 65 20 6c 61 73 74 20  ) # remove last 
3520: 63 68 61 72 20 61 6e 64 20 67 6f 20 6f 0a 20 20  char and go o.  
3530: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f                fo
3540: 72 20 73 52 65 70 6c 20 69 6e 20 63 70 2e 64 46  r sRepl in cp.dF
3550: 69 6e 61 6c 31 2e 67 65 74 28 73 52 65 6d 61 69  inal1.get(sRemai
3560: 6e 2c 20 28 29 29 3a 0a 20 20 20 20 20 20 20 20  n, ()):.        
3570: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
3580: 2e 5f 73 75 67 67 65 73 74 28 6f 53 75 67 67 52  ._suggest(oSuggR
3590: 65 73 75 6c 74 2c 20 73 52 65 70 6c 2c 20 6e 4d  esult, sRepl, nM
35a0: 61 78 44 65 6c 2c 20 6e 4d 61 78 48 61 72 64 52  axDel, nMaxHardR
35b0: 65 70 6c 2c 20 6e 44 65 65 70 2b 31 2c 20 69 41  epl, nDeep+1, iA
35c0: 64 64 72 2c 20 73 4e 65 77 57 6f 72 64 2c 20 73  ddr, sNewWord, s
35d0: 52 65 6d 61 69 6e 20 2b 20 22 20 3e 3e 20 22 20  Remain + " >> " 
35e0: 2b 20 73 52 65 70 6c 2c 20 54 72 75 65 29 0a 20  + sRepl, True). 
35f0: 20 20 20 20 20 20 20 72 65 74 75 72 6e 0a 0a 20         return.. 
3600: 20 20 20 40 74 69 6d 65 74 68 69 73 0a 20 20 20     @timethis.   
3610: 20 64 65 66 20 73 75 67 67 65 73 74 32 20 28 73   def suggest2 (s
3620: 65 6c 66 2c 20 73 57 6f 72 64 2c 20 6e 4d 61 78  elf, sWord, nMax
3630: 53 75 67 67 3d 31 30 29 3a 0a 20 20 20 20 20 20  Sugg=10):.      
3640: 20 20 22 72 65 74 75 72 6e 73 20 61 20 73 65 74    "returns a set
3650: 20 6f 66 20 73 75 67 67 65 73 74 69 6f 6e 73 20   of suggestions 
3660: 66 6f 72 20 3c 73 57 6f 72 64 3e 22 0a 20 20 20  for <sWord>".   
3670: 20 20 20 20 20 73 50 66 78 2c 20 73 57 6f 72 64       sPfx, sWord
3680: 2c 20 73 53 66 78 20 3d 20 63 70 2e 63 75 74 28  , sSfx = cp.cut(
3690: 73 57 6f 72 64 29 0a 20 20 20 20 20 20 20 20 6f  sWord).        o
36a0: 53 75 67 67 52 65 73 75 6c 74 20 3d 20 53 75 67  SuggResult = Sug
36b0: 67 52 65 73 75 6c 74 28 73 57 6f 72 64 29 0a 20  gResult(sWord). 
36c0: 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 73 75 67         self._sug
36d0: 67 65 73 74 32 28 6f 53 75 67 67 52 65 73 75 6c  gest2(oSuggResul
36e0: 74 29 0a 20 20 20 20 20 20 20 20 61 53 75 67 67  t).        aSugg
36f0: 20 3d 20 6f 53 75 67 67 52 65 73 75 6c 74 2e 67   = oSuggResult.g
3700: 65 74 53 75 67 67 65 73 74 69 6f 6e 73 28 29 0a  etSuggestions().
3710: 20 20 20 20 20 20 20 20 69 66 20 73 53 66 78 20          if sSfx 
3720: 6f 72 20 73 50 66 78 3a 0a 20 20 20 20 20 20 20  or sPfx:.       
3730: 20 20 20 20 20 23 20 77 65 20 61 64 64 20 77 68       # we add wh
3740: 61 74 20 77 65 20 72 65 6d 6f 76 65 64 0a 20 20  at we removed.  
3750: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
3760: 20 6c 69 73 74 28 6d 61 70 28 6c 61 6d 62 64 61   list(map(lambda
3770: 20 73 53 75 67 3a 20 73 50 66 78 20 2b 20 73 53   sSug: sPfx + sS
3780: 75 67 20 2b 20 73 53 66 78 2c 20 61 53 75 67 67  ug + sSfx, aSugg
3790: 29 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  )).        retur
37a0: 6e 20 61 53 75 67 67 0a 0a 20 20 20 20 64 65 66  n aSugg..    def
37b0: 20 5f 73 75 67 67 65 73 74 32 20 28 73 65 6c 66   _suggest2 (self
37c0: 2c 20 6f 53 75 67 67 52 65 73 75 6c 74 2c 20 6e  , oSuggResult, n
37d0: 44 65 65 70 3d 30 2c 20 69 41 64 64 72 3d 30 2c  Deep=0, iAddr=0,
37e0: 20 73 4e 65 77 57 6f 72 64 3d 22 22 29 3a 0a 20   sNewWord=""):. 
37f0: 20 20 20 20 20 20 20 23 6c 6f 67 67 69 6e 67 2e         #logging.
3800: 69 6e 66 6f 28 28 6e 44 65 65 70 20 2a 20 22 20  info((nDeep * " 
3810: 20 22 29 20 2b 20 73 4e 65 77 57 6f 72 64 29 0a   ") + sNewWord).
3820: 20 20 20 20 20 20 20 20 69 66 20 6e 44 65 65 70          if nDeep
3830: 20 3e 3d 20 6f 53 75 67 67 52 65 73 75 6c 74 2e   >= oSuggResult.
3840: 6e 44 69 73 74 4c 69 6d 69 74 3a 0a 20 20 20 20  nDistLimit:.    
3850: 20 20 20 20 20 20 20 20 73 43 6c 65 61 6e 4e 65          sCleanNe
3860: 77 57 6f 72 64 20 3d 20 63 70 2e 63 6c 65 61 6e  wWord = cp.clean
3870: 57 6f 72 64 28 73 4e 65 77 57 6f 72 64 29 0a 20  Word(sNewWord). 
3880: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73 74             if st
3890: 2e 64 69 73 74 61 6e 63 65 53 69 66 74 34 28 6f  .distanceSift4(o
38a0: 53 75 67 67 52 65 73 75 6c 74 2e 73 43 6c 65 61  SuggResult.sClea
38b0: 6e 57 6f 72 64 5b 3a 6c 65 6e 28 73 43 6c 65 61  nWord[:len(sClea
38c0: 6e 4e 65 77 57 6f 72 64 29 5d 2c 20 73 43 6c 65  nNewWord)], sCle
38d0: 61 6e 4e 65 77 57 6f 72 64 29 20 3e 20 6f 53 75  anNewWord) > oSu
38e0: 67 67 52 65 73 75 6c 74 2e 6e 44 69 73 74 4c 69  ggResult.nDistLi
38f0: 6d 69 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20  mit:.           
3900: 20 20 20 20 20 72 65 74 75 72 6e 0a 20 20 20 20       return.    
3910: 20 20 20 20 69 66 20 69 6e 74 2e 66 72 6f 6d 5f      if int.from_
3920: 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63  bytes(self.byDic
3930: 5b 69 41 64 64 72 3a 69 41 64 64 72 2b 73 65 6c  [iAddr:iAddr+sel
3940: 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20 62 79  f.nBytesArc], by
3950: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 20 26  teorder='big') &
3960: 20 73 65 6c 66 2e 5f 66 69 6e 61 6c 4e 6f 64 65   self._finalNode
3970: 4d 61 73 6b 3a 0a 20 20 20 20 20 20 20 20 20 20  Mask:.          
3980: 20 20 23 6c 6f 67 67 69 6e 67 2e 69 6e 66 6f 28    #logging.info(
3990: 28 6e 44 65 65 70 20 2a 20 22 20 20 22 29 20 2b  (nDeep * "  ") +
39a0: 20 22 5f 5f 22 20 2b 20 73 4e 65 77 57 6f 72 64   "__" + sNewWord
39b0: 20 2b 20 22 5f 5f 22 29 0a 20 20 20 20 20 20 20   + "__").       
39c0: 20 20 20 20 20 6f 53 75 67 67 52 65 73 75 6c 74       oSuggResult
39d0: 2e 61 64 64 53 75 67 67 28 73 4e 65 77 57 6f 72  .addSugg(sNewWor
39e0: 64 2c 20 6e 44 65 65 70 29 0a 20 20 20 20 20 20  d, nDeep).      
39f0: 20 20 66 6f 72 20 63 43 68 61 72 2c 20 6a 41 64    for cChar, jAd
3a00: 64 72 20 69 6e 20 73 65 6c 66 2e 5f 67 65 74 43  dr in self._getC
3a10: 68 61 72 41 72 63 73 28 69 41 64 64 72 29 3a 0a  harArcs(iAddr):.
3a20: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
3a30: 2e 5f 73 75 67 67 65 73 74 32 28 6f 53 75 67 67  ._suggest2(oSugg
3a40: 52 65 73 75 6c 74 2c 20 6e 44 65 65 70 2b 31 2c  Result, nDeep+1,
3a50: 20 6a 41 64 64 72 2c 20 73 4e 65 77 57 6f 72 64   jAddr, sNewWord
3a60: 2b 63 43 68 61 72 29 0a 20 20 20 20 20 20 20 20  +cChar).        
3a70: 72 65 74 75 72 6e 0a 0a 20 20 20 20 64 65 66 20  return..    def 
3a80: 5f 67 65 74 43 68 61 72 41 72 63 73 20 28 73 65  _getCharArcs (se
3a90: 6c 66 2c 20 69 41 64 64 72 29 3a 0a 20 20 20 20  lf, iAddr):.    
3aa0: 20 20 20 20 22 67 65 6e 65 72 61 74 6f 72 3a 20      "generator: 
3ab0: 79 69 65 6c 64 20 61 6c 6c 20 63 68 61 72 73 20  yield all chars 
3ac0: 61 6e 64 20 61 64 64 72 65 73 73 65 73 20 66 72  and addresses fr
3ad0: 6f 6d 20 6e 6f 64 65 20 61 74 20 61 64 64 72 65  om node at addre
3ae0: 73 73 20 3c 69 41 64 64 72 3e 22 0a 20 20 20 20  ss <iAddr>".    
3af0: 20 20 20 20 66 6f 72 20 6e 56 61 6c 2c 20 6a 41      for nVal, jA
3b00: 64 64 72 20 69 6e 20 73 65 6c 66 2e 5f 67 65 74  ddr in self._get
3b10: 41 72 63 73 28 69 41 64 64 72 29 3a 0a 20 20 20  Arcs(iAddr):.   
3b20: 20 20 20 20 20 20 20 20 20 69 66 20 6e 56 61 6c           if nVal
3b30: 20 3c 20 73 65 6c 66 2e 6e 43 68 61 72 3a 0a 20   < self.nChar:. 
3b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 79                 y
3b50: 69 65 6c 64 20 28 73 65 6c 66 2e 64 43 68 61 72  ield (self.dChar
3b60: 56 61 6c 5b 6e 56 61 6c 5d 2c 20 6a 41 64 64 72  Val[nVal], jAddr
3b70: 29 0a 0a 20 20 20 20 64 65 66 20 5f 67 65 74 53  )..    def _getS
3b80: 69 6d 69 6c 61 72 41 72 63 73 20 28 73 65 6c 66  imilarArcs (self
3b90: 2c 20 63 43 68 61 72 2c 20 69 41 64 64 72 29 3a  , cChar, iAddr):
3ba0: 0a 20 20 20 20 20 20 20 20 22 67 65 6e 65 72 61  .        "genera
3bb0: 74 6f 72 3a 20 79 69 65 6c 64 20 73 69 6d 69 6c  tor: yield simil
3bc0: 61 72 20 63 68 61 72 20 6f 66 20 3c 63 43 68 61  ar char of <cCha
3bd0: 72 3e 20 61 6e 64 20 61 64 64 72 65 73 73 20 6f  r> and address o
3be0: 66 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20  f the following 
3bf0: 6e 6f 64 65 22 0a 20 20 20 20 20 20 20 20 66 6f  node".        fo
3c00: 72 20 63 20 69 6e 20 63 70 2e 64 31 74 6f 31 2e  r c in cp.d1to1.
3c10: 67 65 74 28 63 43 68 61 72 2c 20 5b 63 43 68 61  get(cChar, [cCha
3c20: 72 5d 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  r]):.           
3c30: 20 69 66 20 63 20 69 6e 20 73 65 6c 66 2e 64 43   if c in self.dC
3c40: 68 61 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20  har:.           
3c50: 20 20 20 20 20 6a 41 64 64 72 20 3d 20 73 65 6c       jAddr = sel
3c60: 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64 65  f._lookupArcNode
3c70: 28 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d 2c 20  (self.dChar[c], 
3c80: 69 41 64 64 72 29 0a 20 20 20 20 20 20 20 20 20  iAddr).         
3c90: 20 20 20 20 20 20 20 69 66 20 6a 41 64 64 72 3a         if jAddr:
3ca0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
3cb0: 20 20 20 20 20 79 69 65 6c 64 20 28 63 2c 20 6a       yield (c, j
3cc0: 41 64 64 72 29 0a 0a 20 20 20 20 64 65 66 20 5f  Addr)..    def _
3cd0: 67 65 74 54 61 69 6c 73 20 28 73 65 6c 66 2c 20  getTails (self, 
3ce0: 69 41 64 64 72 2c 20 73 54 61 69 6c 3d 22 22 2c  iAddr, sTail="",
3cf0: 20 6e 3d 32 29 3a 0a 20 20 20 20 20 20 20 20 22   n=2):.        "
3d00: 72 65 74 75 72 6e 20 61 20 6c 69 73 74 20 6f 66  return a list of
3d10: 20 73 75 66 66 69 78 65 73 20 65 6e 64 69 6e 67   suffixes ending
3d20: 20 61 74 20 61 20 64 69 73 74 61 6e 63 65 20 6f   at a distance o
3d30: 66 20 3c 6e 3e 20 66 72 6f 6d 20 3c 69 41 64 64  f <n> from <iAdd
3d40: 72 3e 22 0a 20 20 20 20 20 20 20 20 61 54 61 69  r>".        aTai
3d50: 6c 73 20 3d 20 73 65 74 28 29 0a 20 20 20 20 20  ls = set().     
3d60: 20 20 20 66 6f 72 20 6e 56 61 6c 2c 20 6a 41 64     for nVal, jAd
3d70: 64 72 20 69 6e 20 73 65 6c 66 2e 5f 67 65 74 41  dr in self._getA
3d80: 72 63 73 28 69 41 64 64 72 29 3a 0a 20 20 20 20  rcs(iAddr):.    
3d90: 20 20 20 20 20 20 20 20 69 66 20 6e 56 61 6c 20          if nVal 
3da0: 3c 20 73 65 6c 66 2e 6e 43 68 61 72 3a 0a 20 20  < self.nChar:.  
3db0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
3dc0: 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28   int.from_bytes(
3dd0: 73 65 6c 66 2e 62 79 44 69 63 5b 6a 41 64 64 72  self.byDic[jAddr
3de0: 3a 6a 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74  :jAddr+self.nByt
3df0: 65 73 41 72 63 5d 2c 20 62 79 74 65 6f 72 64 65  esArc], byteorde
3e00: 72 3d 27 62 69 67 27 29 20 26 20 73 65 6c 66 2e  r='big') & self.
3e10: 5f 66 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b 3a 0a  _finalNodeMask:.
3e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3e30: 20 20 20 20 61 54 61 69 6c 73 2e 61 64 64 28 73      aTails.add(s
3e40: 54 61 69 6c 20 2b 20 73 65 6c 66 2e 64 43 68 61  Tail + self.dCha
3e50: 72 56 61 6c 5b 6e 56 61 6c 5d 29 0a 20 20 20 20  rVal[nVal]).    
3e60: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
3e70: 20 61 6e 64 20 6e 6f 74 20 61 54 61 69 6c 73 3a   and not aTails:
3e80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
3e90: 20 20 20 20 20 61 54 61 69 6c 73 2e 75 70 64 61       aTails.upda
3ea0: 74 65 28 73 65 6c 66 2e 5f 67 65 74 54 61 69 6c  te(self._getTail
3eb0: 73 28 6a 41 64 64 72 2c 20 73 54 61 69 6c 2b 73  s(jAddr, sTail+s
3ec0: 65 6c 66 2e 64 43 68 61 72 56 61 6c 5b 6e 56 61  elf.dCharVal[nVa
3ed0: 6c 5d 2c 20 6e 2d 31 29 29 0a 20 20 20 20 20 20  l], n-1)).      
3ee0: 20 20 72 65 74 75 72 6e 20 61 54 61 69 6c 73 0a    return aTails.
3ef0: 0a 20 20 20 20 64 65 66 20 64 72 61 77 50 61 74  .    def drawPat
3f00: 68 20 28 73 65 6c 66 2c 20 73 57 6f 72 64 2c 20  h (self, sWord, 
3f10: 69 41 64 64 72 3d 30 29 3a 0a 20 20 20 20 20 20  iAddr=0):.      
3f20: 20 20 22 73 68 6f 77 20 74 68 65 20 70 61 74 68    "show the path
3f30: 20 74 61 6b 65 6e 20 62 79 20 3c 73 57 6f 72 64   taken by <sWord
3f40: 3e 20 69 6e 20 74 68 65 20 67 72 61 70 68 22 0a  > in the graph".
3f50: 20 20 20 20 20 20 20 20 63 43 68 61 72 20 3d 20          cChar = 
3f60: 73 57 6f 72 64 5b 30 3a 31 5d 20 20 69 66 20 73  sWord[0:1]  if s
3f70: 57 6f 72 64 20 20 65 6c 73 65 20 22 20 22 0a 20  Word  else " ". 
3f80: 20 20 20 20 20 20 20 69 50 6f 73 20 3d 20 2d 31         iPos = -1
3f90: 0a 20 20 20 20 20 20 20 20 6e 20 3d 20 30 0a 20  .        n = 0. 
3fa0: 20 20 20 20 20 20 20 70 72 69 6e 74 28 63 43 68         print(cCh
3fb0: 61 72 20 2b 20 22 3a 20 22 2c 20 65 6e 64 3d 22  ar + ": ", end="
3fc0: 22 29 0a 20 20 20 20 20 20 20 20 66 6f 72 20 6e  ").        for n
3fd0: 56 61 6c 2c 20 6a 41 64 64 72 20 69 6e 20 73 65  Val, jAddr in se
3fe0: 6c 66 2e 5f 67 65 74 41 72 63 73 28 69 41 64 64  lf._getArcs(iAdd
3ff0: 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  r):.            
4000: 69 66 20 6e 56 61 6c 20 69 6e 20 73 65 6c 66 2e  if nVal in self.
4010: 64 43 68 61 72 56 61 6c 3a 0a 20 20 20 20 20 20  dCharVal:.      
4020: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28            print(
4030: 73 65 6c 66 2e 64 43 68 61 72 56 61 6c 5b 6e 56  self.dCharVal[nV
4040: 61 6c 5d 2c 20 65 6e 64 3d 22 22 29 0a 20 20 20  al], end="").   
4050: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
4060: 73 65 6c 66 2e 64 43 68 61 72 56 61 6c 5b 6e 56  self.dCharVal[nV
4070: 61 6c 5d 20 3d 3d 20 73 57 6f 72 64 5b 30 3a 31  al] == sWord[0:1
4080: 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]:.             
4090: 20 20 20 20 20 20 20 69 4e 65 78 74 4e 6f 64 65         iNextNode
40a0: 41 64 64 72 20 3d 20 6a 41 64 64 72 0a 20 20 20  Addr = jAddr.   
40b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
40c0: 20 69 50 6f 73 20 3d 20 6e 0a 20 20 20 20 20 20   iPos = n.      
40d0: 20 20 20 20 20 20 20 20 20 20 6e 20 2b 3d 20 31            n += 1
40e0: 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20  .        if not 
40f0: 73 57 6f 72 64 3a 0a 20 20 20 20 20 20 20 20 20  sWord:.         
4100: 20 20 20 72 65 74 75 72 6e 0a 20 20 20 20 20 20     return.      
4110: 20 20 69 66 20 69 50 6f 73 20 3e 3d 20 30 3a 0a    if iPos >= 0:.
4120: 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e              prin
4130: 74 28 22 5c 6e 20 20 20 22 2b 20 22 20 22 20 2a  t("\n   "+ " " *
4140: 20 69 50 6f 73 20 2b 20 22 7c 22 29 0a 20 20 20   iPos + "|").   
4150: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64 72           self.dr
4160: 61 77 50 61 74 68 28 73 57 6f 72 64 5b 31 3a 5d  awPath(sWord[1:]
4170: 2c 20 69 4e 65 78 74 4e 6f 64 65 41 64 64 72 29  , iNextNodeAddr)
4180: 0a 0a 20 20 20 20 64 65 66 20 73 65 6c 65 63 74  ..    def select
4190: 20 28 73 65 6c 66 2c 20 73 50 61 74 74 65 72 6e   (self, sPattern
41a0: 3d 22 22 29 3a 0a 20 20 20 20 20 20 20 20 22 67  =""):.        "g
41b0: 65 6e 65 72 61 74 6f 72 3a 20 72 65 74 75 72 6e  enerator: return
41c0: 73 20 61 6c 6c 20 65 6e 74 72 69 65 73 20 77 68  s all entries wh
41d0: 69 63 68 20 6d 6f 72 70 68 6f 6c 6f 67 79 20 66  ich morphology f
41e0: 69 74 73 20 3c 73 50 61 74 74 65 72 6e 3e 22 0a  its <sPattern>".
41f0: 20 20 20 20 20 20 20 20 7a 50 61 74 74 65 72 6e          zPattern
4200: 20 3d 20 4e 6f 6e 65 0a 20 20 20 20 20 20 20 20   = None.        
4210: 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20  try:.           
4220: 20 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63   zPattern = re.c
4230: 6f 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29  ompile(sPattern)
4240: 0a 20 20 20 20 20 20 20 20 65 78 63 65 70 74 3a  .        except:
4250: 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69  .            pri
4260: 6e 74 28 22 23 20 45 72 72 6f 72 20 69 6e 20 72  nt("# Error in r
4270: 65 67 65 78 20 70 61 74 74 65 72 6e 22 29 0a 20  egex pattern"). 
4280: 20 20 20 20 20 20 20 20 20 20 20 74 72 61 63 65             trace
4290: 62 61 63 6b 2e 70 72 69 6e 74 5f 65 78 63 28 29  back.print_exc()
42a0: 0a 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 66  .        yield f
42b0: 72 6f 6d 20 73 65 6c 66 2e 5f 73 65 6c 65 63 74  rom self._select
42c0: 31 28 7a 50 61 74 74 65 72 6e 2c 20 30 2c 20 22  1(zPattern, 0, "
42d0: 22 29 0a 0a 20 20 20 20 23 20 64 65 66 20 6d 6f  ")..    # def mo
42e0: 72 70 68 20 28 73 65 6c 66 2c 20 73 57 6f 72 64  rph (self, sWord
42f0: 29 3a 0a 20 20 20 20 23 20 20 20 20 20 69 73 20  ):.    #     is 
4300: 64 65 66 69 6e 65 64 20 69 6e 20 5f 5f 69 6e 69  defined in __ini
4310: 74 5f 5f 0a 0a 20 20 20 20 23 20 56 45 52 53 49  t__..    # VERSI
4320: 4f 4e 20 31 0a 20 20 20 20 64 65 66 20 5f 73 65  ON 1.    def _se
4330: 6c 65 63 74 31 20 28 73 65 6c 66 2c 20 7a 50 61  lect1 (self, zPa
4340: 74 74 65 72 6e 2c 20 69 41 64 64 72 2c 20 73 57  ttern, iAddr, sW
4350: 6f 72 64 29 3a 0a 20 20 20 20 20 20 20 20 23 20  ord):.        # 
4360: 72 65 63 75 72 73 69 76 65 20 67 65 6e 65 72 61  recursive genera
4370: 74 6f 72 0a 20 20 20 20 20 20 20 20 66 6f 72 20  tor.        for 
4380: 6e 56 61 6c 2c 20 6a 41 64 64 72 20 69 6e 20 73  nVal, jAddr in s
4390: 65 6c 66 2e 5f 67 65 74 41 72 63 73 31 28 69 41  elf._getArcs1(iA
43a0: 64 64 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20  ddr):.          
43b0: 20 20 69 66 20 6e 56 61 6c 20 3c 20 73 65 6c 66    if nVal < self
43c0: 2e 6e 43 68 61 72 3a 0a 20 20 20 20 20 20 20 20  .nChar:.        
43d0: 20 20 20 20 20 20 20 20 23 20 73 69 6d 70 6c 65          # simple
43e0: 20 63 68 61 72 61 63 74 65 72 0a 20 20 20 20 20   character.     
43f0: 20 20 20 20 20 20 20 20 20 20 20 79 69 65 6c 64             yield
4400: 20 66 72 6f 6d 20 73 65 6c 66 2e 5f 73 65 6c 65   from self._sele
4410: 63 74 31 28 7a 50 61 74 74 65 72 6e 2c 20 6a 41  ct1(zPattern, jA
4420: 64 64 72 2c 20 73 57 6f 72 64 20 2b 20 73 65 6c  ddr, sWord + sel
4430: 66 2e 6c 41 72 63 56 61 6c 5b 6e 56 61 6c 5d 29  f.lArcVal[nVal])
4440: 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73  .            els
4450: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
4460: 20 20 20 73 45 6e 74 72 79 20 3d 20 73 57 6f 72     sEntry = sWor
4470: 64 20 2b 20 22 5c 74 22 20 2b 20 73 65 6c 66 2e  d + "\t" + self.
4480: 66 75 6e 63 53 74 65 6d 6d 69 6e 67 28 73 57 6f  funcStemming(sWo
4490: 72 64 2c 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c  rd, self.lArcVal
44a0: 5b 6e 56 61 6c 5d 29 0a 20 20 20 20 20 20 20 20  [nVal]).        
44b0: 20 20 20 20 20 20 20 20 66 6f 72 20 6e 4d 6f 72          for nMor
44c0: 70 68 56 61 6c 2c 20 5f 20 69 6e 20 73 65 6c 66  phVal, _ in self
44d0: 2e 5f 67 65 74 41 72 63 73 31 28 6a 41 64 64 72  ._getArcs1(jAddr
44e0: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
44f0: 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 7a 50         if not zP
4500: 61 74 74 65 72 6e 20 6f 72 20 7a 50 61 74 74 65  attern or zPatte
4510: 72 6e 2e 73 65 61 72 63 68 28 73 65 6c 66 2e 6c  rn.search(self.l
4520: 41 72 63 56 61 6c 5b 6e 4d 6f 72 70 68 56 61 6c  ArcVal[nMorphVal
4530: 5d 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ]):.            
4540: 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65 6c              yiel
4550: 64 20 73 45 6e 74 72 79 20 2b 20 22 5c 74 22 20  d sEntry + "\t" 
4560: 2b 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e  + self.lArcVal[n
4570: 4d 6f 72 70 68 56 61 6c 5d 0a 0a 20 20 20 20 64  MorphVal]..    d
4580: 65 66 20 5f 6d 6f 72 70 68 31 20 28 73 65 6c 66  ef _morph1 (self
4590: 2c 20 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20  , sWord):.      
45a0: 20 20 22 72 65 74 75 72 6e 73 20 6d 6f 72 70 68    "returns morph
45b0: 6f 6c 6f 67 69 65 73 20 6f 66 20 3c 73 57 6f 72  ologies of <sWor
45c0: 64 3e 22 0a 20 20 20 20 20 20 20 20 69 41 64 64  d>".        iAdd
45d0: 72 20 3d 20 30 0a 20 20 20 20 20 20 20 20 66 6f  r = 0.        fo
45e0: 72 20 63 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20  r c in sWord:.  
45f0: 20 20 20 20 20 20 20 20 20 20 69 66 20 63 20 6e            if c n
4600: 6f 74 20 69 6e 20 73 65 6c 66 2e 64 43 68 61 72  ot in self.dChar
4610: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
4620: 20 20 72 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20    return [].    
4630: 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20          iAddr = 
4640: 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e  self._lookupArcN
4650: 6f 64 65 28 73 65 6c 66 2e 64 43 68 61 72 5b 63  ode(self.dChar[c
4660: 5d 2c 20 69 41 64 64 72 29 0a 20 20 20 20 20 20  ], iAddr).      
4670: 20 20 20 20 20 20 69 66 20 69 41 64 64 72 20 3d        if iAddr =
4680: 3d 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20  = None:.        
4690: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b          return [
46a0: 5d 0a 20 20 20 20 20 20 20 20 69 66 20 28 69 6e  ].        if (in
46b0: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
46c0: 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 41  f.byDic[iAddr:iA
46d0: 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41  ddr+self.nBytesA
46e0: 72 63 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27  rc], byteorder='
46f0: 62 69 67 27 29 20 26 20 73 65 6c 66 2e 5f 66 69  big') & self._fi
4700: 6e 61 6c 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20 20  nalNodeMask):.  
4710: 20 20 20 20 20 20 20 20 20 20 6c 20 3d 20 5b 5d            l = []
4720: 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e 52 61  .            nRa
4730: 77 41 72 63 20 3d 20 30 0a 20 20 20 20 20 20 20  wArc = 0.       
4740: 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28       while not (
4750: 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f  nRawArc & self._
4760: 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20  lastArcMask):.  
4770: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 45                iE
4780: 6e 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64  ndArcAddr = iAdd
4790: 72 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41  r + self.nBytesA
47a0: 72 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  rc.             
47b0: 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74     nRawArc = int
47c0: 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66  .from_bytes(self
47d0: 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e  .byDic[iAddr:iEn
47e0: 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f  dArcAddr], byteo
47f0: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
4800: 20 20 20 20 20 20 20 20 20 20 20 20 6e 41 72 63              nArc
4810: 20 3d 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c   = nRawArc & sel
4820: 66 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20  f._arcMask.     
4830: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 41             if nA
4840: 72 63 20 3e 3d 20 73 65 6c 66 2e 6e 43 68 61 72  rc >= self.nChar
4850: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
4860: 20 20 20 20 20 20 23 20 54 68 69 73 20 76 61 6c        # This val
4870: 75 65 20 69 73 20 6e 6f 74 20 61 20 63 68 61 72  ue is not a char
4880: 2c 20 74 68 69 73 20 69 73 20 61 20 73 74 65 6d  , this is a stem
4890: 6d 69 6e 67 20 63 6f 64 65 20 0a 20 20 20 20 20  ming code .     
48a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
48b0: 53 74 65 6d 20 3d 20 22 3e 22 20 2b 20 73 65 6c  Stem = ">" + sel
48c0: 66 2e 66 75 6e 63 53 74 65 6d 6d 69 6e 67 28 73  f.funcStemming(s
48d0: 57 6f 72 64 2c 20 73 65 6c 66 2e 6c 41 72 63 56  Word, self.lArcV
48e0: 61 6c 5b 6e 41 72 63 5d 29 0a 20 20 20 20 20 20  al[nArc]).      
48f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
4900: 4e 6f 77 20 2c 20 77 65 20 67 6f 20 74 6f 20 74  Now , we go to t
4910: 68 65 20 6e 65 78 74 20 6e 6f 64 65 20 61 6e 64  he next node and
4920: 20 72 65 74 72 69 65 76 65 20 61 6c 6c 20 66 6f   retrieve all fo
4930: 6c 6c 6f 77 69 6e 67 20 61 72 63 73 20 76 61 6c  llowing arcs val
4940: 75 65 73 2c 20 61 6c 6c 20 6f 66 20 74 68 65 6d  ues, all of them
4950: 20 61 72 65 20 74 61 67 73 0a 20 20 20 20 20 20   are tags.      
4960: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41                iA
4970: 64 64 72 32 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f  ddr2 = int.from_
4980: 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63  bytes(self.byDic
4990: 5b 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e  [iEndArcAddr:iEn
49a0: 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dArcAddr+self.nB
49b0: 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 5d  ytesNodeAddress]
49c0: 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67  , byteorder='big
49d0: 27 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ').             
49e0: 20 20 20 20 20 20 20 6e 52 61 77 41 72 63 32 20         nRawArc2 
49f0: 3d 20 30 0a 20 20 20 20 20 20 20 20 20 20 20 20  = 0.            
4a00: 20 20 20 20 20 20 20 20 77 68 69 6c 65 20 6e 6f          while no
4a10: 74 20 28 6e 52 61 77 41 72 63 32 20 26 20 73 65  t (nRawArc2 & se
4a20: 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29  lf._lastArcMask)
4a30: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
4a40: 20 20 20 20 20 20 20 20 20 20 69 45 6e 64 41 72            iEndAr
4a50: 63 41 64 64 72 32 20 3d 20 69 41 64 64 72 32 20  cAddr2 = iAddr2 
4a60: 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63  + self.nBytesArc
4a70: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4a80: 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63           nRawArc
4a90: 32 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74  2 = int.from_byt
4aa0: 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41  es(self.byDic[iA
4ab0: 64 64 72 32 3a 69 45 6e 64 41 72 63 41 64 64 72  ddr2:iEndArcAddr
4ac0: 32 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62  2], byteorder='b
4ad0: 69 67 27 29 0a 20 20 20 20 20 20 20 20 20 20 20  ig').           
4ae0: 20 20 20 20 20 20 20 20 20 20 20 20 20 6c 2e 61               l.a
4af0: 70 70 65 6e 64 28 73 53 74 65 6d 20 2b 20 22 20  ppend(sStem + " 
4b00: 22 20 2b 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c  " + self.lArcVal
4b10: 5b 6e 52 61 77 41 72 63 32 20 26 20 73 65 6c 66  [nRawArc2 & self
4b20: 2e 5f 61 72 63 4d 61 73 6b 5d 29 0a 20 20 20 20  ._arcMask]).    
4b30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4b40: 20 20 20 20 69 41 64 64 72 32 20 3d 20 69 45 6e      iAddr2 = iEn
4b50: 64 41 72 63 41 64 64 72 32 2b 73 65 6c 66 2e 6e  dArcAddr2+self.n
4b60: 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73  BytesNodeAddress
4b70: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4b80: 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72 63   iAddr = iEndArc
4b90: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
4ba0: 4e 6f 64 65 41 64 64 72 65 73 73 0a 20 20 20 20  NodeAddress.    
4bb0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 6c          return l
4bc0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
4bd0: 5b 5d 0a 0a 20 20 20 20 64 65 66 20 5f 73 74 65  []..    def _ste
4be0: 6d 31 20 28 73 65 6c 66 2c 20 73 57 6f 72 64 29  m1 (self, sWord)
4bf0: 3a 0a 20 20 20 20 20 20 20 20 22 72 65 74 75 72  :.        "retur
4c00: 6e 73 20 73 74 65 6d 73 20 6c 69 73 74 20 6f 66  ns stems list of
4c10: 20 3c 73 57 6f 72 64 3e 22 0a 20 20 20 20 20 20   <sWord>".      
4c20: 20 20 69 41 64 64 72 20 3d 20 30 0a 20 20 20 20    iAddr = 0.    
4c30: 20 20 20 20 66 6f 72 20 63 20 69 6e 20 73 57 6f      for c in sWo
4c40: 72 64 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  rd:.            
4c50: 69 66 20 63 20 6e 6f 74 20 69 6e 20 73 65 6c 66  if c not in self
4c60: 2e 64 43 68 61 72 3a 0a 20 20 20 20 20 20 20 20  .dChar:.        
4c70: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b          return [
4c80: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 41  ].            iA
4c90: 64 64 72 20 3d 20 73 65 6c 66 2e 5f 6c 6f 6f 6b  ddr = self._look
4ca0: 75 70 41 72 63 4e 6f 64 65 28 73 65 6c 66 2e 64  upArcNode(self.d
4cb0: 43 68 61 72 5b 63 5d 2c 20 69 41 64 64 72 29 0a  Char[c], iAddr).
4cc0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 69              if i
4cd0: 41 64 64 72 20 3d 3d 20 4e 6f 6e 65 3a 0a 20 20  Addr == None:.  
4ce0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
4cf0: 74 75 72 6e 20 5b 5d 0a 20 20 20 20 20 20 20 20  turn [].        
4d00: 69 66 20 28 69 6e 74 2e 66 72 6f 6d 5f 62 79 74  if (int.from_byt
4d10: 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41  es(self.byDic[iA
4d20: 64 64 72 3a 69 41 64 64 72 2b 73 65 6c 66 2e 6e  ddr:iAddr+self.n
4d30: 42 79 74 65 73 41 72 63 5d 2c 20 62 79 74 65 6f  BytesArc], byteo
4d40: 72 64 65 72 3d 27 62 69 67 27 29 20 26 20 73 65  rder='big') & se
4d50: 6c 66 2e 5f 66 69 6e 61 6c 4e 6f 64 65 4d 61 73  lf._finalNodeMas
4d60: 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  k):.            
4d70: 6c 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 20  l = [].         
4d80: 20 20 20 6e 52 61 77 41 72 63 20 3d 20 30 0a 20     nRawArc = 0. 
4d90: 20 20 20 20 20 20 20 20 20 20 20 77 68 69 6c 65             while
4da0: 20 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20   not (nRawArc & 
4db0: 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73  self._lastArcMas
4dc0: 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  k):.            
4dd0: 20 20 20 20 69 45 6e 64 41 72 63 41 64 64 72 20      iEndArcAddr 
4de0: 3d 20 69 41 64 64 72 20 2b 20 73 65 6c 66 2e 6e  = iAddr + self.n
4df0: 42 79 74 65 73 41 72 63 0a 20 20 20 20 20 20 20  BytesArc.       
4e00: 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72 63           nRawArc
4e10: 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65   = int.from_byte
4e20: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41 64  s(self.byDic[iAd
4e30: 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72 5d 2c  dr:iEndArcAddr],
4e40: 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27   byteorder='big'
4e50: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
4e60: 20 20 6e 41 72 63 20 3d 20 6e 52 61 77 41 72 63    nArc = nRawArc
4e70: 20 26 20 73 65 6c 66 2e 5f 61 72 63 4d 61 73 6b   & self._arcMask
4e80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4e90: 20 69 66 20 6e 41 72 63 20 3e 3d 20 73 65 6c 66   if nArc >= self
4ea0: 2e 6e 43 68 61 72 3a 0a 20 20 20 20 20 20 20 20  .nChar:.        
4eb0: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 54 68              # Th
4ec0: 69 73 20 76 61 6c 75 65 20 69 73 20 6e 6f 74 20  is value is not 
4ed0: 61 20 63 68 61 72 2c 20 74 68 69 73 20 69 73 20  a char, this is 
4ee0: 61 20 73 74 65 6d 6d 69 6e 67 20 63 6f 64 65 20  a stemming code 
4ef0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4f00: 20 20 20 20 20 6c 2e 61 70 70 65 6e 64 28 73 65       l.append(se
4f10: 6c 66 2e 66 75 6e 63 53 74 65 6d 6d 69 6e 67 28  lf.funcStemming(
4f20: 73 57 6f 72 64 2c 20 73 65 6c 66 2e 6c 41 72 63  sWord, self.lArc
4f30: 56 61 6c 5b 6e 41 72 63 5d 29 29 0a 20 20 20 20  Val[nArc])).    
4f40: 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64              iAdd
4f50: 72 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72 2b  r = iEndArcAddr+
4f60: 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41  self.nBytesNodeA
4f70: 64 64 72 65 73 73 0a 20 20 20 20 20 20 20 20 20  ddress.         
4f80: 20 20 20 72 65 74 75 72 6e 20 6c 0a 20 20 20 20     return l.    
4f90: 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 0a 20      return [].. 
4fa0: 20 20 20 64 65 66 20 5f 6c 6f 6f 6b 75 70 41 72     def _lookupAr
4fb0: 63 4e 6f 64 65 31 20 28 73 65 6c 66 2c 20 6e 56  cNode1 (self, nV
4fc0: 61 6c 2c 20 69 41 64 64 72 29 3a 0a 20 20 20 20  al, iAddr):.    
4fd0: 20 20 20 20 22 6c 6f 6f 6b 73 20 69 66 20 3c 6e      "looks if <n
4fe0: 56 61 6c 3e 20 69 73 20 61 6e 20 61 72 63 20 61  Val> is an arc a
4ff0: 74 20 74 68 65 20 6e 6f 64 65 20 61 74 20 3c 69  t the node at <i
5000: 41 64 64 72 3e 2c 20 69 66 20 79 65 73 2c 20 72  Addr>, if yes, r
5010: 65 74 75 72 6e 73 20 61 64 64 72 65 73 73 20 6f  eturns address o
5020: 66 20 6e 65 78 74 20 6e 6f 64 65 20 65 6c 73 65  f next node else
5030: 20 4e 6f 6e 65 22 0a 20 20 20 20 20 20 20 20 77   None".        w
5040: 68 69 6c 65 20 54 72 75 65 3a 0a 20 20 20 20 20  hile True:.     
5050: 20 20 20 20 20 20 20 69 45 6e 64 41 72 63 41 64         iEndArcAd
5060: 64 72 20 3d 20 69 41 64 64 72 2b 73 65 6c 66 2e  dr = iAddr+self.
5070: 6e 42 79 74 65 73 41 72 63 0a 20 20 20 20 20 20  nBytesArc.      
5080: 20 20 20 20 20 20 6e 52 61 77 41 72 63 20 3d 20        nRawArc = 
5090: 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73  int.from_bytes(s
50a0: 65 6c 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a  elf.byDic[iAddr:
50b0: 69 45 6e 64 41 72 63 41 64 64 72 5d 2c 20 62 79  iEndArcAddr], by
50c0: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20  teorder='big'). 
50d0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 56             if nV
50e0: 61 6c 20 3d 3d 20 28 6e 52 61 77 41 72 63 20 26  al == (nRawArc &
50f0: 20 73 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 29 3a   self._arcMask):
5100: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5110: 20 23 20 74 68 65 20 76 61 6c 75 65 20 77 65 20   # the value we 
5120: 61 72 65 20 6c 6f 6f 6b 69 6e 67 20 66 6f 72 20  are looking for 
5130: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5140: 20 23 20 77 65 20 72 65 74 75 72 6e 20 74 68 65   # we return the
5150: 20 61 64 64 72 65 73 73 20 6f 66 20 74 68 65 20   address of the 
5160: 6e 65 78 74 20 6e 6f 64 65 0a 20 20 20 20 20 20  next node.      
5170: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
5180: 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28   int.from_bytes(
5190: 73 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41  self.byDic[iEndA
51a0: 72 63 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64  rcAddr:iEndArcAd
51b0: 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f  dr+self.nBytesNo
51c0: 64 65 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65  deAddress], byte
51d0: 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20  order='big').   
51e0: 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20           else:. 
51f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
5200: 20 76 61 6c 75 65 20 6e 6f 74 20 66 6f 75 6e 64   value not found
5210: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5220: 20 69 66 20 28 6e 52 61 77 41 72 63 20 26 20 73   if (nRawArc & s
5230: 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b  elf._lastArcMask
5240: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
5250: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 4e 6f         return No
5260: 6e 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ne.             
5270: 20 20 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41     iAddr = iEndA
5280: 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74  rcAddr+self.nByt
5290: 65 73 4e 6f 64 65 41 64 64 72 65 73 73 0a 0a 20  esNodeAddress.. 
52a0: 20 20 20 64 65 66 20 5f 67 65 74 41 72 63 73 31     def _getArcs1
52b0: 20 28 73 65 6c 66 2c 20 69 41 64 64 72 29 3a 0a   (self, iAddr):.
52c0: 20 20 20 20 20 20 20 20 22 67 65 6e 65 72 61 74          "generat
52d0: 6f 72 3a 20 72 65 74 75 72 6e 20 61 6c 6c 20 61  or: return all a
52e0: 72 63 73 20 61 74 20 3c 69 41 64 64 72 3e 20 61  rcs at <iAddr> a
52f0: 73 20 74 75 70 6c 65 73 20 6f 66 20 28 6e 56 61  s tuples of (nVa
5300: 6c 2c 20 69 41 64 64 72 29 22 0a 20 20 20 20 20  l, iAddr)".     
5310: 20 20 20 77 68 69 6c 65 20 54 72 75 65 3a 0a 20     while True:. 
5320: 20 20 20 20 20 20 20 20 20 20 20 69 45 6e 64 41             iEndA
5330: 72 63 41 64 64 72 20 3d 20 69 41 64 64 72 2b 73  rcAddr = iAddr+s
5340: 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a 20 20  elf.nBytesArc.  
5350: 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72            nRawAr
5360: 63 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74  c = int.from_byt
5370: 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 41  es(self.byDic[iA
5380: 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72 5d  ddr:iEndArcAddr]
5390: 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67  , byteorder='big
53a0: 27 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 79  ').            y
53b0: 69 65 6c 64 20 28 6e 52 61 77 41 72 63 20 26 20  ield (nRawArc & 
53c0: 73 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 2c 20 69  self._arcMask, i
53d0: 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65  nt.from_bytes(se
53e0: 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41 72 63  lf.byDic[iEndArc
53f0: 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72  Addr:iEndArcAddr
5400: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65  +self.nBytesNode
5410: 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65 6f 72  Address], byteor
5420: 64 65 72 3d 27 62 69 67 27 29 29 0a 20 20 20 20  der='big')).    
5430: 20 20 20 20 20 20 20 20 69 66 20 28 6e 52 61 77          if (nRaw
5440: 41 72 63 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74  Arc & self._last
5450: 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20  ArcMask):.      
5460: 20 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 0a            break.
5470: 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64              iAdd
5480: 72 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72 2b  r = iEndArcAddr+
5490: 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41  self.nBytesNodeA
54a0: 64 64 72 65 73 73 0a 0a 20 20 20 20 64 65 66 20  ddress..    def 
54b0: 5f 77 72 69 74 65 4e 6f 64 65 73 31 20 28 73 65  _writeNodes1 (se
54c0: 6c 66 2c 20 73 70 66 44 65 73 74 29 3a 0a 20 20  lf, spfDest):.  
54d0: 20 20 20 20 20 20 22 66 6f 72 20 64 65 62 75 67        "for debug
54e0: 67 69 6e 67 20 6f 6e 6c 79 22 0a 20 20 20 20 20  ging only".     
54f0: 20 20 20 70 72 69 6e 74 28 22 20 3e 20 57 72 69     print(" > Wri
5500: 74 65 20 62 69 6e 61 72 79 20 6e 6f 64 65 73 22  te binary nodes"
5510: 29 0a 20 20 20 20 20 20 20 20 77 69 74 68 20 63  ).        with c
5520: 6f 64 65 63 73 2e 6f 70 65 6e 28 73 70 66 44 65  odecs.open(spfDe
5530: 73 74 2c 20 27 77 27 2c 20 27 75 74 66 2d 38 27  st, 'w', 'utf-8'
5540: 2c 20 6e 65 77 6c 69 6e 65 3d 22 5c 6e 22 29 20  , newline="\n") 
5550: 61 73 20 68 44 73 74 3a 0a 20 20 20 20 20 20 20  as hDst:.       
5560: 20 20 20 20 20 69 41 64 64 72 20 3d 20 30 0a 20       iAddr = 0. 
5570: 20 20 20 20 20 20 20 20 20 20 20 68 44 73 74 2e             hDst.
5580: 77 72 69 74 65 28 22 69 7b 3a 5f 3e 31 30 7d 20  write("i{:_>10} 
5590: 2d 2d 20 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66  -- #{:_>10}\n".f
55a0: 6f 72 6d 61 74 28 22 30 22 2c 20 69 41 64 64 72  ormat("0", iAddr
55b0: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 77  )).            w
55c0: 68 69 6c 65 20 69 41 64 64 72 20 3c 20 6c 65 6e  hile iAddr < len
55d0: 28 73 65 6c 66 2e 62 79 44 69 63 29 3a 0a 20 20  (self.byDic):.  
55e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 45                iE
55f0: 6e 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64  ndArcAddr = iAdd
5600: 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63  r+self.nBytesArc
5610: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5620: 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74 2e 66   nRawArc = int.f
5630: 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62  rom_bytes(self.b
5640: 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e 64 41  yDic[iAddr:iEndA
5650: 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f 72 64  rcAddr], byteord
5660: 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20  er='big').      
5670: 20 20 20 20 20 20 20 20 20 20 6e 41 72 63 20 3d            nArc =
5680: 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e   nRawArc & self.
5690: 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20 20 20  _arcMask.       
56a0: 20 20 20 20 20 20 20 20 20 68 44 73 74 2e 77 72           hDst.wr
56b0: 69 74 65 28 22 20 20 7b 3a 3c 32 30 7d 20 20 7b  ite("  {:<20}  {
56c0: 3a 30 3e 31 36 7d 20 20 69 7b 3a 3e 31 30 7d 20  :0>16}  i{:>10} 
56d0: 20 20 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f    #{:_>10}\n".fo
56e0: 72 6d 61 74 28 73 65 6c 66 2e 6c 41 72 63 56 61  rmat(self.lArcVa
56f0: 6c 5b 6e 41 72 63 5d 2c 20 62 69 6e 28 6e 52 61  l[nArc], bin(nRa
5700: 77 41 72 63 29 5b 32 3a 5d 2c 20 22 3f 22 2c 20  wArc)[2:], "?", 
5710: 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  \.              
5720: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5750: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 6e                in
5760: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
5770: 66 2e 62 79 44 69 63 5b 69 45 6e 64 41 72 63 41  f.byDic[iEndArcA
5780: 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64 72 2b  ddr:iEndArcAddr+
5790: 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41  self.nBytesNodeA
57a0: 64 64 72 65 73 73 5d 2c 20 5c 0a 20 20 20 20 20  ddress], \.     
57b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
57c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
57d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
57e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
57f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5800: 20 20 20 20 20 20 62 79 74 65 6f 72 64 65 72 3d        byteorder=
5810: 27 62 69 67 27 29 29 29 0a 20 20 20 20 20 20 20  'big'))).       
5820: 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d           iAddr =
5830: 20 69 45 6e 64 41 72 63 41 64 64 72 2b 73 65 6c   iEndArcAddr+sel
5840: 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72  f.nBytesNodeAddr
5850: 65 73 73 0a 20 20 20 20 20 20 20 20 20 20 20 20  ess.            
5860: 20 20 20 20 69 66 20 28 6e 52 61 77 41 72 63 20      if (nRawArc 
5870: 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d  & self._lastArcM
5880: 61 73 6b 29 20 61 6e 64 20 69 41 64 64 72 20 3c  ask) and iAddr <
5890: 20 6c 65 6e 28 73 65 6c 66 2e 62 79 44 69 63 29   len(self.byDic)
58a0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
58b0: 20 20 20 20 20 20 68 44 73 74 2e 77 72 69 74 65        hDst.write
58c0: 28 22 5c 6e 69 7b 3a 5f 3e 31 30 7d 20 2d 2d 20  ("\ni{:_>10} -- 
58d0: 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d  #{:_>10}\n".form
58e0: 61 74 28 22 3f 22 2c 20 69 41 64 64 72 29 29 0a  at("?", iAddr)).
58f0: 20 20 20 20 20 20 20 20 20 20 20 20 68 44 73 74              hDst
5900: 2e 63 6c 6f 73 65 28 29 0a 0a 20 20 20 20 23 20  .close()..    # 
5910: 56 45 52 53 49 4f 4e 20 32 0a 20 20 20 20 64 65  VERSION 2.    de
5920: 66 20 5f 6d 6f 72 70 68 32 20 28 73 65 6c 66 2c  f _morph2 (self,
5930: 20 73 57 6f 72 64 29 3a 0a 20 20 20 20 20 20 20   sWord):.       
5940: 20 22 72 65 74 75 72 6e 73 20 6d 6f 72 70 68 6f   "returns morpho
5950: 6c 6f 67 69 65 73 20 6f 66 20 3c 73 57 6f 72 64  logies of <sWord
5960: 3e 22 0a 20 20 20 20 20 20 20 20 69 41 64 64 72  >".        iAddr
5970: 20 3d 20 30 0a 20 20 20 20 20 20 20 20 66 6f 72   = 0.        for
5980: 20 63 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20 20   c in sWord:.   
5990: 20 20 20 20 20 20 20 20 20 69 66 20 63 20 6e 6f           if c no
59a0: 74 20 69 6e 20 73 65 6c 66 2e 64 43 68 61 72 3a  t in self.dChar:
59b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
59c0: 20 72 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20 20   return [].     
59d0: 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 73         iAddr = s
59e0: 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f  elf._lookupArcNo
59f0: 64 65 28 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d  de(self.dChar[c]
5a00: 2c 20 69 41 64 64 72 29 0a 20 20 20 20 20 20 20  , iAddr).       
5a10: 20 20 20 20 20 69 66 20 69 41 64 64 72 20 3d 3d       if iAddr ==
5a20: 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 20   None:.         
5a30: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d         return []
5a40: 0a 20 20 20 20 20 20 20 20 69 66 20 28 69 6e 74  .        if (int
5a50: 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66  .from_bytes(self
5a60: 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 41 64  .byDic[iAddr:iAd
5a70: 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72  dr+self.nBytesAr
5a80: 63 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62  c], byteorder='b
5a90: 69 67 27 29 20 26 20 73 65 6c 66 2e 5f 66 69 6e  ig') & self._fin
5aa0: 61 6c 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20 20 20  alNodeMask):.   
5ab0: 20 20 20 20 20 20 20 20 20 6c 20 3d 20 5b 5d 0a           l = [].
5ac0: 20 20 20 20 20 20 20 20 20 20 20 20 6e 52 61 77              nRaw
5ad0: 41 72 63 20 3d 20 30 0a 20 20 20 20 20 20 20 20  Arc = 0.        
5ae0: 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28 6e      while not (n
5af0: 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 6c  RawArc & self._l
5b00: 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20  astArcMask):.   
5b10: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 45 6e               iEn
5b20: 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64 72  dArcAddr = iAddr
5b30: 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72   + self.nBytesAr
5b40: 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  c.              
5b50: 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74 2e    nRawArc = int.
5b60: 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e  from_bytes(self.
5b70: 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e 64  byDic[iAddr:iEnd
5b80: 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f 72  ArcAddr], byteor
5b90: 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20  der='big').     
5ba0: 20 20 20 20 20 20 20 20 20 20 20 6e 41 72 63 20             nArc 
5bb0: 3d 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66  = nRawArc & self
5bc0: 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20 20  ._arcMask.      
5bd0: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 41 72            if nAr
5be0: 63 20 3e 3d 20 73 65 6c 66 2e 6e 43 68 61 72 3a  c >= self.nChar:
5bf0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5c00: 20 20 20 20 20 23 20 54 68 69 73 20 76 61 6c 75       # This valu
5c10: 65 20 69 73 20 6e 6f 74 20 61 20 63 68 61 72 2c  e is not a char,
5c20: 20 74 68 69 73 20 69 73 20 61 20 73 74 65 6d 6d   this is a stemm
5c30: 69 6e 67 20 63 6f 64 65 20 0a 20 20 20 20 20 20  ing code .      
5c40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 53                sS
5c50: 74 65 6d 20 3d 20 22 3e 22 20 2b 20 73 65 6c 66  tem = ">" + self
5c60: 2e 66 75 6e 63 53 74 65 6d 6d 69 6e 67 28 73 57  .funcStemming(sW
5c70: 6f 72 64 2c 20 73 65 6c 66 2e 6c 41 72 63 56 61  ord, self.lArcVa
5c80: 6c 5b 6e 41 72 63 5d 29 0a 20 20 20 20 20 20 20  l[nArc]).       
5c90: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 4e               # N
5ca0: 6f 77 20 2c 20 77 65 20 67 6f 20 74 6f 20 74 68  ow , we go to th
5cb0: 65 20 6e 65 78 74 20 6e 6f 64 65 20 61 6e 64 20  e next node and 
5cc0: 72 65 74 72 69 65 76 65 20 61 6c 6c 20 66 6f 6c  retrieve all fol
5cd0: 6c 6f 77 69 6e 67 20 61 72 63 73 20 76 61 6c 75  lowing arcs valu
5ce0: 65 73 2c 20 61 6c 6c 20 6f 66 20 74 68 65 6d 20  es, all of them 
5cf0: 61 72 65 20 74 61 67 73 0a 20 20 20 20 20 20 20  are tags.       
5d00: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
5d10: 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73  not (nRawArc & s
5d20: 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b  elf._addrBitMask
5d30: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
5d40: 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72             iAddr
5d50: 32 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74  2 = int.from_byt
5d60: 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 45  es(self.byDic[iE
5d70: 6e 64 41 72 63 41 64 64 72 3a 69 45 6e 64 41 72  ndArcAddr:iEndAr
5d80: 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  cAddr+self.nByte
5d90: 73 4e 6f 64 65 41 64 64 72 65 73 73 5d 2c 20 62  sNodeAddress], b
5da0: 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a  yteorder='big').
5db0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5dc0: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
5dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5de0: 20 20 23 20 77 65 20 67 6f 20 74 6f 20 74 68 65    # we go to the
5df0: 20 65 6e 64 20 6f 66 20 74 68 65 20 6e 6f 64 65   end of the node
5e00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5e10: 20 20 20 20 20 20 20 20 20 69 41 64 64 72 32 20           iAddr2 
5e20: 3d 20 69 45 6e 64 41 72 63 41 64 64 72 0a 20 20  = iEndArcAddr.  
5e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e40: 20 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20        while not 
5e50: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
5e60: 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20  _lastArcMask):. 
5e70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e80: 20 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41             nRawA
5e90: 72 63 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79  rc = int.from_by
5ea0: 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69  tes(self.byDic[i
5eb0: 41 64 64 72 32 3a 69 41 64 64 72 32 2b 73 65 6c  Addr2:iAddr2+sel
5ec0: 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20 62 79  f.nBytesArc], by
5ed0: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20  teorder='big'). 
5ee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ef0: 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72             iAddr
5f00: 32 20 2b 3d 20 73 65 6c 66 2e 6e 42 79 74 65 73  2 += self.nBytes
5f10: 41 72 63 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65  Arc + self.nByte
5f20: 73 4e 6f 64 65 41 64 64 72 65 73 73 0a 20 20 20  sNodeAddress.   
5f30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5f40: 20 6e 52 61 77 41 72 63 32 20 3d 20 30 0a 20 20   nRawArc2 = 0.  
5f50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5f60: 20 20 77 68 69 6c 65 20 6e 6f 74 20 28 6e 52 61    while not (nRa
5f70: 77 41 72 63 32 20 26 20 73 65 6c 66 2e 5f 6c 61  wArc2 & self._la
5f80: 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20  stArcMask):.    
5f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5fa0: 20 20 20 20 69 45 6e 64 41 72 63 41 64 64 72 32      iEndArcAddr2
5fb0: 20 3d 20 69 41 64 64 72 32 20 2b 20 73 65 6c 66   = iAddr2 + self
5fc0: 2e 6e 42 79 74 65 73 41 72 63 0a 20 20 20 20 20  .nBytesArc.     
5fd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5fe0: 20 20 20 6e 52 61 77 41 72 63 32 20 3d 20 69 6e     nRawArc2 = in
5ff0: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
6000: 66 2e 62 79 44 69 63 5b 69 41 64 64 72 32 3a 69  f.byDic[iAddr2:i
6010: 45 6e 64 41 72 63 41 64 64 72 32 5d 2c 20 62 79  EndArcAddr2], by
6020: 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20  teorder='big'). 
6030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6040: 20 20 20 20 20 20 20 6c 2e 61 70 70 65 6e 64 28         l.append(
6050: 73 53 74 65 6d 20 2b 20 22 20 22 20 2b 20 73 65  sStem + " " + se
6060: 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 52 61 77 41  lf.lArcVal[nRawA
6070: 72 63 32 20 26 20 73 65 6c 66 2e 5f 61 72 63 4d  rc2 & self._arcM
6080: 61 73 6b 5d 29 0a 20 20 20 20 20 20 20 20 20 20  ask]).          
6090: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41                iA
60a0: 64 64 72 32 20 3d 20 69 45 6e 64 41 72 63 41 64  ddr2 = iEndArcAd
60b0: 64 72 32 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e  dr2+self.nBytesN
60c0: 6f 64 65 41 64 64 72 65 73 73 20 20 69 66 20 6e  odeAddress  if n
60d0: 6f 74 20 28 6e 52 61 77 41 72 63 32 20 26 20 73  ot (nRawArc2 & s
60e0: 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b  elf._addrBitMask
60f0: 29 20 65 6c 73 65 20 69 45 6e 64 41 72 63 41 64  ) else iEndArcAd
6100: 64 72 32 0a 20 20 20 20 20 20 20 20 20 20 20 20  dr2.            
6110: 20 20 20 20 69 41 64 64 72 20 3d 20 69 45 6e 64      iAddr = iEnd
6120: 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79  ArcAddr+self.nBy
6130: 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 20 20  tesNodeAddress  
6140: 69 66 20 6e 6f 74 20 28 6e 52 61 77 41 72 63 20  if not (nRawArc 
6150: 26 20 73 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d  & self._addrBitM
6160: 61 73 6b 29 20 20 65 6c 73 65 20 69 45 6e 64 41  ask)  else iEndA
6170: 72 63 41 64 64 72 0a 20 20 20 20 20 20 20 20 20  rcAddr.         
6180: 20 20 20 72 65 74 75 72 6e 20 6c 0a 20 20 20 20     return l.    
6190: 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 0a 20      return [].. 
61a0: 20 20 20 64 65 66 20 5f 73 74 65 6d 32 20 28 73     def _stem2 (s
61b0: 65 6c 66 2c 20 73 57 6f 72 64 29 3a 0a 20 20 20  elf, sWord):.   
61c0: 20 20 20 20 20 22 72 65 74 75 72 6e 73 20 73 74       "returns st
61d0: 65 6d 73 20 6c 69 73 74 20 6f 66 20 3c 73 57 6f  ems list of <sWo
61e0: 72 64 3e 22 0a 20 20 20 20 20 20 20 20 69 41 64  rd>".        iAd
61f0: 64 72 20 3d 20 30 0a 20 20 20 20 20 20 20 20 66  dr = 0.        f
6200: 6f 72 20 63 20 69 6e 20 73 57 6f 72 64 3a 0a 20  or c in sWord:. 
6210: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 63 20             if c 
6220: 6e 6f 74 20 69 6e 20 73 65 6c 66 2e 64 43 68 61  not in self.dCha
6230: 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r:.             
6240: 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 20 20 20     return [].   
6250: 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d           iAddr =
6260: 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63   self._lookupArc
6270: 4e 6f 64 65 28 73 65 6c 66 2e 64 43 68 61 72 5b  Node(self.dChar[
6280: 63 5d 2c 20 69 41 64 64 72 29 0a 20 20 20 20 20  c], iAddr).     
6290: 20 20 20 20 20 20 20 69 66 20 69 41 64 64 72 20         if iAddr 
62a0: 3d 3d 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20  == None:.       
62b0: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
62c0: 5b 5d 0a 20 20 20 20 20 20 20 20 69 66 20 28 69  [].        if (i
62d0: 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65  nt.from_bytes(se
62e0: 6c 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69  lf.byDic[iAddr:i
62f0: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
6300: 41 72 63 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d  Arc], byteorder=
6310: 27 62 69 67 27 29 20 26 20 73 65 6c 66 2e 5f 66  'big') & self._f
6320: 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20  inalNodeMask):. 
6330: 20 20 20 20 20 20 20 20 20 20 20 6c 20 3d 20 5b             l = [
6340: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e 52  ].            nR
6350: 61 77 41 72 63 20 3d 20 30 0a 20 20 20 20 20 20  awArc = 0.      
6360: 20 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20        while not 
6370: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
6380: 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20  _lastArcMask):. 
6390: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
63a0: 45 6e 64 41 72 63 41 64 64 72 20 3d 20 69 41 64  EndArcAddr = iAd
63b0: 64 72 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73  dr + self.nBytes
63c0: 41 72 63 0a 20 20 20 20 20 20 20 20 20 20 20 20  Arc.            
63d0: 20 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e      nRawArc = in
63e0: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
63f0: 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45  f.byDic[iAddr:iE
6400: 6e 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65  ndArcAddr], byte
6410: 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20  order='big').   
6420: 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 41 72               nAr
6430: 63 20 3d 20 6e 52 61 77 41 72 63 20 26 20 73 65  c = nRawArc & se
6440: 6c 66 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20  lf._arcMask.    
6450: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
6460: 41 72 63 20 3e 3d 20 73 65 6c 66 2e 6e 43 68 61  Arc >= self.nCha
6470: 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  r:.             
6480: 20 20 20 20 20 20 20 23 20 54 68 69 73 20 76 61         # This va
6490: 6c 75 65 20 69 73 20 6e 6f 74 20 61 20 63 68 61  lue is not a cha
64a0: 72 2c 20 74 68 69 73 20 69 73 20 61 20 73 74 65  r, this is a ste
64b0: 6d 6d 69 6e 67 20 63 6f 64 65 20 0a 20 20 20 20  mming code .    
64c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
64d0: 6c 2e 61 70 70 65 6e 64 28 73 65 6c 66 2e 66 75  l.append(self.fu
64e0: 6e 63 53 74 65 6d 6d 69 6e 67 28 73 57 6f 72 64  ncStemming(sWord
64f0: 2c 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e  , self.lArcVal[n
6500: 41 72 63 5d 29 29 0a 20 20 20 20 20 20 20 20 20  Arc])).         
6510: 20 20 20 20 20 20 20 20 20 20 20 23 20 4e 6f 77             # Now
6520: 20 2c 20 77 65 20 67 6f 20 74 6f 20 74 68 65 20   , we go to the 
6530: 6e 65 78 74 20 6e 6f 64 65 0a 20 20 20 20 20 20  next node.      
6540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
6550: 20 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20   not (nRawArc & 
6560: 73 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73  self._addrBitMas
6570: 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  k):.            
6580: 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64              iAdd
6590: 72 32 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79  r2 = int.from_by
65a0: 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69  tes(self.byDic[i
65b0: 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e 64 41  EndArcAddr:iEndA
65c0: 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74  rcAddr+self.nByt
65d0: 65 73 4e 6f 64 65 41 64 64 72 65 73 73 5d 2c 20  esNodeAddress], 
65e0: 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29  byteorder='big')
65f0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6600: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
6610: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6620: 20 20 20 23 20 77 65 20 67 6f 20 74 6f 20 74 68     # we go to th
6630: 65 20 65 6e 64 20 6f 66 20 74 68 65 20 6e 6f 64  e end of the nod
6640: 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e.              
6650: 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72 32            iAddr2
6660: 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72 0a 20   = iEndArcAddr. 
6670: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6680: 20 20 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74         while not
6690: 20 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66   (nRawArc & self
66a0: 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a  ._lastArcMask):.
66b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
66c0: 20 20 20 20 20 20 20 20 20 20 20 20 6e 52 61 77              nRaw
66d0: 41 72 63 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62  Arc = int.from_b
66e0: 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b  ytes(self.byDic[
66f0: 69 41 64 64 72 32 3a 69 41 64 64 72 32 2b 73 65  iAddr2:iAddr2+se
6700: 6c 66 2e 6e 42 79 74 65 73 41 72 63 5d 2c 20 62  lf.nBytesArc], b
6710: 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a  yteorder='big').
6720: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6730: 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64              iAdd
6740: 72 32 20 2b 3d 20 73 65 6c 66 2e 6e 42 79 74 65  r2 += self.nByte
6750: 73 41 72 63 20 2b 20 73 65 6c 66 2e 6e 42 79 74  sArc + self.nByt
6760: 65 73 4e 6f 64 65 41 64 64 72 65 73 73 0a 20 20  esNodeAddress.  
6770: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41                iA
6780: 64 64 72 20 3d 20 69 45 6e 64 41 72 63 41 64 64  ddr = iEndArcAdd
6790: 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64  r+self.nBytesNod
67a0: 65 41 64 64 72 65 73 73 20 20 69 66 20 6e 6f 74  eAddress  if not
67b0: 20 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66   (nRawArc & self
67c0: 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 20 20  ._addrBitMask)  
67d0: 65 6c 73 65 20 69 45 6e 64 41 72 63 41 64 64 72  else iEndArcAddr
67e0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
67f0: 75 72 6e 20 6c 0a 20 20 20 20 20 20 20 20 72 65  urn l.        re
6800: 74 75 72 6e 20 5b 5d 0a 0a 20 20 20 20 64 65 66  turn []..    def
6810: 20 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64 65 32   _lookupArcNode2
6820: 20 28 73 65 6c 66 2c 20 6e 56 61 6c 2c 20 69 41   (self, nVal, iA
6830: 64 64 72 29 3a 0a 20 20 20 20 20 20 20 20 22 6c  ddr):.        "l
6840: 6f 6f 6b 73 20 69 66 20 3c 6e 56 61 6c 3e 20 69  ooks if <nVal> i
6850: 73 20 61 6e 20 61 72 63 20 61 74 20 74 68 65 20  s an arc at the 
6860: 6e 6f 64 65 20 61 74 20 3c 69 41 64 64 72 3e 2c  node at <iAddr>,
6870: 20 69 66 20 79 65 73 2c 20 72 65 74 75 72 6e 73   if yes, returns
6880: 20 61 64 64 72 65 73 73 20 6f 66 20 6e 65 78 74   address of next
6890: 20 6e 6f 64 65 20 65 6c 73 65 20 4e 6f 6e 65 22   node else None"
68a0: 0a 20 20 20 20 20 20 20 20 77 68 69 6c 65 20 54  .        while T
68b0: 72 75 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  rue:.           
68c0: 20 69 45 6e 64 41 72 63 41 64 64 72 20 3d 20 69   iEndArcAddr = i
68d0: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
68e0: 41 72 63 0a 20 20 20 20 20 20 20 20 20 20 20 20  Arc.            
68f0: 6e 52 61 77 41 72 63 20 3d 20 69 6e 74 2e 66 72  nRawArc = int.fr
6900: 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79  om_bytes(self.by
6910: 44 69 63 5b 69 41 64 64 72 3a 69 45 6e 64 41 72  Dic[iAddr:iEndAr
6920: 63 41 64 64 72 5d 2c 20 62 79 74 65 6f 72 64 65  cAddr], byteorde
6930: 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20 20  r='big').       
6940: 20 20 20 20 20 69 66 20 6e 56 61 6c 20 3d 3d 20       if nVal == 
6950: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
6960: 5f 61 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20  _arcMask):.     
6970: 20 20 20 20 20 20 20 20 20 20 20 23 20 74 68 65             # the
6980: 20 76 61 6c 75 65 20 77 65 20 61 72 65 20 6c 6f   value we are lo
6990: 6f 6b 69 6e 67 20 66 6f 72 20 0a 20 20 20 20 20  oking for .     
69a0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f             if no
69b0: 74 20 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c  t (nRawArc & sel
69c0: 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 3a  f._addrBitMask):
69d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
69e0: 20 20 20 20 20 23 20 77 65 20 72 65 74 75 72 6e       # we return
69f0: 20 74 68 65 20 61 64 64 72 65 73 73 20 6f 66 20   the address of 
6a00: 74 68 65 20 6e 65 78 74 20 6e 6f 64 65 0a 20 20  the next node.  
6a10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6a20: 20 20 72 65 74 75 72 6e 20 69 6e 74 2e 66 72 6f    return int.fro
6a30: 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44  m_bytes(self.byD
6a40: 69 63 5b 69 45 6e 64 41 72 63 41 64 64 72 3a 69  ic[iEndArcAddr:i
6a50: 45 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e  EndArcAddr+self.
6a60: 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73  nBytesNodeAddres
6a70: 73 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62  s], byteorder='b
6a80: 69 67 27 29 0a 20 20 20 20 20 20 20 20 20 20 20  ig').           
6a90: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
6aa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
6ab0: 20 77 65 20 67 6f 20 74 6f 20 74 68 65 20 65 6e   we go to the en
6ac0: 64 20 6f 66 20 74 68 65 20 6e 6f 64 65 0a 20 20  d of the node.  
6ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ae0: 20 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72    iAddr = iEndAr
6af0: 63 41 64 64 72 0a 20 20 20 20 20 20 20 20 20 20  cAddr.          
6b00: 20 20 20 20 20 20 20 20 20 20 77 68 69 6c 65 20            while 
6b10: 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73  not (nRawArc & s
6b20: 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b  elf._lastArcMask
6b30: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
6b40: 20 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41             nRawA
6b50: 72 63 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f 62 79  rc = int.from_by
6b60: 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69  tes(self.byDic[i
6b70: 41 64 64 72 3a 69 41 64 64 72 2b 73 65 6c 66 2e  Addr:iAddr+self.
6b80: 6e 42 79 74 65 73 41 72 63 5d 2c 20 62 79 74 65  nBytesArc], byte
6b90: 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20  order='big').   
6ba0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6bb0: 20 20 20 20 20 69 41 64 64 72 20 2b 3d 20 73 65       iAddr += se
6bc0: 6c 66 2e 6e 42 79 74 65 73 41 72 63 20 2b 20 73  lf.nBytesArc + s
6bd0: 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64  elf.nBytesNodeAd
6be0: 64 72 65 73 73 20 20 69 66 20 6e 6f 74 20 28 6e  dress  if not (n
6bf0: 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61  RawArc & self._a
6c00: 64 64 72 42 69 74 4d 61 73 6b 29 20 20 65 6c 73  ddrBitMask)  els
6c10: 65 20 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63  e self.nBytesArc
6c20: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6c30: 20 20 20 20 20 72 65 74 75 72 6e 20 69 41 64 64       return iAdd
6c40: 72 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c  r.            el
6c50: 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
6c60: 20 20 20 20 23 20 76 61 6c 75 65 20 6e 6f 74 20      # value not 
6c70: 66 6f 75 6e 64 0a 20 20 20 20 20 20 20 20 20 20  found.          
6c80: 20 20 20 20 20 20 69 66 20 28 6e 52 61 77 41 72        if (nRawAr
6c90: 63 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72  c & self._lastAr
6ca0: 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20 20  cMask):.        
6cb0: 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
6cc0: 72 6e 20 4e 6f 6e 65 0a 20 20 20 20 20 20 20 20  rn None.        
6cd0: 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d 20          iAddr = 
6ce0: 69 45 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66  iEndArcAddr+self
6cf0: 2e 6e 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65  .nBytesNodeAddre
6d00: 73 73 20 20 69 66 20 6e 6f 74 20 28 6e 52 61 77  ss  if not (nRaw
6d10: 41 72 63 20 26 20 73 65 6c 66 2e 5f 61 64 64 72  Arc & self._addr
6d20: 42 69 74 4d 61 73 6b 29 20 20 65 6c 73 65 20 69  BitMask)  else i
6d30: 45 6e 64 41 72 63 41 64 64 72 0a 0a 20 20 20 20  EndArcAddr..    
6d40: 64 65 66 20 5f 77 72 69 74 65 4e 6f 64 65 73 32  def _writeNodes2
6d50: 20 28 73 65 6c 66 2c 20 73 70 66 44 65 73 74 29   (self, spfDest)
6d60: 3a 0a 20 20 20 20 20 20 20 20 22 66 6f 72 20 64  :.        "for d
6d70: 65 62 75 67 67 69 6e 67 20 6f 6e 6c 79 22 0a 20  ebugging only". 
6d80: 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 20 3e         print(" >
6d90: 20 57 72 69 74 65 20 62 69 6e 61 72 79 20 6e 6f   Write binary no
6da0: 64 65 73 22 29 0a 20 20 20 20 20 20 20 20 77 69  des").        wi
6db0: 74 68 20 63 6f 64 65 63 73 2e 6f 70 65 6e 28 73  th codecs.open(s
6dc0: 70 66 44 65 73 74 2c 20 27 77 27 2c 20 27 75 74  pfDest, 'w', 'ut
6dd0: 66 2d 38 27 2c 20 6e 65 77 6c 69 6e 65 3d 22 5c  f-8', newline="\
6de0: 6e 22 29 20 61 73 20 68 44 73 74 3a 0a 20 20 20  n") as hDst:.   
6df0: 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d           iAddr =
6e00: 20 30 0a 20 20 20 20 20 20 20 20 20 20 20 20 68   0.            h
6e10: 44 73 74 2e 77 72 69 74 65 28 22 69 7b 3a 5f 3e  Dst.write("i{:_>
6e20: 31 30 7d 20 2d 2d 20 23 7b 3a 5f 3e 31 30 7d 5c  10} -- #{:_>10}\
6e30: 6e 22 2e 66 6f 72 6d 61 74 28 22 30 22 2c 20 69  n".format("0", i
6e40: 41 64 64 72 29 29 0a 20 20 20 20 20 20 20 20 20  Addr)).         
6e50: 20 20 20 77 68 69 6c 65 20 69 41 64 64 72 20 3c     while iAddr <
6e60: 20 6c 65 6e 28 73 65 6c 66 2e 62 79 44 69 63 29   len(self.byDic)
6e70: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
6e80: 20 20 69 45 6e 64 41 72 63 41 64 64 72 20 3d 20    iEndArcAddr = 
6e90: 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  iAddr+self.nByte
6ea0: 73 41 72 63 0a 20 20 20 20 20 20 20 20 20 20 20  sArc.           
6eb0: 20 20 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69       nRawArc = i
6ec0: 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65  nt.from_bytes(se
6ed0: 6c 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69  lf.byDic[iAddr:i
6ee0: 45 6e 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74  EndArcAddr], byt
6ef0: 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20  eorder='big').  
6f00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 41                nA
6f10: 72 63 20 3d 20 6e 52 61 77 41 72 63 20 26 20 73  rc = nRawArc & s
6f20: 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20  elf._arcMask.   
6f30: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
6f40: 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73  not (nRawArc & s
6f50: 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b  elf._addrBitMask
6f60: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
6f70: 20 20 20 20 20 20 20 69 4e 65 78 74 4e 6f 64 65         iNextNode
6f80: 41 64 64 72 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f  Addr = int.from_
6f90: 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63  bytes(self.byDic
6fa0: 5b 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e  [iEndArcAddr:iEn
6fb0: 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dArcAddr+self.nB
6fc0: 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 5d  ytesNodeAddress]
6fd0: 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67  , byteorder='big
6fe0: 27 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ').             
6ff0: 20 20 20 20 20 20 20 68 44 73 74 2e 77 72 69 74         hDst.writ
7000: 65 28 22 20 20 7b 3a 3c 32 30 7d 20 20 7b 3a 30  e("  {:<20}  {:0
7010: 3e 31 36 7d 20 20 69 7b 3a 3e 31 30 7d 20 20 20  >16}  i{:>10}   
7020: 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d  #{:_>10}\n".form
7030: 61 74 28 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b  at(self.lArcVal[
7040: 6e 41 72 63 5d 2c 20 62 69 6e 28 6e 52 61 77 41  nArc], bin(nRawA
7050: 72 63 29 5b 32 3a 5d 2c 20 22 3f 22 2c 20 69 4e  rc)[2:], "?", iN
7060: 65 78 74 4e 6f 64 65 41 64 64 72 29 29 0a 20 20  extNodeAddr)).  
7070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7080: 20 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72    iAddr = iEndAr
7090: 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  cAddr+self.nByte
70a0: 73 4e 6f 64 65 41 64 64 72 65 73 73 0a 20 20 20  sNodeAddress.   
70b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73               els
70c0: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
70d0: 20 20 20 20 20 20 20 68 44 73 74 2e 77 72 69 74         hDst.writ
70e0: 65 28 22 20 20 7b 3a 3c 32 30 7d 20 20 7b 3a 30  e("  {:<20}  {:0
70f0: 3e 31 36 7d 5c 6e 22 2e 66 6f 72 6d 61 74 28 73  >16}\n".format(s
7100: 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 41 72 63  elf.lArcVal[nArc
7110: 5d 2c 20 62 69 6e 28 6e 52 61 77 41 72 63 29 5b  ], bin(nRawArc)[
7120: 32 3a 5d 29 29 0a 20 20 20 20 20 20 20 20 20 20  2:])).          
7130: 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20            iAddr 
7140: 3d 20 69 45 6e 64 41 72 63 41 64 64 72 0a 20 20  = iEndArcAddr.  
7150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
7160: 20 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66   (nRawArc & self
7170: 2e 5f 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a  ._lastArcMask):.
7180: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7190: 20 20 20 20 68 44 73 74 2e 77 72 69 74 65 28 22      hDst.write("
71a0: 5c 6e 69 7b 3a 5f 3e 31 30 7d 20 2d 2d 20 23 7b  \ni{:_>10} -- #{
71b0: 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d 61 74  :_>10}\n".format
71c0: 28 22 3f 22 2c 20 69 41 64 64 72 29 29 0a 20 20  ("?", iAddr)).  
71d0: 20 20 20 20 20 20 20 20 20 20 68 44 73 74 2e 63            hDst.c
71e0: 6c 6f 73 65 28 29 0a 0a 20 20 20 20 23 20 56 45  lose()..    # VE
71f0: 52 53 49 4f 4e 20 33 0a 20 20 20 20 64 65 66 20  RSION 3.    def 
7200: 5f 6d 6f 72 70 68 33 20 28 73 65 6c 66 2c 20 73  _morph3 (self, s
7210: 57 6f 72 64 29 3a 0a 20 20 20 20 20 20 20 20 22  Word):.        "
7220: 72 65 74 75 72 6e 73 20 6d 6f 72 70 68 6f 6c 6f  returns morpholo
7230: 67 69 65 73 20 6f 66 20 3c 73 57 6f 72 64 3e 22  gies of <sWord>"
7240: 0a 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d  .        iAddr =
7250: 20 30 0a 20 20 20 20 20 20 20 20 66 6f 72 20 63   0.        for c
7260: 20 69 6e 20 73 57 6f 72 64 3a 0a 20 20 20 20 20   in sWord:.     
7270: 20 20 20 20 20 20 20 69 66 20 63 20 6e 6f 74 20         if c not 
7280: 69 6e 20 73 65 6c 66 2e 64 43 68 61 72 3a 0a 20  in self.dChar:. 
7290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72                 r
72a0: 65 74 75 72 6e 20 5b 5d 0a 20 20 20 20 20 20 20  eturn [].       
72b0: 20 20 20 20 20 69 41 64 64 72 20 3d 20 73 65 6c       iAddr = sel
72c0: 66 2e 5f 6c 6f 6f 6b 75 70 41 72 63 4e 6f 64 65  f._lookupArcNode
72d0: 28 73 65 6c 66 2e 64 43 68 61 72 5b 63 5d 2c 20  (self.dChar[c], 
72e0: 69 41 64 64 72 29 0a 20 20 20 20 20 20 20 20 20  iAddr).         
72f0: 20 20 20 69 66 20 69 41 64 64 72 20 3d 3d 20 4e     if iAddr == N
7300: 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  one:.           
7310: 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 20       return []. 
7320: 20 20 20 20 20 20 20 69 66 20 28 69 6e 74 2e 66         if (int.f
7330: 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62  rom_bytes(self.b
7340: 79 44 69 63 5b 69 41 64 64 72 3a 69 41 64 64 72  yDic[iAddr:iAddr
7350: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 5d  +self.nBytesArc]
7360: 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67  , byteorder='big
7370: 27 29 20 26 20 73 65 6c 66 2e 5f 66 69 6e 61 6c  ') & self._final
7380: 4e 6f 64 65 4d 61 73 6b 29 3a 0a 20 20 20 20 20  NodeMask):.     
7390: 20 20 20 20 20 20 20 6c 20 3d 20 5b 5d 0a 20 20         l = [].  
73a0: 20 20 20 20 20 20 20 20 20 20 6e 52 61 77 41 72            nRawAr
73b0: 63 20 3d 20 30 0a 20 20 20 20 20 20 20 20 20 20  c = 0.          
73c0: 20 20 69 41 64 64 72 4e 6f 64 65 20 3d 20 69 41    iAddrNode = iA
73d0: 64 64 72 0a 20 20 20 20 20 20 20 20 20 20 20 20  ddr.            
73e0: 77 68 69 6c 65 20 6e 6f 74 20 28 6e 52 61 77 41  while not (nRawA
73f0: 72 63 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41  rc & self._lastA
7400: 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20  rcMask):.       
7410: 20 20 20 20 20 20 20 20 20 69 45 6e 64 41 72 63           iEndArc
7420: 41 64 64 72 20 3d 20 69 41 64 64 72 20 2b 20 73  Addr = iAddr + s
7430: 65 6c 66 2e 6e 42 79 74 65 73 41 72 63 0a 20 20  elf.nBytesArc.  
7440: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 52                nR
7450: 61 77 41 72 63 20 3d 20 69 6e 74 2e 66 72 6f 6d  awArc = int.from
7460: 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69  _bytes(self.byDi
7470: 63 5b 69 41 64 64 72 3a 69 45 6e 64 41 72 63 41  c[iAddr:iEndArcA
7480: 64 64 72 5d 2c 20 62 79 74 65 6f 72 64 65 72 3d  ddr], byteorder=
7490: 27 62 69 67 27 29 0a 20 20 20 20 20 20 20 20 20  'big').         
74a0: 20 20 20 20 20 20 20 6e 41 72 63 20 3d 20 6e 52         nArc = nR
74b0: 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f 61 72  awArc & self._ar
74c0: 63 4d 61 73 6b 0a 20 20 20 20 20 20 20 20 20 20  cMask.          
74d0: 20 20 20 20 20 20 69 66 20 6e 41 72 63 20 3e 3d        if nArc >=
74e0: 20 73 65 6c 66 2e 6e 43 68 61 72 3a 0a 20 20 20   self.nChar:.   
74f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7500: 20 23 20 54 68 69 73 20 76 61 6c 75 65 20 69 73   # This value is
7510: 20 6e 6f 74 20 61 20 63 68 61 72 2c 20 74 68 69   not a char, thi
7520: 73 20 69 73 20 61 20 73 74 65 6d 6d 69 6e 67 20  s is a stemming 
7530: 63 6f 64 65 20 0a 20 20 20 20 20 20 20 20 20 20  code .          
7540: 20 20 20 20 20 20 20 20 20 20 73 53 74 65 6d 20            sStem 
7550: 3d 20 22 3e 22 20 2b 20 73 65 6c 66 2e 66 75 6e  = ">" + self.fun
7560: 63 53 74 65 6d 6d 69 6e 67 28 73 57 6f 72 64 2c  cStemming(sWord,
7570: 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 41   self.lArcVal[nA
7580: 72 63 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20  rc]).           
7590: 20 20 20 20 20 20 20 20 20 23 20 4e 6f 77 20 2c           # Now ,
75a0: 20 77 65 20 67 6f 20 74 6f 20 74 68 65 20 6e 65   we go to the ne
75b0: 78 74 20 6e 6f 64 65 20 61 6e 64 20 72 65 74 72  xt node and retr
75c0: 69 65 76 65 20 61 6c 6c 20 66 6f 6c 6c 6f 77 69  ieve all followi
75d0: 6e 67 20 61 72 63 73 20 76 61 6c 75 65 73 2c 20  ng arcs values, 
75e0: 61 6c 6c 20 6f 66 20 74 68 65 6d 20 61 72 65 20  all of them are 
75f0: 74 61 67 73 0a 20 20 20 20 20 20 20 20 20 20 20  tags.           
7600: 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20           if not 
7610: 28 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e  (nRawArc & self.
7620: 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 3a 0a 20  _addrBitMask):. 
7630: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7640: 20 20 20 20 20 20 20 69 41 64 64 72 32 20 3d 20         iAddr2 = 
7650: 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73  int.from_bytes(s
7660: 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41 72  elf.byDic[iEndAr
7670: 63 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64  cAddr:iEndArcAdd
7680: 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64  r+self.nBytesNod
7690: 65 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65 6f  eAddress], byteo
76a0: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
76b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
76c0: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
76d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41                iA
76e0: 64 64 72 32 20 3d 20 69 41 64 64 72 4e 6f 64 65  ddr2 = iAddrNode
76f0: 20 2b 20 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65   + int.from_byte
7700: 73 28 73 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e  s(self.byDic[iEn
7710: 64 41 72 63 41 64 64 72 3a 69 45 6e 64 41 72 63  dArcAddr:iEndArc
7720: 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73  Addr+self.nBytes
7730: 4f 66 66 73 65 74 5d 2c 20 62 79 74 65 6f 72 64  Offset], byteord
7740: 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20 20 20  er='big').      
7750: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 52                nR
7760: 61 77 41 72 63 32 20 3d 20 30 0a 20 20 20 20 20  awArc2 = 0.     
7770: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 77                 w
7780: 68 69 6c 65 20 6e 6f 74 20 28 6e 52 61 77 41 72  hile not (nRawAr
7790: 63 32 20 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41  c2 & self._lastA
77a0: 72 63 4d 61 73 6b 29 3a 0a 20 20 20 20 20 20 20  rcMask):.       
77b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
77c0: 20 69 45 6e 64 41 72 63 41 64 64 72 32 20 3d 20   iEndArcAddr2 = 
77d0: 69 41 64 64 72 32 20 2b 20 73 65 6c 66 2e 6e 42  iAddr2 + self.nB
77e0: 79 74 65 73 41 72 63 0a 20 20 20 20 20 20 20 20  ytesArc.        
77f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7800: 6e 52 61 77 41 72 63 32 20 3d 20 69 6e 74 2e 66  nRawArc2 = int.f
7810: 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62  rom_bytes(self.b
7820: 79 44 69 63 5b 69 41 64 64 72 32 3a 69 45 6e 64  yDic[iAddr2:iEnd
7830: 41 72 63 41 64 64 72 32 5d 2c 20 62 79 74 65 6f  ArcAddr2], byteo
7840: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
7850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7860: 20 20 20 20 6c 2e 61 70 70 65 6e 64 28 73 53 74      l.append(sSt
7870: 65 6d 20 2b 20 22 20 22 20 2b 20 73 65 6c 66 2e  em + " " + self.
7880: 6c 41 72 63 56 61 6c 5b 6e 52 61 77 41 72 63 32  lArcVal[nRawArc2
7890: 20 26 20 73 65 6c 66 2e 5f 61 72 63 4d 61 73 6b   & self._arcMask
78a0: 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]).             
78b0: 20 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72             iAddr
78c0: 32 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72 32  2 = iEndArcAddr2
78d0: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64 65  +self.nBytesNode
78e0: 41 64 64 72 65 73 73 20 20 69 66 20 6e 6f 74 20  Address  if not 
78f0: 28 6e 52 61 77 41 72 63 32 20 26 20 73 65 6c 66  (nRawArc2 & self
7900: 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b 29 20 65  ._addrBitMask) e
7910: 6c 73 65 20 69 45 6e 64 41 72 63 41 64 64 72 32  lse iEndArcAddr2
7920: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4f 66 66 73  +self.nBytesOffs
7930: 65 74 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  et.             
7940: 20 20 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41     iAddr = iEndA
7950: 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74  rcAddr+self.nByt
7960: 65 73 4e 6f 64 65 41 64 64 72 65 73 73 20 20 69  esNodeAddress  i
7970: 66 20 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26  f not (nRawArc &
7980: 20 73 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61   self._addrBitMa
7990: 73 6b 29 20 20 65 6c 73 65 20 69 45 6e 64 41 72  sk)  else iEndAr
79a0: 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  cAddr+self.nByte
79b0: 73 4f 66 66 73 65 74 0a 20 20 20 20 20 20 20 20  sOffset.        
79c0: 20 20 20 20 72 65 74 75 72 6e 20 6c 0a 20 20 20      return l.   
79d0: 20 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 0a       return []..
79e0: 20 20 20 20 64 65 66 20 5f 73 74 65 6d 33 20 28      def _stem3 (
79f0: 73 65 6c 66 2c 20 73 57 6f 72 64 29 3a 0a 20 20  self, sWord):.  
7a00: 20 20 20 20 20 20 22 72 65 74 75 72 6e 73 20 73        "returns s
7a10: 74 65 6d 73 20 6c 69 73 74 20 6f 66 20 3c 73 57  tems list of <sW
7a20: 6f 72 64 3e 22 0a 20 20 20 20 20 20 20 20 69 41  ord>".        iA
7a30: 64 64 72 20 3d 20 30 0a 20 20 20 20 20 20 20 20  ddr = 0.        
7a40: 66 6f 72 20 63 20 69 6e 20 73 57 6f 72 64 3a 0a  for c in sWord:.
7a50: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 63              if c
7a60: 20 6e 6f 74 20 69 6e 20 73 65 6c 66 2e 64 43 68   not in self.dCh
7a70: 61 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ar:.            
7a80: 20 20 20 20 72 65 74 75 72 6e 20 5b 5d 0a 20 20      return [].  
7a90: 20 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20            iAddr 
7aa0: 3d 20 73 65 6c 66 2e 5f 6c 6f 6f 6b 75 70 41 72  = self._lookupAr
7ab0: 63 4e 6f 64 65 28 73 65 6c 66 2e 64 43 68 61 72  cNode(self.dChar
7ac0: 5b 63 5d 2c 20 69 41 64 64 72 29 0a 20 20 20 20  [c], iAddr).    
7ad0: 20 20 20 20 20 20 20 20 69 66 20 69 41 64 64 72          if iAddr
7ae0: 20 3d 3d 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20   == None:.      
7af0: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
7b00: 20 5b 5d 0a 20 20 20 20 20 20 20 20 69 66 20 28   [].        if (
7b10: 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73  int.from_bytes(s
7b20: 65 6c 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a  elf.byDic[iAddr:
7b30: 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  iAddr+self.nByte
7b40: 73 41 72 63 5d 2c 20 62 79 74 65 6f 72 64 65 72  sArc], byteorder
7b50: 3d 27 62 69 67 27 29 20 26 20 73 65 6c 66 2e 5f  ='big') & self._
7b60: 66 69 6e 61 6c 4e 6f 64 65 4d 61 73 6b 29 3a 0a  finalNodeMask):.
7b70: 20 20 20 20 20 20 20 20 20 20 20 20 6c 20 3d 20              l = 
7b80: 5b 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e  [].            n
7b90: 52 61 77 41 72 63 20 3d 20 30 0a 20 20 20 20 20  RawArc = 0.     
7ba0: 20 20 20 20 20 20 20 69 41 64 64 72 4e 6f 64 65         iAddrNode
7bb0: 20 3d 20 69 41 64 64 72 0a 20 20 20 20 20 20 20   = iAddr.       
7bc0: 20 20 20 20 20 77 68 69 6c 65 20 6e 6f 74 20 28       while not (
7bd0: 6e 52 61 77 41 72 63 20 26 20 73 65 6c 66 2e 5f  nRawArc & self._
7be0: 6c 61 73 74 41 72 63 4d 61 73 6b 29 3a 0a 20 20  lastArcMask):.  
7bf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 45                iE
7c00: 6e 64 41 72 63 41 64 64 72 20 3d 20 69 41 64 64  ndArcAddr = iAdd
7c10: 72 20 2b 20 73 65 6c 66 2e 6e 42 79 74 65 73 41  r + self.nBytesA
7c20: 72 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  rc.             
7c30: 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e 74     nRawArc = int
7c40: 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c 66  .from_bytes(self
7c50: 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45 6e  .byDic[iAddr:iEn
7c60: 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65 6f  dArcAddr], byteo
7c70: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
7c80: 20 20 20 20 20 20 20 20 20 20 20 20 6e 41 72 63              nArc
7c90: 20 3d 20 6e 52 61 77 41 72 63 20 26 20 73 65 6c   = nRawArc & sel
7ca0: 66 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20 20 20  f._arcMask.     
7cb0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 41             if nA
7cc0: 72 63 20 3e 3d 20 73 65 6c 66 2e 6e 43 68 61 72  rc >= self.nChar
7cd0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
7ce0: 20 20 20 20 20 20 23 20 54 68 69 73 20 76 61 6c        # This val
7cf0: 75 65 20 69 73 20 6e 6f 74 20 61 20 63 68 61 72  ue is not a char
7d00: 2c 20 74 68 69 73 20 69 73 20 61 20 73 74 65 6d  , this is a stem
7d10: 6d 69 6e 67 20 63 6f 64 65 20 0a 20 20 20 20 20  ming code .     
7d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c                 l
7d30: 2e 61 70 70 65 6e 64 28 73 65 6c 66 2e 66 75 6e  .append(self.fun
7d40: 63 53 74 65 6d 6d 69 6e 67 28 73 57 6f 72 64 2c  cStemming(sWord,
7d50: 20 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 41   self.lArcVal[nA
7d60: 72 63 5d 29 29 0a 20 20 20 20 20 20 20 20 20 20  rc])).          
7d70: 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 69 45        iAddr = iE
7d80: 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e  ndArcAddr+self.n
7d90: 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73  BytesNodeAddress
7da0: 20 20 69 66 20 6e 6f 74 20 28 6e 52 61 77 41 72    if not (nRawAr
7db0: 63 20 26 20 73 65 6c 66 2e 5f 61 64 64 72 42 69  c & self._addrBi
7dc0: 74 4d 61 73 6b 29 20 20 65 6c 73 65 20 69 45 6e  tMask)  else iEn
7dd0: 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dArcAddr+self.nB
7de0: 79 74 65 73 4f 66 66 73 65 74 0a 20 20 20 20 20  ytesOffset.     
7df0: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 6c 0a         return l.
7e00: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 5b          return [
7e10: 5d 0a 0a 20 20 20 20 64 65 66 20 5f 6c 6f 6f 6b  ]..    def _look
7e20: 75 70 41 72 63 4e 6f 64 65 33 20 28 73 65 6c 66  upArcNode3 (self
7e30: 2c 20 6e 56 61 6c 2c 20 69 41 64 64 72 29 3a 0a  , nVal, iAddr):.
7e40: 20 20 20 20 20 20 20 20 22 6c 6f 6f 6b 73 20 69          "looks i
7e50: 66 20 3c 6e 56 61 6c 3e 20 69 73 20 61 6e 20 61  f <nVal> is an a
7e60: 72 63 20 61 74 20 74 68 65 20 6e 6f 64 65 20 61  rc at the node a
7e70: 74 20 3c 69 41 64 64 72 3e 2c 20 69 66 20 79 65  t <iAddr>, if ye
7e80: 73 2c 20 72 65 74 75 72 6e 73 20 61 64 64 72 65  s, returns addre
7e90: 73 73 20 6f 66 20 6e 65 78 74 20 6e 6f 64 65 20  ss of next node 
7ea0: 65 6c 73 65 20 4e 6f 6e 65 22 0a 20 20 20 20 20  else None".     
7eb0: 20 20 20 69 41 64 64 72 4e 6f 64 65 20 3d 20 69     iAddrNode = i
7ec0: 41 64 64 72 0a 20 20 20 20 20 20 20 20 77 68 69  Addr.        whi
7ed0: 6c 65 20 54 72 75 65 3a 0a 20 20 20 20 20 20 20  le True:.       
7ee0: 20 20 20 20 20 69 45 6e 64 41 72 63 41 64 64 72       iEndArcAddr
7ef0: 20 3d 20 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42   = iAddr+self.nB
7f00: 79 74 65 73 41 72 63 0a 20 20 20 20 20 20 20 20  ytesArc.        
7f10: 20 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69 6e      nRawArc = in
7f20: 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65 6c  t.from_bytes(sel
7f30: 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69 45  f.byDic[iAddr:iE
7f40: 6e 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74 65  ndArcAddr], byte
7f50: 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20  order='big').   
7f60: 20 20 20 20 20 20 20 20 20 69 66 20 6e 56 61 6c           if nVal
7f70: 20 3d 3d 20 28 6e 52 61 77 41 72 63 20 26 20 73   == (nRawArc & s
7f80: 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 29 3a 0a 20  elf._arcMask):. 
7f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
7fa0: 20 74 68 65 20 76 61 6c 75 65 20 77 65 20 61 72   the value we ar
7fb0: 65 20 6c 6f 6f 6b 69 6e 67 20 66 6f 72 20 0a 20  e looking for . 
7fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
7fd0: 66 20 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26  f not (nRawArc &
7fe0: 20 73 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61   self._addrBitMa
7ff0: 73 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  sk):.           
8000: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
8010: 69 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73  int.from_bytes(s
8020: 65 6c 66 2e 62 79 44 69 63 5b 69 45 6e 64 41 72  elf.byDic[iEndAr
8030: 63 41 64 64 72 3a 69 45 6e 64 41 72 63 41 64 64  cAddr:iEndArcAdd
8040: 72 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4e 6f 64  r+self.nBytesNod
8050: 65 41 64 64 72 65 73 73 5d 2c 20 62 79 74 65 6f  eAddress], byteo
8060: 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20 20 20  rder='big').    
8070: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
8080: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
8090: 20 20 20 20 20 20 72 65 74 75 72 6e 20 69 41 64        return iAd
80a0: 64 72 4e 6f 64 65 20 2b 20 69 6e 74 2e 66 72 6f  drNode + int.fro
80b0: 6d 5f 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44  m_bytes(self.byD
80c0: 69 63 5b 69 45 6e 64 41 72 63 41 64 64 72 3a 69  ic[iEndArcAddr:i
80d0: 45 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e  EndArcAddr+self.
80e0: 6e 42 79 74 65 73 4f 66 66 73 65 74 5d 2c 20 62  nBytesOffset], b
80f0: 79 74 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a  yteorder='big').
8100: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
8110: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
8120: 20 20 23 20 76 61 6c 75 65 20 6e 6f 74 20 66 6f    # value not fo
8130: 75 6e 64 0a 20 20 20 20 20 20 20 20 20 20 20 20  und.            
8140: 20 20 20 20 69 66 20 28 6e 52 61 77 41 72 63 20      if (nRawArc 
8150: 26 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d  & self._lastArcM
8160: 61 73 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20  ask):.          
8170: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
8180: 20 4e 6f 6e 65 0a 20 20 20 20 20 20 20 20 20 20   None.          
8190: 20 20 20 20 20 20 69 41 64 64 72 20 3d 20 69 45        iAddr = iE
81a0: 6e 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e  ndArcAddr+self.n
81b0: 42 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73  BytesNodeAddress
81c0: 20 20 69 66 20 6e 6f 74 20 28 6e 52 61 77 41 72    if not (nRawAr
81d0: 63 20 26 20 73 65 6c 66 2e 5f 61 64 64 72 42 69  c & self._addrBi
81e0: 74 4d 61 73 6b 29 20 20 65 6c 73 65 20 69 45 6e  tMask)  else iEn
81f0: 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dArcAddr+self.nB
8200: 79 74 65 73 4f 66 66 73 65 74 0a 0a 20 20 20 20  ytesOffset..    
8210: 64 65 66 20 5f 77 72 69 74 65 4e 6f 64 65 73 33  def _writeNodes3
8220: 20 28 73 65 6c 66 2c 20 73 70 66 44 65 73 74 29   (self, spfDest)
8230: 3a 0a 20 20 20 20 20 20 20 20 22 66 6f 72 20 64  :.        "for d
8240: 65 62 75 67 67 69 6e 67 20 6f 6e 6c 79 22 0a 20  ebugging only". 
8250: 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 20 3e         print(" >
8260: 20 57 72 69 74 65 20 62 69 6e 61 72 79 20 6e 6f   Write binary no
8270: 64 65 73 22 29 0a 20 20 20 20 20 20 20 20 77 69  des").        wi
8280: 74 68 20 63 6f 64 65 63 73 2e 6f 70 65 6e 28 73  th codecs.open(s
8290: 70 66 44 65 73 74 2c 20 27 77 27 2c 20 27 75 74  pfDest, 'w', 'ut
82a0: 66 2d 38 27 2c 20 6e 65 77 6c 69 6e 65 3d 22 5c  f-8', newline="\
82b0: 6e 22 29 20 61 73 20 68 44 73 74 3a 0a 20 20 20  n") as hDst:.   
82c0: 20 20 20 20 20 20 20 20 20 69 41 64 64 72 20 3d           iAddr =
82d0: 20 30 0a 20 20 20 20 20 20 20 20 20 20 20 20 68   0.            h
82e0: 44 73 74 2e 77 72 69 74 65 28 22 69 7b 3a 5f 3e  Dst.write("i{:_>
82f0: 31 30 7d 20 2d 2d 20 23 7b 3a 5f 3e 31 30 7d 5c  10} -- #{:_>10}\
8300: 6e 22 2e 66 6f 72 6d 61 74 28 22 30 22 2c 20 69  n".format("0", i
8310: 41 64 64 72 29 29 0a 20 20 20 20 20 20 20 20 20  Addr)).         
8320: 20 20 20 77 68 69 6c 65 20 69 41 64 64 72 20 3c     while iAddr <
8330: 20 6c 65 6e 28 73 65 6c 66 2e 62 79 44 69 63 29   len(self.byDic)
8340: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
8350: 20 20 69 45 6e 64 41 72 63 41 64 64 72 20 3d 20    iEndArcAddr = 
8360: 69 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  iAddr+self.nByte
8370: 73 41 72 63 0a 20 20 20 20 20 20 20 20 20 20 20  sArc.           
8380: 20 20 20 20 20 6e 52 61 77 41 72 63 20 3d 20 69       nRawArc = i
8390: 6e 74 2e 66 72 6f 6d 5f 62 79 74 65 73 28 73 65  nt.from_bytes(se
83a0: 6c 66 2e 62 79 44 69 63 5b 69 41 64 64 72 3a 69  lf.byDic[iAddr:i
83b0: 45 6e 64 41 72 63 41 64 64 72 5d 2c 20 62 79 74  EndArcAddr], byt
83c0: 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20  eorder='big').  
83d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 41                nA
83e0: 72 63 20 3d 20 6e 52 61 77 41 72 63 20 26 20 73  rc = nRawArc & s
83f0: 65 6c 66 2e 5f 61 72 63 4d 61 73 6b 0a 20 20 20  elf._arcMask.   
8400: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
8410: 6e 6f 74 20 28 6e 52 61 77 41 72 63 20 26 20 73  not (nRawArc & s
8420: 65 6c 66 2e 5f 61 64 64 72 42 69 74 4d 61 73 6b  elf._addrBitMask
8430: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
8440: 20 20 20 20 20 20 20 69 4e 65 78 74 4e 6f 64 65         iNextNode
8450: 41 64 64 72 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f  Addr = int.from_
8460: 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63  bytes(self.byDic
8470: 5b 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e  [iEndArcAddr:iEn
8480: 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dArcAddr+self.nB
8490: 79 74 65 73 4e 6f 64 65 41 64 64 72 65 73 73 5d  ytesNodeAddress]
84a0: 2c 20 62 79 74 65 6f 72 64 65 72 3d 27 62 69 67  , byteorder='big
84b0: 27 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ').             
84c0: 20 20 20 20 20 20 20 68 44 73 74 2e 77 72 69 74         hDst.writ
84d0: 65 28 22 20 20 7b 3a 3c 32 30 7d 20 20 7b 3a 30  e("  {:<20}  {:0
84e0: 3e 31 36 7d 20 20 69 7b 3a 3e 31 30 7d 20 20 20  >16}  i{:>10}   
84f0: 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66 6f 72 6d  #{:_>10}\n".form
8500: 61 74 28 73 65 6c 66 2e 6c 41 72 63 56 61 6c 5b  at(self.lArcVal[
8510: 6e 41 72 63 5d 2c 20 62 69 6e 28 6e 52 61 77 41  nArc], bin(nRawA
8520: 72 63 29 5b 32 3a 5d 2c 20 22 3f 22 2c 20 69 4e  rc)[2:], "?", iN
8530: 65 78 74 4e 6f 64 65 41 64 64 72 29 29 0a 20 20  extNodeAddr)).  
8540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8550: 20 20 69 41 64 64 72 20 3d 20 69 45 6e 64 41 72    iAddr = iEndAr
8560: 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42 79 74 65  cAddr+self.nByte
8570: 73 4e 6f 64 65 41 64 64 72 65 73 73 0a 20 20 20  sNodeAddress.   
8580: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73               els
8590: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
85a0: 20 20 20 20 20 20 20 69 4e 65 78 74 4e 6f 64 65         iNextNode
85b0: 41 64 64 72 20 3d 20 69 6e 74 2e 66 72 6f 6d 5f  Addr = int.from_
85c0: 62 79 74 65 73 28 73 65 6c 66 2e 62 79 44 69 63  bytes(self.byDic
85d0: 5b 69 45 6e 64 41 72 63 41 64 64 72 3a 69 45 6e  [iEndArcAddr:iEn
85e0: 64 41 72 63 41 64 64 72 2b 73 65 6c 66 2e 6e 42  dArcAddr+self.nB
85f0: 79 74 65 73 4f 66 66 73 65 74 5d 2c 20 62 79 74  ytesOffset], byt
8600: 65 6f 72 64 65 72 3d 27 62 69 67 27 29 0a 20 20  eorder='big').  
8610: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8620: 20 20 68 44 73 74 2e 77 72 69 74 65 28 22 20 20    hDst.write("  
8630: 7b 3a 3c 32 30 7d 20 20 7b 3a 30 3e 31 36 7d 20  {:<20}  {:0>16} 
8640: 20 69 7b 3a 3e 31 30 7d 20 20 20 2b 7b 3a 5f 3e   i{:>10}   +{:_>
8650: 31 30 7d 5c 6e 22 2e 66 6f 72 6d 61 74 28 73 65  10}\n".format(se
8660: 6c 66 2e 6c 41 72 63 56 61 6c 5b 6e 41 72 63 5d  lf.lArcVal[nArc]
8670: 2c 20 62 69 6e 28 6e 52 61 77 41 72 63 29 5b 32  , bin(nRawArc)[2
8680: 3a 5d 2c 20 22 3f 22 2c 20 69 4e 65 78 74 4e 6f  :], "?", iNextNo
8690: 64 65 41 64 64 72 29 29 0a 20 20 20 20 20 20 20  deAddr)).       
86a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 41 64               iAd
86b0: 64 72 20 3d 20 69 45 6e 64 41 72 63 41 64 64 72  dr = iEndArcAddr
86c0: 2b 73 65 6c 66 2e 6e 42 79 74 65 73 4f 66 66 73  +self.nBytesOffs
86d0: 65 74 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  et.             
86e0: 20 20 20 69 66 20 28 6e 52 61 77 41 72 63 20 26     if (nRawArc &
86f0: 20 73 65 6c 66 2e 5f 6c 61 73 74 41 72 63 4d 61   self._lastArcMa
8700: 73 6b 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  sk):.           
8710: 20 20 20 20 20 20 20 20 20 68 44 73 74 2e 77 72           hDst.wr
8720: 69 74 65 28 22 5c 6e 69 7b 3a 5f 3e 31 30 7d 20  ite("\ni{:_>10} 
8730: 2d 2d 20 23 7b 3a 5f 3e 31 30 7d 5c 6e 22 2e 66  -- #{:_>10}\n".f
8740: 6f 72 6d 61 74 28 22 3f 22 2c 20 69 41 64 64 72  ormat("?", iAddr
8750: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 68  )).            h
8760: 44 73 74 2e 63 6c 6f 73 65 28 29 0a              Dst.close().