Grammalecte  Hex Artifact Content

Artifact b1e910dee6b8efbf98dce8fea7cce13cbdb2fddab69fc547d562ff35f656c29f:


0000: 22 22 22 0a 47 72 61 6d 6d 61 6c 65 63 74 65 0a  """.Grammalecte.
0010: 47 72 61 6d 6d 61 72 20 63 68 65 63 6b 65 72 20  Grammar checker 
0020: 65 6e 67 69 6e 65 0a 22 22 22 0a 0a 69 6d 70 6f  engine."""..impo
0030: 72 74 20 72 65 0a 69 6d 70 6f 72 74 20 74 72 61  rt re.import tra
0040: 63 65 62 61 63 6b 0a 23 69 6d 70 6f 72 74 20 75  ceback.#import u
0050: 6e 69 63 6f 64 65 64 61 74 61 0a 66 72 6f 6d 20  nicodedata.from 
0060: 69 74 65 72 74 6f 6f 6c 73 20 69 6d 70 6f 72 74  itertools import
0070: 20 63 68 61 69 6e 0a 0a 66 72 6f 6d 20 2e 2e 67   chain..from ..g
0080: 72 61 70 68 73 70 65 6c 6c 2e 73 70 65 6c 6c 63  raphspell.spellc
0090: 68 65 63 6b 65 72 20 69 6d 70 6f 72 74 20 53 70  hecker import Sp
00a0: 65 6c 6c 43 68 65 63 6b 65 72 0a 66 72 6f 6d 20  ellChecker.from 
00b0: 2e 2e 67 72 61 70 68 73 70 65 6c 6c 2e 65 63 68  ..graphspell.ech
00c0: 6f 20 69 6d 70 6f 72 74 20 65 63 68 6f 0a 66 72  o import echo.fr
00d0: 6f 6d 20 2e 20 69 6d 70 6f 72 74 20 67 63 5f 6f  om . import gc_o
00e0: 70 74 69 6f 6e 73 0a 0a 74 72 79 3a 0a 20 20 20  ptions..try:.   
00f0: 20 23 20 4c 69 62 72 65 4f 66 66 69 63 65 20 2f   # LibreOffice /
0100: 20 4f 70 65 6e 4f 66 66 69 63 65 0a 20 20 20 20   OpenOffice.    
0110: 66 72 6f 6d 20 63 6f 6d 2e 73 75 6e 2e 73 74 61  from com.sun.sta
0120: 72 2e 6c 69 6e 67 75 69 73 74 69 63 32 20 69 6d  r.linguistic2 im
0130: 70 6f 72 74 20 53 69 6e 67 6c 65 50 72 6f 6f 66  port SingleProof
0140: 72 65 61 64 69 6e 67 45 72 72 6f 72 0a 20 20 20  readingError.   
0150: 20 66 72 6f 6d 20 63 6f 6d 2e 73 75 6e 2e 73 74   from com.sun.st
0160: 61 72 2e 74 65 78 74 2e 54 65 78 74 4d 61 72 6b  ar.text.TextMark
0170: 75 70 54 79 70 65 20 69 6d 70 6f 72 74 20 50 52  upType import PR
0180: 4f 4f 46 52 45 41 44 49 4e 47 0a 20 20 20 20 66  OOFREADING.    f
0190: 72 6f 6d 20 63 6f 6d 2e 73 75 6e 2e 73 74 61 72  rom com.sun.star
01a0: 2e 62 65 61 6e 73 20 69 6d 70 6f 72 74 20 50 72  .beans import Pr
01b0: 6f 70 65 72 74 79 56 61 6c 75 65 0a 20 20 20 20  opertyValue.    
01c0: 23 69 6d 70 6f 72 74 20 6c 69 67 68 74 70 72 6f  #import lightpro
01d0: 6f 66 5f 68 61 6e 64 6c 65 72 5f 24 7b 69 6d 70  of_handler_${imp
01e0: 6c 6e 61 6d 65 7d 20 61 73 20 6f 70 74 0a 20 20  lname} as opt.  
01f0: 20 20 5f 62 57 72 69 74 65 72 45 72 72 6f 72 20    _bWriterError 
0200: 3d 20 54 72 75 65 0a 65 78 63 65 70 74 20 49 6d  = True.except Im
0210: 70 6f 72 74 45 72 72 6f 72 3a 0a 20 20 20 20 5f  portError:.    _
0220: 62 57 72 69 74 65 72 45 72 72 6f 72 20 3d 20 46  bWriterError = F
0230: 61 6c 73 65 0a 0a 0a 5f 5f 61 6c 6c 5f 5f 20 3d  alse...__all__ =
0240: 20 5b 20 22 6c 61 6e 67 22 2c 20 22 6c 6f 63 61   [ "lang", "loca
0250: 6c 65 73 22 2c 20 22 70 6b 67 22 2c 20 22 6e 61  les", "pkg", "na
0260: 6d 65 22 2c 20 22 76 65 72 73 69 6f 6e 22 2c 20  me", "version", 
0270: 22 61 75 74 68 6f 72 22 2c 20 5c 0a 20 20 20 20  "author", \.    
0280: 20 20 20 20 20 20 20 20 22 6c 6f 61 64 22 2c 20          "load", 
0290: 22 70 61 72 73 65 22 2c 20 22 67 65 74 53 70 65  "parse", "getSpe
02a0: 6c 6c 43 68 65 63 6b 65 72 22 2c 20 5c 0a 20 20  llChecker", \.  
02b0: 20 20 20 20 20 20 20 20 20 20 22 73 65 74 4f 70            "setOp
02c0: 74 69 6f 6e 22 2c 20 22 73 65 74 4f 70 74 69 6f  tion", "setOptio
02d0: 6e 73 22 2c 20 22 67 65 74 4f 70 74 69 6f 6e 73  ns", "getOptions
02e0: 22 2c 20 22 67 65 74 44 65 66 61 75 6c 74 4f 70  ", "getDefaultOp
02f0: 74 69 6f 6e 73 22 2c 20 22 67 65 74 4f 70 74 69  tions", "getOpti
0300: 6f 6e 73 4c 61 62 65 6c 73 22 2c 20 22 72 65 73  onsLabels", "res
0310: 65 74 4f 70 74 69 6f 6e 73 22 2c 20 22 64 69 73  etOptions", "dis
0320: 70 6c 61 79 4f 70 74 69 6f 6e 73 22 2c 20 5c 0a  playOptions", \.
0330: 20 20 20 20 20 20 20 20 20 20 20 20 22 69 67 6e              "ign
0340: 6f 72 65 52 75 6c 65 22 2c 20 22 72 65 73 65 74  oreRule", "reset
0350: 49 67 6e 6f 72 65 52 75 6c 65 73 22 2c 20 22 72  IgnoreRules", "r
0360: 65 61 63 74 69 76 61 74 65 52 75 6c 65 22 2c 20  eactivateRule", 
0370: 22 6c 69 73 74 52 75 6c 65 73 22 2c 20 22 64 69  "listRules", "di
0380: 73 70 6c 61 79 52 75 6c 65 73 22 20 5d 0a 0a 5f  splayRules" ].._
0390: 5f 76 65 72 73 69 6f 6e 5f 5f 20 3d 20 22 24 7b  _version__ = "${
03a0: 76 65 72 73 69 6f 6e 7d 22 0a 0a 0a 6c 61 6e 67  version}"...lang
03b0: 20 3d 20 22 24 7b 6c 61 6e 67 7d 22 0a 6c 6f 63   = "${lang}".loc
03c0: 61 6c 65 73 20 3d 20 24 7b 6c 6f 63 7d 0a 70 6b  ales = ${loc}.pk
03d0: 67 20 3d 20 22 24 7b 69 6d 70 6c 6e 61 6d 65 7d  g = "${implname}
03e0: 22 0a 6e 61 6d 65 20 3d 20 22 24 7b 6e 61 6d 65  ".name = "${name
03f0: 7d 22 0a 76 65 72 73 69 6f 6e 20 3d 20 22 24 7b  }".version = "${
0400: 76 65 72 73 69 6f 6e 7d 22 0a 61 75 74 68 6f 72  version}".author
0410: 20 3d 20 22 24 7b 61 75 74 68 6f 72 7d 22 0a 0a   = "${author}"..
0420: 23 20 4d 6f 64 75 6c 65 73 0a 5f 72 75 6c 65 73  # Modules._rules
0430: 20 3d 20 4e 6f 6e 65 20 20 20 20 20 20 20 20 20   = None         
0440: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0450: 20 20 20 20 20 20 23 20 6d 6f 64 75 6c 65 20 67        # module g
0460: 63 5f 72 75 6c 65 73 0a 5f 72 75 6c 65 73 5f 67  c_rules._rules_g
0470: 72 61 70 68 20 3d 20 4e 6f 6e 65 20 20 20 20 20  raph = None     
0480: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0490: 20 20 20 20 23 20 6d 6f 64 75 6c 65 20 67 63 5f      # module gc_
04a0: 72 75 6c 65 73 5f 67 72 61 70 68 0a 0a 23 20 44  rules_graph..# D
04b0: 61 74 61 0a 5f 73 41 70 70 43 6f 6e 74 65 78 74  ata._sAppContext
04c0: 20 3d 20 22 22 20 20 20 20 20 20 20 20 20 20 20   = ""           
04d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
04e0: 23 20 77 68 61 74 20 73 6f 66 74 77 61 72 65 20  # what software 
04f0: 69 73 20 72 75 6e 6e 69 6e 67 0a 5f 64 4f 70 74  is running._dOpt
0500: 69 6f 6e 73 20 3d 20 4e 6f 6e 65 0a 5f 6f 53 70  ions = None._oSp
0510: 65 6c 6c 43 68 65 63 6b 65 72 20 3d 20 4e 6f 6e  ellChecker = Non
0520: 65 0a 5f 6f 54 6f 6b 65 6e 69 7a 65 72 20 3d 20  e._oTokenizer = 
0530: 4e 6f 6e 65 0a 5f 61 49 67 6e 6f 72 65 64 52 75  None._aIgnoredRu
0540: 6c 65 73 20 3d 20 73 65 74 28 29 0a 0a 0a 0a 23  les = set()....#
0550: 23 23 23 20 49 6e 69 74 69 61 6c 69 7a 61 74 69  ### Initializati
0560: 6f 6e 0a 0a 64 65 66 20 6c 6f 61 64 20 28 73 43  on..def load (sC
0570: 6f 6e 74 65 78 74 3d 22 50 79 74 68 6f 6e 22 29  ontext="Python")
0580: 3a 0a 20 20 20 20 22 69 6e 69 74 69 61 6c 69 7a  :.    "initializ
0590: 61 74 69 6f 6e 20 6f 66 20 74 68 65 20 67 72 61  ation of the gra
05a0: 6d 6d 61 72 20 63 68 65 63 6b 65 72 22 0a 20 20  mmar checker".  
05b0: 20 20 67 6c 6f 62 61 6c 20 5f 6f 53 70 65 6c 6c    global _oSpell
05c0: 43 68 65 63 6b 65 72 0a 20 20 20 20 67 6c 6f 62  Checker.    glob
05d0: 61 6c 20 5f 73 41 70 70 43 6f 6e 74 65 78 74 0a  al _sAppContext.
05e0: 20 20 20 20 67 6c 6f 62 61 6c 20 5f 64 4f 70 74      global _dOpt
05f0: 69 6f 6e 73 0a 20 20 20 20 67 6c 6f 62 61 6c 20  ions.    global 
0600: 5f 6f 54 6f 6b 65 6e 69 7a 65 72 0a 20 20 20 20  _oTokenizer.    
0610: 74 72 79 3a 0a 20 20 20 20 20 20 20 20 5f 6f 53  try:.        _oS
0620: 70 65 6c 6c 43 68 65 63 6b 65 72 20 3d 20 53 70  pellChecker = Sp
0630: 65 6c 6c 43 68 65 63 6b 65 72 28 22 24 7b 6c 61  ellChecker("${la
0640: 6e 67 7d 22 2c 20 22 24 7b 64 69 63 5f 6d 61 69  ng}", "${dic_mai
0650: 6e 5f 66 69 6c 65 6e 61 6d 65 5f 70 79 7d 22 2c  n_filename_py}",
0660: 20 22 24 7b 64 69 63 5f 65 78 74 65 6e 64 65 64   "${dic_extended
0670: 5f 66 69 6c 65 6e 61 6d 65 5f 70 79 7d 22 2c 20  _filename_py}", 
0680: 22 24 7b 64 69 63 5f 63 6f 6d 6d 75 6e 69 74 79  "${dic_community
0690: 5f 66 69 6c 65 6e 61 6d 65 5f 70 79 7d 22 2c 20  _filename_py}", 
06a0: 22 24 7b 64 69 63 5f 70 65 72 73 6f 6e 61 6c 5f  "${dic_personal_
06b0: 66 69 6c 65 6e 61 6d 65 5f 70 79 7d 22 29 0a 20  filename_py}"). 
06c0: 20 20 20 20 20 20 20 5f 73 41 70 70 43 6f 6e 74         _sAppCont
06d0: 65 78 74 20 3d 20 73 43 6f 6e 74 65 78 74 0a 20  ext = sContext. 
06e0: 20 20 20 20 20 20 20 5f 64 4f 70 74 69 6f 6e 73         _dOptions
06f0: 20 3d 20 64 69 63 74 28 67 63 5f 6f 70 74 69 6f   = dict(gc_optio
0700: 6e 73 2e 67 65 74 4f 70 74 69 6f 6e 73 28 73 43  ns.getOptions(sC
0710: 6f 6e 74 65 78 74 29 29 20 20 20 23 20 64 75 70  ontext))   # dup
0720: 6c 69 63 61 74 69 6f 6e 20 6e 65 63 65 73 73 61  lication necessa
0730: 72 79 2c 20 74 6f 20 62 65 20 61 62 6c 65 20 74  ry, to be able t
0740: 6f 20 72 65 73 65 74 20 74 6f 20 64 65 66 61 75  o reset to defau
0750: 6c 74 0a 20 20 20 20 20 20 20 20 5f 6f 54 6f 6b  lt.        _oTok
0760: 65 6e 69 7a 65 72 20 3d 20 5f 6f 53 70 65 6c 6c  enizer = _oSpell
0770: 43 68 65 63 6b 65 72 2e 67 65 74 54 6f 6b 65 6e  Checker.getToken
0780: 69 7a 65 72 28 29 0a 20 20 20 20 20 20 20 20 5f  izer().        _
0790: 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 61 63  oSpellChecker.ac
07a0: 74 69 76 61 74 65 53 74 6f 72 61 67 65 28 29 0a  tivateStorage().
07b0: 20 20 20 20 65 78 63 65 70 74 3a 0a 20 20 20 20      except:.    
07c0: 20 20 20 20 74 72 61 63 65 62 61 63 6b 2e 70 72      traceback.pr
07d0: 69 6e 74 5f 65 78 63 28 29 0a 0a 0a 64 65 66 20  int_exc()...def 
07e0: 67 65 74 53 70 65 6c 6c 43 68 65 63 6b 65 72 20  getSpellChecker 
07f0: 28 29 3a 0a 20 20 20 20 22 72 65 74 75 72 6e 20  ():.    "return 
0800: 74 68 65 20 73 70 65 6c 6c 63 68 65 63 6b 65 72  the spellchecker
0810: 20 6f 62 6a 65 63 74 22 0a 20 20 20 20 72 65 74   object".    ret
0820: 75 72 6e 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b  urn _oSpellCheck
0830: 65 72 0a 0a 0a 23 23 23 23 20 52 75 6c 65 73 0a  er...#### Rules.
0840: 0a 64 65 66 20 5f 67 65 74 52 75 6c 65 73 20 28  .def _getRules (
0850: 62 50 61 72 61 67 72 61 70 68 29 3a 0a 20 20 20  bParagraph):.   
0860: 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 69 66   try:.        if
0870: 20 6e 6f 74 20 62 50 61 72 61 67 72 61 70 68 3a   not bParagraph:
0880: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
0890: 75 72 6e 20 5f 72 75 6c 65 73 2e 6c 53 65 6e 74  urn _rules.lSent
08a0: 65 6e 63 65 52 75 6c 65 73 0a 20 20 20 20 20 20  enceRules.      
08b0: 20 20 72 65 74 75 72 6e 20 5f 72 75 6c 65 73 2e    return _rules.
08c0: 6c 50 61 72 61 67 72 61 70 68 52 75 6c 65 73 0a  lParagraphRules.
08d0: 20 20 20 20 65 78 63 65 70 74 3a 0a 20 20 20 20      except:.    
08e0: 20 20 20 20 5f 6c 6f 61 64 52 75 6c 65 73 28 29      _loadRules()
08f0: 0a 20 20 20 20 69 66 20 6e 6f 74 20 62 50 61 72  .    if not bPar
0900: 61 67 72 61 70 68 3a 0a 20 20 20 20 20 20 20 20  agraph:.        
0910: 72 65 74 75 72 6e 20 5f 72 75 6c 65 73 2e 6c 53  return _rules.lS
0920: 65 6e 74 65 6e 63 65 52 75 6c 65 73 0a 20 20 20  entenceRules.   
0930: 20 72 65 74 75 72 6e 20 5f 72 75 6c 65 73 2e 6c   return _rules.l
0940: 50 61 72 61 67 72 61 70 68 52 75 6c 65 73 0a 0a  ParagraphRules..
0950: 0a 64 65 66 20 5f 6c 6f 61 64 52 75 6c 65 73 20  .def _loadRules 
0960: 28 29 3a 0a 20 20 20 20 66 72 6f 6d 20 2e 20 69  ():.    from . i
0970: 6d 70 6f 72 74 20 67 63 5f 72 75 6c 65 73 0a 20  mport gc_rules. 
0980: 20 20 20 66 72 6f 6d 20 2e 20 69 6d 70 6f 72 74     from . import
0990: 20 67 63 5f 72 75 6c 65 73 5f 67 72 61 70 68 0a   gc_rules_graph.
09a0: 20 20 20 20 67 6c 6f 62 61 6c 20 5f 72 75 6c 65      global _rule
09b0: 73 0a 20 20 20 20 67 6c 6f 62 61 6c 20 5f 72 75  s.    global _ru
09c0: 6c 65 73 5f 67 72 61 70 68 0a 20 20 20 20 5f 72  les_graph.    _r
09d0: 75 6c 65 73 20 3d 20 67 63 5f 72 75 6c 65 73 0a  ules = gc_rules.
09e0: 20 20 20 20 5f 72 75 6c 65 73 5f 67 72 61 70 68      _rules_graph
09f0: 20 3d 20 67 63 5f 72 75 6c 65 73 5f 67 72 61 70   = gc_rules_grap
0a00: 68 0a 20 20 20 20 23 20 63 6f 6d 70 69 6c 65 20  h.    # compile 
0a10: 72 75 6c 65 73 20 72 65 67 65 78 0a 20 20 20 20  rules regex.    
0a20: 66 6f 72 20 73 4f 70 74 69 6f 6e 2c 20 6c 52 75  for sOption, lRu
0a30: 6c 65 47 72 6f 75 70 20 69 6e 20 63 68 61 69 6e  leGroup in chain
0a40: 28 5f 72 75 6c 65 73 2e 6c 50 61 72 61 67 72 61  (_rules.lParagra
0a50: 70 68 52 75 6c 65 73 2c 20 5f 72 75 6c 65 73 2e  phRules, _rules.
0a60: 6c 53 65 6e 74 65 6e 63 65 52 75 6c 65 73 29 3a  lSentenceRules):
0a70: 0a 20 20 20 20 20 20 20 20 69 66 20 73 4f 70 74  .        if sOpt
0a80: 69 6f 6e 20 21 3d 20 22 40 40 40 40 22 3a 0a 20  ion != "@@@@":. 
0a90: 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 61             for a
0aa0: 52 75 6c 65 20 69 6e 20 6c 52 75 6c 65 47 72 6f  Rule in lRuleGro
0ab0: 75 70 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  up:.            
0ac0: 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20      try:.       
0ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 61 52 75               aRu
0ae0: 6c 65 5b 30 5d 20 3d 20 72 65 2e 63 6f 6d 70 69  le[0] = re.compi
0af0: 6c 65 28 61 52 75 6c 65 5b 30 5d 29 0a 20 20 20  le(aRule[0]).   
0b00: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 78 63               exc
0b10: 65 70 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ept:.           
0b20: 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 42           echo("B
0b30: 61 64 20 72 65 67 75 6c 61 72 20 65 78 70 72 65  ad regular expre
0b40: 73 73 69 6f 6e 20 69 6e 20 23 20 22 20 2b 20 73  ssion in # " + s
0b50: 74 72 28 61 52 75 6c 65 5b 32 5d 29 29 0a 20 20  tr(aRule[2])).  
0b60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0b70: 20 20 61 52 75 6c 65 5b 30 5d 20 3d 20 22 28 3f    aRule[0] = "(?
0b80: 69 29 3c 47 72 61 6d 6d 61 6c 65 63 74 65 3e 22  i)<Grammalecte>"
0b90: 0a 0a 0a 64 65 66 20 69 67 6e 6f 72 65 52 75 6c  ...def ignoreRul
0ba0: 65 20 28 73 52 75 6c 65 49 64 29 3a 0a 20 20 20  e (sRuleId):.   
0bb0: 20 22 64 69 73 61 62 6c 65 20 72 75 6c 65 20 3c   "disable rule <
0bc0: 73 52 75 6c 65 49 64 3e 22 0a 20 20 20 20 5f 61  sRuleId>".    _a
0bd0: 49 67 6e 6f 72 65 64 52 75 6c 65 73 2e 61 64 64  IgnoredRules.add
0be0: 28 73 52 75 6c 65 49 64 29 0a 0a 0a 64 65 66 20  (sRuleId)...def 
0bf0: 72 65 73 65 74 49 67 6e 6f 72 65 52 75 6c 65 73  resetIgnoreRules
0c00: 20 28 29 3a 0a 20 20 20 20 22 63 6c 65 61 72 20   ():.    "clear 
0c10: 61 6c 6c 20 69 67 6e 6f 72 65 64 20 72 75 6c 65  all ignored rule
0c20: 73 22 0a 20 20 20 20 5f 61 49 67 6e 6f 72 65 64  s".    _aIgnored
0c30: 52 75 6c 65 73 2e 63 6c 65 61 72 28 29 0a 0a 0a  Rules.clear()...
0c40: 64 65 66 20 72 65 61 63 74 69 76 61 74 65 52 75  def reactivateRu
0c50: 6c 65 20 28 73 52 75 6c 65 49 64 29 3a 0a 20 20  le (sRuleId):.  
0c60: 20 20 22 28 72 65 29 61 63 74 69 76 61 74 65 20    "(re)activate 
0c70: 72 75 6c 65 20 3c 73 52 75 6c 65 49 64 3e 22 0a  rule <sRuleId>".
0c80: 20 20 20 20 5f 61 49 67 6e 6f 72 65 64 52 75 6c      _aIgnoredRul
0c90: 65 73 2e 64 69 73 63 61 72 64 28 73 52 75 6c 65  es.discard(sRule
0ca0: 49 64 29 0a 0a 0a 64 65 66 20 6c 69 73 74 52 75  Id)...def listRu
0cb0: 6c 65 73 20 28 73 46 69 6c 74 65 72 3d 4e 6f 6e  les (sFilter=Non
0cc0: 65 29 3a 0a 20 20 20 20 22 67 65 6e 65 72 61 74  e):.    "generat
0cd0: 6f 72 3a 20 72 65 74 75 72 6e 73 20 74 79 70 6c  or: returns typl
0ce0: 65 20 28 73 4f 70 74 69 6f 6e 2c 20 73 4c 69 6e  e (sOption, sLin
0cf0: 65 49 64 2c 20 73 52 75 6c 65 49 64 29 22 0a 20  eId, sRuleId)". 
0d00: 20 20 20 69 66 20 73 46 69 6c 74 65 72 3a 0a 20     if sFilter:. 
0d10: 20 20 20 20 20 20 20 74 72 79 3a 0a 20 20 20 20         try:.    
0d20: 20 20 20 20 20 20 20 20 7a 46 69 6c 74 65 72 20          zFilter 
0d30: 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 46 69  = re.compile(sFi
0d40: 6c 74 65 72 29 0a 20 20 20 20 20 20 20 20 65 78  lter).        ex
0d50: 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20 20 20  cept:.          
0d60: 20 20 65 63 68 6f 28 22 23 20 45 72 72 6f 72 2e    echo("# Error.
0d70: 20 4c 69 73 74 20 72 75 6c 65 73 3a 20 77 72 6f   List rules: wro
0d80: 6e 67 20 72 65 67 65 78 2e 22 29 0a 20 20 20 20  ng regex.").    
0d90: 20 20 20 20 20 20 20 20 73 46 69 6c 74 65 72 20          sFilter 
0da0: 3d 20 4e 6f 6e 65 0a 20 20 20 20 66 6f 72 20 73  = None.    for s
0db0: 4f 70 74 69 6f 6e 2c 20 6c 52 75 6c 65 47 72 6f  Option, lRuleGro
0dc0: 75 70 20 69 6e 20 63 68 61 69 6e 28 5f 67 65 74  up in chain(_get
0dd0: 52 75 6c 65 73 28 54 72 75 65 29 2c 20 5f 67 65  Rules(True), _ge
0de0: 74 52 75 6c 65 73 28 46 61 6c 73 65 29 29 3a 0a  tRules(False)):.
0df0: 20 20 20 20 20 20 20 20 69 66 20 73 4f 70 74 69          if sOpti
0e00: 6f 6e 20 21 3d 20 22 40 40 40 40 22 3a 0a 20 20  on != "@@@@":.  
0e10: 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 5f 2c            for _,
0e20: 20 5f 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52 75   _, sLineId, sRu
0e30: 6c 65 49 64 2c 20 5f 2c 20 5f 20 69 6e 20 6c 52  leId, _, _ in lR
0e40: 75 6c 65 47 72 6f 75 70 3a 0a 20 20 20 20 20 20  uleGroup:.      
0e50: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74            if not
0e60: 20 73 46 69 6c 74 65 72 20 6f 72 20 7a 46 69 6c   sFilter or zFil
0e70: 74 65 72 2e 73 65 61 72 63 68 28 73 52 75 6c 65  ter.search(sRule
0e80: 49 64 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  Id):.           
0e90: 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 28           yield (
0ea0: 73 4f 70 74 69 6f 6e 2c 20 73 4c 69 6e 65 49 64  sOption, sLineId
0eb0: 2c 20 73 52 75 6c 65 49 64 29 0a 0a 0a 64 65 66  , sRuleId)...def
0ec0: 20 64 69 73 70 6c 61 79 52 75 6c 65 73 20 28 73   displayRules (s
0ed0: 46 69 6c 74 65 72 3d 4e 6f 6e 65 29 3a 0a 20 20  Filter=None):.  
0ee0: 20 20 22 64 69 73 70 6c 61 79 20 74 68 65 20 6e    "display the n
0ef0: 61 6d 65 20 6f 66 20 72 75 6c 65 73 2c 20 77 69  ame of rules, wi
0f00: 74 68 20 74 68 65 20 66 69 6c 74 65 72 20 3c 73  th the filter <s
0f10: 46 69 6c 74 65 72 3e 22 0a 20 20 20 20 65 63 68  Filter>".    ech
0f20: 6f 28 22 4c 69 73 74 20 6f 66 20 72 75 6c 65 73  o("List of rules
0f30: 2e 20 46 69 6c 74 65 72 3a 20 3c 3c 20 22 20 2b  . Filter: << " +
0f40: 20 73 74 72 28 73 46 69 6c 74 65 72 29 20 2b 20   str(sFilter) + 
0f50: 22 20 3e 3e 22 29 0a 20 20 20 20 66 6f 72 20 73  " >>").    for s
0f60: 4f 70 74 69 6f 6e 2c 20 73 4c 69 6e 65 49 64 2c  Option, sLineId,
0f70: 20 73 52 75 6c 65 49 64 20 69 6e 20 6c 69 73 74   sRuleId in list
0f80: 52 65 67 65 78 52 75 6c 65 73 28 73 46 69 6c 74  RegexRules(sFilt
0f90: 65 72 29 3a 0a 20 20 20 20 20 20 20 20 65 63 68  er):.        ech
0fa0: 6f 28 22 7b 3a 3c 31 30 7d 20 7b 3a 3c 31 30 7d  o("{:<10} {:<10}
0fb0: 20 7b 7d 22 2e 66 6f 72 6d 61 74 28 73 4f 70 74   {}".format(sOpt
0fc0: 69 6f 6e 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52  ion, sLineId, sR
0fd0: 75 6c 65 49 64 29 29 0a 0a 0a 23 23 23 23 20 4f  uleId))...#### O
0fe0: 70 74 69 6f 6e 73 0a 0a 64 65 66 20 73 65 74 4f  ptions..def setO
0ff0: 70 74 69 6f 6e 20 28 73 4f 70 74 2c 20 62 56 61  ption (sOpt, bVa
1000: 6c 29 3a 0a 20 20 20 20 22 73 65 74 20 6f 70 74  l):.    "set opt
1010: 69 6f 6e 20 3c 73 4f 70 74 3e 20 77 69 74 68 20  ion <sOpt> with 
1020: 3c 62 56 61 6c 3e 20 69 66 20 69 74 20 65 78 69  <bVal> if it exi
1030: 73 74 73 22 0a 20 20 20 20 69 66 20 73 4f 70 74  sts".    if sOpt
1040: 20 69 6e 20 5f 64 4f 70 74 69 6f 6e 73 3a 0a 20   in _dOptions:. 
1050: 20 20 20 20 20 20 20 5f 64 4f 70 74 69 6f 6e 73         _dOptions
1060: 5b 73 4f 70 74 5d 20 3d 20 62 56 61 6c 0a 0a 0a  [sOpt] = bVal...
1070: 64 65 66 20 73 65 74 4f 70 74 69 6f 6e 73 20 28  def setOptions (
1080: 64 4f 70 74 29 3a 0a 20 20 20 20 22 75 70 64 61  dOpt):.    "upda
1090: 74 65 20 74 68 65 20 64 69 63 74 69 6f 6e 61 72  te the dictionar
10a0: 79 20 6f 66 20 6f 70 74 69 6f 6e 73 20 77 69 74  y of options wit
10b0: 68 20 3c 64 4f 70 74 3e 22 0a 20 20 20 20 66 6f  h <dOpt>".    fo
10c0: 72 20 73 4b 65 79 2c 20 62 56 61 6c 20 69 6e 20  r sKey, bVal in 
10d0: 64 4f 70 74 2e 69 74 65 6d 73 28 29 3a 0a 20 20  dOpt.items():.  
10e0: 20 20 20 20 20 20 69 66 20 73 4b 65 79 20 69 6e        if sKey in
10f0: 20 5f 64 4f 70 74 69 6f 6e 73 3a 0a 20 20 20 20   _dOptions:.    
1100: 20 20 20 20 20 20 20 20 5f 64 4f 70 74 69 6f 6e          _dOption
1110: 73 5b 73 4b 65 79 5d 20 3d 20 62 56 61 6c 0a 0a  s[sKey] = bVal..
1120: 0a 64 65 66 20 67 65 74 4f 70 74 69 6f 6e 73 20  .def getOptions 
1130: 28 29 3a 0a 20 20 20 20 22 72 65 74 75 72 6e 20  ():.    "return 
1140: 74 68 65 20 64 69 63 74 69 6f 6e 61 72 79 20 6f  the dictionary o
1150: 66 20 63 75 72 72 65 6e 74 20 6f 70 74 69 6f 6e  f current option
1160: 73 22 0a 20 20 20 20 72 65 74 75 72 6e 20 5f 64  s".    return _d
1170: 4f 70 74 69 6f 6e 73 0a 0a 0a 64 65 66 20 67 65  Options...def ge
1180: 74 44 65 66 61 75 6c 74 4f 70 74 69 6f 6e 73 20  tDefaultOptions 
1190: 28 29 3a 0a 20 20 20 20 22 72 65 74 75 72 6e 20  ():.    "return 
11a0: 74 68 65 20 64 69 63 74 69 6f 6e 61 72 79 20 6f  the dictionary o
11b0: 66 20 64 65 66 61 75 6c 74 20 6f 70 74 69 6f 6e  f default option
11c0: 73 22 0a 20 20 20 20 72 65 74 75 72 6e 20 64 69  s".    return di
11d0: 63 74 28 67 63 5f 6f 70 74 69 6f 6e 73 2e 67 65  ct(gc_options.ge
11e0: 74 4f 70 74 69 6f 6e 73 28 5f 73 41 70 70 43 6f  tOptions(_sAppCo
11f0: 6e 74 65 78 74 29 29 0a 0a 0a 64 65 66 20 67 65  ntext))...def ge
1200: 74 4f 70 74 69 6f 6e 73 4c 61 62 65 6c 73 20 28  tOptionsLabels (
1210: 73 4c 61 6e 67 29 3a 0a 20 20 20 20 22 72 65 74  sLang):.    "ret
1220: 75 72 6e 20 6f 70 74 69 6f 6e 73 20 6c 61 62 65  urn options labe
1230: 6c 73 22 0a 20 20 20 20 72 65 74 75 72 6e 20 67  ls".    return g
1240: 63 5f 6f 70 74 69 6f 6e 73 2e 67 65 74 55 49 28  c_options.getUI(
1250: 73 4c 61 6e 67 29 0a 0a 0a 64 65 66 20 64 69 73  sLang)...def dis
1260: 70 6c 61 79 4f 70 74 69 6f 6e 73 20 28 73 4c 61  playOptions (sLa
1270: 6e 67 29 3a 0a 20 20 20 20 22 64 69 73 70 6c 61  ng):.    "displa
1280: 79 20 74 68 65 20 6c 69 73 74 20 6f 66 20 67 72  y the list of gr
1290: 61 6d 6d 61 72 20 63 68 65 63 6b 69 6e 67 20 6f  ammar checking o
12a0: 70 74 69 6f 6e 73 22 0a 20 20 20 20 65 63 68 6f  ptions".    echo
12b0: 28 22 4c 69 73 74 20 6f 66 20 6f 70 74 69 6f 6e  ("List of option
12c0: 73 22 29 0a 20 20 20 20 65 63 68 6f 28 22 5c 6e  s").    echo("\n
12d0: 22 2e 6a 6f 69 6e 28 20 5b 20 6b 2b 22 3a 5c 74  ".join( [ k+":\t
12e0: 22 2b 73 74 72 28 76 29 2b 22 5c 74 22 2b 67 63  "+str(v)+"\t"+gc
12f0: 5f 6f 70 74 69 6f 6e 73 2e 67 65 74 55 49 28 73  _options.getUI(s
1300: 4c 61 6e 67 29 2e 67 65 74 28 6b 2c 20 28 22 3f  Lang).get(k, ("?
1310: 22 2c 20 22 22 29 29 5b 30 5d 20 20 66 6f 72 20  ", ""))[0]  for 
1320: 6b 2c 20 76 20 20 69 6e 20 73 6f 72 74 65 64 28  k, v  in sorted(
1330: 5f 64 4f 70 74 69 6f 6e 73 2e 69 74 65 6d 73 28  _dOptions.items(
1340: 29 29 20 5d 20 29 29 0a 20 20 20 20 65 63 68 6f  )) ] )).    echo
1350: 28 22 22 29 0a 0a 0a 64 65 66 20 72 65 73 65 74  ("")...def reset
1360: 4f 70 74 69 6f 6e 73 20 28 29 3a 0a 20 20 20 20  Options ():.    
1370: 22 73 65 74 20 6f 70 74 69 6f 6e 73 20 74 6f 20  "set options to 
1380: 64 65 66 61 75 6c 74 20 76 61 6c 75 65 73 22 0a  default values".
1390: 20 20 20 20 67 6c 6f 62 61 6c 20 5f 64 4f 70 74      global _dOpt
13a0: 69 6f 6e 73 0a 20 20 20 20 5f 64 4f 70 74 69 6f  ions.    _dOptio
13b0: 6e 73 20 3d 20 64 69 63 74 28 67 63 5f 6f 70 74  ns = dict(gc_opt
13c0: 69 6f 6e 73 2e 67 65 74 4f 70 74 69 6f 6e 73 28  ions.getOptions(
13d0: 5f 73 41 70 70 43 6f 6e 74 65 78 74 29 29 0a 0a  _sAppContext))..
13e0: 0a 23 23 23 23 20 50 61 72 73 69 6e 67 0a 0a 5f  .#### Parsing.._
13f0: 7a 45 6e 64 4f 66 53 65 6e 74 65 6e 63 65 20 3d  zEndOfSentence =
1400: 20 72 65 2e 63 6f 6d 70 69 6c 65 28 72 27 28 5b   re.compile(r'([
1410: 2e 3f 21 3a 3b e2 80 a6 5d 5b 20 2e 3f 21 e2 80  .?!:;...][ .?!..
1420: a6 20 c2 bb e2 80 9d 22 29 5d 2a 7c 2e 24 29 27  . .....")]*|.$)'
1430: 29 0a 5f 7a 42 65 67 69 6e 4f 66 50 61 72 61 67  )._zBeginOfParag
1440: 72 61 70 68 20 3d 20 72 65 2e 63 6f 6d 70 69 6c  raph = re.compil
1450: 65 28 72 22 5e 5c 57 2a 22 29 0a 5f 7a 45 6e 64  e(r"^\W*")._zEnd
1460: 4f 66 50 61 72 61 67 72 61 70 68 20 3d 20 72 65  OfParagraph = re
1470: 2e 63 6f 6d 70 69 6c 65 28 72 22 5c 57 2a 24 22  .compile(r"\W*$"
1480: 29 0a 0a 64 65 66 20 5f 67 65 74 53 65 6e 74 65  )..def _getSente
1490: 6e 63 65 42 6f 75 6e 64 61 72 69 65 73 20 28 73  nceBoundaries (s
14a0: 54 65 78 74 29 3a 0a 20 20 20 20 69 53 74 61 72  Text):.    iStar
14b0: 74 20 3d 20 5f 7a 42 65 67 69 6e 4f 66 50 61 72  t = _zBeginOfPar
14c0: 61 67 72 61 70 68 2e 6d 61 74 63 68 28 73 54 65  agraph.match(sTe
14d0: 78 74 29 2e 65 6e 64 28 29 0a 20 20 20 20 66 6f  xt).end().    fo
14e0: 72 20 6d 20 69 6e 20 5f 7a 45 6e 64 4f 66 53 65  r m in _zEndOfSe
14f0: 6e 74 65 6e 63 65 2e 66 69 6e 64 69 74 65 72 28  ntence.finditer(
1500: 73 54 65 78 74 29 3a 0a 20 20 20 20 20 20 20 20  sText):.        
1510: 79 69 65 6c 64 20 28 69 53 74 61 72 74 2c 20 6d  yield (iStart, m
1520: 2e 65 6e 64 28 29 29 0a 20 20 20 20 20 20 20 20  .end()).        
1530: 69 53 74 61 72 74 20 3d 20 6d 2e 65 6e 64 28 29  iStart = m.end()
1540: 0a 0a 0a 64 65 66 20 70 61 72 73 65 20 28 73 54  ...def parse (sT
1550: 65 78 74 2c 20 73 43 6f 75 6e 74 72 79 3d 22 24  ext, sCountry="$
1560: 7b 63 6f 75 6e 74 72 79 5f 64 65 66 61 75 6c 74  {country_default
1570: 7d 22 2c 20 62 44 65 62 75 67 3d 46 61 6c 73 65  }", bDebug=False
1580: 2c 20 64 4f 70 74 69 6f 6e 73 3d 4e 6f 6e 65 2c  , dOptions=None,
1590: 20 62 43 6f 6e 74 65 78 74 3d 46 61 6c 73 65 29   bContext=False)
15a0: 3a 0a 20 20 20 20 22 69 6e 69 74 20 70 6f 69 6e  :.    "init poin
15b0: 74 20 74 6f 20 61 6e 61 6c 79 7a 65 20 61 20 74  t to analyze a t
15c0: 65 78 74 22 0a 20 20 20 20 6f 54 65 78 74 20 3d  ext".    oText =
15d0: 20 54 65 78 74 50 61 72 73 65 72 28 73 54 65 78   TextParser(sTex
15e0: 74 29 0a 20 20 20 20 72 65 74 75 72 6e 20 6f 54  t).    return oT
15f0: 65 78 74 2e 70 61 72 73 65 28 73 43 6f 75 6e 74  ext.parse(sCount
1600: 72 79 2c 20 62 44 65 62 75 67 2c 20 64 4f 70 74  ry, bDebug, dOpt
1610: 69 6f 6e 73 2c 20 62 43 6f 6e 74 65 78 74 29 0a  ions, bContext).
1620: 0a 0a 23 23 23 23 20 54 45 58 54 20 50 41 52 53  ..#### TEXT PARS
1630: 45 52 0a 0a 63 6c 61 73 73 20 54 65 78 74 50 61  ER..class TextPa
1640: 72 73 65 72 3a 0a 20 20 20 20 22 54 65 78 74 20  rser:.    "Text 
1650: 70 61 72 73 65 72 22 0a 0a 20 20 20 20 64 65 66  parser"..    def
1660: 20 5f 5f 69 6e 69 74 5f 5f 20 28 73 65 6c 66 2c   __init__ (self,
1670: 20 73 54 65 78 74 29 3a 0a 20 20 20 20 20 20 20   sText):.       
1680: 20 73 65 6c 66 2e 73 54 65 78 74 20 3d 20 73 54   self.sText = sT
1690: 65 78 74 0a 20 20 20 20 20 20 20 20 73 65 6c 66  ext.        self
16a0: 2e 73 54 65 78 74 30 20 3d 20 73 54 65 78 74 0a  .sText0 = sText.
16b0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73 53 65          self.sSe
16c0: 6e 74 65 6e 63 65 20 3d 20 22 22 0a 20 20 20 20  ntence = "".    
16d0: 20 20 20 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e      self.sSenten
16e0: 63 65 30 20 3d 20 22 22 0a 20 20 20 20 20 20 20  ce0 = "".       
16f0: 20 73 65 6c 66 2e 6e 4f 66 66 73 65 74 57 69 74   self.nOffsetWit
1700: 68 69 6e 50 61 72 61 67 72 61 70 68 20 3d 20 30  hinParagraph = 0
1710: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c 54  .        self.lT
1720: 6f 6b 65 6e 20 3d 20 5b 5d 0a 20 20 20 20 20 20  oken = [].      
1730: 20 20 73 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f 73    self.dTokenPos
1740: 20 3d 20 7b 7d 0a 20 20 20 20 20 20 20 20 73 65   = {}.        se
1750: 6c 66 2e 64 54 61 67 73 20 3d 20 7b 7d 0a 20 20  lf.dTags = {}.  
1760: 20 20 20 20 20 20 73 65 6c 66 2e 64 45 72 72 6f        self.dErro
1770: 72 20 3d 20 7b 7d 0a 20 20 20 20 20 20 20 20 73  r = {}.        s
1780: 65 6c 66 2e 64 45 72 72 6f 72 50 72 69 6f 72 69  elf.dErrorPriori
1790: 74 79 20 3d 20 7b 7d 20 20 23 20 4b 65 79 20 3d  ty = {}  # Key =
17a0: 20 70 6f 73 69 74 69 6f 6e 3b 20 76 61 6c 75 65   position; value
17b0: 20 3d 20 70 72 69 6f 72 69 74 79 0a 0a 20 20 20   = priority..   
17c0: 20 64 65 66 20 5f 5f 73 74 72 5f 5f 20 28 73 65   def __str__ (se
17d0: 6c 66 29 3a 0a 20 20 20 20 20 20 20 20 73 20 3d  lf):.        s =
17e0: 20 22 3d 3d 3d 3d 3d 20 54 45 58 54 20 3d 3d 3d   "===== TEXT ===
17f0: 3d 3d 5c 6e 22 0a 20 20 20 20 20 20 20 20 73 20  ==\n".        s 
1800: 2b 3d 20 22 73 65 6e 74 65 6e 63 65 3a 20 22 20  += "sentence: " 
1810: 2b 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65  + self.sSentence
1820: 30 20 2b 20 22 5c 6e 22 0a 20 20 20 20 20 20 20  0 + "\n".       
1830: 20 73 20 2b 3d 20 22 6e 6f 77 3a 20 20 20 20 20   s += "now:     
1840: 20 22 20 2b 20 73 65 6c 66 2e 73 53 65 6e 74 65   " + self.sSente
1850: 6e 63 65 20 20 2b 20 22 5c 6e 22 0a 20 20 20 20  nce  + "\n".    
1860: 20 20 20 20 66 6f 72 20 64 54 6f 6b 65 6e 20 69      for dToken i
1870: 6e 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 3a 0a 20  n self.lToken:. 
1880: 20 20 20 20 20 20 20 20 20 20 20 73 20 2b 3d 20             s += 
1890: 27 23 7b 69 7d 5c 74 7b 6e 53 74 61 72 74 7d 3a  '#{i}\t{nStart}:
18a0: 7b 6e 45 6e 64 7d 5c 74 7b 73 56 61 6c 75 65 7d  {nEnd}\t{sValue}
18b0: 5c 74 7b 73 54 79 70 65 7d 27 2e 66 6f 72 6d 61  \t{sType}'.forma
18c0: 74 28 2a 2a 64 54 6f 6b 65 6e 29 0a 20 20 20 20  t(**dToken).    
18d0: 20 20 20 20 20 20 20 20 69 66 20 22 6c 4d 6f 72          if "lMor
18e0: 70 68 22 20 69 6e 20 64 54 6f 6b 65 6e 3a 0a 20  ph" in dToken:. 
18f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
1900: 20 2b 3d 20 22 5c 74 22 20 2b 20 73 74 72 28 64   += "\t" + str(d
1910: 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 29  Token["lMorph"])
1920: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
1930: 22 61 54 61 67 73 22 20 69 6e 20 64 54 6f 6b 65  "aTags" in dToke
1940: 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  n:.             
1950: 20 20 20 73 20 2b 3d 20 22 5c 74 22 20 2b 20 73     s += "\t" + s
1960: 74 72 28 64 54 6f 6b 65 6e 5b 22 61 54 61 67 73  tr(dToken["aTags
1970: 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  "]).            
1980: 73 20 2b 3d 20 22 5c 6e 22 0a 20 20 20 20 20 20  s += "\n".      
1990: 20 20 23 66 6f 72 20 6e 50 6f 73 2c 20 64 54 6f    #for nPos, dTo
19a0: 6b 65 6e 20 69 6e 20 73 65 6c 66 2e 64 54 6f 6b  ken in self.dTok
19b0: 65 6e 50 6f 73 2e 69 74 65 6d 73 28 29 3a 0a 20  enPos.items():. 
19c0: 20 20 20 20 20 20 20 23 20 20 20 20 73 20 2b 3d         #    s +=
19d0: 20 22 7b 7d 5c 74 7b 7d 5c 6e 22 2e 66 6f 72 6d   "{}\t{}\n".form
19e0: 61 74 28 6e 50 6f 73 2c 20 64 54 6f 6b 65 6e 29  at(nPos, dToken)
19f0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
1a00: 73 0a 0a 20 20 20 20 64 65 66 20 70 61 72 73 65  s..    def parse
1a10: 20 28 73 65 6c 66 2c 20 73 43 6f 75 6e 74 72 79   (self, sCountry
1a20: 3d 22 24 7b 63 6f 75 6e 74 72 79 5f 64 65 66 61  ="${country_defa
1a30: 75 6c 74 7d 22 2c 20 62 44 65 62 75 67 3d 46 61  ult}", bDebug=Fa
1a40: 6c 73 65 2c 20 64 4f 70 74 69 6f 6e 73 3d 4e 6f  lse, dOptions=No
1a50: 6e 65 2c 20 62 43 6f 6e 74 65 78 74 3d 46 61 6c  ne, bContext=Fal
1a60: 73 65 29 3a 0a 20 20 20 20 20 20 20 20 22 61 6e  se):.        "an
1a70: 61 6c 79 73 65 73 20 74 68 65 20 70 61 72 61 67  alyses the parag
1a80: 72 61 70 68 20 73 54 65 78 74 20 61 6e 64 20 72  raph sText and r
1a90: 65 74 75 72 6e 73 20 6c 69 73 74 20 6f 66 20 65  eturns list of e
1aa0: 72 72 6f 72 73 22 0a 20 20 20 20 20 20 20 20 23  rrors".        #
1ab0: 73 54 65 78 74 20 3d 20 75 6e 69 63 6f 64 65 64  sText = unicoded
1ac0: 61 74 61 2e 6e 6f 72 6d 61 6c 69 7a 65 28 22 4e  ata.normalize("N
1ad0: 46 43 22 2c 20 73 54 65 78 74 29 0a 20 20 20 20  FC", sText).    
1ae0: 20 20 20 20 64 4f 70 74 20 3d 20 64 4f 70 74 69      dOpt = dOpti
1af0: 6f 6e 73 20 6f 72 20 5f 64 4f 70 74 69 6f 6e 73  ons or _dOptions
1b00: 0a 20 20 20 20 20 20 20 20 62 53 68 6f 77 52 75  .        bShowRu
1b10: 6c 65 49 64 20 3d 20 6f 70 74 69 6f 6e 28 27 69  leId = option('i
1b20: 64 72 75 6c 65 27 29 0a 0a 20 20 20 20 20 20 20  drule')..       
1b30: 20 23 20 70 61 72 73 65 20 70 61 72 61 67 72 61   # parse paragra
1b40: 70 68 0a 20 20 20 20 20 20 20 20 74 72 79 3a 0a  ph.        try:.
1b50: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
1b60: 2e 70 61 72 73 65 54 65 78 74 28 73 65 6c 66 2e  .parseText(self.
1b70: 73 54 65 78 74 2c 20 73 65 6c 66 2e 73 54 65 78  sText, self.sTex
1b80: 74 30 2c 20 54 72 75 65 2c 20 30 2c 20 73 43 6f  t0, True, 0, sCo
1b90: 75 6e 74 72 79 2c 20 64 4f 70 74 2c 20 62 53 68  untry, dOpt, bSh
1ba0: 6f 77 52 75 6c 65 49 64 2c 20 62 44 65 62 75 67  owRuleId, bDebug
1bb0: 2c 20 62 43 6f 6e 74 65 78 74 29 0a 20 20 20 20  , bContext).    
1bc0: 20 20 20 20 65 78 63 65 70 74 3a 0a 20 20 20 20      except:.    
1bd0: 20 20 20 20 20 20 20 20 72 61 69 73 65 0a 0a 20          raise.. 
1be0: 20 20 20 20 20 20 20 23 20 63 6c 65 61 6e 75 70         # cleanup
1bf0: 0a 20 20 20 20 20 20 20 20 73 54 65 78 74 20 3d  .        sText =
1c00: 20 73 65 6c 66 2e 73 54 65 78 74 0a 20 20 20 20   self.sText.    
1c10: 20 20 20 20 69 66 20 22 c2 a0 22 20 69 6e 20 73      if ".." in s
1c20: 54 65 78 74 3a 0a 20 20 20 20 20 20 20 20 20 20  Text:.          
1c30: 20 20 73 54 65 78 74 20 3d 20 73 54 65 78 74 2e    sText = sText.
1c40: 72 65 70 6c 61 63 65 28 22 c2 a0 22 2c 20 27 20  replace("..", ' 
1c50: 27 29 20 23 20 6e 62 73 70 0a 20 20 20 20 20 20  ') # nbsp.      
1c60: 20 20 69 66 20 22 e2 80 af 22 20 69 6e 20 73 54    if "..." in sT
1c70: 65 78 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ext:.           
1c80: 20 73 54 65 78 74 20 3d 20 73 54 65 78 74 2e 72   sText = sText.r
1c90: 65 70 6c 61 63 65 28 22 e2 80 af 22 2c 20 27 20  eplace("...", ' 
1ca0: 27 29 20 23 20 6e 6e 62 73 70 0a 20 20 20 20 20  ') # nnbsp.     
1cb0: 20 20 20 69 66 20 22 27 22 20 69 6e 20 73 54 65     if "'" in sTe
1cc0: 78 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  xt:.            
1cd0: 73 54 65 78 74 20 3d 20 73 54 65 78 74 2e 72 65  sText = sText.re
1ce0: 70 6c 61 63 65 28 22 27 22 2c 20 22 e2 80 99 22  place("'", "..."
1cf0: 29 0a 20 20 20 20 20 20 20 20 69 66 20 22 e2 80  ).        if "..
1d00: 91 22 20 69 6e 20 73 54 65 78 74 3a 0a 20 20 20  ." in sText:.   
1d10: 20 20 20 20 20 20 20 20 20 73 54 65 78 74 20 3d           sText =
1d20: 20 73 54 65 78 74 2e 72 65 70 6c 61 63 65 28 22   sText.replace("
1d30: e2 80 91 22 2c 20 22 2d 22 29 20 23 20 6e 6f 62  ...", "-") # nob
1d40: 72 65 61 6b 64 61 73 68 0a 0a 20 20 20 20 20 20  reakdash..      
1d50: 20 20 23 20 70 61 72 73 65 20 73 65 6e 74 65 6e    # parse senten
1d60: 63 65 73 0a 20 20 20 20 20 20 20 20 66 6f 72 20  ces.        for 
1d70: 69 53 74 61 72 74 2c 20 69 45 6e 64 20 69 6e 20  iStart, iEnd in 
1d80: 5f 67 65 74 53 65 6e 74 65 6e 63 65 42 6f 75 6e  _getSentenceBoun
1d90: 64 61 72 69 65 73 28 73 54 65 78 74 29 3a 0a 20  daries(sText):. 
1da0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 34 20             if 4 
1db0: 3c 20 28 69 45 6e 64 20 2d 20 69 53 74 61 72 74  < (iEnd - iStart
1dc0: 29 20 3c 20 32 30 30 30 3a 0a 20 20 20 20 20 20  ) < 2000:.      
1dd0: 20 20 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20            try:. 
1de0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1df0: 20 20 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63     self.sSentenc
1e00: 65 20 3d 20 73 54 65 78 74 5b 69 53 74 61 72 74  e = sText[iStart
1e10: 3a 69 45 6e 64 5d 0a 20 20 20 20 20 20 20 20 20  :iEnd].         
1e20: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
1e30: 73 53 65 6e 74 65 6e 63 65 30 20 3d 20 73 65 6c  sSentence0 = sel
1e40: 66 2e 73 54 65 78 74 30 5b 69 53 74 61 72 74 3a  f.sText0[iStart:
1e50: 69 45 6e 64 5d 0a 20 20 20 20 20 20 20 20 20 20  iEnd].          
1e60: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6e            self.n
1e70: 4f 66 66 73 65 74 57 69 74 68 69 6e 50 61 72 61  OffsetWithinPara
1e80: 67 72 61 70 68 20 3d 20 69 53 74 61 72 74 0a 20  graph = iStart. 
1e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ea0: 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 3d     self.lToken =
1eb0: 20 6c 69 73 74 28 5f 6f 54 6f 6b 65 6e 69 7a 65   list(_oTokenize
1ec0: 72 2e 67 65 6e 54 6f 6b 65 6e 73 28 73 65 6c 66  r.genTokens(self
1ed0: 2e 73 53 65 6e 74 65 6e 63 65 2c 20 54 72 75 65  .sSentence, True
1ee0: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  )).             
1ef0: 20 20 20 20 20 20 20 73 65 6c 66 2e 64 54 6f 6b         self.dTok
1f00: 65 6e 50 6f 73 20 3d 20 7b 20 64 54 6f 6b 65 6e  enPos = { dToken
1f10: 5b 22 6e 53 74 61 72 74 22 5d 3a 20 64 54 6f 6b  ["nStart"]: dTok
1f20: 65 6e 20 20 66 6f 72 20 64 54 6f 6b 65 6e 20 69  en  for dToken i
1f30: 6e 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 20 69  n self.lToken  i
1f40: 66 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70 65 22  f dToken["sType"
1f50: 5d 20 21 3d 20 22 49 4e 46 4f 22 20 7d 0a 20 20  ] != "INFO" }.  
1f60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f70: 20 20 73 65 6c 66 2e 70 61 72 73 65 54 65 78 74    self.parseText
1f80: 28 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65 2c  (self.sSentence,
1f90: 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65 30   self.sSentence0
1fa0: 2c 20 46 61 6c 73 65 2c 20 69 53 74 61 72 74 2c  , False, iStart,
1fb0: 20 73 43 6f 75 6e 74 72 79 2c 20 64 4f 70 74 2c   sCountry, dOpt,
1fc0: 20 62 53 68 6f 77 52 75 6c 65 49 64 2c 20 62 44   bShowRuleId, bD
1fd0: 65 62 75 67 2c 20 62 43 6f 6e 74 65 78 74 29 0a  ebug, bContext).
1fe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ff0: 65 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20  except:.        
2000: 20 20 20 20 20 20 20 20 20 20 20 20 72 61 69 73              rais
2010: 65 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  e.        return
2020: 20 73 65 6c 66 2e 64 45 72 72 6f 72 2e 76 61 6c   self.dError.val
2030: 75 65 73 28 29 20 23 20 74 68 69 73 20 69 73 20  ues() # this is 
2040: 61 20 76 69 65 77 20 28 69 74 65 72 61 62 6c 65  a view (iterable
2050: 29 0a 0a 20 20 20 20 64 65 66 20 70 61 72 73 65  )..    def parse
2060: 54 65 78 74 20 28 73 65 6c 66 2c 20 73 54 65 78  Text (self, sTex
2070: 74 2c 20 73 54 65 78 74 30 2c 20 62 50 61 72 61  t, sText0, bPara
2080: 67 72 61 70 68 2c 20 6e 4f 66 66 73 65 74 2c 20  graph, nOffset, 
2090: 73 43 6f 75 6e 74 72 79 2c 20 64 4f 70 74 69 6f  sCountry, dOptio
20a0: 6e 73 2c 20 62 53 68 6f 77 52 75 6c 65 49 64 2c  ns, bShowRuleId,
20b0: 20 62 44 65 62 75 67 2c 20 62 43 6f 6e 74 65 78   bDebug, bContex
20c0: 74 29 3a 0a 20 20 20 20 20 20 20 20 62 43 68 61  t):.        bCha
20d0: 6e 67 65 20 3d 20 46 61 6c 73 65 0a 20 20 20 20  nge = False.    
20e0: 20 20 20 20 66 6f 72 20 73 4f 70 74 69 6f 6e 2c      for sOption,
20f0: 20 6c 52 75 6c 65 47 72 6f 75 70 20 69 6e 20 5f   lRuleGroup in _
2100: 67 65 74 52 75 6c 65 73 28 62 50 61 72 61 67 72  getRules(bParagr
2110: 61 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20  aph):.          
2120: 20 20 69 66 20 73 4f 70 74 69 6f 6e 20 3d 3d 20    if sOption == 
2130: 22 40 40 40 40 22 3a 0a 20 20 20 20 20 20 20 20  "@@@@":.        
2140: 20 20 20 20 20 20 20 20 23 20 67 72 61 70 68 20          # graph 
2150: 72 75 6c 65 73 0a 20 20 20 20 20 20 20 20 20 20  rules.          
2160: 20 20 20 20 20 20 69 66 20 6e 6f 74 20 62 50 61        if not bPa
2170: 72 61 67 72 61 70 68 20 61 6e 64 20 62 43 68 61  ragraph and bCha
2180: 6e 67 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  nge:.           
2190: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 75 70           self.up
21a0: 64 61 74 65 28 73 54 65 78 74 2c 20 62 44 65 62  date(sText, bDeb
21b0: 75 67 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ug).            
21c0: 20 20 20 20 20 20 20 20 62 43 68 61 6e 67 65 20          bChange 
21d0: 3d 20 46 61 6c 73 65 0a 20 20 20 20 20 20 20 20  = False.        
21e0: 20 20 20 20 20 20 20 20 66 6f 72 20 73 47 72 61          for sGra
21f0: 70 68 4e 61 6d 65 2c 20 73 4c 69 6e 65 49 64 20  phName, sLineId 
2200: 69 6e 20 6c 52 75 6c 65 47 72 6f 75 70 3a 0a 20  in lRuleGroup:. 
2210: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2220: 20 20 20 69 66 20 73 47 72 61 70 68 4e 61 6d 65     if sGraphName
2230: 20 6e 6f 74 20 69 6e 20 64 4f 70 74 69 6f 6e 73   not in dOptions
2240: 20 6f 72 20 64 4f 70 74 69 6f 6e 73 5b 73 47 72   or dOptions[sGr
2250: 61 70 68 4e 61 6d 65 5d 3a 0a 20 20 20 20 20 20  aphName]:.      
2260: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2270: 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20    if bDebug:.   
2280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2290: 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 5c           echo("\
22a0: 6e 3e 3e 3e 3e 20 47 52 41 50 48 3a 20 22 20 2b  n>>>> GRAPH: " +
22b0: 20 73 47 72 61 70 68 4e 61 6d 65 20 2b 20 22 20   sGraphName + " 
22c0: 22 20 2b 20 73 4c 69 6e 65 49 64 29 0a 20 20 20  " + sLineId).   
22d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
22e0: 20 20 20 20 20 73 54 65 78 74 20 3d 20 73 65 6c       sText = sel
22f0: 66 2e 70 61 72 73 65 47 72 61 70 68 28 5f 72 75  f.parseGraph(_ru
2300: 6c 65 73 5f 67 72 61 70 68 2e 64 41 6c 6c 47 72  les_graph.dAllGr
2310: 61 70 68 5b 73 47 72 61 70 68 4e 61 6d 65 5d 2c  aph[sGraphName],
2320: 20 73 43 6f 75 6e 74 72 79 2c 20 64 4f 70 74 69   sCountry, dOpti
2330: 6f 6e 73 2c 20 62 53 68 6f 77 52 75 6c 65 49 64  ons, bShowRuleId
2340: 2c 20 62 44 65 62 75 67 2c 20 62 43 6f 6e 74 65  , bDebug, bConte
2350: 78 74 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  xt).            
2360: 65 6c 69 66 20 6e 6f 74 20 73 4f 70 74 69 6f 6e  elif not sOption
2370: 20 6f 72 20 64 4f 70 74 69 6f 6e 73 2e 67 65 74   or dOptions.get
2380: 28 73 4f 70 74 69 6f 6e 2c 20 46 61 6c 73 65 29  (sOption, False)
2390: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
23a0: 20 20 23 20 72 65 67 65 78 20 72 75 6c 65 73 0a    # regex rules.
23b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
23c0: 66 6f 72 20 7a 52 65 67 65 78 2c 20 62 55 70 70  for zRegex, bUpp
23d0: 65 72 63 61 73 65 2c 20 73 4c 69 6e 65 49 64 2c  ercase, sLineId,
23e0: 20 73 52 75 6c 65 49 64 2c 20 6e 50 72 69 6f 72   sRuleId, nPrior
23f0: 69 74 79 2c 20 6c 41 63 74 69 6f 6e 73 20 69 6e  ity, lActions in
2400: 20 6c 52 75 6c 65 47 72 6f 75 70 3a 0a 20 20 20   lRuleGroup:.   
2410: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2420: 20 69 66 20 73 52 75 6c 65 49 64 20 6e 6f 74 20   if sRuleId not 
2430: 69 6e 20 5f 61 49 67 6e 6f 72 65 64 52 75 6c 65  in _aIgnoredRule
2440: 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  s:.             
2450: 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 6d             for m
2460: 20 69 6e 20 7a 52 65 67 65 78 2e 66 69 6e 64 69   in zRegex.findi
2470: 74 65 72 28 73 54 65 78 74 29 3a 0a 20 20 20 20  ter(sText):.    
2480: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2490: 20 20 20 20 20 20 20 20 62 43 6f 6e 64 4d 65 6d          bCondMem
24a0: 6f 20 3d 20 4e 6f 6e 65 0a 20 20 20 20 20 20 20  o = None.       
24b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
24c0: 20 20 20 20 20 66 6f 72 20 73 46 75 6e 63 43 6f       for sFuncCo
24d0: 6e 64 2c 20 63 41 63 74 69 6f 6e 54 79 70 65 2c  nd, cActionType,
24e0: 20 73 57 68 61 74 2c 20 2a 65 41 63 74 20 69 6e   sWhat, *eAct in
24f0: 20 6c 41 63 74 69 6f 6e 73 3a 0a 20 20 20 20 20   lActions:.     
2500: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2510: 20 20 20 20 20 20 20 20 20 20 20 23 20 61 63 74             # act
2520: 69 6f 6e 20 69 6e 20 6c 41 63 74 69 6f 6e 73 3a  ion in lActions:
2530: 20 5b 20 63 6f 6e 64 69 74 69 6f 6e 2c 20 61 63   [ condition, ac
2540: 74 69 6f 6e 20 74 79 70 65 2c 20 72 65 70 6c 61  tion type, repla
2550: 63 65 6d 65 6e 74 2f 73 75 67 67 65 73 74 69 6f  cement/suggestio
2560: 6e 2f 61 63 74 69 6f 6e 5b 2c 20 69 47 72 6f 75  n/action[, iGrou
2570: 70 5b 2c 20 6d 65 73 73 61 67 65 2c 20 55 52 4c  p[, message, URL
2580: 5d 5d 20 5d 0a 20 20 20 20 20 20 20 20 20 20 20  ]] ].           
2590: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
25a0: 20 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20       try:.      
25b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
25c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62 43                bC
25d0: 6f 6e 64 4d 65 6d 6f 20 3d 20 6e 6f 74 20 73 46  ondMemo = not sF
25e0: 75 6e 63 43 6f 6e 64 20 6f 72 20 67 6c 6f 62 61  uncCond or globa
25f0: 6c 73 28 29 5b 73 46 75 6e 63 43 6f 6e 64 5d 28  ls()[sFuncCond](
2600: 73 54 65 78 74 2c 20 73 54 65 78 74 30 2c 20 6d  sText, sText0, m
2610: 2c 20 73 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f 73  , self.dTokenPos
2620: 2c 20 73 43 6f 75 6e 74 72 79 2c 20 62 43 6f 6e  , sCountry, bCon
2630: 64 4d 65 6d 6f 29 0a 20 20 20 20 20 20 20 20 20  dMemo).         
2640: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2650: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62 43             if bC
2660: 6f 6e 64 4d 65 6d 6f 3a 0a 20 20 20 20 20 20 20  ondMemo:.       
2670: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2680: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2690: 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20   if bDebug:.    
26a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
26b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
26c0: 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 52 55          echo("RU
26d0: 4c 45 3a 20 22 20 2b 20 73 4c 69 6e 65 49 64 29  LE: " + sLineId)
26e0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
26f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2700: 20 20 20 20 20 20 20 20 20 69 66 20 63 41 63 74           if cAct
2710: 69 6f 6e 54 79 70 65 20 3d 3d 20 22 2d 22 3a 0a  ionType == "-":.
2720: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2740: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 67 72              # gr
2750: 61 6d 6d 61 72 20 65 72 72 6f 72 0a 20 20 20 20  ammar error.    
2760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2770: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2780: 20 20 20 20 20 20 20 20 6e 45 72 72 6f 72 53 74          nErrorSt
2790: 61 72 74 20 3d 20 6e 4f 66 66 73 65 74 20 2b 20  art = nOffset + 
27a0: 6d 2e 73 74 61 72 74 28 65 41 63 74 5b 30 5d 29  m.start(eAct[0])
27b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
27c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
27d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
27e0: 6e 45 72 72 6f 72 53 74 61 72 74 20 6e 6f 74 20  nErrorStart not 
27f0: 69 6e 20 73 65 6c 66 2e 64 45 72 72 6f 72 20 6f  in self.dError o
2800: 72 20 6e 50 72 69 6f 72 69 74 79 20 3e 20 73 65  r nPriority > se
2810: 6c 66 2e 64 45 72 72 6f 72 50 72 69 6f 72 69 74  lf.dErrorPriorit
2820: 79 2e 67 65 74 28 6e 45 72 72 6f 72 53 74 61 72  y.get(nErrorStar
2830: 74 2c 20 2d 31 29 3a 0a 20 20 20 20 20 20 20 20  t, -1):.        
2840: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2860: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64 45 72          self.dEr
2870: 72 6f 72 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d  ror[nErrorStart]
2880: 20 3d 20 73 65 6c 66 2e 5f 63 72 65 61 74 65 45   = self._createE
2890: 72 72 6f 72 46 72 6f 6d 52 65 67 65 78 28 73 54  rrorFromRegex(sT
28a0: 65 78 74 2c 20 73 54 65 78 74 30 2c 20 73 57 68  ext, sText0, sWh
28b0: 61 74 2c 20 6e 4f 66 66 73 65 74 2c 20 6d 2c 20  at, nOffset, m, 
28c0: 65 41 63 74 5b 30 5d 2c 20 73 4c 69 6e 65 49 64  eAct[0], sLineId
28d0: 2c 20 73 52 75 6c 65 49 64 2c 20 62 55 70 70 65  , sRuleId, bUppe
28e0: 72 63 61 73 65 2c 20 65 41 63 74 5b 31 5d 2c 20  rcase, eAct[1], 
28f0: 65 41 63 74 5b 32 5d 2c 20 62 53 68 6f 77 52 75  eAct[2], bShowRu
2900: 6c 65 49 64 2c 20 73 4f 70 74 69 6f 6e 2c 20 62  leId, sOption, b
2910: 43 6f 6e 74 65 78 74 29 0a 20 20 20 20 20 20 20  Context).       
2920: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2940: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64 45           self.dE
2950: 72 72 6f 72 50 72 69 6f 72 69 74 79 5b 6e 45 72  rrorPriority[nEr
2960: 72 6f 72 53 74 61 72 74 5d 20 3d 20 6e 50 72 69  rorStart] = nPri
2970: 6f 72 69 74 79 0a 20 20 20 20 20 20 20 20 20 20  ority.          
2980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2990: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c                el
29a0: 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20 3d  if cActionType =
29b0: 3d 20 22 7e 22 3a 0a 20 20 20 20 20 20 20 20 20  = "~":.         
29c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
29d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
29e0: 20 20 20 23 20 74 65 78 74 20 70 72 6f 63 65 73     # text proces
29f0: 73 6f 72 0a 20 20 20 20 20 20 20 20 20 20 20 20  sor.            
2a00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2a10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2a20: 73 54 65 78 74 20 3d 20 73 65 6c 66 2e 72 65 77  sText = self.rew
2a30: 72 69 74 65 54 65 78 74 28 73 54 65 78 74 2c 20  riteText(sText, 
2a40: 73 57 68 61 74 2c 20 65 41 63 74 5b 30 5d 2c 20  sWhat, eAct[0], 
2a50: 6d 2c 20 62 55 70 70 65 72 63 61 73 65 29 0a 20  m, bUppercase). 
2a60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2a70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2a80: 20 20 20 20 20 20 20 20 20 20 20 62 43 68 61 6e             bChan
2a90: 67 65 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20  ge = True.      
2aa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2ab0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2ac0: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
2ad0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
2ae0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2af0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2b00: 20 65 63 68 6f 28 22 7e 20 22 20 2b 20 73 54 65   echo("~ " + sTe
2b10: 78 74 20 2b 20 22 20 20 2d 2d 20 22 20 2b 20 6d  xt + "  -- " + m
2b20: 2e 67 72 6f 75 70 28 65 41 63 74 5b 30 5d 29 20  .group(eAct[0]) 
2b30: 2b 20 22 20 20 23 20 22 20 2b 20 73 4c 69 6e 65  + "  # " + sLine
2b40: 49 64 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  Id).            
2b50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2b60: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66              elif
2b70: 20 63 41 63 74 69 6f 6e 54 79 70 65 20 3d 3d 20   cActionType == 
2b80: 22 3d 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20  "=":.           
2b90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2ba0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2bb0: 20 23 20 64 69 73 61 6d 62 69 67 75 61 74 69 6f   # disambiguatio
2bc0: 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  n.              
2bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
2bf0: 20 6e 6f 74 20 62 50 61 72 61 67 72 61 70 68 3a   not bParagraph:
2c00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
2c10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2c20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2c30: 20 67 6c 6f 62 61 6c 73 28 29 5b 73 57 68 61 74   globals()[sWhat
2c40: 5d 28 73 54 65 78 74 2c 20 6d 2c 20 73 65 6c 66  ](sText, m, self
2c50: 2e 64 54 6f 6b 65 6e 50 6f 73 29 0a 20 20 20 20  .dTokenPos).    
2c60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2c80: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62              if b
2c90: 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20  Debug:.         
2ca0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2cc0: 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28             echo(
2cd0: 22 3d 20 22 20 2b 20 6d 2e 67 72 6f 75 70 28 30  "= " + m.group(0
2ce0: 29 20 2b 20 22 20 20 23 20 22 20 2b 20 73 4c 69  ) + "  # " + sLi
2cf0: 6e 65 49 64 29 0a 20 20 20 20 20 20 20 20 20 20  neId).          
2d00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c                el
2d20: 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20 3d  if cActionType =
2d30: 3d 20 22 3e 22 3a 0a 20 20 20 20 20 20 20 20 20  = ">":.         
2d40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2d50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2d60: 20 20 20 23 20 77 65 20 64 6f 20 6e 6f 74 68 69     # we do nothi
2d70: 6e 67 2c 20 74 68 69 73 20 74 65 73 74 20 69 73  ng, this test is
2d80: 20 6a 75 73 74 20 61 20 63 6f 6e 64 69 74 69 6f   just a conditio
2d90: 6e 20 74 6f 20 61 70 70 6c 79 20 61 6c 6c 20 66  n to apply all f
2da0: 6f 6c 6c 6f 77 69 6e 67 20 61 63 74 69 6f 6e 73  ollowing actions
2db0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
2dc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 61 73               pas
2de0: 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  s.              
2df0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2e00: 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a            else:.
2e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2e30: 20 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f              echo
2e40: 28 22 23 20 65 72 72 6f 72 3a 20 75 6e 6b 6e 6f  ("# error: unkno
2e50: 77 6e 20 61 63 74 69 6f 6e 20 61 74 20 22 20 2b  wn action at " +
2e60: 20 73 4c 69 6e 65 49 64 29 0a 20 20 20 20 20 20   sLineId).      
2e70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2e80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c                el
2e90: 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20 3d  if cActionType =
2ea0: 3d 20 22 3e 22 3a 0a 20 20 20 20 20 20 20 20 20  = ">":.         
2eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62                 b
2ed0: 72 65 61 6b 0a 20 20 20 20 20 20 20 20 20 20 20  reak.           
2ee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2ef0: 20 20 20 20 20 65 78 63 65 70 74 20 45 78 63 65       except Exce
2f00: 70 74 69 6f 6e 20 61 73 20 65 3a 0a 20 20 20 20  ption as e:.    
2f10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2f20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2f30: 72 61 69 73 65 20 45 78 63 65 70 74 69 6f 6e 28  raise Exception(
2f40: 73 74 72 28 65 29 2c 20 22 23 20 22 20 2b 20 73  str(e), "# " + s
2f50: 4c 69 6e 65 49 64 20 2b 20 22 20 23 20 22 20 2b  LineId + " # " +
2f60: 20 73 52 75 6c 65 49 64 29 0a 20 20 20 20 20 20   sRuleId).      
2f70: 20 20 69 66 20 62 43 68 61 6e 67 65 3a 0a 20 20    if bChange:.  
2f80: 20 20 20 20 20 20 20 20 20 20 69 66 20 62 50 61            if bPa
2f90: 72 61 67 72 61 70 68 3a 0a 20 20 20 20 20 20 20  ragraph:.       
2fa0: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73 54           self.sT
2fb0: 65 78 74 20 3d 20 73 54 65 78 74 0a 20 20 20 20  ext = sText.    
2fc0: 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20          else:.  
2fd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
2fe0: 6c 66 2e 73 53 65 6e 74 65 6e 63 65 20 3d 20 73  lf.sSentence = s
2ff0: 54 65 78 74 0a 0a 20 20 20 20 64 65 66 20 75 70  Text..    def up
3000: 64 61 74 65 20 28 73 65 6c 66 2c 20 73 53 65 6e  date (self, sSen
3010: 74 65 6e 63 65 2c 20 62 44 65 62 75 67 3d 46 61  tence, bDebug=Fa
3020: 6c 73 65 29 3a 0a 20 20 20 20 20 20 20 20 22 75  lse):.        "u
3030: 70 64 61 74 65 20 3c 73 53 65 6e 74 65 6e 63 65  pdate <sSentence
3040: 3e 20 61 6e 64 20 72 65 74 6f 6b 65 6e 69 7a 65  > and retokenize
3050: 22 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73  ".        self.s
3060: 53 65 6e 74 65 6e 63 65 20 3d 20 73 53 65 6e 74  Sentence = sSent
3070: 65 6e 63 65 0a 20 20 20 20 20 20 20 20 6c 4e 65  ence.        lNe
3080: 77 54 6f 6b 65 6e 20 3d 20 6c 69 73 74 28 5f 6f  wToken = list(_o
3090: 54 6f 6b 65 6e 69 7a 65 72 2e 67 65 6e 54 6f 6b  Tokenizer.genTok
30a0: 65 6e 73 28 73 53 65 6e 74 65 6e 63 65 2c 20 54  ens(sSentence, T
30b0: 72 75 65 29 29 0a 20 20 20 20 20 20 20 20 66 6f  rue)).        fo
30c0: 72 20 64 54 6f 6b 65 6e 20 69 6e 20 6c 4e 65 77  r dToken in lNew
30d0: 54 6f 6b 65 6e 3a 0a 20 20 20 20 20 20 20 20 20  Token:.         
30e0: 20 20 20 69 66 20 22 6c 4d 6f 72 70 68 22 20 69     if "lMorph" i
30f0: 6e 20 73 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f 73  n self.dTokenPos
3100: 2e 67 65 74 28 64 54 6f 6b 65 6e 5b 22 6e 53 74  .get(dToken["nSt
3110: 61 72 74 22 5d 2c 20 7b 7d 29 3a 0a 20 20 20 20  art"], {}):.    
3120: 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b              dTok
3130: 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 73  en["lMorph"] = s
3140: 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f 73 5b 64 54  elf.dTokenPos[dT
3150: 6f 6b 65 6e 5b 22 6e 53 74 61 72 74 22 5d 5d 5b  oken["nStart"]][
3160: 22 6c 4d 6f 72 70 68 22 5d 0a 20 20 20 20 20 20  "lMorph"].      
3170: 20 20 20 20 20 20 69 66 20 22 61 54 61 67 73 22        if "aTags"
3180: 20 69 6e 20 73 65 6c 66 2e 64 54 6f 6b 65 6e 50   in self.dTokenP
3190: 6f 73 2e 67 65 74 28 64 54 6f 6b 65 6e 5b 22 6e  os.get(dToken["n
31a0: 53 74 61 72 74 22 5d 2c 20 7b 7d 29 3a 0a 20 20  Start"], {}):.  
31b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64 54                dT
31c0: 6f 6b 65 6e 5b 22 61 54 61 67 73 22 5d 20 3d 20  oken["aTags"] = 
31d0: 73 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f 73 5b 64  self.dTokenPos[d
31e0: 54 6f 6b 65 6e 5b 22 6e 53 74 61 72 74 22 5d 5d  Token["nStart"]]
31f0: 5b 22 61 54 61 67 73 22 5d 0a 20 20 20 20 20 20  ["aTags"].      
3200: 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 3d 20    self.lToken = 
3210: 6c 4e 65 77 54 6f 6b 65 6e 0a 20 20 20 20 20 20  lNewToken.      
3220: 20 20 73 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f 73    self.dTokenPos
3230: 20 3d 20 7b 20 64 54 6f 6b 65 6e 5b 22 6e 53 74   = { dToken["nSt
3240: 61 72 74 22 5d 3a 20 64 54 6f 6b 65 6e 20 20 66  art"]: dToken  f
3250: 6f 72 20 64 54 6f 6b 65 6e 20 69 6e 20 73 65 6c  or dToken in sel
3260: 66 2e 6c 54 6f 6b 65 6e 20 20 69 66 20 64 54 6f  f.lToken  if dTo
3270: 6b 65 6e 5b 22 73 54 79 70 65 22 5d 20 21 3d 20  ken["sType"] != 
3280: 22 49 4e 46 4f 22 20 7d 0a 20 20 20 20 20 20 20  "INFO" }.       
3290: 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20   if bDebug:.    
32a0: 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 55 50          echo("UP
32b0: 44 41 54 45 3a 22 29 0a 20 20 20 20 20 20 20 20  DATE:").        
32c0: 20 20 20 20 65 63 68 6f 28 73 65 6c 66 29 0a 0a      echo(self)..
32d0: 20 20 20 20 64 65 66 20 5f 67 65 74 4e 65 78 74      def _getNext
32e0: 50 6f 69 6e 74 65 72 73 20 28 73 65 6c 66 2c 20  Pointers (self, 
32f0: 64 54 6f 6b 65 6e 2c 20 64 47 72 61 70 68 2c 20  dToken, dGraph, 
3300: 64 50 6f 69 6e 74 65 72 2c 20 62 44 65 62 75 67  dPointer, bDebug
3310: 3d 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20  =False):.       
3320: 20 22 67 65 6e 65 72 61 74 6f 72 3a 20 72 65 74   "generator: ret
3330: 75 72 6e 20 6e 6f 64 65 73 20 77 68 65 72 65 20  urn nodes where 
3340: 3c 64 54 6f 6b 65 6e 3e 20 e2 80 9c 76 61 6c 75  <dToken> ...valu
3350: 65 73 e2 80 9d 20 6d 61 74 63 68 20 3c 64 4e 6f  es... match <dNo
3360: 64 65 3e 20 61 72 63 73 22 0a 20 20 20 20 20 20  de> arcs".      
3370: 20 20 64 4e 6f 64 65 20 3d 20 64 50 6f 69 6e 74    dNode = dPoint
3380: 65 72 5b 22 64 4e 6f 64 65 22 5d 0a 20 20 20 20  er["dNode"].    
3390: 20 20 20 20 69 4e 6f 64 65 31 20 3d 20 64 50 6f      iNode1 = dPo
33a0: 69 6e 74 65 72 5b 22 69 4e 6f 64 65 31 22 5d 0a  inter["iNode1"].
33b0: 20 20 20 20 20 20 20 20 62 54 6f 6b 65 6e 46 6f          bTokenFo
33c0: 75 6e 64 20 3d 20 46 61 6c 73 65 0a 20 20 20 20  und = False.    
33d0: 20 20 20 20 23 20 74 6f 6b 65 6e 20 76 61 6c 75      # token valu
33e0: 65 0a 20 20 20 20 20 20 20 20 69 66 20 64 54 6f  e.        if dTo
33f0: 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 20 69 6e  ken["sValue"] in
3400: 20 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20   dNode:.        
3410: 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20      if bDebug:. 
3420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
3430: 63 68 6f 28 22 20 20 4d 41 54 43 48 3a 20 22 20  cho("  MATCH: " 
3440: 2b 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65  + dToken["sValue
3450: 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  "]).            
3460: 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31 22  yield { "iNode1"
3470: 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64 65  : iNode1, "dNode
3480: 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b  ": dGraph[dNode[
3490: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
34a0: 5d 5d 20 7d 0a 20 20 20 20 20 20 20 20 20 20 20  ]] }.           
34b0: 20 62 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 54   bTokenFound = T
34c0: 72 75 65 0a 20 20 20 20 20 20 20 20 69 66 20 64  rue.        if d
34d0: 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 5b  Token["sValue"][
34e0: 30 3a 32 5d 2e 69 73 74 69 74 6c 65 28 29 3a 20  0:2].istitle(): 
34f0: 23 20 77 65 20 74 65 73 74 20 6f 6e 6c 79 20 32  # we test only 2
3500: 20 66 69 72 73 74 20 63 68 61 72 73 2c 20 74 6f   first chars, to
3510: 20 6d 61 6b 65 20 76 61 6c 69 64 20 77 6f 72 64   make valid word
3520: 73 20 73 75 63 68 20 61 73 20 22 4c 61 69 73 73  s such as "Laiss
3530: 65 7a 2d 6c 65 73 22 2c 20 22 50 61 73 73 65 2d  ez-les", "Passe-
3540: 70 61 72 74 6f 75 74 22 2e 0a 20 20 20 20 20 20  partout"..      
3550: 20 20 20 20 20 20 73 56 61 6c 75 65 20 3d 20 64        sValue = d
3560: 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2e  Token["sValue"].
3570: 6c 6f 77 65 72 28 29 0a 20 20 20 20 20 20 20 20  lower().        
3580: 20 20 20 20 69 66 20 73 56 61 6c 75 65 20 69 6e      if sValue in
3590: 20 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20   dNode:.        
35a0: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
35b0: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  g:.             
35c0: 20 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 4d         echo("  M
35d0: 41 54 43 48 3a 20 22 20 2b 20 73 56 61 6c 75 65  ATCH: " + sValue
35e0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
35f0: 20 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65    yield { "iNode
3600: 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f  1": iNode1, "dNo
3610: 64 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64  de": dGraph[dNod
3620: 65 5b 73 56 61 6c 75 65 5d 5d 20 7d 0a 20 20 20  e[sValue]] }.   
3630: 20 20 20 20 20 20 20 20 20 20 20 20 20 62 54 6f               bTo
3640: 6b 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a  kenFound = True.
3650: 20 20 20 20 20 20 20 20 65 6c 69 66 20 64 54 6f          elif dTo
3660: 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2e 69 73  ken["sValue"].is
3670: 75 70 70 65 72 28 29 3a 0a 20 20 20 20 20 20 20  upper():.       
3680: 20 20 20 20 20 73 56 61 6c 75 65 20 3d 20 64 54       sValue = dT
3690: 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2e 6c  oken["sValue"].l
36a0: 6f 77 65 72 28 29 0a 20 20 20 20 20 20 20 20 20  ower().         
36b0: 20 20 20 69 66 20 73 56 61 6c 75 65 20 69 6e 20     if sValue in 
36c0: 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20 20  dNode:.         
36d0: 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67         if bDebug
36e0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
36f0: 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 4d 41        echo("  MA
3700: 54 43 48 3a 20 22 20 2b 20 73 56 61 6c 75 65 29  TCH: " + sValue)
3710: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
3720: 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31   yield { "iNode1
3730: 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64  ": iNode1, "dNod
3740: 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64 65  e": dGraph[dNode
3750: 5b 73 56 61 6c 75 65 5d 5d 20 7d 0a 20 20 20 20  [sValue]] }.    
3760: 20 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b              bTok
3770: 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20  enFound = True. 
3780: 20 20 20 20 20 20 20 20 20 20 20 73 56 61 6c 75             sValu
3790: 65 20 3d 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c  e = dToken["sVal
37a0: 75 65 22 5d 2e 63 61 70 69 74 61 6c 69 7a 65 28  ue"].capitalize(
37b0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  ).            if
37c0: 20 73 56 61 6c 75 65 20 69 6e 20 64 4e 6f 64 65   sValue in dNode
37d0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
37e0: 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20    if bDebug:.   
37f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3800: 20 65 63 68 6f 28 22 20 20 4d 41 54 43 48 3a 20   echo("  MATCH: 
3810: 22 20 2b 20 73 56 61 6c 75 65 29 0a 20 20 20 20  " + sValue).    
3820: 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65 6c              yiel
3830: 64 20 7b 20 22 69 4e 6f 64 65 31 22 3a 20 69 4e  d { "iNode1": iN
3840: 6f 64 65 31 2c 20 22 64 4e 6f 64 65 22 3a 20 64  ode1, "dNode": d
3850: 47 72 61 70 68 5b 64 4e 6f 64 65 5b 73 56 61 6c  Graph[dNode[sVal
3860: 75 65 5d 5d 20 7d 0a 20 20 20 20 20 20 20 20 20  ue]] }.         
3870: 20 20 20 20 20 20 20 62 54 6f 6b 65 6e 46 6f 75         bTokenFou
3880: 6e 64 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20  nd = True.      
3890: 20 20 23 20 72 65 67 65 78 20 76 61 6c 75 65 20    # regex value 
38a0: 61 72 63 73 0a 20 20 20 20 20 20 20 20 69 66 20  arcs.        if 
38b0: 64 54 6f 6b 65 6e 5b 22 73 54 79 70 65 22 5d 20  dToken["sType"] 
38c0: 6e 6f 74 20 69 6e 20 66 72 6f 7a 65 6e 73 65 74  not in frozenset
38d0: 28 5b 22 49 4e 46 4f 22 2c 20 22 50 55 4e 43 22  (["INFO", "PUNC"
38e0: 2c 20 22 53 49 47 4e 22 5d 29 3a 0a 20 20 20 20  , "SIGN"]):.    
38f0: 20 20 20 20 20 20 20 20 69 66 20 22 3c 72 65 5f          if "<re_
3900: 76 61 6c 75 65 3e 22 20 69 6e 20 64 4e 6f 64 65  value>" in dNode
3910: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
3920: 20 20 66 6f 72 20 73 52 65 67 65 78 20 69 6e 20    for sRegex in 
3930: 64 4e 6f 64 65 5b 22 3c 72 65 5f 76 61 6c 75 65  dNode["<re_value
3940: 3e 22 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20  >"]:.           
3950: 20 20 20 20 20 20 20 20 20 69 66 20 22 c2 ac 22           if ".."
3960: 20 6e 6f 74 20 69 6e 20 73 52 65 67 65 78 3a 0a   not in sRegex:.
3970: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3980: 20 20 20 20 20 20 20 20 23 20 6e 6f 20 61 6e 74          # no ant
3990: 69 2d 70 61 74 74 65 72 6e 0a 20 20 20 20 20 20  i-pattern.      
39a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
39b0: 20 20 69 66 20 72 65 2e 73 65 61 72 63 68 28 73    if re.search(s
39c0: 52 65 67 65 78 2c 20 64 54 6f 6b 65 6e 5b 22 73  Regex, dToken["s
39d0: 56 61 6c 75 65 22 5d 29 3a 0a 20 20 20 20 20 20  Value"]):.      
39e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
39f0: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
3a00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
3a10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3a20: 20 65 63 68 6f 28 22 20 20 4d 41 54 43 48 3a 20   echo("  MATCH: 
3a30: 7e 22 20 2b 20 73 52 65 67 65 78 29 0a 20 20 20  ~" + sRegex).   
3a40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3a50: 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 7b           yield {
3a60: 20 22 69 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65   "iNode1": iNode
3a70: 31 2c 20 22 64 4e 6f 64 65 22 3a 20 64 47 72 61  1, "dNode": dGra
3a80: 70 68 5b 64 4e 6f 64 65 5b 22 3c 72 65 5f 76 61  ph[dNode["<re_va
3a90: 6c 75 65 3e 22 5d 5b 73 52 65 67 65 78 5d 5d 20  lue>"][sRegex]] 
3aa0: 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  }.              
3ab0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62 54                bT
3ac0: 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65  okenFound = True
3ad0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
3ae0: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
3af0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3b00: 20 20 20 23 20 74 68 65 72 65 20 69 73 20 61 6e     # there is an
3b10: 20 61 6e 74 69 2d 70 61 74 74 65 72 6e 0a 20 20   anti-pattern.  
3b20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3b30: 20 20 20 20 20 20 73 50 61 74 74 65 72 6e 2c 20        sPattern, 
3b40: 73 4e 65 67 50 61 74 74 65 72 6e 20 3d 20 73 52  sNegPattern = sR
3b50: 65 67 65 78 2e 73 70 6c 69 74 28 22 c2 ac 22 2c  egex.split("..",
3b60: 20 31 29 0a 20 20 20 20 20 20 20 20 20 20 20 20   1).            
3b70: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73              if s
3b80: 4e 65 67 50 61 74 74 65 72 6e 20 61 6e 64 20 72  NegPattern and r
3b90: 65 2e 73 65 61 72 63 68 28 73 4e 65 67 50 61 74  e.search(sNegPat
3ba0: 74 65 72 6e 2c 20 64 54 6f 6b 65 6e 5b 22 73 56  tern, dToken["sV
3bb0: 61 6c 75 65 22 5d 29 3a 0a 20 20 20 20 20 20 20  alue"]):.       
3bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3bd0: 20 20 20 20 20 63 6f 6e 74 69 6e 75 65 0a 20 20       continue.  
3be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3bf0: 20 20 20 20 20 20 69 66 20 6e 6f 74 20 73 50 61        if not sPa
3c00: 74 74 65 72 6e 20 6f 72 20 72 65 2e 73 65 61 72  ttern or re.sear
3c10: 63 68 28 73 50 61 74 74 65 72 6e 2c 20 64 54 6f  ch(sPattern, dTo
3c20: 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 3a 0a  ken["sValue"]):.
3c30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3c40: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62              if b
3c50: 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20  Debug:.         
3c60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3c70: 20 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 4d         echo("  M
3c80: 41 54 43 48 3a 20 7e 22 20 2b 20 73 52 65 67 65  ATCH: ~" + sRege
3c90: 78 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  x).             
3ca0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 79                 y
3cb0: 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31 22 3a  ield { "iNode1":
3cc0: 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64 65 22   iNode1, "dNode"
3cd0: 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b 22  : dGraph[dNode["
3ce0: 3c 72 65 5f 76 61 6c 75 65 3e 22 5d 5b 73 52 65  <re_value>"][sRe
3cf0: 67 65 78 5d 5d 20 7d 0a 20 20 20 20 20 20 20 20  gex]] }.        
3d00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3d10: 20 20 20 20 62 54 6f 6b 65 6e 46 6f 75 6e 64 20      bTokenFound 
3d20: 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20 20 23  = True.        #
3d30: 20 61 6e 61 6c 79 73 61 62 6c 65 20 74 6f 6b 65   analysable toke
3d40: 6e 73 0a 20 20 20 20 20 20 20 20 69 66 20 64 54  ns.        if dT
3d50: 6f 6b 65 6e 5b 22 73 54 79 70 65 22 5d 5b 30 3a  oken["sType"][0:
3d60: 34 5d 20 3d 3d 20 22 57 4f 52 44 22 3a 0a 20 20  4] == "WORD":.  
3d70: 20 20 20 20 20 20 20 20 20 20 23 20 74 6f 6b 65            # toke
3d80: 6e 20 6c 65 6d 6d 61 73 0a 20 20 20 20 20 20 20  n lemmas.       
3d90: 20 20 20 20 20 69 66 20 22 3c 6c 65 6d 6d 61 73       if "<lemmas
3da0: 3e 22 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20  >" in dNode:.   
3db0: 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72               for
3dc0: 20 73 4c 65 6d 6d 61 20 69 6e 20 5f 6f 53 70 65   sLemma in _oSpe
3dd0: 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4c 65 6d  llChecker.getLem
3de0: 6d 61 28 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  ma(dToken["sValu
3df0: 65 22 5d 29 3a 0a 20 20 20 20 20 20 20 20 20 20  e"]):.          
3e00: 20 20 20 20 20 20 20 20 20 20 69 66 20 73 4c 65            if sLe
3e10: 6d 6d 61 20 69 6e 20 64 4e 6f 64 65 5b 22 3c 6c  mma in dNode["<l
3e20: 65 6d 6d 61 73 3e 22 5d 3a 0a 20 20 20 20 20 20  emmas>"]:.      
3e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3e40: 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20    if bDebug:.   
3e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3e60: 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 20           echo(" 
3e70: 20 4d 41 54 43 48 3a 20 3e 22 20 2b 20 73 4c 65   MATCH: >" + sLe
3e80: 6d 6d 61 29 0a 20 20 20 20 20 20 20 20 20 20 20  mma).           
3e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65               yie
3ea0: 6c 64 20 7b 20 22 69 4e 6f 64 65 31 22 3a 20 69  ld { "iNode1": i
3eb0: 4e 6f 64 65 31 2c 20 22 64 4e 6f 64 65 22 3a 20  Node1, "dNode": 
3ec0: 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b 22 3c 6c  dGraph[dNode["<l
3ed0: 65 6d 6d 61 73 3e 22 5d 5b 73 4c 65 6d 6d 61 5d  emmas>"][sLemma]
3ee0: 5d 20 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20  ] }.            
3ef0: 20 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b              bTok
3f00: 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20  enFound = True. 
3f10: 20 20 20 20 20 20 20 20 20 20 20 23 20 72 65 67             # reg
3f20: 65 78 20 6d 6f 72 70 68 20 61 72 63 73 0a 20 20  ex morph arcs.  
3f30: 20 20 20 20 20 20 20 20 20 20 69 66 20 22 3c 72            if "<r
3f40: 65 5f 6d 6f 72 70 68 3e 22 20 69 6e 20 64 4e 6f  e_morph>" in dNo
3f50: 64 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  de:.            
3f60: 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20 64 54 6f      lMorph = dTo
3f70: 6b 65 6e 2e 67 65 74 28 22 6c 4d 6f 72 70 68 22  ken.get("lMorph"
3f80: 2c 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72  , _oSpellChecker
3f90: 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e  .getMorph(dToken
3fa0: 5b 22 73 56 61 6c 75 65 22 5d 29 29 0a 20 20 20  ["sValue"])).   
3fb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72               for
3fc0: 20 73 52 65 67 65 78 20 69 6e 20 64 4e 6f 64 65   sRegex in dNode
3fd0: 5b 22 3c 72 65 5f 6d 6f 72 70 68 3e 22 5d 3a 0a  ["<re_morph>"]:.
3fe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3ff0: 20 20 20 20 69 66 20 22 c2 ac 22 20 6e 6f 74 20      if ".." not 
4000: 69 6e 20 73 52 65 67 65 78 3a 0a 20 20 20 20 20  in sRegex:.     
4010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4020: 20 20 20 23 20 6e 6f 20 61 6e 74 69 2d 70 61 74     # no anti-pat
4030: 74 65 72 6e 0a 20 20 20 20 20 20 20 20 20 20 20  tern.           
4040: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
4050: 61 6e 79 28 72 65 2e 73 65 61 72 63 68 28 73 52  any(re.search(sR
4060: 65 67 65 78 2c 20 73 4d 6f 72 70 68 29 20 20 66  egex, sMorph)  f
4070: 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f  or sMorph in lMo
4080: 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20  rph):.          
4090: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
40a0: 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20    if bDebug:.   
40b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
40c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 63 68               ech
40d0: 6f 28 22 20 20 4d 41 54 43 48 3a 20 40 22 20 2b  o("  MATCH: @" +
40e0: 20 73 52 65 67 65 78 29 0a 20 20 20 20 20 20 20   sRegex).       
40f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4100: 20 20 20 20 20 79 69 65 6c 64 20 7b 20 22 69 4e       yield { "iN
4110: 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22  ode1": iNode1, "
4120: 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b 64  dNode": dGraph[d
4130: 4e 6f 64 65 5b 22 3c 72 65 5f 6d 6f 72 70 68 3e  Node["<re_morph>
4140: 22 5d 5b 73 52 65 67 65 78 5d 5d 20 7d 0a 20 20  "][sRegex]] }.  
4150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4160: 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b 65 6e            bToken
4170: 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20 20 20  Found = True.   
4180: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4190: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
41a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
41b0: 20 74 68 65 72 65 20 69 73 20 61 6e 20 61 6e 74   there is an ant
41c0: 69 2d 70 61 74 74 65 72 6e 0a 20 20 20 20 20 20  i-pattern.      
41d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
41e0: 20 20 73 50 61 74 74 65 72 6e 2c 20 73 4e 65 67    sPattern, sNeg
41f0: 50 61 74 74 65 72 6e 20 3d 20 73 52 65 67 65 78  Pattern = sRegex
4200: 2e 73 70 6c 69 74 28 22 c2 ac 22 2c 20 31 29 0a  .split("..", 1).
4210: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4220: 20 20 20 20 20 20 20 20 69 66 20 73 4e 65 67 50          if sNegP
4230: 61 74 74 65 72 6e 20 3d 3d 20 22 2a 22 3a 0a 20  attern == "*":. 
4240: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4250: 20 20 20 20 20 20 20 20 20 20 20 23 20 61 6c 6c             # all
4260: 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 6d 75   morphologies mu
4270: 73 74 20 6d 61 74 63 68 20 77 69 74 68 20 3c 73  st match with <s
4280: 50 61 74 74 65 72 6e 3e 0a 20 20 20 20 20 20 20  Pattern>.       
4290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
42a0: 20 20 20 20 20 69 66 20 73 50 61 74 74 65 72 6e       if sPattern
42b0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
42c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
42d0: 20 20 69 66 20 6c 4d 6f 72 70 68 20 61 6e 64 20    if lMorph and 
42e0: 61 6c 6c 28 72 65 2e 73 65 61 72 63 68 28 73 50  all(re.search(sP
42f0: 61 74 74 65 72 6e 2c 20 73 4d 6f 72 70 68 29 20  attern, sMorph) 
4300: 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c   for sMorph in l
4310: 4d 6f 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20  Morph):.        
4320: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4330: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62              if b
4340: 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20  Debug:.         
4350: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4360: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
4370: 63 68 6f 28 22 20 20 4d 41 54 43 48 3a 20 40 22  cho("  MATCH: @"
4380: 20 2b 20 73 52 65 67 65 78 29 0a 20 20 20 20 20   + sRegex).     
4390: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
43a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 79                 y
43b0: 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31 22 3a  ield { "iNode1":
43c0: 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64 65 22   iNode1, "dNode"
43d0: 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b 22  : dGraph[dNode["
43e0: 3c 72 65 5f 6d 6f 72 70 68 3e 22 5d 5b 73 52 65  <re_morph>"][sRe
43f0: 67 65 78 5d 5d 20 7d 0a 20 20 20 20 20 20 20 20  gex]] }.        
4400: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4410: 20 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b              bTok
4420: 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20  enFound = True. 
4430: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4440: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
4450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4460: 20 20 20 20 20 20 20 20 20 69 66 20 73 4e 65 67           if sNeg
4470: 50 61 74 74 65 72 6e 20 61 6e 64 20 61 6e 79 28  Pattern and any(
4480: 72 65 2e 73 65 61 72 63 68 28 73 4e 65 67 50 61  re.search(sNegPa
4490: 74 74 65 72 6e 2c 20 73 4d 6f 72 70 68 29 20 20  ttern, sMorph)  
44a0: 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d  for sMorph in lM
44b0: 6f 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20  orph):.         
44c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
44d0: 20 20 20 20 20 20 20 63 6f 6e 74 69 6e 75 65 0a         continue.
44e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
44f0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
4500: 6f 74 20 73 50 61 74 74 65 72 6e 20 6f 72 20 61  ot sPattern or a
4510: 6e 79 28 72 65 2e 73 65 61 72 63 68 28 73 50 61  ny(re.search(sPa
4520: 74 74 65 72 6e 2c 20 73 4d 6f 72 70 68 29 20 20  ttern, sMorph)  
4530: 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d  for sMorph in lM
4540: 6f 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20  orph):.         
4550: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4560: 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67         if bDebug
4570: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
4580: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4590: 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 4d 41        echo("  MA
45a0: 54 43 48 3a 20 40 22 20 2b 20 73 52 65 67 65 78  TCH: @" + sRegex
45b0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
45c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
45d0: 20 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65    yield { "iNode
45e0: 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f  1": iNode1, "dNo
45f0: 64 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64  de": dGraph[dNod
4600: 65 5b 22 3c 72 65 5f 6d 6f 72 70 68 3e 22 5d 5b  e["<re_morph>"][
4610: 73 52 65 67 65 78 5d 5d 20 7d 0a 20 20 20 20 20  sRegex]] }.     
4620: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4630: 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b 65             bToke
4640: 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20 20  nFound = True.  
4650: 20 20 20 20 20 20 23 20 74 6f 6b 65 6e 20 74 61        # token ta
4660: 67 73 0a 20 20 20 20 20 20 20 20 69 66 20 22 61  gs.        if "a
4670: 54 61 67 73 22 20 69 6e 20 64 54 6f 6b 65 6e 20  Tags" in dToken 
4680: 61 6e 64 20 22 3c 74 61 67 73 3e 22 20 69 6e 20  and "<tags>" in 
4690: 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20 20  dNode:.         
46a0: 20 20 20 66 6f 72 20 73 54 61 67 20 69 6e 20 64     for sTag in d
46b0: 54 6f 6b 65 6e 5b 22 61 54 61 67 73 22 5d 3a 0a  Token["aTags"]:.
46c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
46d0: 69 66 20 73 54 61 67 20 69 6e 20 64 4e 6f 64 65  if sTag in dNode
46e0: 5b 22 3c 74 61 67 73 3e 22 5d 3a 0a 20 20 20 20  ["<tags>"]:.    
46f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4700: 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20  if bDebug:.     
4710: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4720: 20 20 20 65 63 68 6f 28 22 20 20 4d 41 54 43 48     echo("  MATCH
4730: 3a 20 2f 22 20 2b 20 73 54 61 67 29 0a 20 20 20  : /" + sTag).   
4740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4750: 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31   yield { "iNode1
4760: 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64  ": iNode1, "dNod
4770: 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64 65  e": dGraph[dNode
4780: 5b 22 3c 74 61 67 73 3e 22 5d 5b 73 54 61 67 5d  ["<tags>"][sTag]
4790: 5d 20 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20  ] }.            
47a0: 20 20 20 20 20 20 20 20 62 54 6f 6b 65 6e 46 6f          bTokenFo
47b0: 75 6e 64 20 3d 20 54 72 75 65 0a 20 20 20 20 20  und = True.     
47c0: 20 20 20 23 20 6d 65 74 61 20 61 72 63 20 28 66     # meta arc (f
47d0: 6f 72 20 74 6f 6b 65 6e 20 74 79 70 65 29 0a 20  or token type). 
47e0: 20 20 20 20 20 20 20 69 66 20 22 3c 6d 65 74 61         if "<meta
47f0: 3e 22 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20  >" in dNode:.   
4800: 20 20 20 20 20 20 20 20 20 66 6f 72 20 73 4d 65           for sMe
4810: 74 61 20 69 6e 20 64 4e 6f 64 65 5b 22 3c 6d 65  ta in dNode["<me
4820: 74 61 3e 22 5d 3a 0a 20 20 20 20 20 20 20 20 20  ta>"]:.         
4830: 20 20 20 20 20 20 20 23 20 6e 6f 20 72 65 67 65         # no rege
4840: 78 20 68 65 72 65 2c 20 77 65 20 6a 75 73 74 20  x here, we just 
4850: 73 65 61 72 63 68 20 69 66 20 3c 64 4e 6f 64 65  search if <dNode
4860: 5b 22 73 54 79 70 65 22 5d 3e 20 65 78 69 73 74  ["sType"]> exist
4870: 73 20 77 69 74 68 69 6e 20 3c 73 4d 65 74 61 3e  s within <sMeta>
4880: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4890: 20 69 66 20 73 4d 65 74 61 20 3d 3d 20 22 2a 22   if sMeta == "*"
48a0: 20 6f 72 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70   or dToken["sTyp
48b0: 65 22 5d 20 3d 3d 20 73 4d 65 74 61 3a 0a 20 20  e"] == sMeta:.  
48c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
48d0: 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20    if bDebug:.   
48e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
48f0: 20 20 20 20 20 65 63 68 6f 28 22 20 20 4d 41 54       echo("  MAT
4900: 43 48 3a 20 2a 22 20 2b 20 73 4d 65 74 61 29 0a  CH: *" + sMeta).
4910: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4920: 20 20 20 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f      yield { "iNo
4930: 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64  de1": iNode1, "d
4940: 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b 64 4e  Node": dGraph[dN
4950: 6f 64 65 5b 22 3c 6d 65 74 61 3e 22 5d 5b 73 4d  ode["<meta>"][sM
4960: 65 74 61 5d 5d 20 7d 0a 20 20 20 20 20 20 20 20  eta]] }.        
4970: 20 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b              bTok
4980: 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20  enFound = True. 
4990: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
49a0: 6c 69 66 20 22 c2 ac 22 20 69 6e 20 73 4d 65 74  lif ".." in sMet
49b0: 61 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  a:.             
49c0: 20 20 20 20 20 20 20 69 66 20 64 54 6f 6b 65 6e         if dToken
49d0: 5b 22 73 54 79 70 65 22 5d 20 6e 6f 74 20 69 6e  ["sType"] not in
49e0: 20 73 4d 65 74 61 3a 0a 20 20 20 20 20 20 20 20   sMeta:.        
49f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4a00: 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20  if bDebug:.     
4a10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4a20: 20 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 4d         echo("  M
4a30: 41 54 43 48 3a 20 2a 22 20 2b 20 73 4d 65 74 61  ATCH: *" + sMeta
4a40: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
4a50: 20 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20            yield 
4a60: 7b 20 22 69 4e 6f 64 65 31 22 3a 20 69 4e 6f 64  { "iNode1": iNod
4a70: 65 31 2c 20 22 64 4e 6f 64 65 22 3a 20 64 47 72  e1, "dNode": dGr
4a80: 61 70 68 5b 64 4e 6f 64 65 5b 22 3c 6d 65 74 61  aph[dNode["<meta
4a90: 3e 22 5d 5b 73 4d 65 74 61 5d 5d 20 7d 0a 20 20  >"][sMeta]] }.  
4aa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4ab0: 20 20 20 20 20 20 62 54 6f 6b 65 6e 46 6f 75 6e        bTokenFoun
4ac0: 64 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20  d = True.       
4ad0: 20 69 66 20 6e 6f 74 20 62 54 6f 6b 65 6e 46 6f   if not bTokenFo
4ae0: 75 6e 64 20 61 6e 64 20 22 62 4b 65 65 70 22 20  und and "bKeep" 
4af0: 69 6e 20 64 50 6f 69 6e 74 65 72 3a 0a 20 20 20  in dPointer:.   
4b00: 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 64           yield d
4b10: 50 6f 69 6e 74 65 72 0a 20 20 20 20 20 20 20 20  Pointer.        
4b20: 23 20 4a 55 4d 50 0a 20 20 20 20 20 20 20 20 23  # JUMP.        #
4b30: 20 57 61 72 6e 69 6e 67 21 20 52 65 63 75 72 73   Warning! Recurs
4b40: 73 69 6f 6e 21 0a 20 20 20 20 20 20 20 20 69 66  sion!.        if
4b50: 20 22 3c 3e 22 20 69 6e 20 64 4e 6f 64 65 3a 0a   "<>" in dNode:.
4b60: 20 20 20 20 20 20 20 20 20 20 20 20 64 50 6f 69              dPoi
4b70: 6e 74 65 72 32 20 3d 20 7b 20 22 69 4e 6f 64 65  nter2 = { "iNode
4b80: 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f  1": iNode1, "dNo
4b90: 64 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64  de": dGraph[dNod
4ba0: 65 5b 22 3c 3e 22 5d 5d 2c 20 22 62 4b 65 65 70  e["<>"]], "bKeep
4bb0: 22 3a 20 54 72 75 65 20 7d 0a 20 20 20 20 20 20  ": True }.      
4bc0: 20 20 20 20 20 20 79 69 65 6c 64 20 66 72 6f 6d        yield from
4bd0: 20 73 65 6c 66 2e 5f 67 65 74 4e 65 78 74 50 6f   self._getNextPo
4be0: 69 6e 74 65 72 73 28 64 54 6f 6b 65 6e 2c 20 64  inters(dToken, d
4bf0: 47 72 61 70 68 2c 20 64 50 6f 69 6e 74 65 72 32  Graph, dPointer2
4c00: 2c 20 62 44 65 62 75 67 29 0a 0a 20 20 20 20 64  , bDebug)..    d
4c10: 65 66 20 70 61 72 73 65 47 72 61 70 68 20 28 73  ef parseGraph (s
4c20: 65 6c 66 2c 20 64 47 72 61 70 68 2c 20 73 43 6f  elf, dGraph, sCo
4c30: 75 6e 74 72 79 3d 22 24 7b 63 6f 75 6e 74 72 79  untry="${country
4c40: 5f 64 65 66 61 75 6c 74 7d 22 2c 20 64 4f 70 74  _default}", dOpt
4c50: 69 6f 6e 73 3d 4e 6f 6e 65 2c 20 62 53 68 6f 77  ions=None, bShow
4c60: 52 75 6c 65 49 64 3d 46 61 6c 73 65 2c 20 62 44  RuleId=False, bD
4c70: 65 62 75 67 3d 46 61 6c 73 65 2c 20 62 43 6f 6e  ebug=False, bCon
4c80: 74 65 78 74 3d 46 61 6c 73 65 29 3a 0a 20 20 20  text=False):.   
4c90: 20 20 20 20 20 22 70 61 72 73 65 20 67 72 61 70       "parse grap
4ca0: 68 20 77 69 74 68 20 74 6f 6b 65 6e 73 20 66 72  h with tokens fr
4cb0: 6f 6d 20 74 68 65 20 74 65 78 74 20 61 6e 64 20  om the text and 
4cc0: 65 78 65 63 75 74 65 20 61 63 74 69 6f 6e 73 20  execute actions 
4cd0: 65 6e 63 6f 75 6e 74 65 72 65 64 22 0a 20 20 20  encountered".   
4ce0: 20 20 20 20 20 6c 50 6f 69 6e 74 65 72 20 3d 20       lPointer = 
4cf0: 5b 5d 0a 20 20 20 20 20 20 20 20 62 54 61 67 41  [].        bTagA
4d00: 6e 64 52 65 77 72 69 74 65 20 3d 20 46 61 6c 73  ndRewrite = Fals
4d10: 65 0a 20 20 20 20 20 20 20 20 66 6f 72 20 69 54  e.        for iT
4d20: 6f 6b 65 6e 2c 20 64 54 6f 6b 65 6e 20 69 6e 20  oken, dToken in 
4d30: 65 6e 75 6d 65 72 61 74 65 28 73 65 6c 66 2e 6c  enumerate(self.l
4d40: 54 6f 6b 65 6e 29 3a 0a 20 20 20 20 20 20 20 20  Token):.        
4d50: 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20      if bDebug:. 
4d60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
4d70: 63 68 6f 28 22 54 4f 4b 45 4e 3a 20 22 20 2b 20  cho("TOKEN: " + 
4d80: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
4d90: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 20  ).            # 
4da0: 63 68 65 63 6b 20 61 72 63 73 20 66 6f 72 20 65  check arcs for e
4db0: 61 63 68 20 65 78 69 73 74 69 6e 67 20 70 6f 69  ach existing poi
4dc0: 6e 74 65 72 0a 20 20 20 20 20 20 20 20 20 20 20  nter.           
4dd0: 20 6c 4e 65 78 74 50 6f 69 6e 74 65 72 20 3d 20   lNextPointer = 
4de0: 5b 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 66  [].            f
4df0: 6f 72 20 64 50 6f 69 6e 74 65 72 20 69 6e 20 6c  or dPointer in l
4e00: 50 6f 69 6e 74 65 72 3a 0a 20 20 20 20 20 20 20  Pointer:.       
4e10: 20 20 20 20 20 20 20 20 20 6c 4e 65 78 74 50 6f           lNextPo
4e20: 69 6e 74 65 72 2e 65 78 74 65 6e 64 28 73 65 6c  inter.extend(sel
4e30: 66 2e 5f 67 65 74 4e 65 78 74 50 6f 69 6e 74 65  f._getNextPointe
4e40: 72 73 28 64 54 6f 6b 65 6e 2c 20 64 47 72 61 70  rs(dToken, dGrap
4e50: 68 2c 20 64 50 6f 69 6e 74 65 72 2c 20 62 44 65  h, dPointer, bDe
4e60: 62 75 67 29 29 0a 20 20 20 20 20 20 20 20 20 20  bug)).          
4e70: 20 20 6c 50 6f 69 6e 74 65 72 20 3d 20 6c 4e 65    lPointer = lNe
4e80: 78 74 50 6f 69 6e 74 65 72 0a 20 20 20 20 20 20  xtPointer.      
4e90: 20 20 20 20 20 20 23 20 63 68 65 63 6b 20 61 72        # check ar
4ea0: 63 73 20 6f 66 20 66 69 72 73 74 20 6e 6f 64 65  cs of first node
4eb0: 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 6c 50  s.            lP
4ec0: 6f 69 6e 74 65 72 2e 65 78 74 65 6e 64 28 73 65  ointer.extend(se
4ed0: 6c 66 2e 5f 67 65 74 4e 65 78 74 50 6f 69 6e 74  lf._getNextPoint
4ee0: 65 72 73 28 64 54 6f 6b 65 6e 2c 20 64 47 72 61  ers(dToken, dGra
4ef0: 70 68 2c 20 7b 20 22 69 4e 6f 64 65 31 22 3a 20  ph, { "iNode1": 
4f00: 69 54 6f 6b 65 6e 2c 20 22 64 4e 6f 64 65 22 3a  iToken, "dNode":
4f10: 20 64 47 72 61 70 68 5b 30 5d 20 7d 2c 20 62 44   dGraph[0] }, bD
4f20: 65 62 75 67 29 29 0a 20 20 20 20 20 20 20 20 20  ebug)).         
4f30: 20 20 20 23 20 63 68 65 63 6b 20 69 66 20 74 68     # check if th
4f40: 65 72 65 20 69 73 20 72 75 6c 65 73 20 74 6f 20  ere is rules to 
4f50: 63 68 65 63 6b 20 66 6f 72 20 65 61 63 68 20 70  check for each p
4f60: 6f 69 6e 74 65 72 0a 20 20 20 20 20 20 20 20 20  ointer.         
4f70: 20 20 20 66 6f 72 20 64 50 6f 69 6e 74 65 72 20     for dPointer 
4f80: 69 6e 20 6c 50 6f 69 6e 74 65 72 3a 0a 20 20 20  in lPointer:.   
4f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 69 66               #if
4fa0: 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20   bDebug:.       
4fb0: 20 20 20 20 20 20 20 20 20 23 20 20 20 20 65 63           #    ec
4fc0: 68 6f 28 22 2b 22 2c 20 64 50 6f 69 6e 74 65 72  ho("+", dPointer
4fd0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
4fe0: 20 20 69 66 20 22 3c 72 75 6c 65 73 3e 22 20 69    if "<rules>" i
4ff0: 6e 20 64 50 6f 69 6e 74 65 72 5b 22 64 4e 6f 64  n dPointer["dNod
5000: 65 22 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20  e"]:.           
5010: 20 20 20 20 20 20 20 20 20 62 43 68 61 6e 67 65           bChange
5020: 20 3d 20 73 65 6c 66 2e 5f 65 78 65 63 75 74 65   = self._execute
5030: 41 63 74 69 6f 6e 73 28 64 47 72 61 70 68 2c 20  Actions(dGraph, 
5040: 64 50 6f 69 6e 74 65 72 5b 22 64 4e 6f 64 65 22  dPointer["dNode"
5050: 5d 5b 22 3c 72 75 6c 65 73 3e 22 5d 2c 20 64 50  ]["<rules>"], dP
5060: 6f 69 6e 74 65 72 5b 22 69 4e 6f 64 65 31 22 5d  ointer["iNode1"]
5070: 2d 31 2c 20 69 54 6f 6b 65 6e 2c 20 64 4f 70 74  -1, iToken, dOpt
5080: 69 6f 6e 73 2c 20 73 43 6f 75 6e 74 72 79 2c 20  ions, sCountry, 
5090: 62 53 68 6f 77 52 75 6c 65 49 64 2c 20 62 44 65  bShowRuleId, bDe
50a0: 62 75 67 2c 20 62 43 6f 6e 74 65 78 74 29 0a 20  bug, bContext). 
50b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
50c0: 20 20 20 69 66 20 62 43 68 61 6e 67 65 3a 0a 20     if bChange:. 
50d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
50e0: 20 20 20 20 20 20 20 62 54 61 67 41 6e 64 52 65         bTagAndRe
50f0: 77 72 69 74 65 20 3d 20 54 72 75 65 0a 20 20 20  write = True.   
5100: 20 20 20 20 20 69 66 20 62 54 61 67 41 6e 64 52       if bTagAndR
5110: 65 77 72 69 74 65 3a 0a 20 20 20 20 20 20 20 20  ewrite:.        
5120: 20 20 20 20 73 65 6c 66 2e 72 65 77 72 69 74 65      self.rewrite
5130: 46 72 6f 6d 54 61 67 73 28 62 44 65 62 75 67 29  FromTags(bDebug)
5140: 0a 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62  .        if bDeb
5150: 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ug:.            
5160: 65 63 68 6f 28 73 65 6c 66 29 0a 20 20 20 20 20  echo(self).     
5170: 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 73     return self.s
5180: 53 65 6e 74 65 6e 63 65 0a 0a 20 20 20 20 64 65  Sentence..    de
5190: 66 20 5f 65 78 65 63 75 74 65 41 63 74 69 6f 6e  f _executeAction
51a0: 73 20 28 73 65 6c 66 2c 20 64 47 72 61 70 68 2c  s (self, dGraph,
51b0: 20 64 4e 6f 64 65 2c 20 6e 54 6f 6b 65 6e 4f 66   dNode, nTokenOf
51c0: 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e  fset, nLastToken
51d0: 2c 20 64 4f 70 74 69 6f 6e 73 2c 20 73 43 6f 75  , dOptions, sCou
51e0: 6e 74 72 79 2c 20 62 53 68 6f 77 52 75 6c 65 49  ntry, bShowRuleI
51f0: 64 2c 20 62 44 65 62 75 67 2c 20 62 43 6f 6e 74  d, bDebug, bCont
5200: 65 78 74 29 3a 0a 20 20 20 20 20 20 20 20 22 65  ext):.        "e
5210: 78 65 63 75 74 65 20 61 63 74 69 6f 6e 73 20 66  xecute actions f
5220: 6f 75 6e 64 20 69 6e 20 74 68 65 20 44 41 52 47  ound in the DARG
5230: 22 0a 20 20 20 20 20 20 20 20 62 43 68 61 6e 67  ".        bChang
5240: 65 20 3d 20 46 61 6c 73 65 0a 20 20 20 20 20 20  e = False.      
5250: 20 20 66 6f 72 20 73 4c 69 6e 65 49 64 2c 20 6e    for sLineId, n
5260: 65 78 74 4e 6f 64 65 4b 65 79 20 69 6e 20 64 4e  extNodeKey in dN
5270: 6f 64 65 2e 69 74 65 6d 73 28 29 3a 0a 20 20 20  ode.items():.   
5280: 20 20 20 20 20 20 20 20 20 62 43 6f 6e 64 4d 65           bCondMe
5290: 6d 6f 20 3d 20 4e 6f 6e 65 0a 20 20 20 20 20 20  mo = None.      
52a0: 20 20 20 20 20 20 66 6f 72 20 73 52 75 6c 65 49        for sRuleI
52b0: 64 20 69 6e 20 64 47 72 61 70 68 5b 6e 65 78 74  d in dGraph[next
52c0: 4e 6f 64 65 4b 65 79 5d 3a 0a 20 20 20 20 20 20  NodeKey]:.      
52d0: 20 20 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20            try:. 
52e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
52f0: 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20     if bDebug:.  
5300: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5310: 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 20 3e        echo("   >
5320: 54 52 59 3a 20 22 20 2b 20 73 52 75 6c 65 49 64  TRY: " + sRuleId
5330: 20 2b 20 22 20 22 20 2b 20 73 4c 69 6e 65 49 64   + " " + sLineId
5340: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
5350: 20 20 20 20 20 20 73 4f 70 74 69 6f 6e 2c 20 73        sOption, s
5360: 46 75 6e 63 43 6f 6e 64 2c 20 63 41 63 74 69 6f  FuncCond, cActio
5370: 6e 54 79 70 65 2c 20 73 57 68 61 74 2c 20 2a 65  nType, sWhat, *e
5380: 41 63 74 20 3d 20 5f 72 75 6c 65 73 5f 67 72 61  Act = _rules_gra
5390: 70 68 2e 64 52 75 6c 65 5b 73 52 75 6c 65 49 64  ph.dRule[sRuleId
53a0: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ].              
53b0: 20 20 20 20 20 20 23 20 53 75 67 67 65 73 74 69        # Suggesti
53c0: 6f 6e 20 20 20 20 5b 20 6f 70 74 69 6f 6e 2c 20  on    [ option, 
53d0: 63 6f 6e 64 69 74 69 6f 6e 2c 20 22 2d 22 2c 20  condition, "-", 
53e0: 72 65 70 6c 61 63 65 6d 65 6e 74 2f 73 75 67 67  replacement/sugg
53f0: 65 73 74 69 6f 6e 2f 61 63 74 69 6f 6e 2c 20 69  estion/action, i
5400: 54 6f 6b 65 6e 53 74 61 72 74 2c 20 69 54 6f 6b  TokenStart, iTok
5410: 65 6e 45 6e 64 2c 20 63 53 74 61 72 74 4c 69 6d  enEnd, cStartLim
5420: 69 74 2c 20 63 45 6e 64 4c 69 6d 69 74 2c 20 62  it, cEndLimit, b
5430: 43 61 73 65 53 76 74 79 2c 20 6e 50 72 69 6f 72  CaseSvty, nPrior
5440: 69 74 79 2c 20 73 4d 65 73 73 61 67 65 2c 20 73  ity, sMessage, s
5450: 55 52 4c 20 5d 0a 20 20 20 20 20 20 20 20 20 20  URL ].          
5460: 20 20 20 20 20 20 20 20 20 20 23 20 54 65 78 74            # Text
5470: 50 72 6f 63 65 73 73 6f 72 20 5b 20 6f 70 74 69  Processor [ opti
5480: 6f 6e 2c 20 63 6f 6e 64 69 74 69 6f 6e 2c 20 22  on, condition, "
5490: 7e 22 2c 20 72 65 70 6c 61 63 65 6d 65 6e 74 2f  ~", replacement/
54a0: 73 75 67 67 65 73 74 69 6f 6e 2f 61 63 74 69 6f  suggestion/actio
54b0: 6e 2c 20 69 54 6f 6b 65 6e 53 74 61 72 74 2c 20  n, iTokenStart, 
54c0: 69 54 6f 6b 65 6e 45 6e 64 2c 20 62 43 61 73 65  iTokenEnd, bCase
54d0: 53 76 74 79 20 5d 0a 20 20 20 20 20 20 20 20 20  Svty ].         
54e0: 20 20 20 20 20 20 20 20 20 20 20 23 20 44 69 73             # Dis
54f0: 61 6d 62 69 67 75 61 74 6f 72 20 5b 20 6f 70 74  ambiguator [ opt
5500: 69 6f 6e 2c 20 63 6f 6e 64 69 74 69 6f 6e 2c 20  ion, condition, 
5510: 22 3d 22 2c 20 72 65 70 6c 61 63 65 6d 65 6e 74  "=", replacement
5520: 2f 73 75 67 67 65 73 74 69 6f 6e 2f 61 63 74 69  /suggestion/acti
5530: 6f 6e 20 5d 0a 20 20 20 20 20 20 20 20 20 20 20  on ].           
5540: 20 20 20 20 20 20 20 20 20 23 20 54 61 67 20 20           # Tag  
5550: 20 20 20 20 20 20 20 20 20 5b 20 6f 70 74 69 6f           [ optio
5560: 6e 2c 20 63 6f 6e 64 69 74 69 6f 6e 2c 20 22 2f  n, condition, "/
5570: 22 2c 20 72 65 70 6c 61 63 65 6d 65 6e 74 2f 73  ", replacement/s
5580: 75 67 67 65 73 74 69 6f 6e 2f 61 63 74 69 6f 6e  uggestion/action
5590: 2c 20 69 54 6f 6b 65 6e 53 74 61 72 74 2c 20 69  , iTokenStart, i
55a0: 54 6f 6b 65 6e 45 6e 64 20 5d 0a 20 20 20 20 20  TokenEnd ].     
55b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
55c0: 20 49 6d 6d 75 6e 69 74 79 20 20 20 20 20 20 5b   Immunity      [
55d0: 20 6f 70 74 69 6f 6e 2c 20 63 6f 6e 64 69 74 69   option, conditi
55e0: 6f 6e 2c 20 22 25 22 2c 20 22 22 2c 20 20 20 20  on, "%", "",    
55f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5600: 20 20 20 20 20 20 20 20 69 54 6f 6b 65 6e 53 74          iTokenSt
5610: 61 72 74 2c 20 69 54 6f 6b 65 6e 45 6e 64 20 5d  art, iTokenEnd ]
5620: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5630: 20 20 20 20 20 23 20 54 65 73 74 20 20 20 20 20       # Test     
5640: 20 20 20 20 20 5b 20 6f 70 74 69 6f 6e 2c 20 63       [ option, c
5650: 6f 6e 64 69 74 69 6f 6e 2c 20 22 3e 22 2c 20 22  ondition, ">", "
5660: 22 20 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  " ].            
5670: 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 73          if not s
5680: 4f 70 74 69 6f 6e 20 6f 72 20 64 4f 70 74 69 6f  Option or dOptio
5690: 6e 73 2e 67 65 74 28 73 4f 70 74 69 6f 6e 2c 20  ns.get(sOption, 
56a0: 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20 20  False):.        
56b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
56c0: 62 43 6f 6e 64 4d 65 6d 6f 20 3d 20 6e 6f 74 20  bCondMemo = not 
56d0: 73 46 75 6e 63 43 6f 6e 64 20 6f 72 20 67 6c 6f  sFuncCond or glo
56e0: 62 61 6c 73 28 29 5b 73 46 75 6e 63 43 6f 6e 64  bals()[sFuncCond
56f0: 5d 28 73 65 6c 66 2e 6c 54 6f 6b 65 6e 2c 20 6e  ](self.lToken, n
5700: 54 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 6e 4c 61  TokenOffset, nLa
5710: 73 74 54 6f 6b 65 6e 2c 20 73 43 6f 75 6e 74 72  stToken, sCountr
5720: 79 2c 20 62 43 6f 6e 64 4d 65 6d 6f 2c 20 73 65  y, bCondMemo, se
5730: 6c 66 2e 64 54 61 67 73 2c 20 73 65 6c 66 2e 73  lf.dTags, self.s
5740: 53 65 6e 74 65 6e 63 65 2c 20 73 65 6c 66 2e 73  Sentence, self.s
5750: 53 65 6e 74 65 6e 63 65 30 29 0a 20 20 20 20 20  Sentence0).     
5760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5770: 20 20 20 69 66 20 62 43 6f 6e 64 4d 65 6d 6f 3a     if bCondMemo:
5780: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5790: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
57a0: 63 41 63 74 69 6f 6e 54 79 70 65 20 3d 3d 20 22  cActionType == "
57b0: 2d 22 3a 0a 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 23 20 67 72 61 6d 6d 61 72 20 65 72      # grammar er
57e0: 72 6f 72 0a 20 20 20 20 20 20 20 20 20 20 20 20  ror.            
57f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5800: 20 20 20 20 69 54 6f 6b 65 6e 53 74 61 72 74 2c      iTokenStart,
5810: 20 69 54 6f 6b 65 6e 45 6e 64 2c 20 63 53 74 61   iTokenEnd, cSta
5820: 72 74 4c 69 6d 69 74 2c 20 63 45 6e 64 4c 69 6d  rtLimit, cEndLim
5830: 69 74 2c 20 62 43 61 73 65 53 76 74 79 2c 20 6e  it, bCaseSvty, n
5840: 50 72 69 6f 72 69 74 79 2c 20 73 4d 65 73 73 61  Priority, sMessa
5850: 67 65 2c 20 73 55 52 4c 20 3d 20 65 41 63 74 0a  ge, sURL = eAct.
5860: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5870: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5880: 6e 54 6f 6b 65 6e 45 72 72 6f 72 53 74 61 72 74  nTokenErrorStart
5890: 20 3d 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 20   = nTokenOffset 
58a0: 2b 20 69 54 6f 6b 65 6e 53 74 61 72 74 20 20 69  + iTokenStart  i
58b0: 66 20 69 54 6f 6b 65 6e 53 74 61 72 74 20 3e 20  f iTokenStart > 
58c0: 30 20 20 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b  0  else nLastTok
58d0: 65 6e 20 2b 20 69 54 6f 6b 65 6e 53 74 61 72 74  en + iTokenStart
58e0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
58f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5900: 20 69 66 20 22 62 49 6d 6d 75 6e 65 22 20 6e 6f   if "bImmune" no
5910: 74 20 69 6e 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e  t in self.lToken
5920: 5b 6e 54 6f 6b 65 6e 45 72 72 6f 72 53 74 61 72  [nTokenErrorStar
5930: 74 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  t]:.            
5940: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5950: 20 20 20 20 20 20 20 20 6e 54 6f 6b 65 6e 45 72          nTokenEr
5960: 72 6f 72 45 6e 64 20 3d 20 6e 54 6f 6b 65 6e 4f  rorEnd = nTokenO
5970: 66 66 73 65 74 20 2b 20 69 54 6f 6b 65 6e 45 6e  ffset + iTokenEn
5980: 64 20 20 69 66 20 69 54 6f 6b 65 6e 45 6e 64 20  d  if iTokenEnd 
5990: 3e 20 30 20 20 65 6c 73 65 20 6e 4c 61 73 74 54  > 0  else nLastT
59a0: 6f 6b 65 6e 20 2b 20 69 54 6f 6b 65 6e 45 6e 64  oken + iTokenEnd
59b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
59c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
59d0: 20 20 20 20 20 6e 45 72 72 6f 72 53 74 61 72 74       nErrorStart
59e0: 20 3d 20 73 65 6c 66 2e 6e 4f 66 66 73 65 74 57   = self.nOffsetW
59f0: 69 74 68 69 6e 50 61 72 61 67 72 61 70 68 20 2b  ithinParagraph +
5a00: 20 28 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54   (self.lToken[nT
5a10: 6f 6b 65 6e 45 72 72 6f 72 53 74 61 72 74 5d 5b  okenErrorStart][
5a20: 22 6e 53 74 61 72 74 22 5d 20 69 66 20 63 53 74  "nStart"] if cSt
5a30: 61 72 74 4c 69 6d 69 74 20 3d 3d 20 22 3c 22 20  artLimit == "<" 
5a40: 20 65 6c 73 65 20 73 65 6c 66 2e 6c 54 6f 6b 65   else self.lToke
5a50: 6e 5b 6e 54 6f 6b 65 6e 45 72 72 6f 72 53 74 61  n[nTokenErrorSta
5a60: 72 74 5d 5b 22 6e 45 6e 64 22 5d 29 0a 20 20 20  rt]["nEnd"]).   
5a70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5a80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5a90: 20 6e 45 72 72 6f 72 45 6e 64 20 3d 20 73 65 6c   nErrorEnd = sel
5aa0: 66 2e 6e 4f 66 66 73 65 74 57 69 74 68 69 6e 50  f.nOffsetWithinP
5ab0: 61 72 61 67 72 61 70 68 20 2b 20 28 73 65 6c 66  aragraph + (self
5ac0: 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 45 72  .lToken[nTokenEr
5ad0: 72 6f 72 45 6e 64 5d 5b 22 6e 45 6e 64 22 5d 20  rorEnd]["nEnd"] 
5ae0: 69 66 20 63 45 6e 64 4c 69 6d 69 74 20 3d 3d 20  if cEndLimit == 
5af0: 22 3e 22 20 20 65 6c 73 65 20 73 65 6c 66 2e 6c  ">"  else self.l
5b00: 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 45 72 72 6f  Token[nTokenErro
5b10: 72 45 6e 64 5d 5b 22 6e 53 74 61 72 74 22 5d 29  rEnd]["nStart"])
5b20: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5b30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5b40: 20 20 20 20 20 69 66 20 6e 45 72 72 6f 72 53 74       if nErrorSt
5b50: 61 72 74 20 6e 6f 74 20 69 6e 20 73 65 6c 66 2e  art not in self.
5b60: 64 45 72 72 6f 72 20 6f 72 20 6e 50 72 69 6f 72  dError or nPrior
5b70: 69 74 79 20 3e 20 73 65 6c 66 2e 64 45 72 72 6f  ity > self.dErro
5b80: 72 50 72 69 6f 72 69 74 79 2e 67 65 74 28 6e 45  rPriority.get(nE
5b90: 72 72 6f 72 53 74 61 72 74 2c 20 2d 31 29 3a 0a  rrorStart, -1):.
5ba0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5bc0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64 45 72          self.dEr
5bd0: 72 6f 72 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d  ror[nErrorStart]
5be0: 20 3d 20 73 65 6c 66 2e 5f 63 72 65 61 74 65 45   = self._createE
5bf0: 72 72 6f 72 46 72 6f 6d 54 6f 6b 65 6e 73 28 73  rrorFromTokens(s
5c00: 57 68 61 74 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73  What, nTokenOffs
5c10: 65 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 2c 20  et, nLastToken, 
5c20: 6e 54 6f 6b 65 6e 45 72 72 6f 72 53 74 61 72 74  nTokenErrorStart
5c30: 2c 20 6e 45 72 72 6f 72 53 74 61 72 74 2c 20 6e  , nErrorStart, n
5c40: 45 72 72 6f 72 45 6e 64 2c 20 73 4c 69 6e 65 49  ErrorEnd, sLineI
5c50: 64 2c 20 73 52 75 6c 65 49 64 2c 20 62 43 61 73  d, sRuleId, bCas
5c60: 65 53 76 74 79 2c 20 73 4d 65 73 73 61 67 65 2c  eSvty, sMessage,
5c70: 20 73 55 52 4c 2c 20 62 53 68 6f 77 52 75 6c 65   sURL, bShowRule
5c80: 49 64 2c 20 73 4f 70 74 69 6f 6e 2c 20 62 43 6f  Id, sOption, bCo
5c90: 6e 74 65 78 74 29 0a 20 20 20 20 20 20 20 20 20  ntext).         
5ca0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
5cc0: 65 6c 66 2e 64 45 72 72 6f 72 50 72 69 6f 72 69  elf.dErrorPriori
5cd0: 74 79 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d 20  ty[nErrorStart] 
5ce0: 3d 20 6e 50 72 69 6f 72 69 74 79 0a 20 20 20 20  = nPriority.    
5cf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5d00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5d10: 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20      if bDebug:. 
5d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5d30: 20 20 20 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 65 63 68 6f 28             echo(
5d50: 22 20 20 20 20 4e 45 57 5f 45 52 52 4f 52 3a 20  "    NEW_ERROR: 
5d60: 7b 7d 22 2e 66 6f 72 6d 61 74 28 73 65 6c 66 2e  {}".format(self.
5d70: 64 45 72 72 6f 72 5b 6e 45 72 72 6f 72 53 74 61  dError[nErrorSta
5d80: 72 74 5d 29 29 0a 20 20 20 20 20 20 20 20 20 20  rt])).          
5d90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5da0: 20 20 65 6c 69 66 20 63 41 63 74 69 6f 6e 54 79    elif cActionTy
5db0: 70 65 20 3d 3d 20 22 7e 22 3a 0a 20 20 20 20 20  pe == "~":.     
5dc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5dd0: 20 20 20 20 20 20 20 20 20 20 20 23 20 74 65 78             # tex
5de0: 74 20 70 72 6f 63 65 73 73 6f 72 0a 20 20 20 20  t processor.    
5df0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e00: 20 20 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b              nTok
5e10: 65 6e 53 74 61 72 74 20 3d 20 6e 54 6f 6b 65 6e  enStart = nToken
5e20: 4f 66 66 73 65 74 20 2b 20 65 41 63 74 5b 30 5d  Offset + eAct[0]
5e30: 20 20 69 66 20 65 41 63 74 5b 30 5d 20 3e 20 30    if eAct[0] > 0
5e40: 20 20 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65    else nLastToke
5e50: 6e 20 2b 20 65 41 63 74 5b 30 5d 0a 20 20 20 20  n + eAct[0].    
5e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e70: 20 20 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b              nTok
5e80: 65 6e 45 6e 64 20 3d 20 6e 54 6f 6b 65 6e 4f 66  enEnd = nTokenOf
5e90: 66 73 65 74 20 2b 20 65 41 63 74 5b 31 5d 20 20  fset + eAct[1]  
5ea0: 69 66 20 65 41 63 74 5b 31 5d 20 3e 20 30 20 20  if eAct[1] > 0  
5eb0: 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20  else nLastToken 
5ec0: 2b 20 65 41 63 74 5b 31 5d 0a 20 20 20 20 20 20  + eAct[1].      
5ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ee0: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 5f            self._
5ef0: 74 61 67 41 6e 64 50 72 65 70 61 72 65 54 6f 6b  tagAndPrepareTok
5f00: 65 6e 46 6f 72 52 65 77 72 69 74 69 6e 67 28 73  enForRewriting(s
5f10: 57 68 61 74 2c 20 6e 54 6f 6b 65 6e 53 74 61 72  What, nTokenStar
5f20: 74 2c 20 6e 54 6f 6b 65 6e 45 6e 64 2c 20 6e 54  t, nTokenEnd, nT
5f30: 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 6e 4c 61 73  okenOffset, nLas
5f40: 74 54 6f 6b 65 6e 2c 20 65 41 63 74 5b 32 5d 2c  tToken, eAct[2],
5f50: 20 62 44 65 62 75 67 29 0a 20 20 20 20 20 20 20   bDebug).       
5f60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5f70: 20 20 20 20 20 20 20 20 20 62 43 68 61 6e 67 65           bChange
5f80: 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20 20   = True.        
5f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5fa0: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
5fb0: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  g:.             
5fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5fd0: 20 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 20         echo("   
5fe0: 20 54 45 58 54 5f 50 52 4f 43 45 53 53 4f 52 3a   TEXT_PROCESSOR:
5ff0: 20 5b 7b 7d 3a 7b 7d 5d 20 20 3e 20 7b 7d 22 2e   [{}:{}]  > {}".
6000: 66 6f 72 6d 61 74 28 73 65 6c 66 2e 6c 54 6f 6b  format(self.lTok
6010: 65 6e 5b 6e 54 6f 6b 65 6e 53 74 61 72 74 5d 5b  en[nTokenStart][
6020: 22 73 56 61 6c 75 65 22 5d 2c 20 73 65 6c 66 2e  "sValue"], self.
6030: 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 45 6e 64  lToken[nTokenEnd
6040: 5d 5b 22 73 56 61 6c 75 65 22 5d 2c 20 73 57 68  ]["sValue"], sWh
6050: 61 74 29 29 0a 20 20 20 20 20 20 20 20 20 20 20  at)).           
6060: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6070: 20 65 6c 69 66 20 63 41 63 74 69 6f 6e 54 79 70   elif cActionTyp
6080: 65 20 3d 3d 20 22 3d 22 3a 0a 20 20 20 20 20 20  e == "=":.      
6090: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
60a0: 20 20 20 20 20 20 20 20 20 20 23 20 64 69 73 61            # disa
60b0: 6d 62 69 67 75 61 74 69 6f 6e 0a 20 20 20 20 20  mbiguation.     
60c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
60d0: 20 20 20 20 20 20 20 20 20 20 20 67 6c 6f 62 61             globa
60e0: 6c 73 28 29 5b 73 57 68 61 74 5d 28 73 65 6c 66  ls()[sWhat](self
60f0: 2e 6c 54 6f 6b 65 6e 2c 20 6e 54 6f 6b 65 6e 4f  .lToken, nTokenO
6100: 66 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b 65  ffset, nLastToke
6110: 6e 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  n).             
6120: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6130: 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20     if bDebug:.  
6140: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6160: 20 20 65 63 68 6f 28 22 20 20 20 20 44 49 53 41    echo("    DISA
6170: 4d 42 49 47 55 41 54 4f 52 3a 20 28 7b 7d 29 20  MBIGUATOR: ({}) 
6180: 20 5b 7b 7d 3a 7b 7d 5d 22 2e 66 6f 72 6d 61 74   [{}:{}]".format
6190: 28 73 57 68 61 74 2c 20 73 65 6c 66 2e 6c 54 6f  (sWhat, self.lTo
61a0: 6b 65 6e 5b 6e 54 6f 6b 65 6e 4f 66 66 73 65 74  ken[nTokenOffset
61b0: 2b 31 5d 5b 22 73 56 61 6c 75 65 22 5d 2c 20 73  +1]["sValue"], s
61c0: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 4c 61 73 74  elf.lToken[nLast
61d0: 54 6f 6b 65 6e 5d 5b 22 73 56 61 6c 75 65 22 5d  Token]["sValue"]
61e0: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  )).             
61f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
6200: 6c 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20  lif cActionType 
6210: 3d 3d 20 22 3e 22 3a 0a 20 20 20 20 20 20 20 20  == ">":.        
6220: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6230: 20 20 20 20 20 20 20 20 23 20 77 65 20 64 6f 20          # we do 
6240: 6e 6f 74 68 69 6e 67 2c 20 74 68 69 73 20 74 65  nothing, this te
6250: 73 74 20 69 73 20 6a 75 73 74 20 61 20 63 6f 6e  st is just a con
6260: 64 69 74 69 6f 6e 20 74 6f 20 61 70 70 6c 79 20  dition to apply 
6270: 61 6c 6c 20 66 6f 6c 6c 6f 77 69 6e 67 20 61 63  all following ac
6280: 74 69 6f 6e 73 0a 20 20 20 20 20 20 20 20 20 20  tions.          
6290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
62a0: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
62b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
62c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
62d0: 20 20 20 20 20 65 63 68 6f 28 22 20 20 20 20 43       echo("    C
62e0: 4f 4e 44 5f 4f 4b 22 29 0a 20 20 20 20 20 20 20  OND_OK").       
62f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6300: 20 20 20 20 20 20 20 20 20 70 61 73 73 0a 20 20           pass.  
6310: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6320: 20 20 20 20 20 20 20 20 20 20 65 6c 69 66 20 63            elif c
6330: 41 63 74 69 6f 6e 54 79 70 65 20 3d 3d 20 22 2f  ActionType == "/
6340: 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ":.             
6350: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6360: 20 20 20 23 20 54 61 67 0a 20 20 20 20 20 20 20     # Tag.       
6370: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6380: 20 20 20 20 20 20 20 20 20 6e 54 6f 6b 65 6e 53           nTokenS
6390: 74 61 72 74 20 3d 20 6e 54 6f 6b 65 6e 4f 66 66  tart = nTokenOff
63a0: 73 65 74 20 2b 20 65 41 63 74 5b 30 5d 20 20 69  set + eAct[0]  i
63b0: 66 20 65 41 63 74 5b 30 5d 20 3e 20 30 20 20 65  f eAct[0] > 0  e
63c0: 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20 2b  lse nLastToken +
63d0: 20 65 41 63 74 5b 30 5d 0a 20 20 20 20 20 20 20   eAct[0].       
63e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
63f0: 20 20 20 20 20 20 20 20 20 6e 54 6f 6b 65 6e 45           nTokenE
6400: 6e 64 20 3d 20 6e 54 6f 6b 65 6e 4f 66 66 73 65  nd = nTokenOffse
6410: 74 20 2b 20 65 41 63 74 5b 31 5d 20 20 69 66 20  t + eAct[1]  if 
6420: 65 41 63 74 5b 31 5d 20 3e 20 30 20 20 65 6c 73  eAct[1] > 0  els
6430: 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20 2b 20 65  e nLastToken + e
6440: 41 63 74 5b 31 5d 0a 20 20 20 20 20 20 20 20 20  Act[1].         
6450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6460: 20 20 20 20 20 20 20 66 6f 72 20 69 20 69 6e 20         for i in 
6470: 72 61 6e 67 65 28 6e 54 6f 6b 65 6e 53 74 61 72  range(nTokenStar
6480: 74 2c 20 6e 54 6f 6b 65 6e 45 6e 64 2b 31 29 3a  t, nTokenEnd+1):
6490: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
64a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
64b0: 20 20 20 20 20 69 66 20 22 61 54 61 67 73 22 20       if "aTags" 
64c0: 69 6e 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69  in self.lToken[i
64d0: 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]:.             
64e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
64f0: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
6500: 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 61 54 61 67 73  lToken[i]["aTags
6510: 22 5d 2e 75 70 64 61 74 65 28 73 57 68 61 74 2e  "].update(sWhat.
6520: 73 70 6c 69 74 28 22 7c 22 29 29 0a 20 20 20 20  split("|")).    
6530: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6550: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
6560: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6570: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
6580: 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 61 54  lf.lToken[i]["aT
6590: 61 67 73 22 5d 20 3d 20 73 65 74 28 73 57 68 61  ags"] = set(sWha
65a0: 74 2e 73 70 6c 69 74 28 22 7c 22 29 29 0a 20 20  t.split("|")).  
65b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
65c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
65d0: 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20   bDebug:.       
65e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
65f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 63 68               ech
6600: 6f 28 22 20 20 20 20 54 41 47 3a 20 7b 7d 20 3e  o("    TAG: {} >
6610: 20 20 5b 7b 7d 3a 7b 7d 5d 22 2e 66 6f 72 6d 61    [{}:{}]".forma
6620: 74 28 73 57 68 61 74 2c 20 73 65 6c 66 2e 6c 54  t(sWhat, self.lT
6630: 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 53 74 61 72 74  oken[nTokenStart
6640: 5d 5b 22 73 56 61 6c 75 65 22 5d 2c 20 73 65 6c  ]["sValue"], sel
6650: 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 45  f.lToken[nTokenE
6660: 6e 64 5d 5b 22 73 56 61 6c 75 65 22 5d 29 29 0a  nd]["sValue"])).
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 20 20 20 20 20 20 20 20 20                  
6690: 69 66 20 73 57 68 61 74 20 6e 6f 74 20 69 6e 20  if sWhat not in 
66a0: 73 65 6c 66 2e 64 54 61 67 73 3a 0a 20 20 20 20  self.dTags:.    
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 20 20 20 20                  
66d0: 73 65 6c 66 2e 64 54 61 67 73 5b 73 57 68 61 74  self.dTags[sWhat
66e0: 5d 20 3d 20 5b 6e 54 6f 6b 65 6e 53 74 61 72 74  ] = [nTokenStart
66f0: 2c 20 6e 54 6f 6b 65 6e 53 74 61 72 74 5d 0a 20  , nTokenStart]. 
6700: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6710: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
6720: 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  lse:.           
6730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6740: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64 54           self.dT
6750: 61 67 73 5b 73 57 68 61 74 5d 5b 30 5d 20 3d 20  ags[sWhat][0] = 
6760: 6d 69 6e 28 6e 54 6f 6b 65 6e 53 74 61 72 74 2c  min(nTokenStart,
6770: 20 73 65 6c 66 2e 64 54 61 67 73 5b 73 57 68 61   self.dTags[sWha
6780: 74 5d 5b 30 5d 29 0a 20 20 20 20 20 20 20 20 20  t][0]).         
6790: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
67a0: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
67b0: 64 54 61 67 73 5b 73 57 68 61 74 5d 5b 31 5d 20  dTags[sWhat][1] 
67c0: 3d 20 6d 61 78 28 6e 54 6f 6b 65 6e 45 6e 64 2c  = max(nTokenEnd,
67d0: 20 73 65 6c 66 2e 64 54 61 67 73 5b 73 57 68 61   self.dTags[sWha
67e0: 74 5d 5b 31 5d 29 0a 20 20 20 20 20 20 20 20 20  t][1]).         
67f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6800: 20 20 20 65 6c 69 66 20 63 41 63 74 69 6f 6e 54     elif cActionT
6810: 79 70 65 20 3d 3d 20 22 25 22 3a 0a 20 20 20 20  ype == "%":.    
6820: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6830: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 69 6d              # im
6840: 6d 75 6e 69 74 79 0a 20 20 20 20 20 20 20 20 20  munity.         
6850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6860: 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67         if bDebug
6870: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
6880: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6890: 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 20 20        echo("    
68a0: 49 4d 4d 55 4e 49 54 59 3a 20 22 20 2b 20 5f 72  IMMUNITY: " + _r
68b0: 75 6c 65 73 5f 67 72 61 70 68 2e 64 52 75 6c 65  ules_graph.dRule
68c0: 5b 73 52 75 6c 65 49 64 5d 29 0a 20 20 20 20 20  [sRuleId]).     
68d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
68e0: 20 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b 65             nToke
68f0: 6e 53 74 61 72 74 20 3d 20 6e 54 6f 6b 65 6e 4f  nStart = nTokenO
6900: 66 66 73 65 74 20 2b 20 65 41 63 74 5b 30 5d 20  ffset + eAct[0] 
6910: 20 69 66 20 65 41 63 74 5b 30 5d 20 3e 20 30 20   if eAct[0] > 0 
6920: 20 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e   else nLastToken
6930: 20 2b 20 65 41 63 74 5b 30 5d 0a 20 20 20 20 20   + eAct[0].     
6940: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6950: 20 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b 65             nToke
6960: 6e 45 6e 64 20 3d 20 6e 54 6f 6b 65 6e 4f 66 66  nEnd = nTokenOff
6970: 73 65 74 20 2b 20 65 41 63 74 5b 31 5d 20 20 69  set + eAct[1]  i
6980: 66 20 65 41 63 74 5b 31 5d 20 3e 20 30 20 20 65  f eAct[1] > 0  e
6990: 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20 2b  lse nLastToken +
69a0: 20 65 41 63 74 5b 31 5d 0a 20 20 20 20 20 20 20   eAct[1].       
69b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
69c0: 20 20 20 20 20 20 20 20 20 69 66 20 6e 54 6f 6b           if nTok
69d0: 65 6e 45 6e 64 20 2d 20 6e 54 6f 6b 65 6e 53 74  enEnd - nTokenSt
69e0: 61 72 74 20 3d 3d 20 30 3a 0a 20 20 20 20 20 20  art == 0:.      
69f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6a00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
6a10: 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e  lf.lToken[nToken
6a20: 53 74 61 72 74 5d 5b 22 62 49 6d 6d 75 6e 65 22  Start]["bImmune"
6a30: 5d 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20  ] = True.       
6a40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6a50: 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 45 72               nEr
6a60: 72 6f 72 53 74 61 72 74 20 3d 20 73 65 6c 66 2e  rorStart = self.
6a70: 6e 4f 66 66 73 65 74 57 69 74 68 69 6e 50 61 72  nOffsetWithinPar
6a80: 61 67 72 61 70 68 20 2b 20 73 65 6c 66 2e 6c 54  agraph + self.lT
6a90: 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 53 74 61 72 74  oken[nTokenStart
6aa0: 5d 5b 22 6e 53 74 61 72 74 22 5d 0a 20 20 20 20  ]["nStart"].    
6ab0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ac0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ad0: 69 66 20 6e 45 72 72 6f 72 53 74 61 72 74 20 69  if nErrorStart i
6ae0: 6e 20 73 65 6c 66 2e 64 45 72 72 6f 72 3a 0a 20  n self.dError:. 
6af0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6b00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6b10: 20 20 20 20 20 20 20 64 65 6c 20 73 65 6c 66 2e         del self.
6b20: 64 45 72 72 6f 72 5b 6e 45 72 72 6f 72 53 74 61  dError[nErrorSta
6b30: 72 74 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  rt].            
6b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6b50: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
6b60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f                fo
6b80: 72 20 69 20 69 6e 20 72 61 6e 67 65 28 6e 54 6f  r i in range(nTo
6b90: 6b 65 6e 53 74 61 72 74 2c 20 6e 54 6f 6b 65 6e  kenStart, nToken
6ba0: 45 6e 64 2b 31 29 3a 0a 20 20 20 20 20 20 20 20  End+1):.        
6bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6bd0: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b 22  self.lToken[i]["
6be0: 62 49 6d 6d 75 6e 65 22 5d 20 3d 20 54 72 75 65  bImmune"] = True
6bf0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6c00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c10: 20 20 20 20 20 20 20 20 20 6e 45 72 72 6f 72 53           nErrorS
6c20: 74 61 72 74 20 3d 20 73 65 6c 66 2e 6e 4f 66 66  tart = self.nOff
6c30: 73 65 74 57 69 74 68 69 6e 50 61 72 61 67 72 61  setWithinParagra
6c40: 70 68 20 2b 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e  ph + self.lToken
6c50: 5b 69 5d 5b 22 6e 53 74 61 72 74 22 5d 0a 20 20  [i]["nStart"].  
6c60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c80: 20 20 20 20 20 20 69 66 20 6e 45 72 72 6f 72 53        if nErrorS
6c90: 74 61 72 74 20 69 6e 20 73 65 6c 66 2e 64 45 72  tart in self.dEr
6ca0: 72 6f 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ror:.           
6cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6cc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6cd0: 20 64 65 6c 20 73 65 6c 66 2e 64 45 72 72 6f 72   del self.dError
6ce0: 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d 0a 20 20  [nErrorStart].  
6cf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6d00: 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a            else:.
6d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6d30: 65 63 68 6f 28 22 23 20 65 72 72 6f 72 3a 20 75  echo("# error: u
6d40: 6e 6b 6e 6f 77 6e 20 61 63 74 69 6f 6e 20 61 74  nknown action at
6d50: 20 22 20 2b 20 73 4c 69 6e 65 49 64 29 0a 20 20   " + sLineId).  
6d60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6d70: 20 20 20 20 20 20 65 6c 69 66 20 63 41 63 74 69        elif cActi
6d80: 6f 6e 54 79 70 65 20 3d 3d 20 22 3e 22 3a 0a 20  onType == ">":. 
6d90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6da0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44             if bD
6db0: 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20  ebug:.          
6dc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6dd0: 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 20 20        echo("    
6de0: 43 4f 4e 44 5f 42 52 45 41 4b 22 29 0a 20 20 20  COND_BREAK").   
6df0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6e00: 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 0a 20           break. 
6e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
6e20: 78 63 65 70 74 20 45 78 63 65 70 74 69 6f 6e 20  xcept Exception 
6e30: 61 73 20 65 3a 0a 20 20 20 20 20 20 20 20 20 20  as e:.          
6e40: 20 20 20 20 20 20 20 20 20 20 72 61 69 73 65 20            raise 
6e50: 45 78 63 65 70 74 69 6f 6e 28 73 74 72 28 65 29  Exception(str(e)
6e60: 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65  , sLineId, sRule
6e70: 49 64 2c 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e  Id, self.sSenten
6e80: 63 65 29 0a 20 20 20 20 20 20 20 20 72 65 74 75  ce).        retu
6e90: 72 6e 20 62 43 68 61 6e 67 65 0a 0a 20 20 20 20  rn bChange..    
6ea0: 64 65 66 20 5f 63 72 65 61 74 65 45 72 72 6f 72  def _createError
6eb0: 46 72 6f 6d 52 65 67 65 78 20 28 73 65 6c 66 2c  FromRegex (self,
6ec0: 20 73 54 65 78 74 2c 20 73 54 65 78 74 30 2c 20   sText, sText0, 
6ed0: 73 52 65 70 6c 2c 20 6e 4f 66 66 73 65 74 2c 20  sRepl, nOffset, 
6ee0: 6d 2c 20 69 47 72 6f 75 70 2c 20 73 4c 69 6e 65  m, iGroup, sLine
6ef0: 49 64 2c 20 73 52 75 6c 65 49 64 2c 20 62 55 70  Id, sRuleId, bUp
6f00: 70 65 72 63 61 73 65 2c 20 73 4d 73 67 2c 20 73  percase, sMsg, s
6f10: 55 52 4c 2c 20 62 53 68 6f 77 52 75 6c 65 49 64  URL, bShowRuleId
6f20: 2c 20 73 4f 70 74 69 6f 6e 2c 20 62 43 6f 6e 74  , sOption, bCont
6f30: 65 78 74 29 3a 0a 20 20 20 20 20 20 20 20 6e 53  ext):.        nS
6f40: 74 61 72 74 20 3d 20 6e 4f 66 66 73 65 74 20 2b  tart = nOffset +
6f50: 20 6d 2e 73 74 61 72 74 28 69 47 72 6f 75 70 29   m.start(iGroup)
6f60: 0a 20 20 20 20 20 20 20 20 6e 45 6e 64 20 3d 20  .        nEnd = 
6f70: 6e 4f 66 66 73 65 74 20 2b 20 6d 2e 65 6e 64 28  nOffset + m.end(
6f80: 69 47 72 6f 75 70 29 0a 20 20 20 20 20 20 20 20  iGroup).        
6f90: 23 20 73 75 67 67 65 73 74 69 6f 6e 73 0a 20 20  # suggestions.  
6fa0: 20 20 20 20 20 20 69 66 20 73 52 65 70 6c 5b 30        if sRepl[0
6fb0: 3a 31 5d 20 3d 3d 20 22 3d 22 3a 0a 20 20 20 20  :1] == "=":.    
6fc0: 20 20 20 20 20 20 20 20 73 53 75 67 67 20 3d 20          sSugg = 
6fd0: 67 6c 6f 62 61 6c 73 28 29 5b 73 52 65 70 6c 5b  globals()[sRepl[
6fe0: 31 3a 5d 5d 28 73 54 65 78 74 2c 20 6d 29 0a 20  1:]](sText, m). 
6ff0: 20 20 20 20 20 20 20 20 20 20 20 6c 53 75 67 67             lSugg
7000: 20 3d 20 73 53 75 67 67 2e 73 70 6c 69 74 28 22   = sSugg.split("
7010: 7c 22 29 20 20 69 66 20 73 53 75 67 67 20 20 65  |")  if sSugg  e
7020: 6c 73 65 20 5b 5d 0a 20 20 20 20 20 20 20 20 65  lse [].        e
7030: 6c 69 66 20 73 52 65 70 6c 20 3d 3d 20 22 5f 22  lif sRepl == "_"
7040: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6c 53  :.            lS
7050: 75 67 67 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20  ugg = [].       
7060: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
7070: 20 20 20 6c 53 75 67 67 20 3d 20 6d 2e 65 78 70     lSugg = m.exp
7080: 61 6e 64 28 73 52 65 70 6c 29 2e 73 70 6c 69 74  and(sRepl).split
7090: 28 22 7c 22 29 0a 20 20 20 20 20 20 20 20 69 66  ("|").        if
70a0: 20 62 55 70 70 65 72 63 61 73 65 20 61 6e 64 20   bUppercase and 
70b0: 6c 53 75 67 67 20 61 6e 64 20 6d 2e 67 72 6f 75  lSugg and m.grou
70c0: 70 28 69 47 72 6f 75 70 29 5b 30 3a 31 5d 2e 69  p(iGroup)[0:1].i
70d0: 73 75 70 70 65 72 28 29 3a 0a 20 20 20 20 20 20  supper():.      
70e0: 20 20 20 20 20 20 6c 53 75 67 67 20 3d 20 6c 69        lSugg = li
70f0: 73 74 28 6d 61 70 28 73 74 72 2e 63 61 70 69 74  st(map(str.capit
7100: 61 6c 69 7a 65 2c 20 6c 53 75 67 67 29 29 0a 20  alize, lSugg)). 
7110: 20 20 20 20 20 20 20 23 20 4d 65 73 73 61 67 65         # Message
7120: 0a 20 20 20 20 20 20 20 20 73 4d 65 73 73 61 67  .        sMessag
7130: 65 20 3d 20 67 6c 6f 62 61 6c 73 28 29 5b 73 4d  e = globals()[sM
7140: 73 67 5b 31 3a 5d 5d 28 73 54 65 78 74 2c 20 6d  sg[1:]](sText, m
7150: 29 20 20 69 66 20 73 4d 73 67 5b 30 3a 31 5d 20  )  if sMsg[0:1] 
7160: 3d 3d 20 22 3d 22 20 20 65 6c 73 65 20 20 6d 2e  == "="  else  m.
7170: 65 78 70 61 6e 64 28 73 4d 73 67 29 0a 20 20 20  expand(sMsg).   
7180: 20 20 20 20 20 69 66 20 62 53 68 6f 77 52 75 6c       if bShowRul
7190: 65 49 64 3a 0a 20 20 20 20 20 20 20 20 20 20 20  eId:.           
71a0: 20 73 4d 65 73 73 61 67 65 20 2b 3d 20 22 20 20   sMessage += "  
71b0: 23 20 22 20 2b 20 73 4c 69 6e 65 49 64 20 2b 20  # " + sLineId + 
71c0: 22 20 23 20 22 20 2b 20 73 52 75 6c 65 49 64 0a  " # " + sRuleId.
71d0: 20 20 20 20 20 20 20 20 23 0a 20 20 20 20 20 20          #.      
71e0: 20 20 69 66 20 5f 62 57 72 69 74 65 72 45 72 72    if _bWriterErr
71f0: 6f 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  or:.            
7200: 72 65 74 75 72 6e 20 73 65 6c 66 2e 5f 63 72 65  return self._cre
7210: 61 74 65 45 72 72 6f 72 46 6f 72 57 72 69 74 65  ateErrorForWrite
7220: 72 28 6e 53 74 61 72 74 2c 20 6e 45 6e 64 20 2d  r(nStart, nEnd -
7230: 20 6e 53 74 61 72 74 2c 20 73 52 75 6c 65 49 64   nStart, sRuleId
7240: 2c 20 73 4d 65 73 73 61 67 65 2c 20 6c 53 75 67  , sMessage, lSug
7250: 67 2c 20 73 55 52 4c 29 0a 20 20 20 20 20 20 20  g, sURL).       
7260: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
7270: 20 20 20 72 65 74 75 72 6e 20 73 65 6c 66 2e 5f     return self._
7280: 63 72 65 61 74 65 45 72 72 6f 72 41 73 44 69 63  createErrorAsDic
7290: 74 28 6e 53 74 61 72 74 2c 20 6e 45 6e 64 2c 20  t(nStart, nEnd, 
72a0: 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65 49 64  sLineId, sRuleId
72b0: 2c 20 73 4f 70 74 69 6f 6e 2c 20 73 4d 65 73 73  , sOption, sMess
72c0: 61 67 65 2c 20 6c 53 75 67 67 2c 20 73 55 52 4c  age, lSugg, sURL
72d0: 2c 20 62 43 6f 6e 74 65 78 74 29 0a 0a 20 20 20  , bContext)..   
72e0: 20 64 65 66 20 5f 63 72 65 61 74 65 45 72 72 6f   def _createErro
72f0: 72 46 72 6f 6d 54 6f 6b 65 6e 73 20 28 73 65 6c  rFromTokens (sel
7300: 66 2c 20 73 53 75 67 67 2c 20 6e 54 6f 6b 65 6e  f, sSugg, nToken
7310: 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b  Offset, nLastTok
7320: 65 6e 2c 20 69 46 69 72 73 74 54 6f 6b 65 6e 2c  en, iFirstToken,
7330: 20 6e 53 74 61 72 74 2c 20 6e 45 6e 64 2c 20 73   nStart, nEnd, s
7340: 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65 49 64 2c  LineId, sRuleId,
7350: 20 62 43 61 73 65 53 76 74 79 2c 20 73 4d 73 67   bCaseSvty, sMsg
7360: 2c 20 73 55 52 4c 2c 20 62 53 68 6f 77 52 75 6c  , sURL, bShowRul
7370: 65 49 64 2c 20 73 4f 70 74 69 6f 6e 2c 20 62 43  eId, sOption, bC
7380: 6f 6e 74 65 78 74 29 3a 0a 20 20 20 20 20 20 20  ontext):.       
7390: 20 23 20 73 75 67 67 65 73 74 69 6f 6e 73 0a 20   # suggestions. 
73a0: 20 20 20 20 20 20 20 69 66 20 73 53 75 67 67 5b         if sSugg[
73b0: 30 3a 31 5d 20 3d 3d 20 22 3d 22 3a 0a 20 20 20  0:1] == "=":.   
73c0: 20 20 20 20 20 20 20 20 20 73 53 75 67 67 20 3d           sSugg =
73d0: 20 67 6c 6f 62 61 6c 73 28 29 5b 73 53 75 67 67   globals()[sSugg
73e0: 5b 31 3a 5d 5d 28 73 65 6c 66 2e 6c 54 6f 6b 65  [1:]](self.lToke
73f0: 6e 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2c  n, nTokenOffset,
7400: 20 6e 4c 61 73 74 54 6f 6b 65 6e 29 0a 20 20 20   nLastToken).   
7410: 20 20 20 20 20 20 20 20 20 6c 53 75 67 67 20 3d           lSugg =
7420: 20 73 53 75 67 67 2e 73 70 6c 69 74 28 22 7c 22   sSugg.split("|"
7430: 29 20 20 69 66 20 73 53 75 67 67 20 20 65 6c 73  )  if sSugg  els
7440: 65 20 5b 5d 0a 20 20 20 20 20 20 20 20 65 6c 69  e [].        eli
7450: 66 20 73 53 75 67 67 20 3d 3d 20 22 5f 22 3a 0a  f sSugg == "_":.
7460: 20 20 20 20 20 20 20 20 20 20 20 20 6c 53 75 67              lSug
7470: 67 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 65  g = [].        e
7480: 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  lse:.           
7490: 20 6c 53 75 67 67 20 3d 20 73 65 6c 66 2e 5f 65   lSugg = self._e
74a0: 78 70 61 6e 64 28 73 53 75 67 67 2c 20 6e 54 6f  xpand(sSugg, nTo
74b0: 6b 65 6e 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74  kenOffset, nLast
74c0: 54 6f 6b 65 6e 29 2e 73 70 6c 69 74 28 22 7c 22  Token).split("|"
74d0: 29 0a 20 20 20 20 20 20 20 20 69 66 20 62 43 61  ).        if bCa
74e0: 73 65 53 76 74 79 20 61 6e 64 20 6c 53 75 67 67  seSvty and lSugg
74f0: 20 61 6e 64 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e   and self.lToken
7500: 5b 69 46 69 72 73 74 54 6f 6b 65 6e 5d 5b 22 73  [iFirstToken]["s
7510: 56 61 6c 75 65 22 5d 5b 30 3a 31 5d 2e 69 73 75  Value"][0:1].isu
7520: 70 70 65 72 28 29 3a 0a 20 20 20 20 20 20 20 20  pper():.        
7530: 20 20 20 20 6c 53 75 67 67 20 3d 20 6c 69 73 74      lSugg = list
7540: 28 6d 61 70 28 6c 61 6d 62 64 61 20 73 3a 20 73  (map(lambda s: s
7550: 5b 30 3a 31 5d 2e 75 70 70 65 72 28 29 2b 73 5b  [0:1].upper()+s[
7560: 31 3a 5d 2c 20 6c 53 75 67 67 29 29 0a 20 20 20  1:], lSugg)).   
7570: 20 20 20 20 20 23 20 4d 65 73 73 61 67 65 0a 20       # Message. 
7580: 20 20 20 20 20 20 20 73 4d 65 73 73 61 67 65 20         sMessage 
7590: 3d 20 67 6c 6f 62 61 6c 73 28 29 5b 73 4d 73 67  = globals()[sMsg
75a0: 5b 31 3a 5d 5d 28 73 65 6c 66 2e 6c 54 6f 6b 65  [1:]](self.lToke
75b0: 6e 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2c  n, nTokenOffset,
75c0: 20 6e 4c 61 73 74 54 6f 6b 65 6e 29 20 20 69 66   nLastToken)  if
75d0: 20 73 4d 73 67 5b 30 3a 31 5d 20 3d 3d 20 22 3d   sMsg[0:1] == "=
75e0: 22 20 20 65 6c 73 65 20 73 65 6c 66 2e 5f 65 78  "  else self._ex
75f0: 70 61 6e 64 28 73 4d 73 67 2c 20 6e 54 6f 6b 65  pand(sMsg, nToke
7600: 6e 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f  nOffset, nLastTo
7610: 6b 65 6e 29 0a 20 20 20 20 20 20 20 20 69 66 20  ken).        if 
7620: 62 53 68 6f 77 52 75 6c 65 49 64 3a 0a 20 20 20  bShowRuleId:.   
7630: 20 20 20 20 20 20 20 20 20 73 4d 65 73 73 61 67           sMessag
7640: 65 20 2b 3d 20 22 20 20 22 20 2b 20 73 4c 69 6e  e += "  " + sLin
7650: 65 49 64 20 2b 20 22 20 23 20 22 20 2b 20 73 52  eId + " # " + sR
7660: 75 6c 65 49 64 0a 20 20 20 20 20 20 20 20 23 0a  uleId.        #.
7670: 20 20 20 20 20 20 20 20 69 66 20 5f 62 57 72 69          if _bWri
7680: 74 65 72 45 72 72 6f 72 3a 0a 20 20 20 20 20 20  terError:.      
7690: 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65 6c        return sel
76a0: 66 2e 5f 63 72 65 61 74 65 45 72 72 6f 72 46 6f  f._createErrorFo
76b0: 72 57 72 69 74 65 72 28 6e 53 74 61 72 74 2c 20  rWriter(nStart, 
76c0: 6e 45 6e 64 20 2d 20 6e 53 74 61 72 74 2c 20 73  nEnd - nStart, s
76d0: 52 75 6c 65 49 64 2c 20 73 4d 65 73 73 61 67 65  RuleId, sMessage
76e0: 2c 20 6c 53 75 67 67 2c 20 73 55 52 4c 29 0a 20  , lSugg, sURL). 
76f0: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
7700: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
7710: 73 65 6c 66 2e 5f 63 72 65 61 74 65 45 72 72 6f  self._createErro
7720: 72 41 73 44 69 63 74 28 6e 53 74 61 72 74 2c 20  rAsDict(nStart, 
7730: 6e 45 6e 64 2c 20 73 4c 69 6e 65 49 64 2c 20 73  nEnd, sLineId, s
7740: 52 75 6c 65 49 64 2c 20 73 4f 70 74 69 6f 6e 2c  RuleId, sOption,
7750: 20 73 4d 65 73 73 61 67 65 2c 20 6c 53 75 67 67   sMessage, lSugg
7760: 2c 20 73 55 52 4c 2c 20 62 43 6f 6e 74 65 78 74  , sURL, bContext
7770: 29 0a 0a 20 20 20 20 64 65 66 20 5f 63 72 65 61  )..    def _crea
7780: 74 65 45 72 72 6f 72 46 6f 72 57 72 69 74 65 72  teErrorForWriter
7790: 20 28 73 65 6c 66 2c 20 6e 53 74 61 72 74 2c 20   (self, nStart, 
77a0: 6e 4c 65 6e 2c 20 73 52 75 6c 65 49 64 2c 20 73  nLen, sRuleId, s
77b0: 4d 65 73 73 61 67 65 2c 20 6c 53 75 67 67 2c 20  Message, lSugg, 
77c0: 73 55 52 4c 29 3a 0a 20 20 20 20 20 20 20 20 78  sURL):.        x
77d0: 45 72 72 20 3d 20 53 69 6e 67 6c 65 50 72 6f 6f  Err = SingleProo
77e0: 66 72 65 61 64 69 6e 67 45 72 72 6f 72 28 29 20  freadingError() 
77f0: 20 20 20 23 20 75 6e 6f 2e 63 72 65 61 74 65 55     # uno.createU
7800: 6e 6f 53 74 72 75 63 74 28 20 22 63 6f 6d 2e 73  noStruct( "com.s
7810: 75 6e 2e 73 74 61 72 2e 6c 69 6e 67 75 69 73 74  un.star.linguist
7820: 69 63 32 2e 53 69 6e 67 6c 65 50 72 6f 6f 66 72  ic2.SingleProofr
7830: 65 61 64 69 6e 67 45 72 72 6f 72 22 20 29 0a 20  eadingError" ). 
7840: 20 20 20 20 20 20 20 78 45 72 72 2e 6e 45 72 72         xErr.nErr
7850: 6f 72 53 74 61 72 74 20 3d 20 6e 53 74 61 72 74  orStart = nStart
7860: 0a 20 20 20 20 20 20 20 20 78 45 72 72 2e 6e 45  .        xErr.nE
7870: 72 72 6f 72 4c 65 6e 67 74 68 20 3d 20 6e 4c 65  rrorLength = nLe
7880: 6e 0a 20 20 20 20 20 20 20 20 78 45 72 72 2e 6e  n.        xErr.n
7890: 45 72 72 6f 72 54 79 70 65 20 3d 20 50 52 4f 4f  ErrorType = PROO
78a0: 46 52 45 41 44 49 4e 47 0a 20 20 20 20 20 20 20  FREADING.       
78b0: 20 78 45 72 72 2e 61 52 75 6c 65 49 64 65 6e 74   xErr.aRuleIdent
78c0: 69 66 69 65 72 20 3d 20 73 52 75 6c 65 49 64 0a  ifier = sRuleId.
78d0: 20 20 20 20 20 20 20 20 78 45 72 72 2e 61 53 68          xErr.aSh
78e0: 6f 72 74 43 6f 6d 6d 65 6e 74 20 3d 20 73 4d 65  ortComment = sMe
78f0: 73 73 61 67 65 20 20 20 23 20 73 4d 65 73 73 61  ssage   # sMessa
7900: 67 65 2e 73 70 6c 69 74 28 22 7c 22 29 5b 30 5d  ge.split("|")[0]
7910: 20 20 20 20 20 23 20 69 6e 20 63 6f 6e 74 65 78       # in contex
7920: 74 20 6d 65 6e 75 0a 20 20 20 20 20 20 20 20 78  t menu.        x
7930: 45 72 72 2e 61 46 75 6c 6c 43 6f 6d 6d 65 6e 74  Err.aFullComment
7940: 20 3d 20 73 4d 65 73 73 61 67 65 20 20 20 20 23   = sMessage    #
7950: 20 73 4d 65 73 73 61 67 65 2e 73 70 6c 69 74 28   sMessage.split(
7960: 22 7c 22 29 5b 2d 31 5d 20 20 20 20 23 20 69 6e  "|")[-1]    # in
7970: 20 64 69 61 6c 6f 67 0a 20 20 20 20 20 20 20 20   dialog.        
7980: 78 45 72 72 2e 61 53 75 67 67 65 73 74 69 6f 6e  xErr.aSuggestion
7990: 73 20 3d 20 74 75 70 6c 65 28 6c 53 75 67 67 29  s = tuple(lSugg)
79a0: 0a 20 20 20 20 20 20 20 20 23 78 50 72 6f 70 65  .        #xPrope
79b0: 72 74 79 4c 69 6e 65 54 79 70 65 20 3d 20 50 72  rtyLineType = Pr
79c0: 6f 70 65 72 74 79 56 61 6c 75 65 28 4e 61 6d 65  opertyValue(Name
79d0: 3d 22 4c 69 6e 65 54 79 70 65 22 2c 20 56 61 6c  ="LineType", Val
79e0: 75 65 3d 35 29 20 23 20 44 41 53 48 20 6f 72 20  ue=5) # DASH or 
79f0: 57 41 56 45 0a 20 20 20 20 20 20 20 20 23 78 50  WAVE.        #xP
7a00: 72 6f 70 65 72 74 79 4c 69 6e 65 43 6f 6c 6f 72  ropertyLineColor
7a10: 20 3d 20 50 72 6f 70 65 72 74 79 56 61 6c 75 65   = PropertyValue
7a20: 28 4e 61 6d 65 3d 22 4c 69 6e 65 43 6f 6c 6f 72  (Name="LineColor
7a30: 22 2c 20 56 61 6c 75 65 3d 67 65 74 52 47 42 28  ", Value=getRGB(
7a40: 22 46 46 41 41 30 30 22 29 29 0a 20 20 20 20 20  "FFAA00")).     
7a50: 20 20 20 69 66 20 73 55 52 4c 3a 0a 20 20 20 20     if sURL:.    
7a60: 20 20 20 20 20 20 20 20 78 50 72 6f 70 65 72 74          xPropert
7a70: 79 55 52 4c 20 3d 20 50 72 6f 70 65 72 74 79 56  yURL = PropertyV
7a80: 61 6c 75 65 28 4e 61 6d 65 3d 22 46 75 6c 6c 43  alue(Name="FullC
7a90: 6f 6d 6d 65 6e 74 55 52 4c 22 2c 20 56 61 6c 75  ommentURL", Valu
7aa0: 65 3d 73 55 52 4c 29 0a 20 20 20 20 20 20 20 20  e=sURL).        
7ab0: 20 20 20 20 78 45 72 72 2e 61 50 72 6f 70 65 72      xErr.aProper
7ac0: 74 69 65 73 20 3d 20 28 78 50 72 6f 70 65 72 74  ties = (xPropert
7ad0: 79 55 52 4c 2c 29 0a 20 20 20 20 20 20 20 20 65  yURL,).        e
7ae0: 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  lse:.           
7af0: 20 78 45 72 72 2e 61 50 72 6f 70 65 72 74 69 65   xErr.aPropertie
7b00: 73 20 3d 20 28 29 0a 20 20 20 20 20 20 20 20 72  s = ().        r
7b10: 65 74 75 72 6e 20 78 45 72 72 0a 0a 20 20 20 20  eturn xErr..    
7b20: 64 65 66 20 5f 63 72 65 61 74 65 45 72 72 6f 72  def _createError
7b30: 41 73 44 69 63 74 20 28 73 65 6c 66 2c 20 6e 53  AsDict (self, nS
7b40: 74 61 72 74 2c 20 6e 45 6e 64 2c 20 73 4c 69 6e  tart, nEnd, sLin
7b50: 65 49 64 2c 20 73 52 75 6c 65 49 64 2c 20 73 4f  eId, sRuleId, sO
7b60: 70 74 69 6f 6e 2c 20 73 4d 65 73 73 61 67 65 2c  ption, sMessage,
7b70: 20 6c 53 75 67 67 2c 20 73 55 52 4c 2c 20 62 43   lSugg, sURL, bC
7b80: 6f 6e 74 65 78 74 29 3a 0a 20 20 20 20 20 20 20  ontext):.       
7b90: 20 64 45 72 72 20 3d 20 7b 0a 20 20 20 20 20 20   dErr = {.      
7ba0: 20 20 20 20 20 20 22 6e 53 74 61 72 74 22 3a 20        "nStart": 
7bb0: 6e 53 74 61 72 74 2c 0a 20 20 20 20 20 20 20 20  nStart,.        
7bc0: 20 20 20 20 22 6e 45 6e 64 22 3a 20 6e 45 6e 64      "nEnd": nEnd
7bd0: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 22 73  ,.            "s
7be0: 4c 69 6e 65 49 64 22 3a 20 73 4c 69 6e 65 49 64  LineId": sLineId
7bf0: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 22 73  ,.            "s
7c00: 52 75 6c 65 49 64 22 3a 20 73 52 75 6c 65 49 64  RuleId": sRuleId
7c10: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 22 73  ,.            "s
7c20: 54 79 70 65 22 3a 20 73 4f 70 74 69 6f 6e 20 20  Type": sOption  
7c30: 69 66 20 73 4f 70 74 69 6f 6e 20 20 65 6c 73 65  if sOption  else
7c40: 20 22 6e 6f 74 79 70 65 22 2c 0a 20 20 20 20 20   "notype",.     
7c50: 20 20 20 20 20 20 20 22 73 4d 65 73 73 61 67 65         "sMessage
7c60: 22 3a 20 73 4d 65 73 73 61 67 65 2c 0a 20 20 20  ": sMessage,.   
7c70: 20 20 20 20 20 20 20 20 20 22 61 53 75 67 67 65           "aSugge
7c80: 73 74 69 6f 6e 73 22 3a 20 6c 53 75 67 67 2c 0a  stions": lSugg,.
7c90: 20 20 20 20 20 20 20 20 20 20 20 20 22 55 52 4c              "URL
7ca0: 22 3a 20 73 55 52 4c 0a 20 20 20 20 20 20 20 20  ": sURL.        
7cb0: 7d 0a 20 20 20 20 20 20 20 20 69 66 20 62 43 6f  }.        if bCo
7cc0: 6e 74 65 78 74 3a 0a 20 20 20 20 20 20 20 20 20  ntext:.         
7cd0: 20 20 20 64 45 72 72 5b 27 73 55 6e 64 65 72 6c     dErr['sUnderl
7ce0: 69 6e 65 64 27 5d 20 3d 20 73 65 6c 66 2e 73 54  ined'] = self.sT
7cf0: 65 78 74 30 5b 6e 53 74 61 72 74 3a 6e 45 6e 64  ext0[nStart:nEnd
7d00: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 45  ].            dE
7d10: 72 72 5b 27 73 42 65 66 6f 72 65 27 5d 20 3d 20  rr['sBefore'] = 
7d20: 73 65 6c 66 2e 73 54 65 78 74 30 5b 6d 61 78 28  self.sText0[max(
7d30: 30 2c 6e 53 74 61 72 74 2d 38 30 29 3a 6e 53 74  0,nStart-80):nSt
7d40: 61 72 74 5d 0a 20 20 20 20 20 20 20 20 20 20 20  art].           
7d50: 20 64 45 72 72 5b 27 73 41 66 74 65 72 27 5d 20   dErr['sAfter'] 
7d60: 3d 20 73 65 6c 66 2e 73 54 65 78 74 30 5b 6e 45  = self.sText0[nE
7d70: 6e 64 3a 6e 45 6e 64 2b 38 30 5d 0a 20 20 20 20  nd:nEnd+80].    
7d80: 20 20 20 20 72 65 74 75 72 6e 20 64 45 72 72 0a      return dErr.
7d90: 0a 20 20 20 20 64 65 66 20 5f 65 78 70 61 6e 64  .    def _expand
7da0: 20 28 73 65 6c 66 2c 20 73 54 65 78 74 2c 20 6e   (self, sText, n
7db0: 54 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 6e 4c 61  TokenOffset, nLa
7dc0: 73 74 54 6f 6b 65 6e 29 3a 0a 20 20 20 20 20 20  stToken):.      
7dd0: 20 20 66 6f 72 20 6d 20 69 6e 20 72 65 2e 66 69    for m in re.fi
7de0: 6e 64 69 74 65 72 28 72 22 5c 5c 28 2d 3f 5b 30  nditer(r"\\(-?[0
7df0: 2d 39 5d 2b 29 22 2c 20 73 54 65 78 74 29 3a 0a  -9]+)", sText):.
7e00: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6d              if m
7e10: 2e 67 72 6f 75 70 28 31 29 5b 30 3a 31 5d 20 3d  .group(1)[0:1] =
7e20: 3d 20 22 2d 22 3a 0a 20 20 20 20 20 20 20 20 20  = "-":.         
7e30: 20 20 20 20 20 20 20 73 54 65 78 74 20 3d 20 73         sText = s
7e40: 54 65 78 74 2e 72 65 70 6c 61 63 65 28 6d 2e 67  Text.replace(m.g
7e50: 72 6f 75 70 28 30 29 2c 20 73 65 6c 66 2e 6c 54  roup(0), self.lT
7e60: 6f 6b 65 6e 5b 6e 4c 61 73 74 54 6f 6b 65 6e 2b  oken[nLastToken+
7e70: 69 6e 74 28 6d 2e 67 72 6f 75 70 28 31 29 29 2b  int(m.group(1))+
7e80: 31 5d 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20  1]["sValue"]).  
7e90: 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a            else:.
7ea0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7eb0: 73 54 65 78 74 20 3d 20 73 54 65 78 74 2e 72 65  sText = sText.re
7ec0: 70 6c 61 63 65 28 6d 2e 67 72 6f 75 70 28 30 29  place(m.group(0)
7ed0: 2c 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54  , self.lToken[nT
7ee0: 6f 6b 65 6e 4f 66 66 73 65 74 2b 69 6e 74 28 6d  okenOffset+int(m
7ef0: 2e 67 72 6f 75 70 28 31 29 29 5d 5b 22 73 56 61  .group(1))]["sVa
7f00: 6c 75 65 22 5d 29 0a 20 20 20 20 20 20 20 20 72  lue"]).        r
7f10: 65 74 75 72 6e 20 73 54 65 78 74 0a 0a 20 20 20  eturn sText..   
7f20: 20 64 65 66 20 72 65 77 72 69 74 65 54 65 78 74   def rewriteText
7f30: 20 28 73 65 6c 66 2c 20 73 54 65 78 74 2c 20 73   (self, sText, s
7f40: 52 65 70 6c 2c 20 69 47 72 6f 75 70 2c 20 6d 2c  Repl, iGroup, m,
7f50: 20 62 55 70 70 65 72 63 61 73 65 29 3a 0a 20 20   bUppercase):.  
7f60: 20 20 20 20 20 20 22 74 65 78 74 20 70 72 6f 63        "text proc
7f70: 65 73 73 6f 72 3a 20 77 72 69 74 65 20 3c 73 52  essor: write <sR
7f80: 65 70 6c 3e 20 69 6e 20 3c 73 54 65 78 74 3e 20  epl> in <sText> 
7f90: 61 74 20 3c 69 47 72 6f 75 70 3e 20 70 6f 73 69  at <iGroup> posi
7fa0: 74 69 6f 6e 22 0a 20 20 20 20 20 20 20 20 6e 4c  tion".        nL
7fb0: 65 6e 20 3d 20 6d 2e 65 6e 64 28 69 47 72 6f 75  en = m.end(iGrou
7fc0: 70 29 20 2d 20 6d 2e 73 74 61 72 74 28 69 47 72  p) - m.start(iGr
7fd0: 6f 75 70 29 0a 20 20 20 20 20 20 20 20 69 66 20  oup).        if 
7fe0: 73 52 65 70 6c 20 3d 3d 20 22 2a 22 3a 0a 20 20  sRepl == "*":.  
7ff0: 20 20 20 20 20 20 20 20 20 20 73 4e 65 77 20 3d            sNew =
8000: 20 22 20 22 20 2a 20 6e 4c 65 6e 0a 20 20 20 20   " " * nLen.    
8010: 20 20 20 20 65 6c 69 66 20 73 52 65 70 6c 20 3d      elif sRepl =
8020: 3d 20 22 5f 22 3a 0a 20 20 20 20 20 20 20 20 20  = "_":.         
8030: 20 20 20 73 4e 65 77 20 3d 20 73 52 65 70 6c 20     sNew = sRepl 
8040: 2b 20 22 20 22 20 2a 20 28 6e 4c 65 6e 2d 31 29  + " " * (nLen-1)
8050: 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 73 52  .        elif sR
8060: 65 70 6c 5b 30 3a 31 5d 20 3d 3d 20 22 3d 22 3a  epl[0:1] == "=":
8070: 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 4e 65  .            sNe
8080: 77 20 3d 20 67 6c 6f 62 61 6c 73 28 29 5b 73 52  w = globals()[sR
8090: 65 70 6c 5b 31 3a 5d 5d 28 73 54 65 78 74 2c 20  epl[1:]](sText, 
80a0: 6d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  m).            s
80b0: 4e 65 77 20 3d 20 73 4e 65 77 20 2b 20 22 20 22  New = sNew + " "
80c0: 20 2a 20 28 6e 4c 65 6e 2d 6c 65 6e 28 73 4e 65   * (nLen-len(sNe
80d0: 77 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  w)).            
80e0: 69 66 20 62 55 70 70 65 72 63 61 73 65 20 61 6e  if bUppercase an
80f0: 64 20 6d 2e 67 72 6f 75 70 28 69 47 72 6f 75 70  d m.group(iGroup
8100: 29 5b 30 3a 31 5d 2e 69 73 75 70 70 65 72 28 29  )[0:1].isupper()
8110: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
8120: 20 20 73 4e 65 77 20 3d 20 73 4e 65 77 2e 63 61    sNew = sNew.ca
8130: 70 69 74 61 6c 69 7a 65 28 29 0a 20 20 20 20 20  pitalize().     
8140: 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20     else:.       
8150: 20 20 20 20 20 73 4e 65 77 20 3d 20 6d 2e 65 78       sNew = m.ex
8160: 70 61 6e 64 28 73 52 65 70 6c 29 0a 20 20 20 20  pand(sRepl).    
8170: 20 20 20 20 20 20 20 20 73 4e 65 77 20 3d 20 73          sNew = s
8180: 4e 65 77 20 2b 20 22 20 22 20 2a 20 28 6e 4c 65  New + " " * (nLe
8190: 6e 2d 6c 65 6e 28 73 4e 65 77 29 29 0a 20 20 20  n-len(sNew)).   
81a0: 20 20 20 20 20 72 65 74 75 72 6e 20 73 54 65 78       return sTex
81b0: 74 5b 30 3a 6d 2e 73 74 61 72 74 28 69 47 72 6f  t[0:m.start(iGro
81c0: 75 70 29 5d 20 2b 20 73 4e 65 77 20 2b 20 73 54  up)] + sNew + sT
81d0: 65 78 74 5b 6d 2e 65 6e 64 28 69 47 72 6f 75 70  ext[m.end(iGroup
81e0: 29 3a 5d 0a 0a 20 20 20 20 64 65 66 20 5f 74 61  ):]..    def _ta
81f0: 67 41 6e 64 50 72 65 70 61 72 65 54 6f 6b 65 6e  gAndPrepareToken
8200: 46 6f 72 52 65 77 72 69 74 69 6e 67 20 28 73 65  ForRewriting (se
8210: 6c 66 2c 20 73 57 68 61 74 2c 20 6e 54 6f 6b 65  lf, sWhat, nToke
8220: 6e 52 65 77 72 69 74 65 53 74 61 72 74 2c 20 6e  nRewriteStart, n
8230: 54 6f 6b 65 6e 52 65 77 72 69 74 65 45 6e 64 2c  TokenRewriteEnd,
8240: 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 6e   nTokenOffset, n
8250: 4c 61 73 74 54 6f 6b 65 6e 2c 20 62 43 61 73 65  LastToken, bCase
8260: 53 76 74 79 2c 20 62 44 65 62 75 67 29 3a 0a 20  Svty, bDebug):. 
8270: 20 20 20 20 20 20 20 22 74 65 78 74 20 70 72 6f         "text pro
8280: 63 65 73 73 6f 72 3a 20 72 65 77 72 69 74 65 20  cessor: rewrite 
8290: 74 6f 6b 65 6e 73 20 62 65 74 77 65 65 6e 20 3c  tokens between <
82a0: 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61  nTokenRewriteSta
82b0: 72 74 3e 20 61 6e 64 20 3c 6e 54 6f 6b 65 6e 52  rt> and <nTokenR
82c0: 65 77 72 69 74 65 45 6e 64 3e 20 70 6f 73 69 74  ewriteEnd> posit
82d0: 69 6f 6e 22 0a 20 20 20 20 20 20 20 20 69 66 20  ion".        if 
82e0: 73 57 68 61 74 20 3d 3d 20 22 2a 22 3a 0a 20 20  sWhat == "*":.  
82f0: 20 20 20 20 20 20 20 20 20 20 23 20 70 75 72 67            # purg
8300: 65 20 74 65 78 74 0a 20 20 20 20 20 20 20 20 20  e text.         
8310: 20 20 20 69 66 20 6e 54 6f 6b 65 6e 52 65 77 72     if nTokenRewr
8320: 69 74 65 45 6e 64 20 2d 20 6e 54 6f 6b 65 6e 52  iteEnd - nTokenR
8330: 65 77 72 69 74 65 53 74 61 72 74 20 3d 3d 20 30  ewriteStart == 0
8340: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
8350: 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54    self.lToken[nT
8360: 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72 74  okenRewriteStart
8370: 5d 5b 22 62 54 6f 52 65 6d 6f 76 65 22 5d 20 3d  ]["bToRemove"] =
8380: 20 54 72 75 65 0a 20 20 20 20 20 20 20 20 20 20   True.          
8390: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
83a0: 20 20 20 20 20 20 20 20 66 6f 72 20 69 20 69 6e          for i in
83b0: 20 72 61 6e 67 65 28 6e 54 6f 6b 65 6e 52 65 77   range(nTokenRew
83c0: 72 69 74 65 53 74 61 72 74 2c 20 6e 54 6f 6b 65  riteStart, nToke
83d0: 6e 52 65 77 72 69 74 65 45 6e 64 2b 31 29 3a 0a  nRewriteEnd+1):.
83e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
83f0: 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b      self.lToken[
8400: 69 5d 5b 22 62 54 6f 52 65 6d 6f 76 65 22 5d 20  i]["bToRemove"] 
8410: 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20 20 65  = True.        e
8420: 6c 69 66 20 73 57 68 61 74 20 3d 3d 20 22 e2 90  lif sWhat == "..
8430: a3 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  .":.            
8440: 23 20 6d 65 72 67 65 20 74 6f 6b 65 6e 73 0a 20  # merge tokens. 
8450: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
8460: 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 52 65 77  lToken[nTokenRew
8470: 72 69 74 65 53 74 61 72 74 5d 5b 22 6e 4d 65 72  riteStart]["nMer
8480: 67 65 55 6e 74 69 6c 22 5d 20 3d 20 6e 54 6f 6b  geUntil"] = nTok
8490: 65 6e 52 65 77 72 69 74 65 45 6e 64 0a 20 20 20  enRewriteEnd.   
84a0: 20 20 20 20 20 65 6c 69 66 20 73 57 68 61 74 20       elif sWhat 
84b0: 3d 3d 20 22 5f 22 3a 0a 20 20 20 20 20 20 20 20  == "_":.        
84c0: 20 20 20 20 23 20 6e 65 75 74 72 61 6c 69 7a 65      # neutralize
84d0: 64 20 74 6f 6b 65 6e 0a 20 20 20 20 20 20 20 20  d token.        
84e0: 20 20 20 20 69 66 20 6e 54 6f 6b 65 6e 52 65 77      if nTokenRew
84f0: 72 69 74 65 45 6e 64 20 2d 20 6e 54 6f 6b 65 6e  riteEnd - nToken
8500: 52 65 77 72 69 74 65 53 74 61 72 74 20 3d 3d 20  RewriteStart == 
8510: 30 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  0:.             
8520: 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e     self.lToken[n
8530: 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72  TokenRewriteStar
8540: 74 5d 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d 20  t]["sNewValue"] 
8550: 3d 20 22 5f 22 0a 20 20 20 20 20 20 20 20 20 20  = "_".          
8560: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
8570: 20 20 20 20 20 20 20 20 66 6f 72 20 69 20 69 6e          for i in
8580: 20 72 61 6e 67 65 28 6e 54 6f 6b 65 6e 52 65 77   range(nTokenRew
8590: 72 69 74 65 53 74 61 72 74 2c 20 6e 54 6f 6b 65  riteStart, nToke
85a0: 6e 52 65 77 72 69 74 65 45 6e 64 2b 31 29 3a 0a  nRewriteEnd+1):.
85b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
85c0: 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b      self.lToken[
85d0: 69 5d 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d 20  i]["sNewValue"] 
85e0: 3d 20 22 5f 22 0a 20 20 20 20 20 20 20 20 65 6c  = "_".        el
85f0: 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
8600: 69 66 20 73 57 68 61 74 2e 73 74 61 72 74 73 77  if sWhat.startsw
8610: 69 74 68 28 22 3d 22 29 3a 0a 20 20 20 20 20 20  ith("="):.      
8620: 20 20 20 20 20 20 20 20 20 20 73 57 68 61 74 20            sWhat 
8630: 3d 20 67 6c 6f 62 61 6c 73 28 29 5b 73 57 68 61  = globals()[sWha
8640: 74 5b 31 3a 5d 5d 28 73 65 6c 66 2e 6c 54 6f 6b  t[1:]](self.lTok
8650: 65 6e 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74  en, nTokenOffset
8660: 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 29 0a 20 20  , nLastToken).  
8670: 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a            else:.
8680: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8690: 73 57 68 61 74 20 3d 20 73 65 6c 66 2e 5f 65 78  sWhat = self._ex
86a0: 70 61 6e 64 28 73 57 68 61 74 2c 20 6e 54 6f 6b  pand(sWhat, nTok
86b0: 65 6e 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54  enOffset, nLastT
86c0: 6f 6b 65 6e 29 0a 20 20 20 20 20 20 20 20 20 20  oken).          
86d0: 20 20 62 55 70 70 65 72 63 61 73 65 20 3d 20 62    bUppercase = b
86e0: 43 61 73 65 53 76 74 79 20 61 6e 64 20 73 65 6c  CaseSvty and sel
86f0: 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 52  f.lToken[nTokenR
8700: 65 77 72 69 74 65 53 74 61 72 74 5d 5b 22 73 56  ewriteStart]["sV
8710: 61 6c 75 65 22 5d 5b 30 3a 31 5d 2e 69 73 75 70  alue"][0:1].isup
8720: 70 65 72 28 29 0a 20 20 20 20 20 20 20 20 20 20  per().          
8730: 20 20 69 66 20 6e 54 6f 6b 65 6e 52 65 77 72 69    if nTokenRewri
8740: 74 65 45 6e 64 20 2d 20 6e 54 6f 6b 65 6e 52 65  teEnd - nTokenRe
8750: 77 72 69 74 65 53 74 61 72 74 20 3d 3d 20 30 3a  writeStart == 0:
8760: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8770: 20 23 20 6f 6e 65 20 74 6f 6b 65 6e 0a 20 20 20   # one token.   
8780: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
8790: 62 55 70 70 65 72 63 61 73 65 3a 0a 20 20 20 20  bUppercase:.    
87a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
87b0: 73 57 68 61 74 20 3d 20 73 57 68 61 74 5b 30 3a  sWhat = sWhat[0:
87c0: 31 5d 2e 75 70 70 65 72 28 29 20 2b 20 73 57 68  1].upper() + sWh
87d0: 61 74 5b 31 3a 5d 0a 20 20 20 20 20 20 20 20 20  at[1:].         
87e0: 20 20 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b         self.lTok
87f0: 65 6e 5b 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65  en[nTokenRewrite
8800: 53 74 61 72 74 5d 5b 22 73 4e 65 77 56 61 6c 75  Start]["sNewValu
8810: 65 22 5d 20 3d 20 73 57 68 61 74 0a 20 20 20 20  e"] = sWhat.    
8820: 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20          else:.  
8830: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
8840: 73 65 76 65 72 61 6c 20 74 6f 6b 65 6e 73 0a 20  several tokens. 
8850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c                 l
8860: 54 6f 6b 65 6e 56 61 6c 75 65 20 3d 20 73 57 68  TokenValue = sWh
8870: 61 74 2e 73 70 6c 69 74 28 22 7c 22 29 0a 20 20  at.split("|").  
8880: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
8890: 20 6c 65 6e 28 6c 54 6f 6b 65 6e 56 61 6c 75 65   len(lTokenValue
88a0: 29 20 21 3d 20 28 6e 54 6f 6b 65 6e 52 65 77 72  ) != (nTokenRewr
88b0: 69 74 65 45 6e 64 20 2d 20 6e 54 6f 6b 65 6e 52  iteEnd - nTokenR
88c0: 65 77 72 69 74 65 53 74 61 72 74 20 2b 20 31 29  ewriteStart + 1)
88d0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
88e0: 20 20 20 20 20 20 65 63 68 6f 28 22 45 72 72 6f        echo("Erro
88f0: 72 2e 20 54 65 78 74 20 70 72 6f 63 65 73 73 6f  r. Text processo
8900: 72 3a 20 6e 75 6d 62 65 72 20 6f 66 20 72 65 70  r: number of rep
8910: 6c 61 63 65 6d 65 6e 74 73 20 21 3d 20 6e 75 6d  lacements != num
8920: 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73 2e 22 29  ber of tokens.")
8930: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8940: 20 20 20 20 20 72 65 74 75 72 6e 0a 20 20 20 20       return.    
8950: 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20              for 
8960: 69 2c 20 73 56 61 6c 75 65 20 69 6e 20 7a 69 70  i, sValue in zip
8970: 28 72 61 6e 67 65 28 6e 54 6f 6b 65 6e 52 65 77  (range(nTokenRew
8980: 72 69 74 65 53 74 61 72 74 2c 20 6e 54 6f 6b 65  riteStart, nToke
8990: 6e 52 65 77 72 69 74 65 45 6e 64 2b 31 29 2c 20  nRewriteEnd+1), 
89a0: 6c 54 6f 6b 65 6e 56 61 6c 75 65 29 3a 0a 20 20  lTokenValue):.  
89b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
89c0: 20 20 69 66 20 6e 6f 74 20 73 56 61 6c 75 65 20    if not sValue 
89d0: 6f 72 20 73 56 61 6c 75 65 20 3d 3d 20 22 2a 22  or sValue == "*"
89e0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
89f0: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c            self.l
8a00: 54 6f 6b 65 6e 5b 69 5d 5b 22 62 54 6f 52 65 6d  Token[i]["bToRem
8a10: 6f 76 65 22 5d 20 3d 20 54 72 75 65 0a 20 20 20  ove"] = True.   
8a20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8a30: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
8a40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
8a50: 66 20 62 55 70 70 65 72 63 61 73 65 3a 0a 20 20  f bUppercase:.  
8a60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8a70: 20 20 20 20 20 20 20 20 20 20 73 56 61 6c 75 65            sValue
8a80: 20 3d 20 73 56 61 6c 75 65 5b 30 3a 31 5d 2e 75   = sValue[0:1].u
8a90: 70 70 65 72 28 29 20 2b 20 73 56 61 6c 75 65 5b  pper() + sValue[
8aa0: 31 3a 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  1:].            
8ab0: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
8ac0: 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 73 4e 65 77  .lToken[i]["sNew
8ad0: 56 61 6c 75 65 22 5d 20 3d 20 73 56 61 6c 75 65  Value"] = sValue
8ae0: 0a 0a 20 20 20 20 64 65 66 20 72 65 77 72 69 74  ..    def rewrit
8af0: 65 46 72 6f 6d 54 61 67 73 20 28 73 65 6c 66 2c  eFromTags (self,
8b00: 20 62 44 65 62 75 67 3d 46 61 6c 73 65 29 3a 0a   bDebug=False):.
8b10: 20 20 20 20 20 20 20 20 22 72 65 77 72 69 74 65          "rewrite
8b20: 20 74 68 65 20 73 65 6e 74 65 6e 63 65 2c 20 6d   the sentence, m
8b30: 6f 64 69 66 79 20 74 6f 6b 65 6e 73 2c 20 70 75  odify tokens, pu
8b40: 72 67 65 20 74 68 65 20 74 6f 6b 65 6e 20 6c 69  rge the token li
8b50: 73 74 22 0a 20 20 20 20 20 20 20 20 69 66 20 62  st".        if b
8b60: 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20  Debug:.         
8b70: 20 20 20 65 63 68 6f 28 22 52 45 57 52 49 54 45     echo("REWRITE
8b80: 22 29 0a 20 20 20 20 20 20 20 20 6c 4e 65 77 54  ").        lNewT
8b90: 6f 6b 65 6e 20 3d 20 5b 5d 0a 20 20 20 20 20 20  oken = [].      
8ba0: 20 20 6e 4d 65 72 67 65 55 6e 74 69 6c 20 3d 20    nMergeUntil = 
8bb0: 30 0a 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e  0.        dToken
8bc0: 4d 65 72 67 65 72 20 3d 20 4e 6f 6e 65 0a 20 20  Merger = None.  
8bd0: 20 20 20 20 20 20 66 6f 72 20 69 54 6f 6b 65 6e        for iToken
8be0: 2c 20 64 54 6f 6b 65 6e 20 69 6e 20 65 6e 75 6d  , dToken in enum
8bf0: 65 72 61 74 65 28 73 65 6c 66 2e 6c 54 6f 6b 65  erate(self.lToke
8c00: 6e 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  n):.            
8c10: 62 4b 65 65 70 54 6f 6b 65 6e 20 3d 20 54 72 75  bKeepToken = Tru
8c20: 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  e.            if
8c30: 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70 65 22 5d   dToken["sType"]
8c40: 20 21 3d 20 22 49 4e 46 4f 22 3a 0a 20 20 20 20   != "INFO":.    
8c50: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
8c60: 4d 65 72 67 65 55 6e 74 69 6c 20 61 6e 64 20 69  MergeUntil and i
8c70: 54 6f 6b 65 6e 20 3c 3d 20 6e 4d 65 72 67 65 55  Token <= nMergeU
8c80: 6e 74 69 6c 3a 0a 20 20 20 20 20 20 20 20 20 20  ntil:.          
8c90: 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e            dToken
8ca0: 4d 65 72 67 65 72 5b 22 73 56 61 6c 75 65 22 5d  Merger["sValue"]
8cb0: 20 2b 3d 20 22 20 22 20 2a 20 28 64 54 6f 6b 65   += " " * (dToke
8cc0: 6e 5b 22 6e 53 74 61 72 74 22 5d 20 2d 20 64 54  n["nStart"] - dT
8cd0: 6f 6b 65 6e 4d 65 72 67 65 72 5b 22 6e 45 6e 64  okenMerger["nEnd
8ce0: 22 5d 29 20 2b 20 64 54 6f 6b 65 6e 5b 22 73 56  "]) + dToken["sV
8cf0: 61 6c 75 65 22 5d 0a 20 20 20 20 20 20 20 20 20  alue"].         
8d00: 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65             dToke
8d10: 6e 4d 65 72 67 65 72 5b 22 6e 45 6e 64 22 5d 20  nMerger["nEnd"] 
8d20: 3d 20 64 54 6f 6b 65 6e 5b 22 6e 45 6e 64 22 5d  = dToken["nEnd"]
8d30: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8d40: 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a       if bDebug:.
8d50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8d60: 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 20 20          echo("  
8d70: 4d 45 52 47 45 44 20 54 4f 4b 45 4e 3a 20 22 20  MERGED TOKEN: " 
8d80: 2b 20 64 54 6f 6b 65 6e 4d 65 72 67 65 72 5b 22  + dTokenMerger["
8d90: 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20 20 20  sValue"]).      
8da0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62 4b                bK
8db0: 65 65 70 54 6f 6b 65 6e 20 3d 20 46 61 6c 73 65  eepToken = False
8dc0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8dd0: 20 69 66 20 22 6e 4d 65 72 67 65 55 6e 74 69 6c   if "nMergeUntil
8de0: 22 20 69 6e 20 64 54 6f 6b 65 6e 3a 0a 20 20 20  " in dToken:.   
8df0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8e00: 20 69 66 20 69 54 6f 6b 65 6e 20 3e 20 6e 4d 65   if iToken > nMe
8e10: 72 67 65 55 6e 74 69 6c 3a 20 23 20 74 68 69 73  rgeUntil: # this
8e20: 20 74 6f 6b 65 6e 20 69 73 20 6e 6f 74 20 61 6c   token is not al
8e30: 72 65 61 64 79 20 6d 65 72 67 65 64 20 77 69 74  ready merged wit
8e40: 68 20 61 20 70 72 65 76 69 6f 75 73 20 74 6f 6b  h a previous tok
8e50: 65 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  en.             
8e60: 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65             dToke
8e70: 6e 4d 65 72 67 65 72 20 3d 20 64 54 6f 6b 65 6e  nMerger = dToken
8e80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8e90: 20 20 20 20 20 69 66 20 64 54 6f 6b 65 6e 5b 22       if dToken["
8ea0: 6e 4d 65 72 67 65 55 6e 74 69 6c 22 5d 20 3e 20  nMergeUntil"] > 
8eb0: 6e 4d 65 72 67 65 55 6e 74 69 6c 3a 0a 20 20 20  nMergeUntil:.   
8ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8ed0: 20 20 20 20 20 6e 4d 65 72 67 65 55 6e 74 69 6c       nMergeUntil
8ee0: 20 3d 20 64 54 6f 6b 65 6e 5b 22 6e 4d 65 72 67   = dToken["nMerg
8ef0: 65 55 6e 74 69 6c 22 5d 0a 20 20 20 20 20 20 20  eUntil"].       
8f00: 20 20 20 20 20 20 20 20 20 20 20 20 20 64 65 6c               del
8f10: 20 64 54 6f 6b 65 6e 5b 22 6e 4d 65 72 67 65 55   dToken["nMergeU
8f20: 6e 74 69 6c 22 5d 0a 20 20 20 20 20 20 20 20 20  ntil"].         
8f30: 20 20 20 20 20 20 20 65 6c 69 66 20 22 62 54 6f         elif "bTo
8f40: 52 65 6d 6f 76 65 22 20 69 6e 20 64 54 6f 6b 65  Remove" in dToke
8f50: 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  n:.             
8f60: 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67         if bDebug
8f70: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
8f80: 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22            echo("
8f90: 20 20 52 45 4d 4f 56 45 44 3a 20 22 20 2b 20 64    REMOVED: " + d
8fa0: 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29  Token["sValue"])
8fb0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8fc0: 20 20 20 20 20 73 65 6c 66 2e 73 53 65 6e 74 65       self.sSente
8fd0: 6e 63 65 20 3d 20 73 65 6c 66 2e 73 53 65 6e 74  nce = self.sSent
8fe0: 65 6e 63 65 5b 3a 64 54 6f 6b 65 6e 5b 22 6e 53  ence[:dToken["nS
8ff0: 74 61 72 74 22 5d 5d 20 2b 20 22 20 22 20 2a 20  tart"]] + " " * 
9000: 28 64 54 6f 6b 65 6e 5b 22 6e 45 6e 64 22 5d 20  (dToken["nEnd"] 
9010: 2d 20 64 54 6f 6b 65 6e 5b 22 6e 53 74 61 72 74  - dToken["nStart
9020: 22 5d 29 20 2b 20 73 65 6c 66 2e 73 53 65 6e 74  "]) + self.sSent
9030: 65 6e 63 65 5b 64 54 6f 6b 65 6e 5b 22 6e 45 6e  ence[dToken["nEn
9040: 64 22 5d 3a 5d 0a 20 20 20 20 20 20 20 20 20 20  d"]:].          
9050: 20 20 20 20 20 20 20 20 20 20 62 4b 65 65 70 54            bKeepT
9060: 6f 6b 65 6e 20 3d 20 46 61 6c 73 65 0a 20 20 20  oken = False.   
9070: 20 20 20 20 20 20 20 20 20 23 0a 20 20 20 20 20           #.     
9080: 20 20 20 20 20 20 20 69 66 20 62 4b 65 65 70 54         if bKeepT
9090: 6f 6b 65 6e 3a 0a 20 20 20 20 20 20 20 20 20 20  oken:.          
90a0: 20 20 20 20 20 20 6c 4e 65 77 54 6f 6b 65 6e 2e        lNewToken.
90b0: 61 70 70 65 6e 64 28 64 54 6f 6b 65 6e 29 0a 20  append(dToken). 
90c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
90d0: 66 20 22 73 4e 65 77 56 61 6c 75 65 22 20 69 6e  f "sNewValue" in
90e0: 20 64 54 6f 6b 65 6e 3a 0a 20 20 20 20 20 20 20   dToken:.       
90f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 72               # r
9100: 65 77 72 69 74 65 20 74 6f 6b 65 6e 20 61 6e 64  ewrite token and
9110: 20 73 65 6e 74 65 6e 63 65 0a 20 20 20 20 20 20   sentence.      
9120: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
9130: 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20   bDebug:.       
9140: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9150: 20 65 63 68 6f 28 64 54 6f 6b 65 6e 5b 22 73 56   echo(dToken["sV
9160: 61 6c 75 65 22 5d 20 2b 20 22 20 2d 3e 20 22 20  alue"] + " -> " 
9170: 2b 20 64 54 6f 6b 65 6e 5b 22 73 4e 65 77 56 61  + dToken["sNewVa
9180: 6c 75 65 22 5d 29 0a 20 20 20 20 20 20 20 20 20  lue"]).         
9190: 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65             dToke
91a0: 6e 5b 22 73 52 65 61 6c 56 61 6c 75 65 22 5d 20  n["sRealValue"] 
91b0: 3d 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65  = dToken["sValue
91c0: 22 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  "].             
91d0: 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22 73         dToken["s
91e0: 56 61 6c 75 65 22 5d 20 3d 20 64 54 6f 6b 65 6e  Value"] = dToken
91f0: 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d 0a 20 20  ["sNewValue"].  
9200: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9210: 20 20 6e 44 69 66 66 4c 65 6e 20 3d 20 6c 65 6e    nDiffLen = len
9220: 28 64 54 6f 6b 65 6e 5b 22 73 52 65 61 6c 56 61  (dToken["sRealVa
9230: 6c 75 65 22 5d 29 20 2d 20 6c 65 6e 28 64 54 6f  lue"]) - len(dTo
9240: 6b 65 6e 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d  ken["sNewValue"]
9250: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
9260: 20 20 20 20 20 20 73 4e 65 77 52 65 70 6c 20 3d        sNewRepl =
9270: 20 28 64 54 6f 6b 65 6e 5b 22 73 4e 65 77 56 61   (dToken["sNewVa
9280: 6c 75 65 22 5d 20 2b 20 22 20 22 20 2a 20 6e 44  lue"] + " " * nD
9290: 69 66 66 4c 65 6e 29 20 20 69 66 20 6e 44 69 66  iffLen)  if nDif
92a0: 66 4c 65 6e 20 3e 3d 20 30 20 20 65 6c 73 65 20  fLen >= 0  else 
92b0: 64 54 6f 6b 65 6e 5b 22 73 4e 65 77 56 61 6c 75  dToken["sNewValu
92c0: 65 22 5d 5b 3a 6c 65 6e 28 64 54 6f 6b 65 6e 5b  e"][:len(dToken[
92d0: 22 73 52 65 61 6c 56 61 6c 75 65 22 5d 29 5d 0a  "sRealValue"])].
92e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
92f0: 20 20 20 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e      self.sSenten
9300: 63 65 20 3d 20 73 65 6c 66 2e 73 53 65 6e 74 65  ce = self.sSente
9310: 6e 63 65 5b 3a 64 54 6f 6b 65 6e 5b 22 6e 53 74  nce[:dToken["nSt
9320: 61 72 74 22 5d 5d 20 2b 20 73 4e 65 77 52 65 70  art"]] + sNewRep
9330: 6c 20 2b 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e  l + self.sSenten
9340: 63 65 5b 64 54 6f 6b 65 6e 5b 22 6e 45 6e 64 22  ce[dToken["nEnd"
9350: 5d 3a 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  ]:].            
9360: 20 20 20 20 20 20 20 20 64 65 6c 20 64 54 6f 6b          del dTok
9370: 65 6e 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d 0a  en["sNewValue"].
9380: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
9390: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
93a0: 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20    try:.         
93b0: 20 20 20 20 20 20 20 20 20 20 20 64 65 6c 20 73             del s
93c0: 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f 73 5b 64 54  elf.dTokenPos[dT
93d0: 6f 6b 65 6e 5b 22 6e 53 74 61 72 74 22 5d 5d 0a  oken["nStart"]].
93e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
93f0: 65 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20  except:.        
9400: 20 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f              echo
9410: 28 73 65 6c 66 29 0a 20 20 20 20 20 20 20 20 20  (self).         
9420: 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28             echo(
9430: 64 54 6f 6b 65 6e 29 0a 20 20 20 20 20 20 20 20  dToken).        
9440: 20 20 20 20 20 20 20 20 20 20 20 20 65 78 69 74              exit
9450: 28 29 0a 20 20 20 20 20 20 20 20 69 66 20 62 44  ().        if bD
9460: 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20  ebug:.          
9470: 20 20 65 63 68 6f 28 22 20 20 54 45 58 54 20 52    echo("  TEXT R
9480: 45 57 52 49 54 45 44 3a 20 22 20 2b 20 73 65 6c  EWRITED: " + sel
9490: 66 2e 73 53 65 6e 74 65 6e 63 65 29 0a 20 20 20  f.sSentence).   
94a0: 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e       self.lToken
94b0: 2e 63 6c 65 61 72 28 29 0a 20 20 20 20 20 20 20  .clear().       
94c0: 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 3d 20 6c   self.lToken = l
94d0: 4e 65 77 54 6f 6b 65 6e 0a 0a 0a 23 23 23 23 20  NewToken...#### 
94e0: 63 6f 6d 6d 6f 6e 20 66 75 6e 63 74 69 6f 6e 73  common functions
94f0: 0a 0a 64 65 66 20 6f 70 74 69 6f 6e 20 28 73 4f  ..def option (sO
9500: 70 74 29 3a 0a 20 20 20 20 22 72 65 74 75 72 6e  pt):.    "return
9510: 20 54 72 75 65 20 69 66 20 6f 70 74 69 6f 6e 20   True if option 
9520: 3c 73 4f 70 74 3e 20 69 73 20 61 63 74 69 76 65  <sOpt> is active
9530: 22 0a 20 20 20 20 72 65 74 75 72 6e 20 5f 64 4f  ".    return _dO
9540: 70 74 69 6f 6e 73 2e 67 65 74 28 73 4f 70 74 2c  ptions.get(sOpt,
9550: 20 46 61 6c 73 65 29 0a 0a 0a 23 23 23 23 20 46   False)...#### F
9560: 75 6e 63 74 69 6f 6e 73 20 74 6f 20 67 65 74 20  unctions to get 
9570: 74 65 78 74 20 6f 75 74 73 69 64 65 20 70 61 74  text outside pat
9580: 74 65 72 6e 20 73 63 6f 70 65 0a 0a 23 20 77 61  tern scope..# wa
9590: 72 6e 69 6e 67 3a 20 63 68 65 63 6b 20 63 6f 6d  rning: check com
95a0: 70 69 6c 65 5f 72 75 6c 65 73 2e 70 79 20 74 6f  pile_rules.py to
95b0: 20 75 6e 64 65 72 73 74 61 6e 64 20 68 6f 77 20   understand how 
95c0: 69 74 20 77 6f 72 6b 73 0a 0a 5f 7a 4e 65 78 74  it works.._zNext
95d0: 57 6f 72 64 20 3d 20 72 65 2e 63 6f 6d 70 69 6c  Word = re.compil
95e0: 65 28 72 22 20 2b 28 5c 77 5b 5c 77 2d 5d 2a 29  e(r" +(\w[\w-]*)
95f0: 22 29 0a 5f 7a 50 72 65 76 57 6f 72 64 20 3d 20  ")._zPrevWord = 
9600: 72 65 2e 63 6f 6d 70 69 6c 65 28 72 22 28 5c 77  re.compile(r"(\w
9610: 5b 5c 77 2d 5d 2a 29 20 2b 24 22 29 0a 0a 64 65  [\w-]*) +$")..de
9620: 66 20 6e 65 78 74 77 6f 72 64 20 28 73 2c 20 69  f nextword (s, i
9630: 53 74 61 72 74 2c 20 6e 29 3a 0a 20 20 20 20 22  Start, n):.    "
9640: 67 65 74 20 74 68 65 20 6e 74 68 20 77 6f 72 64  get the nth word
9650: 20 6f 66 20 74 68 65 20 69 6e 70 75 74 20 73 74   of the input st
9660: 72 69 6e 67 20 6f 72 20 65 6d 70 74 79 20 73 74  ring or empty st
9670: 72 69 6e 67 22 0a 20 20 20 20 6d 20 3d 20 72 65  ring".    m = re
9680: 2e 6d 61 74 63 68 28 22 28 3f 3a 20 2b 5b 5c 5c  .match("(?: +[\\
9690: 77 25 2d 5d 2b 29 7b 22 20 2b 20 73 74 72 28 6e  w%-]+){" + str(n
96a0: 2d 31 29 20 2b 20 22 7d 20 2b 28 5b 5c 5c 77 25  -1) + "} +([\\w%
96b0: 2d 5d 2b 29 22 2c 20 73 5b 69 53 74 61 72 74 3a  -]+)", s[iStart:
96c0: 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6d 3a  ]).    if not m:
96d0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
96e0: 4e 6f 6e 65 0a 20 20 20 20 72 65 74 75 72 6e 20  None.    return 
96f0: 28 69 53 74 61 72 74 2b 6d 2e 73 74 61 72 74 28  (iStart+m.start(
9700: 31 29 2c 20 6d 2e 67 72 6f 75 70 28 31 29 29 0a  1), m.group(1)).
9710: 0a 0a 64 65 66 20 70 72 65 76 77 6f 72 64 20 28  ..def prevword (
9720: 73 2c 20 69 45 6e 64 2c 20 6e 29 3a 0a 20 20 20  s, iEnd, n):.   
9730: 20 22 67 65 74 20 74 68 65 20 28 2d 29 6e 74 68   "get the (-)nth
9740: 20 77 6f 72 64 20 6f 66 20 74 68 65 20 69 6e 70   word of the inp
9750: 75 74 20 73 74 72 69 6e 67 20 6f 72 20 65 6d 70  ut string or emp
9760: 74 79 20 73 74 72 69 6e 67 22 0a 20 20 20 20 6d  ty string".    m
9770: 20 3d 20 72 65 2e 73 65 61 72 63 68 28 22 28 5b   = re.search("([
9780: 5c 5c 77 25 2d 5d 2b 29 20 2b 28 3f 3a 5b 5c 5c  \\w%-]+) +(?:[\\
9790: 77 25 2d 5d 2b 20 2b 29 7b 22 20 2b 20 73 74 72  w%-]+ +){" + str
97a0: 28 6e 2d 31 29 20 2b 20 22 7d 24 22 2c 20 73 5b  (n-1) + "}$", s[
97b0: 3a 69 45 6e 64 5d 29 0a 20 20 20 20 69 66 20 6e  :iEnd]).    if n
97c0: 6f 74 20 6d 3a 0a 20 20 20 20 20 20 20 20 72 65  ot m:.        re
97d0: 74 75 72 6e 20 4e 6f 6e 65 0a 20 20 20 20 72 65  turn None.    re
97e0: 74 75 72 6e 20 28 6d 2e 73 74 61 72 74 28 31 29  turn (m.start(1)
97f0: 2c 20 6d 2e 67 72 6f 75 70 28 31 29 29 0a 0a 0a  , m.group(1))...
9800: 64 65 66 20 6e 65 78 74 77 6f 72 64 31 20 28 73  def nextword1 (s
9810: 2c 20 69 53 74 61 72 74 29 3a 0a 20 20 20 20 22  , iStart):.    "
9820: 67 65 74 20 6e 65 78 74 20 77 6f 72 64 20 28 6f  get next word (o
9830: 70 74 69 6d 69 7a 61 74 69 6f 6e 29 22 0a 20 20  ptimization)".  
9840: 20 20 6d 20 3d 20 5f 7a 4e 65 78 74 57 6f 72 64    m = _zNextWord
9850: 2e 6d 61 74 63 68 28 73 5b 69 53 74 61 72 74 3a  .match(s[iStart:
9860: 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6d 3a  ]).    if not m:
9870: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
9880: 4e 6f 6e 65 0a 20 20 20 20 72 65 74 75 72 6e 20  None.    return 
9890: 28 69 53 74 61 72 74 2b 6d 2e 73 74 61 72 74 28  (iStart+m.start(
98a0: 31 29 2c 20 6d 2e 67 72 6f 75 70 28 31 29 29 0a  1), m.group(1)).
98b0: 0a 0a 64 65 66 20 70 72 65 76 77 6f 72 64 31 20  ..def prevword1 
98c0: 28 73 2c 20 69 45 6e 64 29 3a 0a 20 20 20 20 22  (s, iEnd):.    "
98d0: 67 65 74 20 70 72 65 76 69 6f 75 73 20 77 6f 72  get previous wor
98e0: 64 20 28 6f 70 74 69 6d 69 7a 61 74 69 6f 6e 29  d (optimization)
98f0: 22 0a 20 20 20 20 6d 20 3d 20 5f 7a 50 72 65 76  ".    m = _zPrev
9900: 57 6f 72 64 2e 73 65 61 72 63 68 28 73 5b 3a 69  Word.search(s[:i
9910: 45 6e 64 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74  End]).    if not
9920: 20 6d 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75   m:.        retu
9930: 72 6e 20 4e 6f 6e 65 0a 20 20 20 20 72 65 74 75  rn None.    retu
9940: 72 6e 20 28 6d 2e 73 74 61 72 74 28 31 29 2c 20  rn (m.start(1), 
9950: 6d 2e 67 72 6f 75 70 28 31 29 29 0a 0a 0a 64 65  m.group(1))...de
9960: 66 20 6c 6f 6f 6b 20 28 73 2c 20 73 50 61 74 74  f look (s, sPatt
9970: 65 72 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e  ern, sNegPattern
9980: 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 73 65 65  =None):.    "see
9990: 6b 20 73 50 61 74 74 65 72 6e 20 69 6e 20 73 20  k sPattern in s 
99a0: 28 62 65 66 6f 72 65 2f 61 66 74 65 72 2f 66 75  (before/after/fu
99b0: 6c 6c 74 65 78 74 29 2c 20 69 66 20 73 4e 65 67  lltext), if sNeg
99c0: 50 61 74 74 65 72 6e 20 6e 6f 74 20 69 6e 20 73  Pattern not in s
99d0: 22 0a 20 20 20 20 69 66 20 73 4e 65 67 50 61 74  ".    if sNegPat
99e0: 74 65 72 6e 20 61 6e 64 20 72 65 2e 73 65 61 72  tern and re.sear
99f0: 63 68 28 73 4e 65 67 50 61 74 74 65 72 6e 2c 20  ch(sNegPattern, 
9a00: 73 29 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75  s):.        retu
9a10: 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 69 66 20  rn False.    if 
9a20: 72 65 2e 73 65 61 72 63 68 28 73 50 61 74 74 65  re.search(sPatte
9a30: 72 6e 2c 20 73 29 3a 0a 20 20 20 20 20 20 20 20  rn, s):.        
9a40: 72 65 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20  return True.    
9a50: 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 0a 0a 64  return False...d
9a60: 65 66 20 6c 6f 6f 6b 5f 63 68 6b 31 20 28 64 54  ef look_chk1 (dT
9a70: 6f 6b 65 6e 50 6f 73 2c 20 73 2c 20 6e 4f 66 66  okenPos, s, nOff
9a80: 73 65 74 2c 20 73 50 61 74 74 65 72 6e 2c 20 73  set, sPattern, s
9a90: 50 61 74 74 65 72 6e 47 72 6f 75 70 31 2c 20 73  PatternGroup1, s
9aa0: 4e 65 67 50 61 74 74 65 72 6e 47 72 6f 75 70 31  NegPatternGroup1
9ab0: 3d 22 22 29 3a 0a 20 20 20 20 22 72 65 74 75 72  =""):.    "retur
9ac0: 6e 73 20 54 72 75 65 20 69 66 20 73 20 68 61 73  ns True if s has
9ad0: 20 70 61 74 74 65 72 6e 20 73 50 61 74 74 65 72   pattern sPatter
9ae0: 6e 20 61 6e 64 20 6d 2e 67 72 6f 75 70 28 31 29  n and m.group(1)
9af0: 20 68 61 73 20 70 61 74 74 65 72 6e 20 73 50 61   has pattern sPa
9b00: 74 74 65 72 6e 47 72 6f 75 70 31 22 0a 20 20 20  tternGroup1".   
9b10: 20 6d 20 3d 20 72 65 2e 73 65 61 72 63 68 28 73   m = re.search(s
9b20: 50 61 74 74 65 72 6e 2c 20 73 29 0a 20 20 20 20  Pattern, s).    
9b30: 69 66 20 6e 6f 74 20 6d 3a 0a 20 20 20 20 20 20  if not m:.      
9b40: 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20    return False. 
9b50: 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20     try:.        
9b60: 73 57 6f 72 64 20 3d 20 6d 2e 67 72 6f 75 70 28  sWord = m.group(
9b70: 31 29 0a 20 20 20 20 20 20 20 20 6e 50 6f 73 20  1).        nPos 
9b80: 3d 20 6d 2e 73 74 61 72 74 28 31 29 20 2b 20 6e  = m.start(1) + n
9b90: 4f 66 66 73 65 74 0a 20 20 20 20 65 78 63 65 70  Offset.    excep
9ba0: 74 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  t:.        retur
9bb0: 6e 20 46 61 6c 73 65 0a 20 20 20 20 72 65 74 75  n False.    retu
9bc0: 72 6e 20 6d 6f 72 70 68 28 64 54 6f 6b 65 6e 50  rn morph(dTokenP
9bd0: 6f 73 2c 20 28 6e 50 6f 73 2c 20 73 57 6f 72 64  os, (nPos, sWord
9be0: 29 2c 20 73 50 61 74 74 65 72 6e 47 72 6f 75 70  ), sPatternGroup
9bf0: 31 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 47 72  1, sNegPatternGr
9c00: 6f 75 70 31 29 0a 0a 0a 0a 23 23 23 23 20 41 6e  oup1)....#### An
9c10: 61 6c 79 73 65 20 67 72 6f 75 70 73 20 66 6f 72  alyse groups for
9c20: 20 72 65 67 65 78 20 72 75 6c 65 73 0a 0a 64 65   regex rules..de
9c30: 66 20 64 69 73 70 6c 61 79 49 6e 66 6f 20 28 64  f displayInfo (d
9c40: 54 6f 6b 65 6e 50 6f 73 2c 20 74 57 6f 72 64 29  TokenPos, tWord)
9c50: 3a 0a 20 20 20 20 22 66 6f 72 20 64 65 62 75 67  :.    "for debug
9c60: 67 69 6e 67 3a 20 72 65 74 72 69 65 76 65 20 69  ging: retrieve i
9c70: 6e 66 6f 20 6f 66 20 77 6f 72 64 22 0a 20 20 20  nfo of word".   
9c80: 20 69 66 20 6e 6f 74 20 74 57 6f 72 64 3a 0a 20   if not tWord:. 
9c90: 20 20 20 20 20 20 20 65 63 68 6f 28 22 3e 20 6e         echo("> n
9ca0: 6f 74 68 69 6e 67 20 74 6f 20 66 69 6e 64 22 29  othing to find")
9cb0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
9cc0: 54 72 75 65 0a 20 20 20 20 6c 4d 6f 72 70 68 20  True.    lMorph 
9cd0: 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72  = _oSpellChecker
9ce0: 2e 67 65 74 4d 6f 72 70 68 28 74 57 6f 72 64 5b  .getMorph(tWord[
9cf0: 31 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c  1]).    if not l
9d00: 4d 6f 72 70 68 3a 0a 20 20 20 20 20 20 20 20 65  Morph:.        e
9d10: 63 68 6f 28 22 3e 20 6e 6f 74 20 69 6e 20 64 69  cho("> not in di
9d20: 63 74 69 6f 6e 61 72 79 22 29 0a 20 20 20 20 20  ctionary").     
9d30: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
9d40: 20 20 20 65 63 68 6f 28 22 54 4f 4b 45 4e 53 3a     echo("TOKENS:
9d50: 22 2c 20 64 54 6f 6b 65 6e 50 6f 73 29 0a 20 20  ", dTokenPos).  
9d60: 20 20 69 66 20 74 57 6f 72 64 5b 30 5d 20 69 6e    if tWord[0] in
9d70: 20 64 54 6f 6b 65 6e 50 6f 73 20 61 6e 64 20 22   dTokenPos and "
9d80: 6c 4d 6f 72 70 68 22 20 69 6e 20 64 54 6f 6b 65  lMorph" in dToke
9d90: 6e 50 6f 73 5b 74 57 6f 72 64 5b 30 5d 5d 3a 0a  nPos[tWord[0]]:.
9da0: 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 44 41          echo("DA
9db0: 3a 20 22 20 2b 20 73 74 72 28 64 54 6f 6b 65 6e  : " + str(dToken
9dc0: 50 6f 73 5b 74 57 6f 72 64 5b 30 5d 5d 5b 22 6c  Pos[tWord[0]]["l
9dd0: 4d 6f 72 70 68 22 5d 29 29 0a 20 20 20 20 65 63  Morph"])).    ec
9de0: 68 6f 28 22 46 53 41 3a 20 22 20 2b 20 73 74 72  ho("FSA: " + str
9df0: 28 6c 4d 6f 72 70 68 29 29 0a 20 20 20 20 72 65  (lMorph)).    re
9e00: 74 75 72 6e 20 54 72 75 65 0a 0a 0a 64 65 66 20  turn True...def 
9e10: 6d 6f 72 70 68 20 28 64 54 6f 6b 65 6e 50 6f 73  morph (dTokenPos
9e20: 2c 20 74 57 6f 72 64 2c 20 73 50 61 74 74 65 72  , tWord, sPatter
9e30: 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 3d 22  n, sNegPattern="
9e40: 22 2c 20 62 4e 6f 57 6f 72 64 3d 46 61 6c 73 65  ", bNoWord=False
9e50: 29 3a 0a 20 20 20 20 22 61 6e 61 6c 79 73 65 20  ):.    "analyse 
9e60: 61 20 74 75 70 6c 65 20 28 70 6f 73 69 74 69 6f  a tuple (positio
9e70: 6e 2c 20 77 6f 72 64 29 2c 20 72 65 74 75 72 6e  n, word), return
9e80: 73 20 54 72 75 65 20 69 66 20 6e 6f 74 20 73 4e  s True if not sN
9e90: 65 67 50 61 74 74 65 72 6e 20 69 6e 20 77 6f 72  egPattern in wor
9ea0: 64 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 61  d morphologies a
9eb0: 6e 64 20 73 50 61 74 74 65 72 6e 20 69 6e 20 77  nd sPattern in w
9ec0: 6f 72 64 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73  ord morphologies
9ed0: 20 28 64 69 73 61 6d 62 69 67 75 61 74 69 6f 6e   (disambiguation
9ee0: 20 6f 6e 29 22 0a 20 20 20 20 69 66 20 6e 6f 74   on)".    if not
9ef0: 20 74 57 6f 72 64 3a 0a 20 20 20 20 20 20 20 20   tWord:.        
9f00: 72 65 74 75 72 6e 20 62 4e 6f 57 6f 72 64 0a 20  return bNoWord. 
9f10: 20 20 20 6c 4d 6f 72 70 68 20 3d 20 64 54 6f 6b     lMorph = dTok
9f20: 65 6e 50 6f 73 5b 74 57 6f 72 64 5b 30 5d 5d 5b  enPos[tWord[0]][
9f30: 22 6c 4d 6f 72 70 68 22 5d 20 20 69 66 20 74 57  "lMorph"]  if tW
9f40: 6f 72 64 5b 30 5d 20 69 6e 20 64 54 6f 6b 65 6e  ord[0] in dToken
9f50: 50 6f 73 20 61 6e 64 20 22 6c 4d 6f 72 70 68 22  Pos and "lMorph"
9f60: 20 69 6e 20 64 54 6f 6b 65 6e 50 6f 73 5b 74 57   in dTokenPos[tW
9f70: 6f 72 64 5b 30 5d 5d 20 20 65 6c 73 65 20 5f 6f  ord[0]]  else _o
9f80: 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74  SpellChecker.get
9f90: 4d 6f 72 70 68 28 74 57 6f 72 64 5b 31 5d 29 0a  Morph(tWord[1]).
9fa0: 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70      if not lMorp
9fb0: 68 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  h:.        retur
9fc0: 6e 20 46 61 6c 73 65 0a 20 20 20 20 23 20 63 68  n False.    # ch
9fd0: 65 63 6b 20 6e 65 67 61 74 69 76 65 20 63 6f 6e  eck negative con
9fe0: 64 69 74 69 6f 6e 0a 20 20 20 20 69 66 20 73 4e  dition.    if sN
9ff0: 65 67 50 61 74 74 65 72 6e 3a 0a 20 20 20 20 20  egPattern:.     
a000: 20 20 20 69 66 20 73 4e 65 67 50 61 74 74 65 72     if sNegPatter
a010: 6e 20 3d 3d 20 22 2a 22 3a 0a 20 20 20 20 20 20  n == "*":.      
a020: 20 20 20 20 20 20 23 20 61 6c 6c 20 6d 6f 72 70        # all morp
a030: 68 20 6d 75 73 74 20 6d 61 74 63 68 20 73 50 61  h must match sPa
a040: 74 74 65 72 6e 0a 20 20 20 20 20 20 20 20 20 20  ttern.          
a050: 20 20 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e    zPattern = re.
a060: 63 6f 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e  compile(sPattern
a070: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  ).            re
a080: 74 75 72 6e 20 61 6c 6c 28 7a 50 61 74 74 65 72  turn all(zPatter
a090: 6e 2e 73 65 61 72 63 68 28 73 4d 6f 72 70 68 29  n.search(sMorph)
a0a0: 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20    for sMorph in 
a0b0: 6c 4d 6f 72 70 68 29 0a 20 20 20 20 20 20 20 20  lMorph).        
a0c0: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
a0d0: 20 20 7a 4e 65 67 50 61 74 74 65 72 6e 20 3d 20    zNegPattern = 
a0e0: 72 65 2e 63 6f 6d 70 69 6c 65 28 73 4e 65 67 50  re.compile(sNegP
a0f0: 61 74 74 65 72 6e 29 0a 20 20 20 20 20 20 20 20  attern).        
a100: 20 20 20 20 69 66 20 61 6e 79 28 7a 4e 65 67 50      if any(zNegP
a110: 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73 4d  attern.search(sM
a120: 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70  orph)  for sMorp
a130: 68 20 69 6e 20 6c 4d 6f 72 70 68 29 3a 0a 20 20  h in lMorph):.  
a140: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
a150: 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 23  turn False.    #
a160: 20 73 65 61 72 63 68 20 73 50 61 74 74 65 72 6e   search sPattern
a170: 0a 20 20 20 20 7a 50 61 74 74 65 72 6e 20 3d 20  .    zPattern = 
a180: 72 65 2e 63 6f 6d 70 69 6c 65 28 73 50 61 74 74  re.compile(sPatt
a190: 65 72 6e 29 0a 20 20 20 20 72 65 74 75 72 6e 20  ern).    return 
a1a0: 61 6e 79 28 7a 50 61 74 74 65 72 6e 2e 73 65 61  any(zPattern.sea
a1b0: 72 63 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72  rch(sMorph)  for
a1c0: 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70   sMorph in lMorp
a1d0: 68 29 0a 0a 0a 64 65 66 20 61 6e 61 6c 79 73 65  h)...def analyse
a1e0: 20 28 73 57 6f 72 64 2c 20 73 50 61 74 74 65 72   (sWord, sPatter
a1f0: 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 3d 22  n, sNegPattern="
a200: 22 29 3a 0a 20 20 20 20 22 61 6e 61 6c 79 73 65  "):.    "analyse
a210: 20 61 20 77 6f 72 64 2c 20 72 65 74 75 72 6e 73   a word, returns
a220: 20 54 72 75 65 20 69 66 20 6e 6f 74 20 73 4e 65   True if not sNe
a230: 67 50 61 74 74 65 72 6e 20 69 6e 20 77 6f 72 64  gPattern in word
a240: 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 61 6e   morphologies an
a250: 64 20 73 50 61 74 74 65 72 6e 20 69 6e 20 77 6f  d sPattern in wo
a260: 72 64 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20  rd morphologies 
a270: 28 64 69 73 61 6d 62 69 67 75 61 74 69 6f 6e 20  (disambiguation 
a280: 6f 66 66 29 22 0a 20 20 20 20 6c 4d 6f 72 70 68  off)".    lMorph
a290: 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65   = _oSpellChecke
a2a0: 72 2e 67 65 74 4d 6f 72 70 68 28 73 57 6f 72 64  r.getMorph(sWord
a2b0: 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f  ).    if not lMo
a2c0: 72 70 68 3a 0a 20 20 20 20 20 20 20 20 72 65 74  rph:.        ret
a2d0: 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 23 20  urn False.    # 
a2e0: 63 68 65 63 6b 20 6e 65 67 61 74 69 76 65 20 63  check negative c
a2f0: 6f 6e 64 69 74 69 6f 6e 0a 20 20 20 20 69 66 20  ondition.    if 
a300: 73 4e 65 67 50 61 74 74 65 72 6e 3a 0a 20 20 20  sNegPattern:.   
a310: 20 20 20 20 20 69 66 20 73 4e 65 67 50 61 74 74       if sNegPatt
a320: 65 72 6e 20 3d 3d 20 22 2a 22 3a 0a 20 20 20 20  ern == "*":.    
a330: 20 20 20 20 20 20 20 20 7a 50 61 74 74 65 72 6e          zPattern
a340: 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 50   = re.compile(sP
a350: 61 74 74 65 72 6e 29 0a 20 20 20 20 20 20 20 20  attern).        
a360: 20 20 20 20 72 65 74 75 72 6e 20 61 6c 6c 28 7a      return all(z
a370: 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73  Pattern.search(s
a380: 4d 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72  Morph)  for sMor
a390: 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29 0a 20 20  ph in lMorph).  
a3a0: 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20        else:.    
a3b0: 20 20 20 20 20 20 20 20 7a 4e 65 67 50 61 74 74          zNegPatt
a3c0: 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65  ern = re.compile
a3d0: 28 73 4e 65 67 50 61 74 74 65 72 6e 29 0a 20 20  (sNegPattern).  
a3e0: 20 20 20 20 20 20 20 20 20 20 69 66 20 61 6e 79            if any
a3f0: 28 7a 4e 65 67 50 61 74 74 65 72 6e 2e 73 65 61  (zNegPattern.sea
a400: 72 63 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72  rch(sMorph)  for
a410: 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70   sMorph in lMorp
a420: 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  h):.            
a430: 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65      return False
a440: 0a 20 20 20 20 23 20 73 65 61 72 63 68 20 73 50  .    # search sP
a450: 61 74 74 65 72 6e 0a 20 20 20 20 7a 50 61 74 74  attern.    zPatt
a460: 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65  ern = re.compile
a470: 28 73 50 61 74 74 65 72 6e 29 0a 20 20 20 20 72  (sPattern).    r
a480: 65 74 75 72 6e 20 61 6e 79 28 7a 50 61 74 74 65  eturn any(zPatte
a490: 72 6e 2e 73 65 61 72 63 68 28 73 4d 6f 72 70 68  rn.search(sMorph
a4a0: 29 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e  )  for sMorph in
a4b0: 20 6c 4d 6f 72 70 68 29 0a 0a 0a 23 23 23 23 20   lMorph)...#### 
a4c0: 41 6e 61 6c 79 73 65 20 74 6f 6b 65 6e 73 20 66  Analyse tokens f
a4d0: 6f 72 20 67 72 61 70 68 20 72 75 6c 65 73 0a 0a  or graph rules..
a4e0: 64 65 66 20 67 5f 76 61 6c 75 65 20 28 64 54 6f  def g_value (dTo
a4f0: 6b 65 6e 2c 20 73 56 61 6c 75 65 73 2c 20 6e 4c  ken, sValues, nL
a500: 65 66 74 3d 4e 6f 6e 65 2c 20 6e 52 69 67 68 74  eft=None, nRight
a510: 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 74 65 73  =None):.    "tes
a520: 74 20 69 66 20 3c 64 54 6f 6b 65 6e 5b 27 73 56  t if <dToken['sV
a530: 61 6c 75 65 27 5d 3e 20 69 73 20 69 6e 20 73 56  alue']> is in sV
a540: 61 6c 75 65 73 20 28 65 61 63 68 20 76 61 6c 75  alues (each valu
a550: 65 20 73 68 6f 75 6c 64 20 62 65 20 73 65 70 61  e should be sepa
a560: 72 61 74 65 64 20 77 69 74 68 20 7c 29 22 0a 20  rated with |)". 
a570: 20 20 20 73 56 61 6c 75 65 20 3d 20 22 7c 22 2b     sValue = "|"+
a580: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
a590: 2b 22 7c 22 20 20 69 66 20 6e 4c 65 66 74 20 69  +"|"  if nLeft i
a5a0: 73 20 4e 6f 6e 65 20 20 65 6c 73 65 20 22 7c 22  s None  else "|"
a5b0: 2b 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22  +dToken["sValue"
a5c0: 5d 5b 73 6c 69 63 65 28 6e 4c 65 66 74 2c 20 6e  ][slice(nLeft, n
a5d0: 52 69 67 68 74 29 5d 2b 22 7c 22 0a 20 20 20 20  Right)]+"|".    
a5e0: 69 66 20 73 56 61 6c 75 65 20 69 6e 20 73 56 61  if sValue in sVa
a5f0: 6c 75 65 73 3a 0a 20 20 20 20 20 20 20 20 72 65  lues:.        re
a600: 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 69 66  turn True.    if
a610: 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22   dToken["sValue"
a620: 5d 5b 30 3a 32 5d 2e 69 73 74 69 74 6c 65 28 29  ][0:2].istitle()
a630: 3a 20 23 20 77 65 20 74 65 73 74 20 6f 6e 6c 79  : # we test only
a640: 20 32 20 66 69 72 73 74 20 63 68 61 72 73 2c 20   2 first chars, 
a650: 74 6f 20 6d 61 6b 65 20 76 61 6c 69 64 20 77 6f  to make valid wo
a660: 72 64 73 20 73 75 63 68 20 61 73 20 22 4c 61 69  rds such as "Lai
a670: 73 73 65 7a 2d 6c 65 73 22 2c 20 22 50 61 73 73  ssez-les", "Pass
a680: 65 2d 70 61 72 74 6f 75 74 22 2e 0a 20 20 20 20  e-partout"..    
a690: 20 20 20 20 69 66 20 73 56 61 6c 75 65 2e 6c 6f      if sValue.lo
a6a0: 77 65 72 28 29 20 69 6e 20 73 56 61 6c 75 65 73  wer() in sValues
a6b0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  :.            re
a6c0: 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 65 6c  turn True.    el
a6d0: 69 66 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  if dToken["sValu
a6e0: 65 22 5d 2e 69 73 75 70 70 65 72 28 29 3a 0a 20  e"].isupper():. 
a6f0: 20 20 20 20 20 20 20 23 69 66 20 73 56 61 6c 75         #if sValu
a700: 65 2e 6c 6f 77 65 72 28 29 20 69 6e 20 73 56 61  e.lower() in sVa
a710: 6c 75 65 73 3a 0a 20 20 20 20 20 20 20 20 23 20  lues:.        # 
a720: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
a730: 20 20 20 20 20 20 20 73 56 61 6c 75 65 20 3d 20         sValue = 
a740: 22 7c 22 2b 73 56 61 6c 75 65 5b 31 3a 5d 2e 63  "|"+sValue[1:].c
a750: 61 70 69 74 61 6c 69 7a 65 28 29 0a 20 20 20 20  apitalize().    
a760: 20 20 20 20 69 66 20 73 56 61 6c 75 65 20 69 6e      if sValue in
a770: 20 73 56 61 6c 75 65 73 3a 0a 20 20 20 20 20 20   sValues:.      
a780: 20 20 20 20 20 20 72 65 74 75 72 6e 20 54 72 75        return Tru
a790: 65 0a 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c  e.    return Fal
a7a0: 73 65 0a 0a 0a 64 65 66 20 67 5f 6d 6f 72 70 68  se...def g_morph
a7b0: 20 28 64 54 6f 6b 65 6e 2c 20 73 50 61 74 74 65   (dToken, sPatte
a7c0: 72 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 3d  rn, sNegPattern=
a7d0: 22 22 2c 20 6e 4c 65 66 74 3d 4e 6f 6e 65 2c 20  "", nLeft=None, 
a7e0: 6e 52 69 67 68 74 3d 4e 6f 6e 65 2c 20 62 4d 65  nRight=None, bMe
a7f0: 6d 6f 72 69 7a 65 4d 6f 72 70 68 3d 54 72 75 65  morizeMorph=True
a800: 29 3a 0a 20 20 20 20 22 61 6e 61 6c 79 73 65 20  ):.    "analyse 
a810: 61 20 74 6f 6b 65 6e 2c 20 72 65 74 75 72 6e 20  a token, return 
a820: 54 72 75 65 20 69 66 20 3c 73 4e 65 67 50 61 74  True if <sNegPat
a830: 74 65 72 6e 3e 20 6e 6f 74 20 69 6e 20 6d 6f 72  tern> not in mor
a840: 70 68 6f 6c 6f 67 69 65 73 20 61 6e 64 20 3c 73  phologies and <s
a850: 50 61 74 74 65 72 6e 3e 20 69 6e 20 6d 6f 72 70  Pattern> in morp
a860: 68 6f 6c 6f 67 69 65 73 22 0a 20 20 20 20 69 66  hologies".    if
a870: 20 22 6c 4d 6f 72 70 68 22 20 69 6e 20 64 54 6f   "lMorph" in dTo
a880: 6b 65 6e 3a 0a 20 20 20 20 20 20 20 20 6c 4d 6f  ken:.        lMo
a890: 72 70 68 20 3d 20 64 54 6f 6b 65 6e 5b 22 6c 4d  rph = dToken["lM
a8a0: 6f 72 70 68 22 5d 0a 20 20 20 20 65 6c 73 65 3a  orph"].    else:
a8b0: 0a 20 20 20 20 20 20 20 20 69 66 20 6e 4c 65 66  .        if nLef
a8c0: 74 20 69 73 20 6e 6f 74 20 4e 6f 6e 65 3a 0a 20  t is not None:. 
a8d0: 20 20 20 20 20 20 20 20 20 20 20 6c 4d 6f 72 70             lMorp
a8e0: 68 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b  h = _oSpellCheck
a8f0: 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b  er.getMorph(dTok
a900: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 5b 73 6c 69  en["sValue"][sli
a910: 63 65 28 6e 4c 65 66 74 2c 20 6e 52 69 67 68 74  ce(nLeft, nRight
a920: 29 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  )]).            
a930: 69 66 20 62 4d 65 6d 6f 72 69 7a 65 4d 6f 72 70  if bMemorizeMorp
a940: 68 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  h:.             
a950: 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70     dToken["lMorp
a960: 68 22 5d 20 3d 20 6c 4d 6f 72 70 68 0a 20 20 20  h"] = lMorph.   
a970: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
a980: 20 20 20 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20         lMorph = 
a990: 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67  _oSpellChecker.g
a9a0: 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e 5b 22  etMorph(dToken["
a9b0: 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20 69 66  sValue"]).    if
a9c0: 20 6e 6f 74 20 6c 4d 6f 72 70 68 3a 0a 20 20 20   not lMorph:.   
a9d0: 20 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73       return Fals
a9e0: 65 0a 20 20 20 20 23 20 63 68 65 63 6b 20 6e 65  e.    # check ne
a9f0: 67 61 74 69 76 65 20 63 6f 6e 64 69 74 69 6f 6e  gative condition
aa00: 0a 20 20 20 20 69 66 20 73 4e 65 67 50 61 74 74  .    if sNegPatt
aa10: 65 72 6e 3a 0a 20 20 20 20 20 20 20 20 69 66 20  ern:.        if 
aa20: 73 4e 65 67 50 61 74 74 65 72 6e 20 3d 3d 20 22  sNegPattern == "
aa30: 2a 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  *":.            
aa40: 23 20 61 6c 6c 20 6d 6f 72 70 68 20 6d 75 73 74  # all morph must
aa50: 20 6d 61 74 63 68 20 73 50 61 74 74 65 72 6e 0a   match sPattern.
aa60: 20 20 20 20 20 20 20 20 20 20 20 20 7a 50 61 74              zPat
aa70: 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c  tern = re.compil
aa80: 65 28 73 50 61 74 74 65 72 6e 29 0a 20 20 20 20  e(sPattern).    
aa90: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 61          return a
aaa0: 6c 6c 28 7a 50 61 74 74 65 72 6e 2e 73 65 61 72  ll(zPattern.sear
aab0: 63 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72 20  ch(sMorph)  for 
aac0: 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68  sMorph in lMorph
aad0: 29 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a  ).        else:.
aae0: 20 20 20 20 20 20 20 20 20 20 20 20 7a 4e 65 67              zNeg
aaf0: 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d  Pattern = re.com
ab00: 70 69 6c 65 28 73 4e 65 67 50 61 74 74 65 72 6e  pile(sNegPattern
ab10: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  ).            if
ab20: 20 61 6e 79 28 7a 4e 65 67 50 61 74 74 65 72 6e   any(zNegPattern
ab30: 2e 73 65 61 72 63 68 28 73 4d 6f 72 70 68 29 20  .search(sMorph) 
ab40: 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c   for sMorph in l
ab50: 4d 6f 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20  Morph):.        
ab60: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 46          return F
ab70: 61 6c 73 65 0a 20 20 20 20 23 20 73 65 61 72 63  alse.    # searc
ab80: 68 20 73 50 61 74 74 65 72 6e 0a 20 20 20 20 7a  h sPattern.    z
ab90: 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d  Pattern = re.com
aba0: 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29 0a 20  pile(sPattern). 
abb0: 20 20 20 72 65 74 75 72 6e 20 61 6e 79 28 7a 50     return any(zP
abc0: 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73 4d  attern.search(sM
abd0: 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70  orph)  for sMorp
abe0: 68 20 69 6e 20 6c 4d 6f 72 70 68 29 0a 0a 0a 64  h in lMorph)...d
abf0: 65 66 20 67 5f 61 6e 61 6c 79 73 65 20 28 64 54  ef g_analyse (dT
ac00: 6f 6b 65 6e 2c 20 73 50 61 74 74 65 72 6e 2c 20  oken, sPattern, 
ac10: 73 4e 65 67 50 61 74 74 65 72 6e 3d 22 22 2c 20  sNegPattern="", 
ac20: 6e 4c 65 66 74 3d 4e 6f 6e 65 2c 20 6e 52 69 67  nLeft=None, nRig
ac30: 68 74 3d 4e 6f 6e 65 2c 20 62 4d 65 6d 6f 72 69  ht=None, bMemori
ac40: 7a 65 4d 6f 72 70 68 3d 54 72 75 65 29 3a 0a 20  zeMorph=True):. 
ac50: 20 20 20 22 61 6e 61 6c 79 73 65 20 61 20 74 6f     "analyse a to
ac60: 6b 65 6e 2c 20 72 65 74 75 72 6e 20 54 72 75 65  ken, return True
ac70: 20 69 66 20 3c 73 4e 65 67 50 61 74 74 65 72 6e   if <sNegPattern
ac80: 3e 20 6e 6f 74 20 69 6e 20 6d 6f 72 70 68 6f 6c  > not in morphol
ac90: 6f 67 69 65 73 20 61 6e 64 20 3c 73 50 61 74 74  ogies and <sPatt
aca0: 65 72 6e 3e 20 69 6e 20 6d 6f 72 70 68 6f 6c 6f  ern> in morpholo
acb0: 67 69 65 73 20 28 64 69 73 61 6d 62 69 67 75 61  gies (disambigua
acc0: 74 69 6f 6e 20 6f 66 66 29 22 0a 20 20 20 20 69  tion off)".    i
acd0: 66 20 6e 4c 65 66 74 20 69 73 20 6e 6f 74 20 4e  f nLeft is not N
ace0: 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 6c 4d 6f  one:.        lMo
acf0: 72 70 68 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65  rph = _oSpellChe
ad00: 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54  cker.getMorph(dT
ad10: 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 5b 73  oken["sValue"][s
ad20: 6c 69 63 65 28 6e 4c 65 66 74 2c 20 6e 52 69 67  lice(nLeft, nRig
ad30: 68 74 29 5d 29 0a 20 20 20 20 20 20 20 20 69 66  ht)]).        if
ad40: 20 62 4d 65 6d 6f 72 69 7a 65 4d 6f 72 70 68 3a   bMemorizeMorph:
ad50: 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f  .            dTo
ad60: 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20  ken["lMorph"] = 
ad70: 6c 4d 6f 72 70 68 0a 20 20 20 20 65 6c 73 65 3a  lMorph.    else:
ad80: 0a 20 20 20 20 20 20 20 20 6c 4d 6f 72 70 68 20  .        lMorph 
ad90: 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72  = _oSpellChecker
ada0: 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e  .getMorph(dToken
adb0: 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20  ["sValue"]).    
adc0: 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 3a 0a 20  if not lMorph:. 
add0: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 46 61         return Fa
ade0: 6c 73 65 0a 20 20 20 20 23 20 63 68 65 63 6b 20  lse.    # check 
adf0: 6e 65 67 61 74 69 76 65 20 63 6f 6e 64 69 74 69  negative conditi
ae00: 6f 6e 0a 20 20 20 20 69 66 20 73 4e 65 67 50 61  on.    if sNegPa
ae10: 74 74 65 72 6e 3a 0a 20 20 20 20 20 20 20 20 69  ttern:.        i
ae20: 66 20 73 4e 65 67 50 61 74 74 65 72 6e 20 3d 3d  f sNegPattern ==
ae30: 20 22 2a 22 3a 0a 20 20 20 20 20 20 20 20 20 20   "*":.          
ae40: 20 20 23 20 61 6c 6c 20 6d 6f 72 70 68 20 6d 75    # all morph mu
ae50: 73 74 20 6d 61 74 63 68 20 73 50 61 74 74 65 72  st match sPatter
ae60: 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 7a 50  n.            zP
ae70: 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70  attern = re.comp
ae80: 69 6c 65 28 73 50 61 74 74 65 72 6e 29 0a 20 20  ile(sPattern).  
ae90: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
aea0: 20 61 6c 6c 28 7a 50 61 74 74 65 72 6e 2e 73 65   all(zPattern.se
aeb0: 61 72 63 68 28 73 4d 6f 72 70 68 29 20 20 66 6f  arch(sMorph)  fo
aec0: 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72  r sMorph in lMor
aed0: 70 68 29 0a 20 20 20 20 20 20 20 20 65 6c 73 65  ph).        else
aee0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 7a 4e  :.            zN
aef0: 65 67 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63  egPattern = re.c
af00: 6f 6d 70 69 6c 65 28 73 4e 65 67 50 61 74 74 65  ompile(sNegPatte
af10: 72 6e 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  rn).            
af20: 69 66 20 61 6e 79 28 7a 4e 65 67 50 61 74 74 65  if any(zNegPatte
af30: 72 6e 2e 73 65 61 72 63 68 28 73 4d 6f 72 70 68  rn.search(sMorph
af40: 29 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e  )  for sMorph in
af50: 20 6c 4d 6f 72 70 68 29 3a 0a 20 20 20 20 20 20   lMorph):.      
af60: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
af70: 20 46 61 6c 73 65 0a 20 20 20 20 23 20 73 65 61   False.    # sea
af80: 72 63 68 20 73 50 61 74 74 65 72 6e 0a 20 20 20  rch sPattern.   
af90: 20 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63   zPattern = re.c
afa0: 6f 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29  ompile(sPattern)
afb0: 0a 20 20 20 20 72 65 74 75 72 6e 20 61 6e 79 28  .    return any(
afc0: 7a 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28  zPattern.search(
afd0: 73 4d 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f  sMorph)  for sMo
afe0: 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29 0a 0a  rph in lMorph)..
aff0: 0a 64 65 66 20 67 5f 6d 65 72 67 65 64 5f 61 6e  .def g_merged_an
b000: 61 6c 79 73 65 20 28 64 54 6f 6b 65 6e 31 2c 20  alyse (dToken1, 
b010: 64 54 6f 6b 65 6e 32 2c 20 63 4d 65 72 67 65 72  dToken2, cMerger
b020: 2c 20 73 50 61 74 74 65 72 6e 2c 20 73 4e 65 67  , sPattern, sNeg
b030: 50 61 74 74 65 72 6e 3d 22 22 2c 20 62 53 65 74  Pattern="", bSet
b040: 4d 6f 72 70 68 3d 54 72 75 65 29 3a 0a 20 20 20  Morph=True):.   
b050: 20 22 6d 65 72 67 65 20 74 77 6f 20 74 6f 6b 65   "merge two toke
b060: 6e 20 76 61 6c 75 65 73 2c 20 72 65 74 75 72 6e  n values, return
b070: 20 54 72 75 65 20 69 66 20 3c 73 4e 65 67 50 61   True if <sNegPa
b080: 74 74 65 72 6e 3e 20 6e 6f 74 20 69 6e 20 6d 6f  ttern> not in mo
b090: 72 70 68 6f 6c 6f 67 69 65 73 20 61 6e 64 20 3c  rphologies and <
b0a0: 73 50 61 74 74 65 72 6e 3e 20 69 6e 20 6d 6f 72  sPattern> in mor
b0b0: 70 68 6f 6c 6f 67 69 65 73 20 28 64 69 73 61 6d  phologies (disam
b0c0: 62 69 67 75 61 74 69 6f 6e 20 6f 66 66 29 22 0a  biguation off)".
b0d0: 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53      lMorph = _oS
b0e0: 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d  pellChecker.getM
b0f0: 6f 72 70 68 28 64 54 6f 6b 65 6e 31 5b 22 73 56  orph(dToken1["sV
b100: 61 6c 75 65 22 5d 20 2b 20 63 4d 65 72 67 65 72  alue"] + cMerger
b110: 20 2b 20 64 54 6f 6b 65 6e 32 5b 22 73 56 61 6c   + dToken2["sVal
b120: 75 65 22 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74  ue"]).    if not
b130: 20 6c 4d 6f 72 70 68 3a 0a 20 20 20 20 20 20 20   lMorph:.       
b140: 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20   return False.  
b150: 20 20 23 20 63 68 65 63 6b 20 6e 65 67 61 74 69    # check negati
b160: 76 65 20 63 6f 6e 64 69 74 69 6f 6e 0a 20 20 20  ve condition.   
b170: 20 69 66 20 73 4e 65 67 50 61 74 74 65 72 6e 3a   if sNegPattern:
b180: 0a 20 20 20 20 20 20 20 20 69 66 20 73 4e 65 67  .        if sNeg
b190: 50 61 74 74 65 72 6e 20 3d 3d 20 22 2a 22 3a 0a  Pattern == "*":.
b1a0: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 61 6c              # al
b1b0: 6c 20 6d 6f 72 70 68 20 6d 75 73 74 20 6d 61 74  l morph must mat
b1c0: 63 68 20 73 50 61 74 74 65 72 6e 0a 20 20 20 20  ch sPattern.    
b1d0: 20 20 20 20 20 20 20 20 7a 50 61 74 74 65 72 6e          zPattern
b1e0: 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 50   = re.compile(sP
b1f0: 61 74 74 65 72 6e 29 0a 20 20 20 20 20 20 20 20  attern).        
b200: 20 20 20 20 62 52 65 73 75 6c 74 20 3d 20 61 6c      bResult = al
b210: 6c 28 7a 50 61 74 74 65 72 6e 2e 73 65 61 72 63  l(zPattern.searc
b220: 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72 20 73  h(sMorph)  for s
b230: 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29  Morph in lMorph)
b240: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
b250: 62 52 65 73 75 6c 74 20 61 6e 64 20 62 53 65 74  bResult and bSet
b260: 4d 6f 72 70 68 3a 0a 20 20 20 20 20 20 20 20 20  Morph:.         
b270: 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 31 5b 22         dToken1["
b280: 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 4d 6f 72 70  lMorph"] = lMorp
b290: 68 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  h.            re
b2a0: 74 75 72 6e 20 62 52 65 73 75 6c 74 0a 20 20 20  turn bResult.   
b2b0: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
b2c0: 20 20 20 20 20 20 20 7a 4e 65 67 50 61 74 74 65         zNegPatte
b2d0: 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28  rn = re.compile(
b2e0: 73 4e 65 67 50 61 74 74 65 72 6e 29 0a 20 20 20  sNegPattern).   
b2f0: 20 20 20 20 20 20 20 20 20 69 66 20 61 6e 79 28           if any(
b300: 7a 4e 65 67 50 61 74 74 65 72 6e 2e 73 65 61 72  zNegPattern.sear
b310: 63 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72 20  ch(sMorph)  for 
b320: 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68  sMorph in lMorph
b330: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
b340: 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a     return False.
b350: 20 20 20 20 23 20 73 65 61 72 63 68 20 73 50 61      # search sPa
b360: 74 74 65 72 6e 0a 20 20 20 20 7a 50 61 74 74 65  ttern.    zPatte
b370: 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28  rn = re.compile(
b380: 73 50 61 74 74 65 72 6e 29 0a 20 20 20 20 62 52  sPattern).    bR
b390: 65 73 75 6c 74 20 3d 20 61 6e 79 28 7a 50 61 74  esult = any(zPat
b3a0: 74 65 72 6e 2e 73 65 61 72 63 68 28 73 4d 6f 72  tern.search(sMor
b3b0: 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70 68 20  ph)  for sMorph 
b3c0: 69 6e 20 6c 4d 6f 72 70 68 29 0a 20 20 20 20 69  in lMorph).    i
b3d0: 66 20 62 52 65 73 75 6c 74 20 61 6e 64 20 62 53  f bResult and bS
b3e0: 65 74 4d 6f 72 70 68 3a 0a 20 20 20 20 20 20 20  etMorph:.       
b3f0: 20 64 54 6f 6b 65 6e 31 5b 22 6c 4d 6f 72 70 68   dToken1["lMorph
b400: 22 5d 20 3d 20 6c 4d 6f 72 70 68 0a 20 20 20 20  "] = lMorph.    
b410: 72 65 74 75 72 6e 20 62 52 65 73 75 6c 74 0a 0a  return bResult..
b420: 0a 64 65 66 20 67 5f 74 61 67 5f 62 65 66 6f 72  .def g_tag_befor
b430: 65 20 28 64 54 6f 6b 65 6e 2c 20 64 54 61 67 73  e (dToken, dTags
b440: 2c 20 73 54 61 67 29 3a 0a 20 20 20 20 69 66 20  , sTag):.    if 
b450: 73 54 61 67 20 6e 6f 74 20 69 6e 20 64 54 61 67  sTag not in dTag
b460: 73 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  s:.        retur
b470: 6e 20 46 61 6c 73 65 0a 20 20 20 20 69 66 20 64  n False.    if d
b480: 54 6f 6b 65 6e 5b 22 69 22 5d 20 3e 20 64 54 61  Token["i"] > dTa
b490: 67 73 5b 73 54 61 67 5d 5b 30 5d 3a 0a 20 20 20  gs[sTag][0]:.   
b4a0: 20 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65       return True
b4b0: 0a 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73  .    return Fals
b4c0: 65 0a 0a 0a 64 65 66 20 67 5f 74 61 67 5f 61 66  e...def g_tag_af
b4d0: 74 65 72 20 28 64 54 6f 6b 65 6e 2c 20 64 54 61  ter (dToken, dTa
b4e0: 67 73 2c 20 73 54 61 67 29 3a 0a 20 20 20 20 69  gs, sTag):.    i
b4f0: 66 20 73 54 61 67 20 6e 6f 74 20 69 6e 20 64 54  f sTag not in dT
b500: 61 67 73 3a 0a 20 20 20 20 20 20 20 20 72 65 74  ags:.        ret
b510: 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 69 66  urn False.    if
b520: 20 64 54 6f 6b 65 6e 5b 22 69 22 5d 20 3c 20 64   dToken["i"] < d
b530: 54 61 67 73 5b 73 54 61 67 5d 5b 31 5d 3a 0a 20  Tags[sTag][1]:. 
b540: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54 72         return Tr
b550: 75 65 0a 20 20 20 20 72 65 74 75 72 6e 20 46 61  ue.    return Fa
b560: 6c 73 65 0a 0a 0a 64 65 66 20 67 5f 74 61 67 20  lse...def g_tag 
b570: 28 64 54 6f 6b 65 6e 2c 20 73 54 61 67 29 3a 0a  (dToken, sTag):.
b580: 20 20 20 20 72 65 74 75 72 6e 20 22 61 54 61 67      return "aTag
b590: 73 22 20 69 6e 20 64 54 6f 6b 65 6e 20 61 6e 64  s" in dToken and
b5a0: 20 73 54 61 67 20 69 6e 20 64 54 6f 6b 65 6e 5b   sTag in dToken[
b5b0: 22 61 54 61 67 73 22 5d 0a 0a 0a 64 65 66 20 67  "aTags"]...def g
b5c0: 5f 73 70 61 63 65 5f 62 65 74 77 65 65 6e 5f 74  _space_between_t
b5d0: 6f 6b 65 6e 73 20 28 64 54 6f 6b 65 6e 31 2c 20  okens (dToken1, 
b5e0: 64 54 6f 6b 65 6e 32 2c 20 6e 4d 69 6e 2c 20 6e  dToken2, nMin, n
b5f0: 4d 61 78 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 6e  Max=None):.    n
b600: 53 70 61 63 65 20 3d 20 64 54 6f 6b 65 6e 32 5b  Space = dToken2[
b610: 22 6e 53 74 61 72 74 22 5d 20 2d 20 64 54 6f 6b  "nStart"] - dTok
b620: 65 6e 31 5b 22 6e 45 6e 64 22 5d 0a 20 20 20 20  en1["nEnd"].    
b630: 69 66 20 6e 53 70 61 63 65 20 3c 20 6e 4d 69 6e  if nSpace < nMin
b640: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
b650: 20 46 61 6c 73 65 0a 20 20 20 20 69 66 20 6e 4d   False.    if nM
b660: 61 78 20 69 73 20 6e 6f 74 20 4e 6f 6e 65 20 61  ax is not None a
b670: 6e 64 20 6e 53 70 61 63 65 20 3e 20 6e 4d 61 78  nd nSpace > nMax
b680: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
b690: 20 46 61 6c 73 65 0a 20 20 20 20 72 65 74 75 72   False.    retur
b6a0: 6e 20 54 72 75 65 0a 0a 0a 64 65 66 20 67 5f 74  n True...def g_t
b6b0: 6f 6b 65 6e 20 28 6c 54 6f 6b 65 6e 2c 20 69 29  oken (lToken, i)
b6c0: 3a 0a 20 20 20 20 69 66 20 69 20 3c 20 30 3a 0a  :.    if i < 0:.
b6d0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 6c          return l
b6e0: 54 6f 6b 65 6e 5b 30 5d 0a 20 20 20 20 69 66 20  Token[0].    if 
b6f0: 69 20 3e 3d 20 6c 65 6e 28 6c 54 6f 6b 65 6e 29  i >= len(lToken)
b700: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
b710: 20 6c 54 6f 6b 65 6e 5b 2d 31 5d 0a 20 20 20 20   lToken[-1].    
b720: 72 65 74 75 72 6e 20 6c 54 6f 6b 65 6e 5b 69 5d  return lToken[i]
b730: 0a 0a 0a 0a 23 23 23 23 20 44 69 73 61 6d 62 69  ....#### Disambi
b740: 67 75 61 74 6f 72 20 66 6f 72 20 72 65 67 65 78  guator for regex
b750: 20 72 75 6c 65 73 0a 0a 64 65 66 20 73 65 6c 65   rules..def sele
b760: 63 74 20 28 64 54 6f 6b 65 6e 50 6f 73 2c 20 6e  ct (dTokenPos, n
b770: 50 6f 73 2c 20 73 57 6f 72 64 2c 20 73 50 61 74  Pos, sWord, sPat
b780: 74 65 72 6e 2c 20 6c 44 65 66 61 75 6c 74 3d 4e  tern, lDefault=N
b790: 6f 6e 65 29 3a 0a 20 20 20 20 22 44 69 73 61 6d  one):.    "Disam
b7a0: 62 69 67 75 61 74 69 6f 6e 3a 20 73 65 6c 65 63  biguation: selec
b7b0: 74 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 6f  t morphologies o
b7c0: 66 20 3c 73 57 6f 72 64 3e 20 6d 61 74 63 68 69  f <sWord> matchi
b7d0: 6e 67 20 3c 73 50 61 74 74 65 72 6e 3e 22 0a 20  ng <sPattern>". 
b7e0: 20 20 20 69 66 20 6e 6f 74 20 73 57 6f 72 64 3a     if not sWord:
b7f0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
b800: 54 72 75 65 0a 20 20 20 20 69 66 20 6e 50 6f 73  True.    if nPos
b810: 20 6e 6f 74 20 69 6e 20 64 54 6f 6b 65 6e 50 6f   not in dTokenPo
b820: 73 3a 0a 20 20 20 20 20 20 20 20 65 63 68 6f 28  s:.        echo(
b830: 22 45 72 72 6f 72 2e 20 54 68 65 72 65 20 73 68  "Error. There sh
b840: 6f 75 6c 64 20 62 65 20 61 20 74 6f 6b 65 6e 20  ould be a token 
b850: 61 74 20 74 68 69 73 20 70 6f 73 69 74 69 6f 6e  at this position
b860: 3a 20 22 2c 20 6e 50 6f 73 29 0a 20 20 20 20 20  : ", nPos).     
b870: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
b880: 20 20 20 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53 70     lMorph = _oSp
b890: 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f  ellChecker.getMo
b8a0: 72 70 68 28 73 57 6f 72 64 29 0a 20 20 20 20 69  rph(sWord).    i
b8b0: 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 20 6f 72 20  f not lMorph or 
b8c0: 6c 65 6e 28 6c 4d 6f 72 70 68 29 20 3d 3d 20 31  len(lMorph) == 1
b8d0: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
b8e0: 20 54 72 75 65 0a 20 20 20 20 6c 53 65 6c 65 63   True.    lSelec
b8f0: 74 20 3d 20 5b 20 73 4d 6f 72 70 68 20 20 66 6f  t = [ sMorph  fo
b900: 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72  r sMorph in lMor
b910: 70 68 20 20 69 66 20 72 65 2e 73 65 61 72 63 68  ph  if re.search
b920: 28 73 50 61 74 74 65 72 6e 2c 20 73 4d 6f 72 70  (sPattern, sMorp
b930: 68 29 20 5d 0a 20 20 20 20 69 66 20 6c 53 65 6c  h) ].    if lSel
b940: 65 63 74 3a 0a 20 20 20 20 20 20 20 20 69 66 20  ect:.        if 
b950: 6c 65 6e 28 6c 53 65 6c 65 63 74 29 20 21 3d 20  len(lSelect) != 
b960: 6c 65 6e 28 6c 4d 6f 72 70 68 29 3a 0a 20 20 20  len(lMorph):.   
b970: 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 50           dTokenP
b980: 6f 73 5b 6e 50 6f 73 5d 5b 22 6c 4d 6f 72 70 68  os[nPos]["lMorph
b990: 22 5d 20 3d 20 6c 53 65 6c 65 63 74 0a 20 20 20  "] = lSelect.   
b9a0: 20 65 6c 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a   elif lDefault:.
b9b0: 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 50 6f          dTokenPo
b9c0: 73 5b 6e 50 6f 73 5d 5b 22 6c 4d 6f 72 70 68 22  s[nPos]["lMorph"
b9d0: 5d 20 3d 20 6c 44 65 66 61 75 6c 74 0a 20 20 20  ] = lDefault.   
b9e0: 20 72 65 74 75 72 6e 20 54 72 75 65 0a 0a 0a 64   return True...d
b9f0: 65 66 20 65 78 63 6c 75 64 65 20 28 64 54 6f 6b  ef exclude (dTok
ba00: 65 6e 50 6f 73 2c 20 6e 50 6f 73 2c 20 73 57 6f  enPos, nPos, sWo
ba10: 72 64 2c 20 73 50 61 74 74 65 72 6e 2c 20 6c 44  rd, sPattern, lD
ba20: 65 66 61 75 6c 74 3d 4e 6f 6e 65 29 3a 0a 20 20  efault=None):.  
ba30: 20 20 22 44 69 73 61 6d 62 69 67 75 61 74 69 6f    "Disambiguatio
ba40: 6e 3a 20 65 78 63 6c 75 64 65 20 6d 6f 72 70 68  n: exclude morph
ba50: 6f 6c 6f 67 69 65 73 20 6f 66 20 3c 73 57 6f 72  ologies of <sWor
ba60: 64 3e 20 6d 61 74 63 68 69 6e 67 20 3c 73 50 61  d> matching <sPa
ba70: 74 74 65 72 6e 3e 22 0a 20 20 20 20 69 66 20 6e  ttern>".    if n
ba80: 6f 74 20 73 57 6f 72 64 3a 0a 20 20 20 20 20 20  ot sWord:.      
ba90: 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20 20    return True.  
baa0: 20 20 69 66 20 6e 50 6f 73 20 6e 6f 74 20 69 6e    if nPos not in
bab0: 20 64 54 6f 6b 65 6e 50 6f 73 3a 0a 20 20 20 20   dTokenPos:.    
bac0: 20 20 20 20 65 63 68 6f 28 22 45 72 72 6f 72 2e      echo("Error.
bad0: 20 54 68 65 72 65 20 73 68 6f 75 6c 64 20 62 65   There should be
bae0: 20 61 20 74 6f 6b 65 6e 20 61 74 20 74 68 69 73   a token at this
baf0: 20 70 6f 73 69 74 69 6f 6e 3a 20 22 2c 20 6e 50   position: ", nP
bb00: 6f 73 29 0a 20 20 20 20 20 20 20 20 72 65 74 75  os).        retu
bb10: 72 6e 20 54 72 75 65 0a 20 20 20 20 6c 4d 6f 72  rn True.    lMor
bb20: 70 68 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63  ph = _oSpellChec
bb30: 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 73 57 6f  ker.getMorph(sWo
bb40: 72 64 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c  rd).    if not l
bb50: 4d 6f 72 70 68 20 6f 72 20 6c 65 6e 28 6c 4d 6f  Morph or len(lMo
bb60: 72 70 68 29 20 3d 3d 20 31 3a 0a 20 20 20 20 20  rph) == 1:.     
bb70: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
bb80: 20 20 20 6c 53 65 6c 65 63 74 20 3d 20 5b 20 73     lSelect = [ s
bb90: 4d 6f 72 70 68 20 20 66 6f 72 20 73 4d 6f 72 70  Morph  for sMorp
bba0: 68 20 69 6e 20 6c 4d 6f 72 70 68 20 20 69 66 20  h in lMorph  if 
bbb0: 6e 6f 74 20 72 65 2e 73 65 61 72 63 68 28 73 50  not re.search(sP
bbc0: 61 74 74 65 72 6e 2c 20 73 4d 6f 72 70 68 29 20  attern, sMorph) 
bbd0: 5d 0a 20 20 20 20 69 66 20 6c 53 65 6c 65 63 74  ].    if lSelect
bbe0: 3a 0a 20 20 20 20 20 20 20 20 69 66 20 6c 65 6e  :.        if len
bbf0: 28 6c 53 65 6c 65 63 74 29 20 21 3d 20 6c 65 6e  (lSelect) != len
bc00: 28 6c 4d 6f 72 70 68 29 3a 0a 20 20 20 20 20 20  (lMorph):.      
bc10: 20 20 20 20 20 20 64 54 6f 6b 65 6e 50 6f 73 5b        dTokenPos[
bc20: 6e 50 6f 73 5d 5b 22 6c 4d 6f 72 70 68 22 5d 20  nPos]["lMorph"] 
bc30: 3d 20 6c 53 65 6c 65 63 74 0a 20 20 20 20 65 6c  = lSelect.    el
bc40: 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a 20 20 20  if lDefault:.   
bc50: 20 20 20 20 20 64 54 6f 6b 65 6e 50 6f 73 5b 6e       dTokenPos[n
bc60: 50 6f 73 5d 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d  Pos]["lMorph"] =
bc70: 20 6c 44 65 66 61 75 6c 74 0a 20 20 20 20 72 65   lDefault.    re
bc80: 74 75 72 6e 20 54 72 75 65 0a 0a 0a 64 65 66 20  turn True...def 
bc90: 64 65 66 69 6e 65 20 28 64 54 6f 6b 65 6e 50 6f  define (dTokenPo
bca0: 73 2c 20 6e 50 6f 73 2c 20 6c 4d 6f 72 70 68 29  s, nPos, lMorph)
bcb0: 3a 0a 20 20 20 20 22 44 69 73 61 6d 62 69 67 75  :.    "Disambigu
bcc0: 61 74 69 6f 6e 3a 20 73 65 74 20 6d 6f 72 70 68  ation: set morph
bcd0: 6f 6c 6f 67 69 65 73 20 6f 66 20 74 6f 6b 65 6e  ologies of token
bce0: 20 61 74 20 3c 6e 50 6f 73 3e 20 77 69 74 68 20   at <nPos> with 
bcf0: 3c 6c 4d 6f 72 70 68 3e 22 0a 20 20 20 20 69 66  <lMorph>".    if
bd00: 20 6e 50 6f 73 20 6e 6f 74 20 69 6e 20 64 54 6f   nPos not in dTo
bd10: 6b 65 6e 50 6f 73 3a 0a 20 20 20 20 20 20 20 20  kenPos:.        
bd20: 65 63 68 6f 28 22 45 72 72 6f 72 2e 20 54 68 65  echo("Error. The
bd30: 72 65 20 73 68 6f 75 6c 64 20 62 65 20 61 20 74  re should be a t
bd40: 6f 6b 65 6e 20 61 74 20 74 68 69 73 20 70 6f 73  oken at this pos
bd50: 69 74 69 6f 6e 3a 20 22 2c 20 6e 50 6f 73 29 0a  ition: ", nPos).
bd60: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54          return T
bd70: 72 75 65 0a 20 20 20 20 64 54 6f 6b 65 6e 50 6f  rue.    dTokenPo
bd80: 73 5b 6e 50 6f 73 5d 5b 22 6c 4d 6f 72 70 68 22  s[nPos]["lMorph"
bd90: 5d 20 3d 20 6c 4d 6f 72 70 68 0a 20 20 20 20 72  ] = lMorph.    r
bda0: 65 74 75 72 6e 20 54 72 75 65 0a 0a 0a 23 23 23  eturn True...###
bdb0: 23 20 44 69 73 61 6d 62 69 67 75 61 74 69 6f 6e  # Disambiguation
bdc0: 20 66 6f 72 20 67 72 61 70 68 20 72 75 6c 65 73   for graph rules
bdd0: 0a 0a 64 65 66 20 67 5f 73 65 6c 65 63 74 20 28  ..def g_select (
bde0: 64 54 6f 6b 65 6e 2c 20 73 50 61 74 74 65 72 6e  dToken, sPattern
bdf0: 2c 20 6c 44 65 66 61 75 6c 74 3d 4e 6f 6e 65 29  , lDefault=None)
be00: 3a 0a 20 20 20 20 22 73 65 6c 65 63 74 20 6d 6f  :.    "select mo
be10: 72 70 68 6f 6c 6f 67 69 65 73 20 66 6f 72 20 3c  rphologies for <
be20: 64 54 6f 6b 65 6e 3e 20 61 63 63 6f 72 64 69 6e  dToken> accordin
be30: 67 20 74 6f 20 3c 73 50 61 74 74 65 72 6e 3e 2c  g to <sPattern>,
be40: 20 61 6c 77 61 79 73 20 72 65 74 75 72 6e 20 54   always return T
be50: 72 75 65 22 0a 20 20 20 20 6c 4d 6f 72 70 68 20  rue".    lMorph 
be60: 3d 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68  = dToken["lMorph
be70: 22 5d 20 20 69 66 20 22 6c 4d 6f 72 70 68 22 20  "]  if "lMorph" 
be80: 69 6e 20 64 54 6f 6b 65 6e 20 20 65 6c 73 65 20  in dToken  else 
be90: 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67  _oSpellChecker.g
bea0: 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e 5b 22  etMorph(dToken["
beb0: 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20 69 66  sValue"]).    if
bec0: 20 6e 6f 74 20 6c 4d 6f 72 70 68 20 6f 72 20 6c   not lMorph or l
bed0: 65 6e 28 6c 4d 6f 72 70 68 29 20 3d 3d 20 31 3a  en(lMorph) == 1:
bee0: 0a 20 20 20 20 20 20 20 20 69 66 20 6c 44 65 66  .        if lDef
bef0: 61 75 6c 74 3a 0a 20 20 20 20 20 20 20 20 20 20  ault:.          
bf00: 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68    dToken["lMorph
bf10: 22 5d 20 3d 20 6c 44 65 66 61 75 6c 74 0a 20 20  "] = lDefault.  
bf20: 20 20 20 20 20 20 20 20 20 20 23 65 63 68 6f 28            #echo(
bf30: 22 44 41 3a 22 2c 20 64 54 6f 6b 65 6e 5b 22 73  "DA:", dToken["s
bf40: 56 61 6c 75 65 22 5d 2c 20 64 54 6f 6b 65 6e 5b  Value"], dToken[
bf50: 22 6c 4d 6f 72 70 68 22 5d 29 0a 20 20 20 20 20  "lMorph"]).     
bf60: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
bf70: 20 20 20 6c 53 65 6c 65 63 74 20 3d 20 5b 20 73     lSelect = [ s
bf80: 4d 6f 72 70 68 20 20 66 6f 72 20 73 4d 6f 72 70  Morph  for sMorp
bf90: 68 20 69 6e 20 6c 4d 6f 72 70 68 20 20 69 66 20  h in lMorph  if 
bfa0: 72 65 2e 73 65 61 72 63 68 28 73 50 61 74 74 65  re.search(sPatte
bfb0: 72 6e 2c 20 73 4d 6f 72 70 68 29 20 5d 0a 20 20  rn, sMorph) ].  
bfc0: 20 20 69 66 20 6c 53 65 6c 65 63 74 3a 0a 20 20    if lSelect:.  
bfd0: 20 20 20 20 20 20 69 66 20 6c 65 6e 28 6c 53 65        if len(lSe
bfe0: 6c 65 63 74 29 20 21 3d 20 6c 65 6e 28 6c 4d 6f  lect) != len(lMo
bff0: 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20  rph):.          
c000: 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68    dToken["lMorph
c010: 22 5d 20 3d 20 6c 53 65 6c 65 63 74 0a 20 20 20  "] = lSelect.   
c020: 20 65 6c 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a   elif lDefault:.
c030: 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22          dToken["
c040: 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 44 65 66 61  lMorph"] = lDefa
c050: 75 6c 74 0a 20 20 20 20 23 65 63 68 6f 28 22 44  ult.    #echo("D
c060: 41 3a 22 2c 20 64 54 6f 6b 65 6e 5b 22 73 56 61  A:", dToken["sVa
c070: 6c 75 65 22 5d 2c 20 64 54 6f 6b 65 6e 5b 22 6c  lue"], dToken["l
c080: 4d 6f 72 70 68 22 5d 29 0a 20 20 20 20 72 65 74  Morph"]).    ret
c090: 75 72 6e 20 54 72 75 65 0a 0a 0a 64 65 66 20 67  urn True...def g
c0a0: 5f 65 78 63 6c 75 64 65 20 28 64 54 6f 6b 65 6e  _exclude (dToken
c0b0: 2c 20 73 50 61 74 74 65 72 6e 2c 20 6c 44 65 66  , sPattern, lDef
c0c0: 61 75 6c 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20  ault=None):.    
c0d0: 22 73 65 6c 65 63 74 20 6d 6f 72 70 68 6f 6c 6f  "select morpholo
c0e0: 67 69 65 73 20 66 6f 72 20 3c 64 54 6f 6b 65 6e  gies for <dToken
c0f0: 3e 20 61 63 63 6f 72 64 69 6e 67 20 74 6f 20 3c  > according to <
c100: 73 50 61 74 74 65 72 6e 3e 2c 20 61 6c 77 61 79  sPattern>, alway
c110: 73 20 72 65 74 75 72 6e 20 54 72 75 65 22 0a 20  s return True". 
c120: 20 20 20 6c 4d 6f 72 70 68 20 3d 20 64 54 6f 6b     lMorph = dTok
c130: 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 20 69 66  en["lMorph"]  if
c140: 20 22 6c 4d 6f 72 70 68 22 20 69 6e 20 64 54 6f   "lMorph" in dTo
c150: 6b 65 6e 20 20 65 6c 73 65 20 5f 6f 53 70 65 6c  ken  else _oSpel
c160: 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70  lChecker.getMorp
c170: 68 28 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65  h(dToken["sValue
c180: 22 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c  "]).    if not l
c190: 4d 6f 72 70 68 20 6f 72 20 6c 65 6e 28 6c 4d 6f  Morph or len(lMo
c1a0: 72 70 68 29 20 3d 3d 20 31 3a 0a 20 20 20 20 20  rph) == 1:.     
c1b0: 20 20 20 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a     if lDefault:.
c1c0: 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b              dTok
c1d0: 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c  en["lMorph"] = l
c1e0: 44 65 66 61 75 6c 74 0a 20 20 20 20 20 20 20 20  Default.        
c1f0: 20 20 20 20 23 65 63 68 6f 28 22 44 41 3a 22 2c      #echo("DA:",
c200: 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22   dToken["sValue"
c210: 5d 2c 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70  ], dToken["lMorp
c220: 68 22 5d 29 0a 20 20 20 20 20 20 20 20 72 65 74  h"]).        ret
c230: 75 72 6e 20 54 72 75 65 0a 20 20 20 20 6c 53 65  urn True.    lSe
c240: 6c 65 63 74 20 3d 20 5b 20 73 4d 6f 72 70 68 20  lect = [ sMorph 
c250: 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c   for sMorph in l
c260: 4d 6f 72 70 68 20 20 69 66 20 6e 6f 74 20 72 65  Morph  if not re
c270: 2e 73 65 61 72 63 68 28 73 50 61 74 74 65 72 6e  .search(sPattern
c280: 2c 20 73 4d 6f 72 70 68 29 20 5d 0a 20 20 20 20  , sMorph) ].    
c290: 69 66 20 6c 53 65 6c 65 63 74 3a 0a 20 20 20 20  if lSelect:.    
c2a0: 20 20 20 20 69 66 20 6c 65 6e 28 6c 53 65 6c 65      if len(lSele
c2b0: 63 74 29 20 21 3d 20 6c 65 6e 28 6c 4d 6f 72 70  ct) != len(lMorp
c2c0: 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  h):.            
c2d0: 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d  dToken["lMorph"]
c2e0: 20 3d 20 6c 53 65 6c 65 63 74 0a 20 20 20 20 65   = lSelect.    e
c2f0: 6c 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a 20 20  lif lDefault:.  
c300: 20 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d        dToken["lM
c310: 6f 72 70 68 22 5d 20 3d 20 6c 44 65 66 61 75 6c  orph"] = lDefaul
c320: 74 0a 20 20 20 20 23 65 63 68 6f 28 22 44 41 3a  t.    #echo("DA:
c330: 22 2c 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  ", dToken["sValu
c340: 65 22 5d 2c 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f  e"], dToken["lMo
c350: 72 70 68 22 5d 29 0a 20 20 20 20 72 65 74 75 72  rph"]).    retur
c360: 6e 20 54 72 75 65 0a 0a 0a 64 65 66 20 67 5f 64  n True...def g_d
c370: 65 66 69 6e 65 20 28 64 54 6f 6b 65 6e 2c 20 6c  efine (dToken, l
c380: 4d 6f 72 70 68 29 3a 0a 20 20 20 20 22 73 65 74  Morph):.    "set
c390: 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 6f 66   morphologies of
c3a0: 20 3c 64 54 6f 6b 65 6e 3e 2c 20 61 6c 77 61 79   <dToken>, alway
c3b0: 73 20 72 65 74 75 72 6e 20 54 72 75 65 22 0a 20  s return True". 
c3c0: 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70     dToken["lMorp
c3d0: 68 22 5d 20 3d 20 6c 4d 6f 72 70 68 0a 20 20 20  h"] = lMorph.   
c3e0: 20 23 65 63 68 6f 28 22 44 41 3a 22 2c 20 64 54   #echo("DA:", dT
c3f0: 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2c 20  oken["sValue"], 
c400: 6c 4d 6f 72 70 68 29 0a 20 20 20 20 72 65 74 75  lMorph).    retu
c410: 72 6e 20 54 72 75 65 0a 0a 0a 64 65 66 20 67 5f  rn True...def g_
c420: 64 65 66 69 6e 65 5f 66 72 6f 6d 20 28 64 54 6f  define_from (dTo
c430: 6b 65 6e 2c 20 6e 4c 65 66 74 3d 4e 6f 6e 65 2c  ken, nLeft=None,
c440: 20 6e 52 69 67 68 74 3d 4e 6f 6e 65 29 3a 0a 20   nRight=None):. 
c450: 20 20 20 69 66 20 6e 4c 65 66 74 20 69 73 20 6e     if nLeft is n
c460: 6f 74 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20  ot None:.       
c470: 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22   dToken["lMorph"
c480: 5d 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b  ] = _oSpellCheck
c490: 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b  er.getMorph(dTok
c4a0: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 5b 73 6c 69  en["sValue"][sli
c4b0: 63 65 28 6e 4c 65 66 74 2c 20 6e 52 69 67 68 74  ce(nLeft, nRight
c4c0: 29 5d 29 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20  )]).    else:.  
c4d0: 20 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d        dToken["lM
c4e0: 6f 72 70 68 22 5d 20 3d 20 5f 6f 53 70 65 6c 6c  orph"] = _oSpell
c4f0: 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68  Checker.getMorph
c500: 28 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22  (dToken["sValue"
c510: 5d 29 0a 20 20 20 20 72 65 74 75 72 6e 20 54 72  ]).    return Tr
c520: 75 65 0a 0a 0a 0a 23 23 23 23 20 47 52 41 4d 4d  ue....#### GRAMM
c530: 41 52 20 43 48 45 43 4b 45 52 20 50 4c 55 47 49  AR CHECKER PLUGI
c540: 4e 53 0a 0a 24 7b 70 6c 75 67 69 6e 73 7d 0a 0a  NS..${plugins}..
c550: 0a 23 23 23 23 20 43 41 4c 4c 41 42 4c 45 53 20  .#### CALLABLES 
c560: 46 4f 52 20 52 45 47 45 58 20 52 55 4c 45 53 20  FOR REGEX RULES 
c570: 28 67 65 6e 65 72 61 74 65 64 20 63 6f 64 65 29  (generated code)
c580: 0a 0a 24 7b 63 61 6c 6c 61 62 6c 65 73 7d 0a 0a  ..${callables}..
c590: 0a 23 23 23 23 20 43 41 4c 4c 41 42 4c 45 53 20  .#### CALLABLES 
c5a0: 46 4f 52 20 47 52 41 50 48 20 52 55 4c 45 53 20  FOR GRAPH RULES 
c5b0: 28 67 65 6e 65 72 61 74 65 64 20 63 6f 64 65 29  (generated code)
c5c0: 0a 0a 24 7b 67 72 61 70 68 5f 63 61 6c 6c 61 62  ..${graph_callab
c5d0: 6c 65 73 7d 0a                                   les}.