Grammalecte  Hex Artifact Content

Artifact cb20ef452b81b57abbb6a59e7bd107e551aaf938721229e45c6aece40c21ed7f:


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 0a 66  o import echo..f
00d0: 72 6f 6d 20 2e 2e 20 69 6d 70 6f 72 74 20 74 65  rom .. import te
00e0: 78 74 0a 0a 66 72 6f 6d 20 2e 20 69 6d 70 6f 72  xt..from . impor
00f0: 74 20 67 63 5f 6f 70 74 69 6f 6e 73 0a 0a 74 72  t gc_options..tr
0100: 79 3a 0a 20 20 20 20 23 20 4c 69 62 72 65 4f 66  y:.    # LibreOf
0110: 66 69 63 65 20 2f 20 4f 70 65 6e 4f 66 66 69 63  fice / OpenOffic
0120: 65 0a 20 20 20 20 66 72 6f 6d 20 63 6f 6d 2e 73  e.    from com.s
0130: 75 6e 2e 73 74 61 72 2e 6c 69 6e 67 75 69 73 74  un.star.linguist
0140: 69 63 32 20 69 6d 70 6f 72 74 20 53 69 6e 67 6c  ic2 import Singl
0150: 65 50 72 6f 6f 66 72 65 61 64 69 6e 67 45 72 72  eProofreadingErr
0160: 6f 72 0a 20 20 20 20 66 72 6f 6d 20 63 6f 6d 2e  or.    from com.
0170: 73 75 6e 2e 73 74 61 72 2e 74 65 78 74 2e 54 65  sun.star.text.Te
0180: 78 74 4d 61 72 6b 75 70 54 79 70 65 20 69 6d 70  xtMarkupType imp
0190: 6f 72 74 20 50 52 4f 4f 46 52 45 41 44 49 4e 47  ort PROOFREADING
01a0: 0a 20 20 20 20 66 72 6f 6d 20 63 6f 6d 2e 73 75  .    from com.su
01b0: 6e 2e 73 74 61 72 2e 62 65 61 6e 73 20 69 6d 70  n.star.beans imp
01c0: 6f 72 74 20 50 72 6f 70 65 72 74 79 56 61 6c 75  ort PropertyValu
01d0: 65 0a 20 20 20 20 23 69 6d 70 6f 72 74 20 6c 69  e.    #import li
01e0: 67 68 74 70 72 6f 6f 66 5f 68 61 6e 64 6c 65 72  ghtproof_handler
01f0: 5f 24 7b 69 6d 70 6c 6e 61 6d 65 7d 20 61 73 20  _${implname} as 
0200: 6f 70 74 0a 20 20 20 20 5f 62 57 72 69 74 65 72  opt.    _bWriter
0210: 45 72 72 6f 72 20 3d 20 54 72 75 65 0a 65 78 63  Error = True.exc
0220: 65 70 74 20 49 6d 70 6f 72 74 45 72 72 6f 72 3a  ept ImportError:
0230: 0a 20 20 20 20 5f 62 57 72 69 74 65 72 45 72 72  .    _bWriterErr
0240: 6f 72 20 3d 20 46 61 6c 73 65 0a 0a 0a 5f 5f 61  or = False...__a
0250: 6c 6c 5f 5f 20 3d 20 5b 20 22 6c 61 6e 67 22 2c  ll__ = [ "lang",
0260: 20 22 6c 6f 63 61 6c 65 73 22 2c 20 22 70 6b 67   "locales", "pkg
0270: 22 2c 20 22 6e 61 6d 65 22 2c 20 22 76 65 72 73  ", "name", "vers
0280: 69 6f 6e 22 2c 20 22 61 75 74 68 6f 72 22 2c 20  ion", "author", 
0290: 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20 22 6c  \.            "l
02a0: 6f 61 64 22 2c 20 22 70 61 72 73 65 22 2c 20 22  oad", "parse", "
02b0: 67 65 74 53 70 65 6c 6c 43 68 65 63 6b 65 72 22  getSpellChecker"
02c0: 2c 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20  , \.            
02d0: 22 73 65 74 4f 70 74 69 6f 6e 22 2c 20 22 73 65  "setOption", "se
02e0: 74 4f 70 74 69 6f 6e 73 22 2c 20 22 67 65 74 4f  tOptions", "getO
02f0: 70 74 69 6f 6e 73 22 2c 20 22 67 65 74 44 65 66  ptions", "getDef
0300: 61 75 6c 74 4f 70 74 69 6f 6e 73 22 2c 20 22 67  aultOptions", "g
0310: 65 74 4f 70 74 69 6f 6e 73 4c 61 62 65 6c 73 22  etOptionsLabels"
0320: 2c 20 22 72 65 73 65 74 4f 70 74 69 6f 6e 73 22  , "resetOptions"
0330: 2c 20 22 64 69 73 70 6c 61 79 4f 70 74 69 6f 6e  , "displayOption
0340: 73 22 2c 20 5c 0a 20 20 20 20 20 20 20 20 20 20  s", \.          
0350: 20 20 22 69 67 6e 6f 72 65 52 75 6c 65 22 2c 20    "ignoreRule", 
0360: 22 72 65 73 65 74 49 67 6e 6f 72 65 52 75 6c 65  "resetIgnoreRule
0370: 73 22 2c 20 22 72 65 61 63 74 69 76 61 74 65 52  s", "reactivateR
0380: 75 6c 65 22 2c 20 22 6c 69 73 74 52 75 6c 65 73  ule", "listRules
0390: 22 2c 20 22 64 69 73 70 6c 61 79 52 75 6c 65 73  ", "displayRules
03a0: 22 20 5d 0a 0a 5f 5f 76 65 72 73 69 6f 6e 5f 5f  " ]..__version__
03b0: 20 3d 20 22 24 7b 76 65 72 73 69 6f 6e 7d 22 0a   = "${version}".
03c0: 0a 0a 6c 61 6e 67 20 3d 20 22 24 7b 6c 61 6e 67  ..lang = "${lang
03d0: 7d 22 0a 6c 6f 63 61 6c 65 73 20 3d 20 24 7b 6c  }".locales = ${l
03e0: 6f 63 7d 0a 70 6b 67 20 3d 20 22 24 7b 69 6d 70  oc}.pkg = "${imp
03f0: 6c 6e 61 6d 65 7d 22 0a 6e 61 6d 65 20 3d 20 22  lname}".name = "
0400: 24 7b 6e 61 6d 65 7d 22 0a 76 65 72 73 69 6f 6e  ${name}".version
0410: 20 3d 20 22 24 7b 76 65 72 73 69 6f 6e 7d 22 0a   = "${version}".
0420: 61 75 74 68 6f 72 20 3d 20 22 24 7b 61 75 74 68  author = "${auth
0430: 6f 72 7d 22 0a 0a 23 20 4d 6f 64 75 6c 65 73 0a  or}"..# Modules.
0440: 5f 72 75 6c 65 73 20 3d 20 4e 6f 6e 65 20 20 20  _rules = None   
0450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0460: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 6d 6f              # mo
0470: 64 75 6c 65 20 67 63 5f 72 75 6c 65 73 0a 5f 72  dule gc_rules._r
0480: 75 6c 65 73 5f 67 72 61 70 68 20 3d 20 4e 6f 6e  ules_graph = Non
0490: 65 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e               
04a0: 20 20 20 20 20 20 20 20 20 20 23 20 6d 6f 64 75            # modu
04b0: 6c 65 20 67 63 5f 72 75 6c 65 73 5f 67 72 61 70  le gc_rules_grap
04c0: 68 0a 0a 23 20 44 61 74 61 0a 5f 73 41 70 70 43  h..# Data._sAppC
04d0: 6f 6e 74 65 78 74 20 3d 20 22 22 20 20 20 20 20  ontext = ""     
04e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
04f0: 20 20 20 20 20 20 23 20 77 68 61 74 20 73 6f 66        # what sof
0500: 74 77 61 72 65 20 69 73 20 72 75 6e 6e 69 6e 67  tware is running
0510: 0a 5f 64 4f 70 74 69 6f 6e 73 20 3d 20 4e 6f 6e  ._dOptions = Non
0520: 65 0a 5f 64 4f 70 74 69 6f 6e 73 43 6f 6c 6f 72  e._dOptionsColor
0530: 73 20 3d 20 4e 6f 6e 65 0a 5f 6f 53 70 65 6c 6c  s = None._oSpell
0540: 43 68 65 63 6b 65 72 20 3d 20 4e 6f 6e 65 0a 5f  Checker = None._
0550: 6f 54 6f 6b 65 6e 69 7a 65 72 20 3d 20 4e 6f 6e  oTokenizer = Non
0560: 65 0a 5f 61 49 67 6e 6f 72 65 64 52 75 6c 65 73  e._aIgnoredRules
0570: 20 3d 20 73 65 74 28 29 0a 0a 0a 0a 23 23 23 23   = set()....####
0580: 20 49 6e 69 74 69 61 6c 69 7a 61 74 69 6f 6e 0a   Initialization.
0590: 0a 64 65 66 20 6c 6f 61 64 20 28 73 43 6f 6e 74  .def load (sCont
05a0: 65 78 74 3d 22 50 79 74 68 6f 6e 22 2c 20 73 43  ext="Python", sC
05b0: 6f 6c 6f 72 54 79 70 65 3d 22 61 52 47 42 22 29  olorType="aRGB")
05c0: 3a 0a 20 20 20 20 22 69 6e 69 74 69 61 6c 69 7a  :.    "initializ
05d0: 61 74 69 6f 6e 20 6f 66 20 74 68 65 20 67 72 61  ation of the gra
05e0: 6d 6d 61 72 20 63 68 65 63 6b 65 72 22 0a 20 20  mmar checker".  
05f0: 20 20 67 6c 6f 62 61 6c 20 5f 6f 53 70 65 6c 6c    global _oSpell
0600: 43 68 65 63 6b 65 72 0a 20 20 20 20 67 6c 6f 62  Checker.    glob
0610: 61 6c 20 5f 73 41 70 70 43 6f 6e 74 65 78 74 0a  al _sAppContext.
0620: 20 20 20 20 67 6c 6f 62 61 6c 20 5f 64 4f 70 74      global _dOpt
0630: 69 6f 6e 73 0a 20 20 20 20 67 6c 6f 62 61 6c 20  ions.    global 
0640: 5f 64 4f 70 74 69 6f 6e 73 43 6f 6c 6f 72 73 0a  _dOptionsColors.
0650: 20 20 20 20 67 6c 6f 62 61 6c 20 5f 6f 54 6f 6b      global _oTok
0660: 65 6e 69 7a 65 72 0a 20 20 20 20 74 72 79 3a 0a  enizer.    try:.
0670: 20 20 20 20 20 20 20 20 5f 6f 53 70 65 6c 6c 43          _oSpellC
0680: 68 65 63 6b 65 72 20 3d 20 53 70 65 6c 6c 43 68  hecker = SpellCh
0690: 65 63 6b 65 72 28 22 24 7b 6c 61 6e 67 7d 22 2c  ecker("${lang}",
06a0: 20 22 24 7b 64 69 63 5f 6d 61 69 6e 5f 66 69 6c   "${dic_main_fil
06b0: 65 6e 61 6d 65 5f 70 79 7d 22 2c 20 22 24 7b 64  ename_py}", "${d
06c0: 69 63 5f 63 6f 6d 6d 75 6e 69 74 79 5f 66 69 6c  ic_community_fil
06d0: 65 6e 61 6d 65 5f 70 79 7d 22 2c 20 22 24 7b 64  ename_py}", "${d
06e0: 69 63 5f 70 65 72 73 6f 6e 61 6c 5f 66 69 6c 65  ic_personal_file
06f0: 6e 61 6d 65 5f 70 79 7d 22 29 0a 20 20 20 20 20  name_py}").     
0700: 20 20 20 5f 73 41 70 70 43 6f 6e 74 65 78 74 20     _sAppContext 
0710: 3d 20 73 43 6f 6e 74 65 78 74 0a 20 20 20 20 20  = sContext.     
0720: 20 20 20 5f 64 4f 70 74 69 6f 6e 73 20 3d 20 67     _dOptions = g
0730: 63 5f 6f 70 74 69 6f 6e 73 2e 67 65 74 4f 70 74  c_options.getOpt
0740: 69 6f 6e 73 28 73 43 6f 6e 74 65 78 74 29 2e 63  ions(sContext).c
0750: 6f 70 79 28 29 20 20 20 23 20 64 75 70 6c 69 63  opy()   # duplic
0760: 61 74 69 6f 6e 20 6e 65 63 65 73 73 61 72 79 2c  ation necessary,
0770: 20 74 6f 20 62 65 20 61 62 6c 65 20 74 6f 20 72   to be able to r
0780: 65 73 65 74 20 74 6f 20 64 65 66 61 75 6c 74 0a  eset to default.
0790: 20 20 20 20 20 20 20 20 5f 64 4f 70 74 69 6f 6e          _dOption
07a0: 73 43 6f 6c 6f 72 73 20 3d 20 67 63 5f 6f 70 74  sColors = gc_opt
07b0: 69 6f 6e 73 2e 67 65 74 4f 70 74 69 6f 6e 73 43  ions.getOptionsC
07c0: 6f 6c 6f 72 73 28 73 43 6f 6e 74 65 78 74 2c 20  olors(sContext, 
07d0: 73 43 6f 6c 6f 72 54 79 70 65 29 0a 20 20 20 20  sColorType).    
07e0: 20 20 20 20 5f 6f 54 6f 6b 65 6e 69 7a 65 72 20      _oTokenizer 
07f0: 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72  = _oSpellChecker
0800: 2e 67 65 74 54 6f 6b 65 6e 69 7a 65 72 28 29 0a  .getTokenizer().
0810: 20 20 20 20 20 20 20 20 5f 6f 53 70 65 6c 6c 43          _oSpellC
0820: 68 65 63 6b 65 72 2e 61 63 74 69 76 61 74 65 53  hecker.activateS
0830: 74 6f 72 61 67 65 28 29 0a 20 20 20 20 65 78 63  torage().    exc
0840: 65 70 74 3a 0a 20 20 20 20 20 20 20 20 74 72 61  ept:.        tra
0850: 63 65 62 61 63 6b 2e 70 72 69 6e 74 5f 65 78 63  ceback.print_exc
0860: 28 29 0a 0a 0a 64 65 66 20 67 65 74 53 70 65 6c  ()...def getSpel
0870: 6c 43 68 65 63 6b 65 72 20 28 29 3a 0a 20 20 20  lChecker ():.   
0880: 20 22 72 65 74 75 72 6e 20 74 68 65 20 73 70 65   "return the spe
0890: 6c 6c 63 68 65 63 6b 65 72 20 6f 62 6a 65 63 74  llchecker object
08a0: 22 0a 20 20 20 20 72 65 74 75 72 6e 20 5f 6f 53  ".    return _oS
08b0: 70 65 6c 6c 43 68 65 63 6b 65 72 0a 0a 0a 23 23  pellChecker...##
08c0: 23 23 20 52 75 6c 65 73 0a 0a 64 65 66 20 5f 67  ## Rules..def _g
08d0: 65 74 52 75 6c 65 73 20 28 62 50 61 72 61 67 72  etRules (bParagr
08e0: 61 70 68 29 3a 0a 20 20 20 20 74 72 79 3a 0a 20  aph):.    try:. 
08f0: 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 62 50         if not bP
0900: 61 72 61 67 72 61 70 68 3a 0a 20 20 20 20 20 20  aragraph:.      
0910: 20 20 20 20 20 20 72 65 74 75 72 6e 20 5f 72 75        return _ru
0920: 6c 65 73 2e 6c 53 65 6e 74 65 6e 63 65 52 75 6c  les.lSentenceRul
0930: 65 73 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  es.        retur
0940: 6e 20 5f 72 75 6c 65 73 2e 6c 50 61 72 61 67 72  n _rules.lParagr
0950: 61 70 68 52 75 6c 65 73 0a 20 20 20 20 65 78 63  aphRules.    exc
0960: 65 70 74 3a 0a 20 20 20 20 20 20 20 20 5f 6c 6f  ept:.        _lo
0970: 61 64 52 75 6c 65 73 28 29 0a 20 20 20 20 69 66  adRules().    if
0980: 20 6e 6f 74 20 62 50 61 72 61 67 72 61 70 68 3a   not bParagraph:
0990: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
09a0: 5f 72 75 6c 65 73 2e 6c 53 65 6e 74 65 6e 63 65  _rules.lSentence
09b0: 52 75 6c 65 73 0a 20 20 20 20 72 65 74 75 72 6e  Rules.    return
09c0: 20 5f 72 75 6c 65 73 2e 6c 50 61 72 61 67 72 61   _rules.lParagra
09d0: 70 68 52 75 6c 65 73 0a 0a 0a 64 65 66 20 5f 6c  phRules...def _l
09e0: 6f 61 64 52 75 6c 65 73 20 28 29 3a 0a 20 20 20  oadRules ():.   
09f0: 20 66 72 6f 6d 20 2e 20 69 6d 70 6f 72 74 20 67   from . import g
0a00: 63 5f 72 75 6c 65 73 0a 20 20 20 20 66 72 6f 6d  c_rules.    from
0a10: 20 2e 20 69 6d 70 6f 72 74 20 67 63 5f 72 75 6c   . import gc_rul
0a20: 65 73 5f 67 72 61 70 68 0a 20 20 20 20 67 6c 6f  es_graph.    glo
0a30: 62 61 6c 20 5f 72 75 6c 65 73 0a 20 20 20 20 67  bal _rules.    g
0a40: 6c 6f 62 61 6c 20 5f 72 75 6c 65 73 5f 67 72 61  lobal _rules_gra
0a50: 70 68 0a 20 20 20 20 5f 72 75 6c 65 73 20 3d 20  ph.    _rules = 
0a60: 67 63 5f 72 75 6c 65 73 0a 20 20 20 20 5f 72 75  gc_rules.    _ru
0a70: 6c 65 73 5f 67 72 61 70 68 20 3d 20 67 63 5f 72  les_graph = gc_r
0a80: 75 6c 65 73 5f 67 72 61 70 68 0a 20 20 20 20 23  ules_graph.    #
0a90: 20 63 6f 6d 70 69 6c 65 20 72 75 6c 65 73 20 72   compile rules r
0aa0: 65 67 65 78 0a 20 20 20 20 66 6f 72 20 73 4f 70  egex.    for sOp
0ab0: 74 69 6f 6e 2c 20 6c 52 75 6c 65 47 72 6f 75 70  tion, lRuleGroup
0ac0: 20 69 6e 20 63 68 61 69 6e 28 5f 72 75 6c 65 73   in chain(_rules
0ad0: 2e 6c 50 61 72 61 67 72 61 70 68 52 75 6c 65 73  .lParagraphRules
0ae0: 2c 20 5f 72 75 6c 65 73 2e 6c 53 65 6e 74 65 6e  , _rules.lSenten
0af0: 63 65 52 75 6c 65 73 29 3a 0a 20 20 20 20 20 20  ceRules):.      
0b00: 20 20 69 66 20 73 4f 70 74 69 6f 6e 20 21 3d 20    if sOption != 
0b10: 22 40 40 40 40 22 3a 0a 20 20 20 20 20 20 20 20  "@@@@":.        
0b20: 20 20 20 20 66 6f 72 20 61 52 75 6c 65 20 69 6e      for aRule in
0b30: 20 6c 52 75 6c 65 47 72 6f 75 70 3a 0a 20 20 20   lRuleGroup:.   
0b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 74 72 79               try
0b50: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
0b60: 20 20 20 20 20 20 61 52 75 6c 65 5b 30 5d 20 3d        aRule[0] =
0b70: 20 72 65 2e 63 6f 6d 70 69 6c 65 28 61 52 75 6c   re.compile(aRul
0b80: 65 5b 30 5d 29 0a 20 20 20 20 20 20 20 20 20 20  e[0]).          
0b90: 20 20 20 20 20 20 65 78 63 65 70 74 20 28 49 6e        except (In
0ba0: 64 65 78 45 72 72 6f 72 2c 20 72 65 2e 65 72 72  dexError, re.err
0bb0: 6f 72 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  or):.           
0bc0: 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 42           echo("B
0bd0: 61 64 20 72 65 67 75 6c 61 72 20 65 78 70 72 65  ad regular expre
0be0: 73 73 69 6f 6e 20 69 6e 20 23 20 22 20 2b 20 73  ssion in # " + s
0bf0: 74 72 28 61 52 75 6c 65 5b 32 5d 29 29 0a 20 20  tr(aRule[2])).  
0c00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0c10: 20 20 61 52 75 6c 65 5b 30 5d 20 3d 20 22 28 3f    aRule[0] = "(?
0c20: 69 29 3c 47 72 61 6d 6d 61 6c 65 63 74 65 3e 22  i)<Grammalecte>"
0c30: 0a 0a 0a 64 65 66 20 69 67 6e 6f 72 65 52 75 6c  ...def ignoreRul
0c40: 65 20 28 73 52 75 6c 65 49 64 29 3a 0a 20 20 20  e (sRuleId):.   
0c50: 20 22 64 69 73 61 62 6c 65 20 72 75 6c 65 20 3c   "disable rule <
0c60: 73 52 75 6c 65 49 64 3e 22 0a 20 20 20 20 5f 61  sRuleId>".    _a
0c70: 49 67 6e 6f 72 65 64 52 75 6c 65 73 2e 61 64 64  IgnoredRules.add
0c80: 28 73 52 75 6c 65 49 64 29 0a 0a 0a 64 65 66 20  (sRuleId)...def 
0c90: 72 65 73 65 74 49 67 6e 6f 72 65 52 75 6c 65 73  resetIgnoreRules
0ca0: 20 28 29 3a 0a 20 20 20 20 22 63 6c 65 61 72 20   ():.    "clear 
0cb0: 61 6c 6c 20 69 67 6e 6f 72 65 64 20 72 75 6c 65  all ignored rule
0cc0: 73 22 0a 20 20 20 20 5f 61 49 67 6e 6f 72 65 64  s".    _aIgnored
0cd0: 52 75 6c 65 73 2e 63 6c 65 61 72 28 29 0a 0a 0a  Rules.clear()...
0ce0: 64 65 66 20 72 65 61 63 74 69 76 61 74 65 52 75  def reactivateRu
0cf0: 6c 65 20 28 73 52 75 6c 65 49 64 29 3a 0a 20 20  le (sRuleId):.  
0d00: 20 20 22 28 72 65 29 61 63 74 69 76 61 74 65 20    "(re)activate 
0d10: 72 75 6c 65 20 3c 73 52 75 6c 65 49 64 3e 22 0a  rule <sRuleId>".
0d20: 20 20 20 20 5f 61 49 67 6e 6f 72 65 64 52 75 6c      _aIgnoredRul
0d30: 65 73 2e 64 69 73 63 61 72 64 28 73 52 75 6c 65  es.discard(sRule
0d40: 49 64 29 0a 0a 0a 64 65 66 20 6c 69 73 74 52 75  Id)...def listRu
0d50: 6c 65 73 20 28 73 46 69 6c 74 65 72 3d 4e 6f 6e  les (sFilter=Non
0d60: 65 29 3a 0a 20 20 20 20 22 67 65 6e 65 72 61 74  e):.    "generat
0d70: 6f 72 3a 20 72 65 74 75 72 6e 73 20 74 79 70 6c  or: returns typl
0d80: 65 20 28 73 4f 70 74 69 6f 6e 2c 20 73 4c 69 6e  e (sOption, sLin
0d90: 65 49 64 2c 20 73 52 75 6c 65 49 64 29 22 0a 20  eId, sRuleId)". 
0da0: 20 20 20 69 66 20 73 46 69 6c 74 65 72 3a 0a 20     if sFilter:. 
0db0: 20 20 20 20 20 20 20 74 72 79 3a 0a 20 20 20 20         try:.    
0dc0: 20 20 20 20 20 20 20 20 7a 46 69 6c 74 65 72 20          zFilter 
0dd0: 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 46 69  = re.compile(sFi
0de0: 6c 74 65 72 29 0a 20 20 20 20 20 20 20 20 65 78  lter).        ex
0df0: 63 65 70 74 20 72 65 2e 65 72 72 6f 72 3a 0a 20  cept re.error:. 
0e00: 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28             echo(
0e10: 22 23 20 45 72 72 6f 72 2e 20 4c 69 73 74 20 72  "# Error. List r
0e20: 75 6c 65 73 3a 20 77 72 6f 6e 67 20 72 65 67 65  ules: wrong rege
0e30: 78 2e 22 29 0a 20 20 20 20 20 20 20 20 20 20 20  x.").           
0e40: 20 73 46 69 6c 74 65 72 20 3d 20 4e 6f 6e 65 0a   sFilter = None.
0e50: 20 20 20 20 66 6f 72 20 73 4f 70 74 69 6f 6e 2c      for sOption,
0e60: 20 6c 52 75 6c 65 47 72 6f 75 70 20 69 6e 20 63   lRuleGroup in c
0e70: 68 61 69 6e 28 5f 67 65 74 52 75 6c 65 73 28 54  hain(_getRules(T
0e80: 72 75 65 29 2c 20 5f 67 65 74 52 75 6c 65 73 28  rue), _getRules(
0e90: 46 61 6c 73 65 29 29 3a 0a 20 20 20 20 20 20 20  False)):.       
0ea0: 20 69 66 20 73 4f 70 74 69 6f 6e 20 21 3d 20 22   if sOption != "
0eb0: 40 40 40 40 22 3a 0a 20 20 20 20 20 20 20 20 20  @@@@":.         
0ec0: 20 20 20 66 6f 72 20 5f 2c 20 5f 2c 20 73 4c 69     for _, _, sLi
0ed0: 6e 65 49 64 2c 20 73 52 75 6c 65 49 64 2c 20 5f  neId, sRuleId, _
0ee0: 2c 20 5f 20 69 6e 20 6c 52 75 6c 65 47 72 6f 75  , _ in lRuleGrou
0ef0: 70 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  p:.             
0f00: 20 20 20 69 66 20 6e 6f 74 20 73 46 69 6c 74 65     if not sFilte
0f10: 72 20 6f 72 20 7a 46 69 6c 74 65 72 2e 73 65 61  r or zFilter.sea
0f20: 72 63 68 28 73 52 75 6c 65 49 64 29 3a 0a 20 20  rch(sRuleId):.  
0f30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0f40: 20 20 79 69 65 6c 64 20 28 73 4f 70 74 69 6f 6e    yield (sOption
0f50: 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65  , sLineId, sRule
0f60: 49 64 29 0a 0a 0a 64 65 66 20 64 69 73 70 6c 61  Id)...def displa
0f70: 79 52 75 6c 65 73 20 28 73 46 69 6c 74 65 72 3d  yRules (sFilter=
0f80: 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 64 69 73 70  None):.    "disp
0f90: 6c 61 79 20 74 68 65 20 6e 61 6d 65 20 6f 66 20  lay the name of 
0fa0: 72 75 6c 65 73 2c 20 77 69 74 68 20 74 68 65 20  rules, with the 
0fb0: 66 69 6c 74 65 72 20 3c 73 46 69 6c 74 65 72 3e  filter <sFilter>
0fc0: 22 0a 20 20 20 20 65 63 68 6f 28 22 4c 69 73 74  ".    echo("List
0fd0: 20 6f 66 20 72 75 6c 65 73 2e 20 46 69 6c 74 65   of rules. Filte
0fe0: 72 3a 20 3c 3c 20 22 20 2b 20 73 74 72 28 73 46  r: << " + str(sF
0ff0: 69 6c 74 65 72 29 20 2b 20 22 20 3e 3e 22 29 0a  ilter) + " >>").
1000: 20 20 20 20 66 6f 72 20 73 4f 70 74 69 6f 6e 2c      for sOption,
1010: 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65 49   sLineId, sRuleI
1020: 64 20 69 6e 20 6c 69 73 74 52 75 6c 65 73 28 73  d in listRules(s
1030: 46 69 6c 74 65 72 29 3a 0a 20 20 20 20 20 20 20  Filter):.       
1040: 20 65 63 68 6f 28 22 7b 3a 3c 31 30 7d 20 7b 3a   echo("{:<10} {:
1050: 3c 31 30 7d 20 7b 7d 22 2e 66 6f 72 6d 61 74 28  <10} {}".format(
1060: 73 4f 70 74 69 6f 6e 2c 20 73 4c 69 6e 65 49 64  sOption, sLineId
1070: 2c 20 73 52 75 6c 65 49 64 29 29 0a 0a 0a 23 23  , sRuleId))...##
1080: 23 23 20 4f 70 74 69 6f 6e 73 0a 0a 64 65 66 20  ## Options..def 
1090: 73 65 74 4f 70 74 69 6f 6e 20 28 73 4f 70 74 2c  setOption (sOpt,
10a0: 20 62 56 61 6c 29 3a 0a 20 20 20 20 22 73 65 74   bVal):.    "set
10b0: 20 6f 70 74 69 6f 6e 20 3c 73 4f 70 74 3e 20 77   option <sOpt> w
10c0: 69 74 68 20 3c 62 56 61 6c 3e 20 69 66 20 69 74  ith <bVal> if it
10d0: 20 65 78 69 73 74 73 22 0a 20 20 20 20 69 66 20   exists".    if 
10e0: 73 4f 70 74 20 69 6e 20 5f 64 4f 70 74 69 6f 6e  sOpt in _dOption
10f0: 73 3a 0a 20 20 20 20 20 20 20 20 5f 64 4f 70 74  s:.        _dOpt
1100: 69 6f 6e 73 5b 73 4f 70 74 5d 20 3d 20 62 56 61  ions[sOpt] = bVa
1110: 6c 0a 0a 0a 64 65 66 20 73 65 74 4f 70 74 69 6f  l...def setOptio
1120: 6e 73 20 28 64 4f 70 74 29 3a 0a 20 20 20 20 22  ns (dOpt):.    "
1130: 75 70 64 61 74 65 20 74 68 65 20 64 69 63 74 69  update the dicti
1140: 6f 6e 61 72 79 20 6f 66 20 6f 70 74 69 6f 6e 73  onary of options
1150: 20 77 69 74 68 20 3c 64 4f 70 74 3e 22 0a 20 20   with <dOpt>".  
1160: 20 20 66 6f 72 20 73 4b 65 79 2c 20 62 56 61 6c    for sKey, bVal
1170: 20 69 6e 20 64 4f 70 74 2e 69 74 65 6d 73 28 29   in dOpt.items()
1180: 3a 0a 20 20 20 20 20 20 20 20 69 66 20 73 4b 65  :.        if sKe
1190: 79 20 69 6e 20 5f 64 4f 70 74 69 6f 6e 73 3a 0a  y in _dOptions:.
11a0: 20 20 20 20 20 20 20 20 20 20 20 20 5f 64 4f 70              _dOp
11b0: 74 69 6f 6e 73 5b 73 4b 65 79 5d 20 3d 20 62 56  tions[sKey] = bV
11c0: 61 6c 0a 0a 0a 64 65 66 20 67 65 74 4f 70 74 69  al...def getOpti
11d0: 6f 6e 73 20 28 29 3a 0a 20 20 20 20 22 72 65 74  ons ():.    "ret
11e0: 75 72 6e 20 74 68 65 20 64 69 63 74 69 6f 6e 61  urn the dictiona
11f0: 72 79 20 6f 66 20 63 75 72 72 65 6e 74 20 6f 70  ry of current op
1200: 74 69 6f 6e 73 22 0a 20 20 20 20 72 65 74 75 72  tions".    retur
1210: 6e 20 5f 64 4f 70 74 69 6f 6e 73 0a 0a 0a 64 65  n _dOptions...de
1220: 66 20 67 65 74 44 65 66 61 75 6c 74 4f 70 74 69  f getDefaultOpti
1230: 6f 6e 73 20 28 29 3a 0a 20 20 20 20 22 72 65 74  ons ():.    "ret
1240: 75 72 6e 20 74 68 65 20 64 69 63 74 69 6f 6e 61  urn the dictiona
1250: 72 79 20 6f 66 20 64 65 66 61 75 6c 74 20 6f 70  ry of default op
1260: 74 69 6f 6e 73 22 0a 20 20 20 20 72 65 74 75 72  tions".    retur
1270: 6e 20 67 63 5f 6f 70 74 69 6f 6e 73 2e 67 65 74  n gc_options.get
1280: 4f 70 74 69 6f 6e 73 28 5f 73 41 70 70 43 6f 6e  Options(_sAppCon
1290: 74 65 78 74 29 2e 63 6f 70 79 28 29 0a 0a 0a 64  text).copy()...d
12a0: 65 66 20 67 65 74 4f 70 74 69 6f 6e 73 4c 61 62  ef getOptionsLab
12b0: 65 6c 73 20 28 73 4c 61 6e 67 29 3a 0a 20 20 20  els (sLang):.   
12c0: 20 22 72 65 74 75 72 6e 20 6f 70 74 69 6f 6e 73   "return options
12d0: 20 6c 61 62 65 6c 73 22 0a 20 20 20 20 72 65 74   labels".    ret
12e0: 75 72 6e 20 67 63 5f 6f 70 74 69 6f 6e 73 2e 67  urn gc_options.g
12f0: 65 74 55 49 28 73 4c 61 6e 67 29 0a 0a 0a 64 65  etUI(sLang)...de
1300: 66 20 64 69 73 70 6c 61 79 4f 70 74 69 6f 6e 73  f displayOptions
1310: 20 28 73 4c 61 6e 67 3d 22 24 7b 6c 61 6e 67 7d   (sLang="${lang}
1320: 22 29 3a 0a 20 20 20 20 22 64 69 73 70 6c 61 79  "):.    "display
1330: 20 74 68 65 20 6c 69 73 74 20 6f 66 20 67 72 61   the list of gra
1340: 6d 6d 61 72 20 63 68 65 63 6b 69 6e 67 20 6f 70  mmar checking op
1350: 74 69 6f 6e 73 22 0a 20 20 20 20 65 63 68 6f 28  tions".    echo(
1360: 22 4f 70 74 69 6f 6e 73 3a 22 29 0a 20 20 20 20  "Options:").    
1370: 65 63 68 6f 28 22 5c 6e 22 2e 6a 6f 69 6e 28 20  echo("\n".join( 
1380: 5b 20 6b 2b 22 3a 5c 74 22 2b 73 74 72 28 76 29  [ k+":\t"+str(v)
1390: 2b 22 5c 74 22 2b 67 63 5f 6f 70 74 69 6f 6e 73  +"\t"+gc_options
13a0: 2e 67 65 74 55 49 28 73 4c 61 6e 67 29 2e 67 65  .getUI(sLang).ge
13b0: 74 28 6b 2c 20 28 22 3f 22 2c 20 22 22 29 29 5b  t(k, ("?", ""))[
13c0: 30 5d 20 20 66 6f 72 20 6b 2c 20 76 20 20 69 6e  0]  for k, v  in
13d0: 20 73 6f 72 74 65 64 28 5f 64 4f 70 74 69 6f 6e   sorted(_dOption
13e0: 73 2e 69 74 65 6d 73 28 29 29 20 5d 20 29 29 0a  s.items()) ] )).
13f0: 20 20 20 20 65 63 68 6f 28 22 22 29 0a 0a 0a 64      echo("")...d
1400: 65 66 20 72 65 73 65 74 4f 70 74 69 6f 6e 73 20  ef resetOptions 
1410: 28 29 3a 0a 20 20 20 20 22 73 65 74 20 6f 70 74  ():.    "set opt
1420: 69 6f 6e 73 20 74 6f 20 64 65 66 61 75 6c 74 20  ions to default 
1430: 76 61 6c 75 65 73 22 0a 20 20 20 20 67 6c 6f 62  values".    glob
1440: 61 6c 20 5f 64 4f 70 74 69 6f 6e 73 0a 20 20 20  al _dOptions.   
1450: 20 5f 64 4f 70 74 69 6f 6e 73 20 3d 20 67 65 74   _dOptions = get
1460: 44 65 66 61 75 6c 74 4f 70 74 69 6f 6e 73 28 29  DefaultOptions()
1470: 0a 0a 0a 23 23 23 23 20 50 61 72 73 69 6e 67 0a  ...#### Parsing.
1480: 0a 64 65 66 20 70 61 72 73 65 20 28 73 54 65 78  .def parse (sTex
1490: 74 2c 20 73 43 6f 75 6e 74 72 79 3d 22 24 7b 63  t, sCountry="${c
14a0: 6f 75 6e 74 72 79 5f 64 65 66 61 75 6c 74 7d 22  ountry_default}"
14b0: 2c 20 62 44 65 62 75 67 3d 46 61 6c 73 65 2c 20  , bDebug=False, 
14c0: 64 4f 70 74 69 6f 6e 73 3d 4e 6f 6e 65 2c 20 62  dOptions=None, b
14d0: 43 6f 6e 74 65 78 74 3d 46 61 6c 73 65 2c 20 62  Context=False, b
14e0: 46 75 6c 6c 49 6e 66 6f 3d 46 61 6c 73 65 29 3a  FullInfo=False):
14f0: 0a 20 20 20 20 22 69 6e 69 74 20 70 6f 69 6e 74  .    "init point
1500: 20 74 6f 20 61 6e 61 6c 79 73 65 20 3c 73 54 65   to analyse <sTe
1510: 78 74 3e 20 61 6e 64 20 72 65 74 75 72 6e 73 20  xt> and returns 
1520: 61 6e 20 69 74 65 72 61 62 6c 65 20 6f 66 20 65  an iterable of e
1530: 72 72 6f 72 73 20 6f 72 20 28 77 69 74 68 20 6f  rrors or (with o
1540: 70 74 69 6f 6e 20 3c 62 46 75 6c 6c 49 6e 66 6f  ption <bFullInfo
1550: 3e 29 20 70 61 72 61 67 72 61 70 68 73 20 65 72  >) paragraphs er
1560: 72 6f 72 73 20 61 6e 64 20 73 65 6e 74 65 6e 63  rors and sentenc
1570: 65 73 20 77 69 74 68 20 74 6f 6b 65 6e 73 20 61  es with tokens a
1580: 6e 64 20 65 72 72 6f 72 73 22 0a 20 20 20 20 6f  nd errors".    o
1590: 54 65 78 74 20 3d 20 54 65 78 74 50 61 72 73 65  Text = TextParse
15a0: 72 28 73 54 65 78 74 29 0a 20 20 20 20 72 65 74  r(sText).    ret
15b0: 75 72 6e 20 6f 54 65 78 74 2e 70 61 72 73 65 28  urn oText.parse(
15c0: 73 43 6f 75 6e 74 72 79 2c 20 62 44 65 62 75 67  sCountry, bDebug
15d0: 2c 20 64 4f 70 74 69 6f 6e 73 2c 20 62 43 6f 6e  , dOptions, bCon
15e0: 74 65 78 74 2c 20 62 46 75 6c 6c 49 6e 66 6f 29  text, bFullInfo)
15f0: 0a 0a 0a 23 23 23 23 20 54 45 58 54 20 50 41 52  ...#### TEXT PAR
1600: 53 45 52 0a 0a 63 6c 61 73 73 20 54 65 78 74 50  SER..class TextP
1610: 61 72 73 65 72 3a 0a 20 20 20 20 22 54 65 78 74  arser:.    "Text
1620: 20 70 61 72 73 65 72 22 0a 0a 20 20 20 20 64 65   parser"..    de
1630: 66 20 5f 5f 69 6e 69 74 5f 5f 20 28 73 65 6c 66  f __init__ (self
1640: 2c 20 73 54 65 78 74 29 3a 0a 20 20 20 20 20 20  , sText):.      
1650: 20 20 73 65 6c 66 2e 73 54 65 78 74 20 3d 20 73    self.sText = s
1660: 54 65 78 74 0a 20 20 20 20 20 20 20 20 73 65 6c  Text.        sel
1670: 66 2e 73 54 65 78 74 30 20 3d 20 73 54 65 78 74  f.sText0 = sText
1680: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73 53  .        self.sS
1690: 65 6e 74 65 6e 63 65 20 3d 20 22 22 0a 20 20 20  entence = "".   
16a0: 20 20 20 20 20 73 65 6c 66 2e 73 53 65 6e 74 65       self.sSente
16b0: 6e 63 65 30 20 3d 20 22 22 0a 20 20 20 20 20 20  nce0 = "".      
16c0: 20 20 73 65 6c 66 2e 6e 4f 66 66 73 65 74 57 69    self.nOffsetWi
16d0: 74 68 69 6e 50 61 72 61 67 72 61 70 68 20 3d 20  thinParagraph = 
16e0: 30 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c  0.        self.l
16f0: 54 6f 6b 65 6e 20 3d 20 5b 5d 0a 20 20 20 20 20  Token = [].     
1700: 20 20 20 73 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f     self.dTokenPo
1710: 73 20 3d 20 7b 7d 20 20 20 20 20 20 20 20 20 23  s = {}         #
1720: 20 7b 70 6f 73 69 74 69 6f 6e 3a 20 74 6f 6b 65   {position: toke
1730: 6e 7d 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e  n}.        self.
1740: 64 54 61 67 73 20 3d 20 7b 7d 20 20 20 20 20 20  dTags = {}      
1750: 20 20 20 20 20 20 20 23 20 7b 70 6f 73 69 74 69         # {positi
1760: 6f 6e 3a 20 74 61 67 73 7d 0a 20 20 20 20 20 20  on: tags}.      
1770: 20 20 73 65 6c 66 2e 64 45 72 72 6f 72 20 3d 20    self.dError = 
1780: 7b 7d 20 20 20 20 20 20 20 20 20 20 20 20 23 20  {}            # 
1790: 7b 70 6f 73 69 74 69 6f 6e 3a 20 65 72 72 6f 72  {position: error
17a0: 7d 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64  }.        self.d
17b0: 53 65 6e 74 65 6e 63 65 45 72 72 6f 72 20 3d 20  SentenceError = 
17c0: 7b 7d 20 20 20 20 23 20 7b 70 6f 73 69 74 69 6f  {}    # {positio
17d0: 6e 3a 20 65 72 72 6f 72 7d 20 28 66 6f 72 20 74  n: error} (for t
17e0: 68 65 20 63 75 72 72 65 6e 74 20 73 65 6e 74 65  he current sente
17f0: 6e 63 65 20 6f 6e 6c 79 29 0a 20 20 20 20 20 20  nce only).      
1800: 20 20 73 65 6c 66 2e 64 45 72 72 6f 72 50 72 69    self.dErrorPri
1810: 6f 72 69 74 79 20 3d 20 7b 7d 20 20 20 20 23 20  ority = {}    # 
1820: 7b 70 6f 73 69 74 69 6f 6e 3a 20 70 72 69 6f 72  {position: prior
1830: 69 74 79 20 6f 66 20 74 68 65 20 63 75 72 72 65  ity of the curre
1840: 6e 74 20 65 72 72 6f 72 7d 0a 0a 20 20 20 20 64  nt error}..    d
1850: 65 66 20 5f 5f 73 74 72 5f 5f 20 28 73 65 6c 66  ef __str__ (self
1860: 29 3a 0a 20 20 20 20 20 20 20 20 73 20 3d 20 22  ):.        s = "
1870: 3d 3d 3d 3d 3d 20 54 45 58 54 20 3d 3d 3d 3d 3d  ===== TEXT =====
1880: 5c 6e 22 0a 20 20 20 20 20 20 20 20 73 20 2b 3d  \n".        s +=
1890: 20 22 73 65 6e 74 65 6e 63 65 3a 20 22 20 2b 20   "sentence: " + 
18a0: 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65 30 20  self.sSentence0 
18b0: 2b 20 22 5c 6e 22 0a 20 20 20 20 20 20 20 20 73  + "\n".        s
18c0: 20 2b 3d 20 22 6e 6f 77 3a 20 20 20 20 20 20 22   += "now:      "
18d0: 20 2b 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63   + self.sSentenc
18e0: 65 20 20 2b 20 22 5c 6e 22 0a 20 20 20 20 20 20  e  + "\n".      
18f0: 20 20 66 6f 72 20 64 54 6f 6b 65 6e 20 69 6e 20    for dToken in 
1900: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 3a 0a 20 20 20  self.lToken:.   
1910: 20 20 20 20 20 20 20 20 20 73 20 2b 3d 20 27 23           s += '#
1920: 7b 69 7d 5c 74 7b 6e 53 74 61 72 74 7d 3a 7b 6e  {i}\t{nStart}:{n
1930: 45 6e 64 7d 5c 74 7b 73 56 61 6c 75 65 7d 5c 74  End}\t{sValue}\t
1940: 7b 73 54 79 70 65 7d 27 2e 66 6f 72 6d 61 74 28  {sType}'.format(
1950: 2a 2a 64 54 6f 6b 65 6e 29 0a 20 20 20 20 20 20  **dToken).      
1960: 20 20 20 20 20 20 69 66 20 22 6c 4d 6f 72 70 68        if "lMorph
1970: 22 20 69 6e 20 64 54 6f 6b 65 6e 3a 0a 20 20 20  " in dToken:.   
1980: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 20 2b               s +
1990: 3d 20 22 5c 74 22 20 2b 20 73 74 72 28 64 54 6f  = "\t" + str(dTo
19a0: 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 29 0a 20  ken["lMorph"]). 
19b0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 22 61             if "a
19c0: 54 61 67 73 22 20 69 6e 20 64 54 6f 6b 65 6e 3a  Tags" in dToken:
19d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
19e0: 20 73 20 2b 3d 20 22 5c 74 22 20 2b 20 73 74 72   s += "\t" + str
19f0: 28 64 54 6f 6b 65 6e 5b 22 61 54 61 67 73 22 5d  (dToken["aTags"]
1a00: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 20  ).            s 
1a10: 2b 3d 20 22 5c 6e 22 0a 20 20 20 20 20 20 20 20  += "\n".        
1a20: 23 66 6f 72 20 6e 50 6f 73 2c 20 64 54 6f 6b 65  #for nPos, dToke
1a30: 6e 20 69 6e 20 73 65 6c 66 2e 64 54 6f 6b 65 6e  n in self.dToken
1a40: 50 6f 73 2e 69 74 65 6d 73 28 29 3a 0a 20 20 20  Pos.items():.   
1a50: 20 20 20 20 20 23 20 20 20 20 73 20 2b 3d 20 22       #    s += "
1a60: 7b 7d 5c 74 7b 7d 5c 6e 22 2e 66 6f 72 6d 61 74  {}\t{}\n".format
1a70: 28 6e 50 6f 73 2c 20 64 54 6f 6b 65 6e 29 0a 20  (nPos, dToken). 
1a80: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 0a         return s.
1a90: 0a 20 20 20 20 64 65 66 20 70 61 72 73 65 20 28  .    def parse (
1aa0: 73 65 6c 66 2c 20 73 43 6f 75 6e 74 72 79 3d 22  self, sCountry="
1ab0: 24 7b 63 6f 75 6e 74 72 79 5f 64 65 66 61 75 6c  ${country_defaul
1ac0: 74 7d 22 2c 20 62 44 65 62 75 67 3d 46 61 6c 73  t}", bDebug=Fals
1ad0: 65 2c 20 64 4f 70 74 69 6f 6e 73 3d 4e 6f 6e 65  e, dOptions=None
1ae0: 2c 20 62 43 6f 6e 74 65 78 74 3d 46 61 6c 73 65  , bContext=False
1af0: 2c 20 62 46 75 6c 6c 49 6e 66 6f 3d 46 61 6c 73  , bFullInfo=Fals
1b00: 65 29 3a 0a 20 20 20 20 20 20 20 20 22 61 6e 61  e):.        "ana
1b10: 6c 79 73 65 73 20 3c 73 54 65 78 74 3e 20 61 6e  lyses <sText> an
1b20: 64 20 72 65 74 75 72 6e 73 20 61 6e 20 69 74 65  d returns an ite
1b30: 72 61 62 6c 65 20 6f 66 20 65 72 72 6f 72 73 20  rable of errors 
1b40: 6f 72 20 28 77 69 74 68 20 6f 70 74 69 6f 6e 20  or (with option 
1b50: 3c 62 46 75 6c 6c 49 6e 66 6f 3e 29 20 70 61 72  <bFullInfo>) par
1b60: 61 67 72 61 70 68 73 20 65 72 72 6f 72 73 20 61  agraphs errors a
1b70: 6e 64 20 73 65 6e 74 65 6e 63 65 73 20 77 69 74  nd sentences wit
1b80: 68 20 74 6f 6b 65 6e 73 20 61 6e 64 20 65 72 72  h tokens and err
1b90: 6f 72 73 22 0a 20 20 20 20 20 20 20 20 23 73 54  ors".        #sT
1ba0: 65 78 74 20 3d 20 75 6e 69 63 6f 64 65 64 61 74  ext = unicodedat
1bb0: 61 2e 6e 6f 72 6d 61 6c 69 7a 65 28 22 4e 46 43  a.normalize("NFC
1bc0: 22 2c 20 73 54 65 78 74 29 0a 20 20 20 20 20 20  ", sText).      
1bd0: 20 20 64 4f 70 74 20 3d 20 64 4f 70 74 69 6f 6e    dOpt = dOption
1be0: 73 20 6f 72 20 5f 64 4f 70 74 69 6f 6e 73 0a 20  s or _dOptions. 
1bf0: 20 20 20 20 20 20 20 62 53 68 6f 77 52 75 6c 65         bShowRule
1c00: 49 64 20 3d 20 6f 70 74 69 6f 6e 28 27 69 64 72  Id = option('idr
1c10: 75 6c 65 27 29 0a 20 20 20 20 20 20 20 20 23 20  ule').        # 
1c20: 70 61 72 73 65 20 70 61 72 61 67 72 61 70 68 0a  parse paragraph.
1c30: 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20 20 20          try:.   
1c40: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 70 61           self.pa
1c50: 72 73 65 54 65 78 74 28 73 65 6c 66 2e 73 54 65  rseText(self.sTe
1c60: 78 74 2c 20 73 65 6c 66 2e 73 54 65 78 74 30 2c  xt, self.sText0,
1c70: 20 54 72 75 65 2c 20 30 2c 20 73 43 6f 75 6e 74   True, 0, sCount
1c80: 72 79 2c 20 64 4f 70 74 2c 20 62 53 68 6f 77 52  ry, dOpt, bShowR
1c90: 75 6c 65 49 64 2c 20 62 44 65 62 75 67 2c 20 62  uleId, bDebug, b
1ca0: 43 6f 6e 74 65 78 74 29 0a 20 20 20 20 20 20 20  Context).       
1cb0: 20 65 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20   except:.       
1cc0: 20 20 20 20 20 72 61 69 73 65 0a 20 20 20 20 20       raise.     
1cd0: 20 20 20 69 66 20 62 46 75 6c 6c 49 6e 66 6f 3a     if bFullInfo:
1ce0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 6c 50 61  .            lPa
1cf0: 72 61 67 72 61 70 68 45 72 72 6f 72 73 20 3d 20  ragraphErrors = 
1d00: 6c 69 73 74 28 73 65 6c 66 2e 64 45 72 72 6f 72  list(self.dError
1d10: 2e 76 61 6c 75 65 73 28 29 29 0a 20 20 20 20 20  .values()).     
1d20: 20 20 20 20 20 20 20 6c 53 65 6e 74 65 6e 63 65         lSentence
1d30: 73 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 20  s = [].         
1d40: 20 20 20 73 65 6c 66 2e 64 53 65 6e 74 65 6e 63     self.dSentenc
1d50: 65 45 72 72 6f 72 2e 63 6c 65 61 72 28 29 0a 20  eError.clear(). 
1d60: 20 20 20 20 20 20 20 23 20 70 61 72 73 65 20 73         # parse s
1d70: 65 6e 74 65 6e 63 65 73 0a 20 20 20 20 20 20 20  entences.       
1d80: 20 73 54 65 78 74 20 3d 20 73 65 6c 66 2e 5f 67   sText = self._g
1d90: 65 74 43 6c 65 61 6e 54 65 78 74 28 29 0a 20 20  etCleanText().  
1da0: 20 20 20 20 20 20 66 6f 72 20 69 53 74 61 72 74        for iStart
1db0: 2c 20 69 45 6e 64 20 69 6e 20 74 65 78 74 2e 67  , iEnd in text.g
1dc0: 65 74 53 65 6e 74 65 6e 63 65 42 6f 75 6e 64 61  etSentenceBounda
1dd0: 72 69 65 73 28 73 54 65 78 74 29 3a 0a 20 20 20  ries(sText):.   
1de0: 20 20 20 20 20 20 20 20 20 69 66 20 34 20 3c 20           if 4 < 
1df0: 28 69 45 6e 64 20 2d 20 69 53 74 61 72 74 29 20  (iEnd - iStart) 
1e00: 3c 20 32 30 30 30 3a 0a 20 20 20 20 20 20 20 20  < 2000:.        
1e10: 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20 20 20          try:.   
1e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e30: 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65 20   self.sSentence 
1e40: 3d 20 73 54 65 78 74 5b 69 53 74 61 72 74 3a 69  = sText[iStart:i
1e50: 45 6e 64 5d 0a 20 20 20 20 20 20 20 20 20 20 20  End].           
1e60: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73 53           self.sS
1e70: 65 6e 74 65 6e 63 65 30 20 3d 20 73 65 6c 66 2e  entence0 = self.
1e80: 73 54 65 78 74 30 5b 69 53 74 61 72 74 3a 69 45  sText0[iStart:iE
1e90: 6e 64 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  nd].            
1ea0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6e 4f 66          self.nOf
1eb0: 66 73 65 74 57 69 74 68 69 6e 50 61 72 61 67 72  fsetWithinParagr
1ec0: 61 70 68 20 3d 20 69 53 74 61 72 74 0a 20 20 20  aph = iStart.   
1ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ee0: 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 3d 20 6c   self.lToken = l
1ef0: 69 73 74 28 5f 6f 54 6f 6b 65 6e 69 7a 65 72 2e  ist(_oTokenizer.
1f00: 67 65 6e 54 6f 6b 65 6e 73 28 73 65 6c 66 2e 73  genTokens(self.s
1f10: 53 65 6e 74 65 6e 63 65 2c 20 54 72 75 65 29 29  Sentence, True))
1f20: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1f30: 20 20 20 20 20 73 65 6c 66 2e 64 54 6f 6b 65 6e       self.dToken
1f40: 50 6f 73 20 3d 20 7b 20 64 54 6f 6b 65 6e 5b 22  Pos = { dToken["
1f50: 6e 53 74 61 72 74 22 5d 3a 20 64 54 6f 6b 65 6e  nStart"]: dToken
1f60: 20 20 66 6f 72 20 64 54 6f 6b 65 6e 20 69 6e 20    for dToken in 
1f70: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 20 69 66 20  self.lToken  if 
1f80: 64 54 6f 6b 65 6e 5b 22 73 54 79 70 65 22 5d 20  dToken["sType"] 
1f90: 21 3d 20 22 49 4e 46 4f 22 20 7d 0a 20 20 20 20  != "INFO" }.    
1fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1fb0: 69 66 20 62 46 75 6c 6c 49 6e 66 6f 3a 0a 20 20  if bFullInfo:.  
1fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1fd0: 20 20 20 20 20 20 64 53 65 6e 74 65 6e 63 65 20        dSentence 
1fe0: 3d 20 7b 20 22 6e 53 74 61 72 74 22 3a 20 69 53  = { "nStart": iS
1ff0: 74 61 72 74 2c 20 22 6e 45 6e 64 22 3a 20 69 45  tart, "nEnd": iE
2000: 6e 64 2c 20 22 73 53 65 6e 74 65 6e 63 65 22 3a  nd, "sSentence":
2010: 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65 2c   self.sSentence,
2020: 20 22 6c 54 6f 6b 65 6e 22 3a 20 6c 69 73 74 28   "lToken": list(
2030: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 29 20 7d 0a 20  self.lToken) }. 
2040: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2050: 20 20 20 20 20 20 20 66 6f 72 20 64 54 6f 6b 65         for dToke
2060: 6e 20 69 6e 20 64 53 65 6e 74 65 6e 63 65 5b 22  n in dSentence["
2070: 6c 54 6f 6b 65 6e 22 5d 3a 0a 20 20 20 20 20 20  lToken"]:.      
2080: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2090: 20 20 20 20 20 20 69 66 20 64 54 6f 6b 65 6e 5b        if dToken[
20a0: 22 73 54 79 70 65 22 5d 20 3d 3d 20 22 57 4f 52  "sType"] == "WOR
20b0: 44 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  D":.            
20c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
20d0: 20 20 20 20 64 54 6f 6b 65 6e 5b 22 62 56 61 6c      dToken["bVal
20e0: 69 64 54 6f 6b 65 6e 22 5d 20 3d 20 5f 6f 53 70  idToken"] = _oSp
20f0: 65 6c 6c 43 68 65 63 6b 65 72 2e 69 73 56 61 6c  ellChecker.isVal
2100: 69 64 54 6f 6b 65 6e 28 64 54 6f 6b 65 6e 5b 22  idToken(dToken["
2110: 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20 20 20  sValue"]).      
2120: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2130: 20 20 23 20 74 68 65 20 6c 69 73 74 20 6f 66 20    # the list of 
2140: 74 6f 6b 65 6e 73 20 69 73 20 64 75 70 6c 69 63  tokens is duplic
2150: 61 74 65 64 2c 20 74 6f 20 6b 65 65 70 20 61 6c  ated, to keep al
2160: 6c 20 74 6f 6b 65 6e 73 20 66 72 6f 6d 20 62 65  l tokens from be
2170: 69 6e 67 20 64 65 6c 65 74 65 64 20 77 68 65 6e  ing deleted when
2180: 20 61 6e 61 6c 79 73 69 73 0a 20 20 20 20 20 20   analysis.      
2190: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
21a0: 6c 66 2e 70 61 72 73 65 54 65 78 74 28 73 65 6c  lf.parseText(sel
21b0: 66 2e 73 53 65 6e 74 65 6e 63 65 2c 20 73 65 6c  f.sSentence, sel
21c0: 66 2e 73 53 65 6e 74 65 6e 63 65 30 2c 20 46 61  f.sSentence0, Fa
21d0: 6c 73 65 2c 20 69 53 74 61 72 74 2c 20 73 43 6f  lse, iStart, sCo
21e0: 75 6e 74 72 79 2c 20 64 4f 70 74 2c 20 62 53 68  untry, dOpt, bSh
21f0: 6f 77 52 75 6c 65 49 64 2c 20 62 44 65 62 75 67  owRuleId, bDebug
2200: 2c 20 62 43 6f 6e 74 65 78 74 29 0a 20 20 20 20  , bContext).    
2210: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2220: 69 66 20 62 46 75 6c 6c 49 6e 66 6f 3a 0a 20 20  if bFullInfo:.  
2230: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2240: 20 20 20 20 20 20 64 53 65 6e 74 65 6e 63 65 5b        dSentence[
2250: 22 6c 47 72 61 6d 6d 61 72 45 72 72 6f 72 73 22  "lGrammarErrors"
2260: 5d 20 3d 20 6c 69 73 74 28 73 65 6c 66 2e 64 53  ] = list(self.dS
2270: 65 6e 74 65 6e 63 65 45 72 72 6f 72 2e 76 61 6c  entenceError.val
2280: 75 65 73 28 29 29 0a 20 20 20 20 20 20 20 20 20  ues()).         
2290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c                 l
22a0: 53 65 6e 74 65 6e 63 65 73 2e 61 70 70 65 6e 64  Sentences.append
22b0: 28 64 53 65 6e 74 65 6e 63 65 29 0a 20 20 20 20  (dSentence).    
22c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
22d0: 20 20 20 20 73 65 6c 66 2e 64 53 65 6e 74 65 6e      self.dSenten
22e0: 63 65 45 72 72 6f 72 2e 63 6c 65 61 72 28 29 0a  ceError.clear().
22f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2300: 65 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20  except:.        
2310: 20 20 20 20 20 20 20 20 20 20 20 20 72 61 69 73              rais
2320: 65 0a 20 20 20 20 20 20 20 20 69 66 20 62 46 75  e.        if bFu
2330: 6c 6c 49 6e 66 6f 3a 0a 20 20 20 20 20 20 20 20  llInfo:.        
2340: 20 20 20 20 23 20 47 72 61 6d 6d 61 72 20 63 68      # Grammar ch
2350: 65 63 6b 69 6e 67 20 61 6e 64 20 73 65 6e 74 65  ecking and sente
2360: 6e 63 65 20 61 6e 61 6c 79 73 69 73 0a 20 20 20  nce analysis.   
2370: 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20           return 
2380: 6c 50 61 72 61 67 72 61 70 68 45 72 72 6f 72 73  lParagraphErrors
2390: 2c 20 6c 53 65 6e 74 65 6e 63 65 73 0a 20 20 20  , lSentences.   
23a0: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
23b0: 20 20 20 20 20 20 20 23 20 47 72 61 6d 6d 61 72         # Grammar
23c0: 20 63 68 65 63 6b 69 6e 67 20 6f 6e 6c 79 0a 20   checking only. 
23d0: 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72             retur
23e0: 6e 20 73 65 6c 66 2e 64 45 72 72 6f 72 2e 76 61  n self.dError.va
23f0: 6c 75 65 73 28 29 20 23 20 74 68 69 73 20 69 73  lues() # this is
2400: 20 61 20 76 69 65 77 20 28 69 74 65 72 61 62 6c   a view (iterabl
2410: 65 29 0a 0a 20 20 20 20 64 65 66 20 5f 67 65 74  e)..    def _get
2420: 43 6c 65 61 6e 54 65 78 74 20 28 73 65 6c 66 29  CleanText (self)
2430: 3a 0a 20 20 20 20 20 20 20 20 73 54 65 78 74 20  :.        sText 
2440: 3d 20 73 65 6c 66 2e 73 54 65 78 74 0a 20 20 20  = self.sText.   
2450: 20 20 20 20 20 69 66 20 22 c2 a0 22 20 69 6e 20       if ".." in 
2460: 73 54 65 78 74 3a 0a 20 20 20 20 20 20 20 20 20  sText:.         
2470: 20 20 20 73 54 65 78 74 20 3d 20 73 54 65 78 74     sText = sText
2480: 2e 72 65 70 6c 61 63 65 28 22 c2 a0 22 2c 20 27  .replace("..", '
2490: 20 27 29 20 23 20 6e 62 73 70 0a 20 20 20 20 20   ') # nbsp.     
24a0: 20 20 20 69 66 20 22 e2 80 af 22 20 69 6e 20 73     if "..." in s
24b0: 54 65 78 74 3a 0a 20 20 20 20 20 20 20 20 20 20  Text:.          
24c0: 20 20 73 54 65 78 74 20 3d 20 73 54 65 78 74 2e    sText = sText.
24d0: 72 65 70 6c 61 63 65 28 22 e2 80 af 22 2c 20 27  replace("...", '
24e0: 20 27 29 20 23 20 6e 6e 62 73 70 0a 20 20 20 20   ') # nnbsp.    
24f0: 20 20 20 20 69 66 20 22 27 22 20 69 6e 20 73 54      if "'" in sT
2500: 65 78 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ext:.           
2510: 20 73 54 65 78 74 20 3d 20 73 54 65 78 74 2e 72   sText = sText.r
2520: 65 70 6c 61 63 65 28 22 27 22 2c 20 22 e2 80 99  eplace("'", "...
2530: 22 29 0a 20 20 20 20 20 20 20 20 69 66 20 22 e2  ").        if ".
2540: 80 91 22 20 69 6e 20 73 54 65 78 74 3a 0a 20 20  .." in sText:.  
2550: 20 20 20 20 20 20 20 20 20 20 73 54 65 78 74 20            sText 
2560: 3d 20 73 54 65 78 74 2e 72 65 70 6c 61 63 65 28  = sText.replace(
2570: 22 e2 80 91 22 2c 20 22 2d 22 29 20 23 20 6e 6f  "...", "-") # no
2580: 62 72 65 61 6b 64 61 73 68 0a 20 20 20 20 20 20  breakdash.      
2590: 20 20 69 66 20 22 40 40 22 20 69 6e 20 73 54 65    if "@@" in sTe
25a0: 78 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  xt:.            
25b0: 73 54 65 78 74 20 3d 20 72 65 2e 73 75 62 28 22  sText = re.sub("
25c0: 40 40 2b 22 2c 20 22 22 2c 20 73 54 65 78 74 29  @@+", "", sText)
25d0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
25e0: 73 54 65 78 74 0a 0a 20 20 20 20 64 65 66 20 70  sText..    def p
25f0: 61 72 73 65 54 65 78 74 20 28 73 65 6c 66 2c 20  arseText (self, 
2600: 73 54 65 78 74 2c 20 73 54 65 78 74 30 2c 20 62  sText, sText0, b
2610: 50 61 72 61 67 72 61 70 68 2c 20 6e 4f 66 66 73  Paragraph, nOffs
2620: 65 74 2c 20 73 43 6f 75 6e 74 72 79 2c 20 64 4f  et, sCountry, dO
2630: 70 74 69 6f 6e 73 2c 20 62 53 68 6f 77 52 75 6c  ptions, bShowRul
2640: 65 49 64 2c 20 62 44 65 62 75 67 2c 20 62 43 6f  eId, bDebug, bCo
2650: 6e 74 65 78 74 29 3a 0a 20 20 20 20 20 20 20 20  ntext):.        
2660: 22 70 61 72 73 65 20 74 68 65 20 74 65 78 74 20  "parse the text 
2670: 77 69 74 68 20 72 75 6c 65 73 22 0a 20 20 20 20  with rules".    
2680: 20 20 20 20 62 43 68 61 6e 67 65 20 3d 20 46 61      bChange = Fa
2690: 6c 73 65 0a 20 20 20 20 20 20 20 20 66 6f 72 20  lse.        for 
26a0: 73 4f 70 74 69 6f 6e 2c 20 6c 52 75 6c 65 47 72  sOption, lRuleGr
26b0: 6f 75 70 20 69 6e 20 5f 67 65 74 52 75 6c 65 73  oup in _getRules
26c0: 28 62 50 61 72 61 67 72 61 70 68 29 3a 0a 20 20  (bParagraph):.  
26d0: 20 20 20 20 20 20 20 20 20 20 69 66 20 73 4f 70            if sOp
26e0: 74 69 6f 6e 20 3d 3d 20 22 40 40 40 40 22 3a 0a  tion == "@@@@":.
26f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2700: 23 20 67 72 61 70 68 20 72 75 6c 65 73 0a 20 20  # graph rules.  
2710: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
2720: 20 6e 6f 74 20 62 50 61 72 61 67 72 61 70 68 20   not bParagraph 
2730: 61 6e 64 20 62 43 68 61 6e 67 65 3a 0a 20 20 20  and bChange:.   
2740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2750: 20 73 65 6c 66 2e 75 70 64 61 74 65 28 73 54 65   self.update(sTe
2760: 78 74 2c 20 62 44 65 62 75 67 29 0a 20 20 20 20  xt, bDebug).    
2770: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2780: 62 43 68 61 6e 67 65 20 3d 20 46 61 6c 73 65 0a  bChange = False.
2790: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
27a0: 66 6f 72 20 73 47 72 61 70 68 4e 61 6d 65 2c 20  for sGraphName, 
27b0: 73 4c 69 6e 65 49 64 20 69 6e 20 6c 52 75 6c 65  sLineId in lRule
27c0: 47 72 6f 75 70 3a 0a 20 20 20 20 20 20 20 20 20  Group:.         
27d0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73 47             if sG
27e0: 72 61 70 68 4e 61 6d 65 20 6e 6f 74 20 69 6e 20  raphName not in 
27f0: 64 4f 70 74 69 6f 6e 73 20 6f 72 20 64 4f 70 74  dOptions or dOpt
2800: 69 6f 6e 73 5b 73 47 72 61 70 68 4e 61 6d 65 5d  ions[sGraphName]
2810: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
2820: 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65            if bDe
2830: 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  bug:.           
2840: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2850: 20 65 63 68 6f 28 22 5c 6e 3e 3e 3e 3e 20 47 52   echo("\n>>>> GR
2860: 41 50 48 3a 20 22 20 2b 20 73 47 72 61 70 68 4e  APH: " + sGraphN
2870: 61 6d 65 20 2b 20 22 20 22 20 2b 20 73 4c 69 6e  ame + " " + sLin
2880: 65 49 64 29 0a 20 20 20 20 20 20 20 20 20 20 20  eId).           
2890: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 54 65               sTe
28a0: 78 74 20 3d 20 73 65 6c 66 2e 70 61 72 73 65 47  xt = self.parseG
28b0: 72 61 70 68 28 5f 72 75 6c 65 73 5f 67 72 61 70  raph(_rules_grap
28c0: 68 2e 64 41 6c 6c 47 72 61 70 68 5b 73 47 72 61  h.dAllGraph[sGra
28d0: 70 68 4e 61 6d 65 5d 2c 20 73 43 6f 75 6e 74 72  phName], sCountr
28e0: 79 2c 20 64 4f 70 74 69 6f 6e 73 2c 20 62 53 68  y, dOptions, bSh
28f0: 6f 77 52 75 6c 65 49 64 2c 20 62 44 65 62 75 67  owRuleId, bDebug
2900: 2c 20 62 43 6f 6e 74 65 78 74 29 0a 20 20 20 20  , bContext).    
2910: 20 20 20 20 20 20 20 20 65 6c 69 66 20 6e 6f 74          elif not
2920: 20 73 4f 70 74 69 6f 6e 20 6f 72 20 64 4f 70 74   sOption or dOpt
2930: 69 6f 6e 73 2e 67 65 74 28 73 4f 70 74 69 6f 6e  ions.get(sOption
2940: 2c 20 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20  , False):.      
2950: 20 20 20 20 20 20 20 20 20 20 23 20 72 65 67 65            # rege
2960: 78 20 72 75 6c 65 73 0a 20 20 20 20 20 20 20 20  x rules.        
2970: 20 20 20 20 20 20 20 20 66 6f 72 20 7a 52 65 67          for zReg
2980: 65 78 2c 20 62 55 70 70 65 72 63 61 73 65 2c 20  ex, bUppercase, 
2990: 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65 49 64  sLineId, sRuleId
29a0: 2c 20 6e 50 72 69 6f 72 69 74 79 2c 20 6c 41 63  , nPriority, lAc
29b0: 74 69 6f 6e 73 20 69 6e 20 6c 52 75 6c 65 47 72  tions in lRuleGr
29c0: 6f 75 70 3a 0a 20 20 20 20 20 20 20 20 20 20 20  oup:.           
29d0: 20 20 20 20 20 20 20 20 20 69 66 20 73 52 75 6c           if sRul
29e0: 65 49 64 20 6e 6f 74 20 69 6e 20 5f 61 49 67 6e  eId not in _aIgn
29f0: 6f 72 65 64 52 75 6c 65 73 3a 0a 20 20 20 20 20  oredRules:.     
2a00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2a10: 20 20 20 66 6f 72 20 6d 20 69 6e 20 7a 52 65 67     for m in zReg
2a20: 65 78 2e 66 69 6e 64 69 74 65 72 28 73 54 65 78  ex.finditer(sTex
2a30: 74 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  t):.            
2a40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2a50: 62 43 6f 6e 64 4d 65 6d 6f 20 3d 20 4e 6f 6e 65  bCondMemo = None
2a60: 0a 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 66 6f 72               for
2a80: 20 73 46 75 6e 63 43 6f 6e 64 2c 20 63 41 63 74   sFuncCond, cAct
2a90: 69 6f 6e 54 79 70 65 2c 20 73 57 68 61 74 2c 20  ionType, sWhat, 
2aa0: 2a 65 41 63 74 20 69 6e 20 6c 41 63 74 69 6f 6e  *eAct in lAction
2ab0: 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  s:.             
2ac0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2ad0: 20 20 20 23 20 61 63 74 69 6f 6e 20 69 6e 20 6c     # action in l
2ae0: 41 63 74 69 6f 6e 73 3a 20 5b 20 63 6f 6e 64 69  Actions: [ condi
2af0: 74 69 6f 6e 2c 20 61 63 74 69 6f 6e 20 74 79 70  tion, action typ
2b00: 65 2c 20 72 65 70 6c 61 63 65 6d 65 6e 74 2f 73  e, replacement/s
2b10: 75 67 67 65 73 74 69 6f 6e 2f 61 63 74 69 6f 6e  uggestion/action
2b20: 5b 2c 20 69 47 72 6f 75 70 5b 2c 20 6d 65 73 73  [, iGroup[, mess
2b30: 61 67 65 2c 20 55 52 4c 5d 5d 20 5d 0a 20 20 20  age, URL]] ].   
2b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2b50: 20 20 20 20 20 20 20 20 20 20 20 20 20 74 72 79               try
2b60: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
2b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2b80: 20 20 20 20 20 20 62 43 6f 6e 64 4d 65 6d 6f 20        bCondMemo 
2b90: 3d 20 6e 6f 74 20 73 46 75 6e 63 43 6f 6e 64 20  = not sFuncCond 
2ba0: 6f 72 20 67 6c 6f 62 61 6c 73 28 29 5b 73 46 75  or globals()[sFu
2bb0: 6e 63 43 6f 6e 64 5d 28 73 54 65 78 74 2c 20 73  ncCond](sText, s
2bc0: 54 65 78 74 30 2c 20 6d 2c 20 73 65 6c 66 2e 64  Text0, m, self.d
2bd0: 54 6f 6b 65 6e 50 6f 73 2c 20 73 43 6f 75 6e 74  TokenPos, sCount
2be0: 72 79 2c 20 62 43 6f 6e 64 4d 65 6d 6f 29 0a 20  ry, bCondMemo). 
2bf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2c00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2c10: 20 20 20 69 66 20 62 43 6f 6e 64 4d 65 6d 6f 3a     if bCondMemo:
2c20: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
2c30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2c40: 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62           if bDeb
2c50: 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ug:.            
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: 65 63 68 6f 28 22 52 55 4c 45 3a 20 22 20 2b 20  echo("RULE: " + 
2c90: 73 4c 69 6e 65 49 64 29 0a 20 20 20 20 20 20 20  sLineId).       
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 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20   if cActionType 
2cd0: 3d 3d 20 22 2d 22 3a 0a 20 20 20 20 20 20 20 20  == "-":.        
2ce0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2cf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2d00: 20 20 20 20 23 20 67 72 61 6d 6d 61 72 20 65 72      # grammar er
2d10: 72 6f 72 0a 20 20 20 20 20 20 20 20 20 20 20 20  ror.            
2d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2d40: 6e 45 72 72 6f 72 53 74 61 72 74 20 3d 20 6e 4f  nErrorStart = nO
2d50: 66 66 73 65 74 20 2b 20 6d 2e 73 74 61 72 74 28  ffset + m.start(
2d60: 65 41 63 74 5b 30 5d 29 0a 20 20 20 20 20 20 20  eAct[0]).       
2d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2d90: 20 20 20 20 20 69 66 20 6e 45 72 72 6f 72 53 74       if nErrorSt
2da0: 61 72 74 20 6e 6f 74 20 69 6e 20 73 65 6c 66 2e  art not in self.
2db0: 64 45 72 72 6f 72 20 6f 72 20 6e 50 72 69 6f 72  dError or nPrior
2dc0: 69 74 79 20 3e 20 73 65 6c 66 2e 64 45 72 72 6f  ity > self.dErro
2dd0: 72 50 72 69 6f 72 69 74 79 2e 67 65 74 28 6e 45  rPriority.get(nE
2de0: 72 72 6f 72 53 74 61 72 74 2c 20 2d 31 29 3a 0a  rrorStart, -1):.
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 20 20 20 20 20 20                  
2e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2e20: 73 65 6c 66 2e 64 45 72 72 6f 72 5b 6e 45 72 72  self.dError[nErr
2e30: 6f 72 53 74 61 72 74 5d 20 3d 20 73 65 6c 66 2e  orStart] = self.
2e40: 5f 63 72 65 61 74 65 45 72 72 6f 72 46 72 6f 6d  _createErrorFrom
2e50: 52 65 67 65 78 28 73 54 65 78 74 2c 20 73 54 65  Regex(sText, sTe
2e60: 78 74 30 2c 20 73 57 68 61 74 2c 20 6e 4f 66 66  xt0, sWhat, nOff
2e70: 73 65 74 2c 20 6d 2c 20 65 41 63 74 5b 30 5d 2c  set, m, eAct[0],
2e80: 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65 49   sLineId, sRuleI
2e90: 64 2c 20 62 55 70 70 65 72 63 61 73 65 2c 20 65  d, bUppercase, e
2ea0: 41 63 74 5b 31 5d 2c 20 65 41 63 74 5b 32 5d 2c  Act[1], eAct[2],
2eb0: 20 62 53 68 6f 77 52 75 6c 65 49 64 2c 20 73 4f   bShowRuleId, sO
2ec0: 70 74 69 6f 6e 2c 20 62 43 6f 6e 74 65 78 74 29  ption, bContext)
2ed0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
2ee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2ef0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2f00: 20 73 65 6c 66 2e 64 45 72 72 6f 72 50 72 69 6f   self.dErrorPrio
2f10: 72 69 74 79 5b 6e 45 72 72 6f 72 53 74 61 72 74  rity[nErrorStart
2f20: 5d 20 3d 20 6e 50 72 69 6f 72 69 74 79 0a 20 20  ] = nPriority.  
2f30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2f40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2f50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
2f60: 6c 66 2e 64 53 65 6e 74 65 6e 63 65 45 72 72 6f  lf.dSentenceErro
2f70: 72 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d 20 3d  r[nErrorStart] =
2f80: 20 73 65 6c 66 2e 64 45 72 72 6f 72 5b 6e 45 72   self.dError[nEr
2f90: 72 6f 72 53 74 61 72 74 5d 0a 20 20 20 20 20 20  rorStart].      
2fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2fb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2fc0: 20 20 65 6c 69 66 20 63 41 63 74 69 6f 6e 54 79    elif cActionTy
2fd0: 70 65 20 3d 3d 20 22 7e 22 3a 0a 20 20 20 20 20  pe == "~":.     
2fe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2ff0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3000: 20 20 20 20 20 20 20 23 20 74 65 78 74 20 70 72         # text pr
3010: 6f 63 65 73 73 6f 72 0a 20 20 20 20 20 20 20 20  ocessor.        
3020: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3040: 20 20 20 20 73 54 65 78 74 20 3d 20 73 65 6c 66      sText = self
3050: 2e 72 65 77 72 69 74 65 54 65 78 74 28 73 54 65  .rewriteText(sTe
3060: 78 74 2c 20 73 57 68 61 74 2c 20 65 41 63 74 5b  xt, sWhat, eAct[
3070: 30 5d 2c 20 6d 2c 20 62 55 70 70 65 72 63 61 73  0], m, bUppercas
3080: 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e).             
3090: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
30a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62                 b
30b0: 43 68 61 6e 67 65 20 3d 20 54 72 75 65 0a 20 20  Change = True.  
30c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
30d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
30e0: 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65            if bDe
30f0: 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  bug:.           
3100: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3110: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3120: 20 20 20 20 20 65 63 68 6f 28 22 7e 20 22 20 2b       echo("~ " +
3130: 20 73 54 65 78 74 20 2b 20 22 20 20 2d 2d 20 22   sText + "  -- "
3140: 20 2b 20 6d 2e 67 72 6f 75 70 28 65 41 63 74 5b   + m.group(eAct[
3150: 30 5d 29 20 2b 20 22 20 20 23 20 22 20 2b 20 73  0]) + "  # " + s
3160: 4c 69 6e 65 49 64 29 0a 20 20 20 20 20 20 20 20  LineId).        
3170: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3180: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3190: 65 6c 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65  elif cActionType
31a0: 20 3d 3d 20 22 3d 22 3a 0a 20 20 20 20 20 20 20   == "=":.       
31b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
31c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
31d0: 20 20 20 20 20 23 20 64 69 73 61 6d 62 69 67 75       # disambigu
31e0: 61 74 69 6f 6e 0a 20 20 20 20 20 20 20 20 20 20  ation.          
31f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3200: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3210: 20 20 69 66 20 6e 6f 74 20 62 50 61 72 61 67 72    if not bParagr
3220: 61 70 68 3a 0a 20 20 20 20 20 20 20 20 20 20 20  aph:.           
3230: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3240: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3250: 20 20 20 20 20 67 6c 6f 62 61 6c 73 28 29 5b 73       globals()[s
3260: 57 68 61 74 5d 28 73 54 65 78 74 2c 20 6d 2c 20  What](sText, m, 
3270: 73 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f 73 29 0a  self.dTokenPos).
3280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
32a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
32b0: 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20  if bDebug:.     
32c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
32d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
32e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
32f0: 63 68 6f 28 22 3d 20 22 20 2b 20 6d 2e 67 72 6f  cho("= " + m.gro
3300: 75 70 28 30 29 20 2b 20 22 20 20 23 20 22 20 2b  up(0) + "  # " +
3310: 20 73 4c 69 6e 65 49 64 29 0a 20 20 20 20 20 20   sLineId).      
3320: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3330: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3340: 20 20 65 6c 69 66 20 63 41 63 74 69 6f 6e 54 79    elif cActionTy
3350: 70 65 20 3d 3d 20 22 3e 22 3a 0a 20 20 20 20 20  pe == ">":.     
3360: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3370: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3380: 20 20 20 20 20 20 20 23 20 77 65 20 64 6f 20 6e         # we do n
3390: 6f 74 68 69 6e 67 2c 20 74 68 69 73 20 74 65 73  othing, this tes
33a0: 74 20 69 73 20 6a 75 73 74 20 61 20 63 6f 6e 64  t is just a cond
33b0: 69 74 69 6f 6e 20 74 6f 20 61 70 70 6c 79 20 61  ition to apply a
33c0: 6c 6c 20 66 6f 6c 6c 6f 77 69 6e 67 20 61 63 74  ll following act
33d0: 69 6f 6e 73 0a 20 20 20 20 20 20 20 20 20 20 20  ions.           
33e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
33f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3400: 20 70 61 73 73 0a 20 20 20 20 20 20 20 20 20 20   pass.          
3410: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c                el
3430: 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
3440: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3460: 65 63 68 6f 28 22 23 20 65 72 72 6f 72 3a 20 75  echo("# error: u
3470: 6e 6b 6e 6f 77 6e 20 61 63 74 69 6f 6e 20 61 74  nknown action at
3480: 20 22 20 2b 20 73 4c 69 6e 65 49 64 29 0a 20 20   " + sLineId).  
3490: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
34a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
34b0: 20 20 65 6c 69 66 20 63 41 63 74 69 6f 6e 54 79    elif cActionTy
34c0: 70 65 20 3d 3d 20 22 3e 22 3a 0a 20 20 20 20 20  pe == ">":.     
34d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
34e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
34f0: 20 20 20 62 72 65 61 6b 0a 20 20 20 20 20 20 20     break.       
3500: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3510: 20 20 20 20 20 20 20 20 20 65 78 63 65 70 74 20           except 
3520: 45 78 63 65 70 74 69 6f 6e 20 61 73 20 65 3a 0a  Exception as e:.
3530: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3550: 20 20 20 20 72 61 69 73 65 20 45 78 63 65 70 74      raise Except
3560: 69 6f 6e 28 73 74 72 28 65 29 2c 20 22 23 20 22  ion(str(e), "# "
3570: 20 2b 20 73 4c 69 6e 65 49 64 20 2b 20 22 20 23   + sLineId + " #
3580: 20 22 20 2b 20 73 52 75 6c 65 49 64 29 0a 20 20   " + sRuleId).  
3590: 20 20 20 20 20 20 69 66 20 62 43 68 61 6e 67 65        if bChange
35a0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  :.            if
35b0: 20 62 50 61 72 61 67 72 61 70 68 3a 0a 20 20 20   bParagraph:.   
35c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c               sel
35d0: 66 2e 73 54 65 78 74 20 3d 20 73 54 65 78 74 0a  f.sText = sText.
35e0: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
35f0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
3600: 20 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65    self.sSentence
3610: 20 3d 20 73 54 65 78 74 0a 0a 20 20 20 20 64 65   = sText..    de
3620: 66 20 75 70 64 61 74 65 20 28 73 65 6c 66 2c 20  f update (self, 
3630: 73 53 65 6e 74 65 6e 63 65 2c 20 62 44 65 62 75  sSentence, bDebu
3640: 67 3d 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20  g=False):.      
3650: 20 20 22 75 70 64 61 74 65 20 3c 73 53 65 6e 74    "update <sSent
3660: 65 6e 63 65 3e 20 61 6e 64 20 72 65 74 6f 6b 65  ence> and retoke
3670: 6e 69 7a 65 22 0a 20 20 20 20 20 20 20 20 73 65  nize".        se
3680: 6c 66 2e 73 53 65 6e 74 65 6e 63 65 20 3d 20 73  lf.sSentence = s
3690: 53 65 6e 74 65 6e 63 65 0a 20 20 20 20 20 20 20  Sentence.       
36a0: 20 6c 4e 65 77 54 6f 6b 65 6e 20 3d 20 6c 69 73   lNewToken = lis
36b0: 74 28 5f 6f 54 6f 6b 65 6e 69 7a 65 72 2e 67 65  t(_oTokenizer.ge
36c0: 6e 54 6f 6b 65 6e 73 28 73 53 65 6e 74 65 6e 63  nTokens(sSentenc
36d0: 65 2c 20 54 72 75 65 29 29 0a 20 20 20 20 20 20  e, True)).      
36e0: 20 20 66 6f 72 20 64 54 6f 6b 65 6e 20 69 6e 20    for dToken in 
36f0: 6c 4e 65 77 54 6f 6b 65 6e 3a 0a 20 20 20 20 20  lNewToken:.     
3700: 20 20 20 20 20 20 20 69 66 20 22 6c 4d 6f 72 70         if "lMorp
3710: 68 22 20 69 6e 20 73 65 6c 66 2e 64 54 6f 6b 65  h" in self.dToke
3720: 6e 50 6f 73 2e 67 65 74 28 64 54 6f 6b 65 6e 5b  nPos.get(dToken[
3730: 22 6e 53 74 61 72 74 22 5d 2c 20 7b 7d 29 3a 0a  "nStart"], {}):.
3740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3750: 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d  dToken["lMorph"]
3760: 20 3d 20 73 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f   = self.dTokenPo
3770: 73 5b 64 54 6f 6b 65 6e 5b 22 6e 53 74 61 72 74  s[dToken["nStart
3780: 22 5d 5d 5b 22 6c 4d 6f 72 70 68 22 5d 0a 20 20  "]]["lMorph"].  
3790: 20 20 20 20 20 20 20 20 20 20 69 66 20 22 61 54            if "aT
37a0: 61 67 73 22 20 69 6e 20 73 65 6c 66 2e 64 54 6f  ags" in self.dTo
37b0: 6b 65 6e 50 6f 73 2e 67 65 74 28 64 54 6f 6b 65  kenPos.get(dToke
37c0: 6e 5b 22 6e 53 74 61 72 74 22 5d 2c 20 7b 7d 29  n["nStart"], {})
37d0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
37e0: 20 20 64 54 6f 6b 65 6e 5b 22 61 54 61 67 73 22    dToken["aTags"
37f0: 5d 20 3d 20 73 65 6c 66 2e 64 54 6f 6b 65 6e 50  ] = self.dTokenP
3800: 6f 73 5b 64 54 6f 6b 65 6e 5b 22 6e 53 74 61 72  os[dToken["nStar
3810: 74 22 5d 5d 5b 22 61 54 61 67 73 22 5d 0a 20 20  t"]]["aTags"].  
3820: 20 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65        self.lToke
3830: 6e 20 3d 20 6c 4e 65 77 54 6f 6b 65 6e 0a 20 20  n = lNewToken.  
3840: 20 20 20 20 20 20 73 65 6c 66 2e 64 54 6f 6b 65        self.dToke
3850: 6e 50 6f 73 20 3d 20 7b 20 64 54 6f 6b 65 6e 5b  nPos = { dToken[
3860: 22 6e 53 74 61 72 74 22 5d 3a 20 64 54 6f 6b 65  "nStart"]: dToke
3870: 6e 20 20 66 6f 72 20 64 54 6f 6b 65 6e 20 69 6e  n  for dToken in
3880: 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 20 69 66   self.lToken  if
3890: 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70 65 22 5d   dToken["sType"]
38a0: 20 21 3d 20 22 49 4e 46 4f 22 20 7d 0a 20 20 20   != "INFO" }.   
38b0: 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a       if bDebug:.
38c0: 20 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f              echo
38d0: 28 22 55 50 44 41 54 45 3a 22 29 0a 20 20 20 20  ("UPDATE:").    
38e0: 20 20 20 20 20 20 20 20 65 63 68 6f 28 73 65 6c          echo(sel
38f0: 66 29 0a 0a 20 20 20 20 64 65 66 20 5f 67 65 74  f)..    def _get
3900: 4e 65 78 74 50 6f 69 6e 74 65 72 73 20 28 73 65  NextPointers (se
3910: 6c 66 2c 20 64 54 6f 6b 65 6e 2c 20 64 47 72 61  lf, dToken, dGra
3920: 70 68 2c 20 64 50 6f 69 6e 74 65 72 2c 20 62 44  ph, dPointer, bD
3930: 65 62 75 67 3d 46 61 6c 73 65 29 3a 0a 20 20 20  ebug=False):.   
3940: 20 20 20 20 20 22 67 65 6e 65 72 61 74 6f 72 3a       "generator:
3950: 20 72 65 74 75 72 6e 20 6e 6f 64 65 73 20 77 68   return nodes wh
3960: 65 72 65 20 3c 64 54 6f 6b 65 6e 3e 20 e2 80 9c  ere <dToken> ...
3970: 76 61 6c 75 65 73 e2 80 9d 20 6d 61 74 63 68 20  values... match 
3980: 3c 64 4e 6f 64 65 3e 20 61 72 63 73 22 0a 20 20  <dNode> arcs".  
3990: 20 20 20 20 20 20 64 4e 6f 64 65 20 3d 20 64 50        dNode = dP
39a0: 6f 69 6e 74 65 72 5b 22 64 4e 6f 64 65 22 5d 0a  ointer["dNode"].
39b0: 20 20 20 20 20 20 20 20 69 4e 6f 64 65 31 20 3d          iNode1 =
39c0: 20 64 50 6f 69 6e 74 65 72 5b 22 69 4e 6f 64 65   dPointer["iNode
39d0: 31 22 5d 0a 20 20 20 20 20 20 20 20 62 54 6f 6b  1"].        bTok
39e0: 65 6e 46 6f 75 6e 64 20 3d 20 46 61 6c 73 65 0a  enFound = False.
39f0: 20 20 20 20 20 20 20 20 23 20 74 6f 6b 65 6e 20          # token 
3a00: 76 61 6c 75 65 0a 20 20 20 20 20 20 20 20 69 66  value.        if
3a10: 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22   dToken["sValue"
3a20: 5d 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20 20  ] in dNode:.    
3a30: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
3a40: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  g:.             
3a50: 20 20 20 65 63 68 6f 28 22 20 20 4d 41 54 43 48     echo("  MATCH
3a60: 3a 20 22 20 2b 20 64 54 6f 6b 65 6e 5b 22 73 56  : " + dToken["sV
3a70: 61 6c 75 65 22 5d 29 0a 20 20 20 20 20 20 20 20  alue"]).        
3a80: 20 20 20 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f      yield { "iNo
3a90: 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64  de1": iNode1, "d
3aa0: 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b 64 4e  Node": dGraph[dN
3ab0: 6f 64 65 5b 64 54 6f 6b 65 6e 5b 22 73 56 61 6c  ode[dToken["sVal
3ac0: 75 65 22 5d 5d 5d 20 7d 0a 20 20 20 20 20 20 20  ue"]]] }.       
3ad0: 20 20 20 20 20 62 54 6f 6b 65 6e 46 6f 75 6e 64       bTokenFound
3ae0: 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20 20   = True.        
3af0: 69 66 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  if dToken["sValu
3b00: 65 22 5d 5b 30 3a 32 5d 2e 69 73 74 69 74 6c 65  e"][0:2].istitle
3b10: 28 29 3a 20 23 20 77 65 20 74 65 73 74 20 6f 6e  (): # we test on
3b20: 6c 79 20 32 20 66 69 72 73 74 20 63 68 61 72 73  ly 2 first chars
3b30: 2c 20 74 6f 20 6d 61 6b 65 20 76 61 6c 69 64 20  , to make valid 
3b40: 77 6f 72 64 73 20 73 75 63 68 20 61 73 20 22 4c  words such as "L
3b50: 61 69 73 73 65 7a 2d 6c 65 73 22 2c 20 22 50 61  aissez-les", "Pa
3b60: 73 73 65 2d 70 61 72 74 6f 75 74 22 2e 0a 20 20  sse-partout"..  
3b70: 20 20 20 20 20 20 20 20 20 20 73 56 61 6c 75 65            sValue
3b80: 20 3d 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75   = dToken["sValu
3b90: 65 22 5d 2e 6c 6f 77 65 72 28 29 0a 20 20 20 20  e"].lower().    
3ba0: 20 20 20 20 20 20 20 20 69 66 20 73 56 61 6c 75          if sValu
3bb0: 65 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20 20  e in dNode:.    
3bc0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62              if b
3bd0: 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20  Debug:.         
3be0: 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28             echo(
3bf0: 22 20 20 4d 41 54 43 48 3a 20 22 20 2b 20 73 56  "  MATCH: " + sV
3c00: 61 6c 75 65 29 0a 20 20 20 20 20 20 20 20 20 20  alue).          
3c10: 20 20 20 20 20 20 79 69 65 6c 64 20 7b 20 22 69        yield { "i
3c20: 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20  Node1": iNode1, 
3c30: 22 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b  "dNode": dGraph[
3c40: 64 4e 6f 64 65 5b 73 56 61 6c 75 65 5d 5d 20 7d  dNode[sValue]] }
3c50: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
3c60: 20 62 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 54   bTokenFound = T
3c70: 72 75 65 0a 20 20 20 20 20 20 20 20 65 6c 69 66  rue.        elif
3c80: 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22   dToken["sValue"
3c90: 5d 2e 69 73 75 70 70 65 72 28 29 3a 0a 20 20 20  ].isupper():.   
3ca0: 20 20 20 20 20 20 20 20 20 73 56 61 6c 75 65 20           sValue 
3cb0: 3d 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65  = dToken["sValue
3cc0: 22 5d 2e 6c 6f 77 65 72 28 29 0a 20 20 20 20 20  "].lower().     
3cd0: 20 20 20 20 20 20 20 69 66 20 73 56 61 6c 75 65         if sValue
3ce0: 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20 20 20   in dNode:.     
3cf0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44             if bD
3d00: 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20  ebug:.          
3d10: 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22            echo("
3d20: 20 20 4d 41 54 43 48 3a 20 22 20 2b 20 73 56 61    MATCH: " + sVa
3d30: 6c 75 65 29 0a 20 20 20 20 20 20 20 20 20 20 20  lue).           
3d40: 20 20 20 20 20 79 69 65 6c 64 20 7b 20 22 69 4e       yield { "iN
3d50: 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22  ode1": iNode1, "
3d60: 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b 64  dNode": dGraph[d
3d70: 4e 6f 64 65 5b 73 56 61 6c 75 65 5d 5d 20 7d 0a  Node[sValue]] }.
3d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3d90: 62 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 54 72  bTokenFound = Tr
3da0: 75 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  ue.            s
3db0: 56 61 6c 75 65 20 3d 20 64 54 6f 6b 65 6e 5b 22  Value = dToken["
3dc0: 73 56 61 6c 75 65 22 5d 2e 63 61 70 69 74 61 6c  sValue"].capital
3dd0: 69 7a 65 28 29 0a 20 20 20 20 20 20 20 20 20 20  ize().          
3de0: 20 20 69 66 20 73 56 61 6c 75 65 20 69 6e 20 64    if sValue in d
3df0: 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20 20 20  Node:.          
3e00: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
3e10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
3e20: 20 20 20 20 20 65 63 68 6f 28 22 20 20 4d 41 54       echo("  MAT
3e30: 43 48 3a 20 22 20 2b 20 73 56 61 6c 75 65 29 0a  CH: " + sValue).
3e40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3e50: 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31 22  yield { "iNode1"
3e60: 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64 65  : iNode1, "dNode
3e70: 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b  ": dGraph[dNode[
3e80: 73 56 61 6c 75 65 5d 5d 20 7d 0a 20 20 20 20 20  sValue]] }.     
3e90: 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b 65             bToke
3ea0: 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20 20  nFound = True.  
3eb0: 20 20 20 20 20 20 23 20 72 65 67 65 78 20 76 61        # regex va
3ec0: 6c 75 65 20 61 72 63 73 0a 20 20 20 20 20 20 20  lue arcs.       
3ed0: 20 69 66 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70   if dToken["sTyp
3ee0: 65 22 5d 20 6e 6f 74 20 69 6e 20 66 72 6f 7a 65  e"] not in froze
3ef0: 6e 73 65 74 28 5b 22 49 4e 46 4f 22 2c 20 22 50  nset(["INFO", "P
3f00: 55 4e 43 22 2c 20 22 53 49 47 4e 22 5d 29 3a 0a  UNC", "SIGN"]):.
3f10: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 22              if "
3f20: 3c 72 65 5f 76 61 6c 75 65 3e 22 20 69 6e 20 64  <re_value>" in d
3f30: 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20 20 20  Node:.          
3f40: 20 20 20 20 20 20 66 6f 72 20 73 52 65 67 65 78        for sRegex
3f50: 20 69 6e 20 64 4e 6f 64 65 5b 22 3c 72 65 5f 76   in dNode["<re_v
3f60: 61 6c 75 65 3e 22 5d 3a 0a 20 20 20 20 20 20 20  alue>"]:.       
3f70: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
3f80: 22 c2 ac 22 20 6e 6f 74 20 69 6e 20 73 52 65 67  ".." not in sReg
3f90: 65 78 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ex:.            
3fa0: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 6e 6f              # no
3fb0: 20 61 6e 74 69 2d 70 61 74 74 65 72 6e 0a 20 20   anti-pattern.  
3fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3fd0: 20 20 20 20 20 20 69 66 20 72 65 2e 73 65 61 72        if re.sear
3fe0: 63 68 28 73 52 65 67 65 78 2c 20 64 54 6f 6b 65  ch(sRegex, dToke
3ff0: 6e 5b 22 73 56 61 6c 75 65 22 5d 29 3a 0a 20 20  n["sValue"]):.  
4000: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4010: 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65            if bDe
4020: 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  bug:.           
4030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4040: 20 20 20 20 20 65 63 68 6f 28 22 20 20 4d 41 54       echo("  MAT
4050: 43 48 3a 20 7e 22 20 2b 20 73 52 65 67 65 78 29  CH: ~" + sRegex)
4060: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4070: 20 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65               yie
4080: 6c 64 20 7b 20 22 69 4e 6f 64 65 31 22 3a 20 69  ld { "iNode1": i
4090: 4e 6f 64 65 31 2c 20 22 64 4e 6f 64 65 22 3a 20  Node1, "dNode": 
40a0: 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b 22 3c 72  dGraph[dNode["<r
40b0: 65 5f 76 61 6c 75 65 3e 22 5d 5b 73 52 65 67 65  e_value>"][sRege
40c0: 78 5d 5d 20 7d 0a 20 20 20 20 20 20 20 20 20 20  x]] }.          
40d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
40e0: 20 20 62 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20    bTokenFound = 
40f0: 54 72 75 65 0a 20 20 20 20 20 20 20 20 20 20 20  True.           
4100: 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20           else:. 
4110: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4120: 20 20 20 20 20 20 20 23 20 74 68 65 72 65 20 69         # there i
4130: 73 20 61 6e 20 61 6e 74 69 2d 70 61 74 74 65 72  s an anti-patter
4140: 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  n.              
4150: 20 20 20 20 20 20 20 20 20 20 73 50 61 74 74 65            sPatte
4160: 72 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 20  rn, sNegPattern 
4170: 3d 20 73 52 65 67 65 78 2e 73 70 6c 69 74 28 22  = sRegex.split("
4180: c2 ac 22 2c 20 31 29 0a 20 20 20 20 20 20 20 20  ..", 1).        
4190: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
41a0: 69 66 20 73 4e 65 67 50 61 74 74 65 72 6e 20 61  if sNegPattern a
41b0: 6e 64 20 72 65 2e 73 65 61 72 63 68 28 73 4e 65  nd re.search(sNe
41c0: 67 50 61 74 74 65 72 6e 2c 20 64 54 6f 6b 65 6e  gPattern, dToken
41d0: 5b 22 73 56 61 6c 75 65 22 5d 29 3a 0a 20 20 20  ["sValue"]):.   
41e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
41f0: 20 20 20 20 20 20 20 20 20 63 6f 6e 74 69 6e 75           continu
4200: 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e.              
4210: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74            if not
4220: 20 73 50 61 74 74 65 72 6e 20 6f 72 20 72 65 2e   sPattern or re.
4230: 73 65 61 72 63 68 28 73 50 61 74 74 65 72 6e 2c  search(sPattern,
4240: 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22   dToken["sValue"
4250: 5d 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ]):.            
4260: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4270: 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20  if bDebug:.     
4280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4290: 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28             echo(
42a0: 22 20 20 4d 41 54 43 48 3a 20 7e 22 20 2b 20 73  "  MATCH: ~" + s
42b0: 52 65 67 65 78 29 0a 20 20 20 20 20 20 20 20 20  Regex).         
42c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
42d0: 20 20 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64     yield { "iNod
42e0: 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e  e1": iNode1, "dN
42f0: 6f 64 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f  ode": dGraph[dNo
4300: 64 65 5b 22 3c 72 65 5f 76 61 6c 75 65 3e 22 5d  de["<re_value>"]
4310: 5b 73 52 65 67 65 78 5d 5d 20 7d 0a 20 20 20 20  [sRegex]] }.    
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 62 54 6f 6b 65 6e 46 6f          bTokenFo
4340: 75 6e 64 20 3d 20 54 72 75 65 0a 20 20 20 20 20  und = True.     
4350: 20 20 20 23 20 61 6e 61 6c 79 73 61 62 6c 65 20     # analysable 
4360: 74 6f 6b 65 6e 73 0a 20 20 20 20 20 20 20 20 69  tokens.        i
4370: 66 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70 65 22  f dToken["sType"
4380: 5d 5b 30 3a 34 5d 20 3d 3d 20 22 57 4f 52 44 22  ][0:4] == "WORD"
4390: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 20  :.            # 
43a0: 74 6f 6b 65 6e 20 6c 65 6d 6d 61 73 0a 20 20 20  token lemmas.   
43b0: 20 20 20 20 20 20 20 20 20 69 66 20 22 3c 6c 65           if "<le
43c0: 6d 6d 61 73 3e 22 20 69 6e 20 64 4e 6f 64 65 3a  mmas>" in dNode:
43d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
43e0: 20 66 6f 72 20 73 4c 65 6d 6d 61 20 69 6e 20 5f   for sLemma in _
43f0: 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65  oSpellChecker.ge
4400: 74 4c 65 6d 6d 61 28 64 54 6f 6b 65 6e 5b 22 73  tLemma(dToken["s
4410: 56 61 6c 75 65 22 5d 29 3a 0a 20 20 20 20 20 20  Value"]):.      
4420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
4430: 20 73 4c 65 6d 6d 61 20 69 6e 20 64 4e 6f 64 65   sLemma in dNode
4440: 5b 22 3c 6c 65 6d 6d 61 73 3e 22 5d 3a 0a 20 20  ["<lemmas>"]:.  
4450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4460: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
4470: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4480: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 63 68               ech
4490: 6f 28 22 20 20 4d 41 54 43 48 3a 20 3e 22 20 2b  o("  MATCH: >" +
44a0: 20 73 4c 65 6d 6d 61 29 0a 20 20 20 20 20 20 20   sLemma).       
44b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
44c0: 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31   yield { "iNode1
44d0: 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64  ": iNode1, "dNod
44e0: 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64 65  e": dGraph[dNode
44f0: 5b 22 3c 6c 65 6d 6d 61 73 3e 22 5d 5b 73 4c 65  ["<lemmas>"][sLe
4500: 6d 6d 61 5d 5d 20 7d 0a 20 20 20 20 20 20 20 20  mma]] }.        
4510: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4520: 62 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 54 72  bTokenFound = Tr
4530: 75 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 23  ue.            #
4540: 20 72 65 67 65 78 20 6d 6f 72 70 68 20 61 72 63   regex morph arc
4550: 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  s.            if
4560: 20 22 3c 72 65 5f 6d 6f 72 70 68 3e 22 20 69 6e   "<re_morph>" in
4570: 20 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20   dNode:.        
4580: 20 20 20 20 20 20 20 20 6c 4d 6f 72 70 68 20 3d          lMorph =
4590: 20 64 54 6f 6b 65 6e 2e 67 65 74 28 22 6c 4d 6f   dToken.get("lMo
45a0: 72 70 68 22 2c 20 5f 6f 53 70 65 6c 6c 43 68 65  rph", _oSpellChe
45b0: 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54  cker.getMorph(dT
45c0: 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 29  oken["sValue"]))
45d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
45e0: 20 66 6f 72 20 73 52 65 67 65 78 20 69 6e 20 64   for sRegex in d
45f0: 4e 6f 64 65 5b 22 3c 72 65 5f 6d 6f 72 70 68 3e  Node["<re_morph>
4600: 22 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  "]:.            
4610: 20 20 20 20 20 20 20 20 69 66 20 22 c2 ac 22 20          if ".." 
4620: 6e 6f 74 20 69 6e 20 73 52 65 67 65 78 3a 0a 20  not in sRegex:. 
4630: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4640: 20 20 20 20 20 20 20 23 20 6e 6f 20 61 6e 74 69         # no anti
4650: 2d 70 61 74 74 65 72 6e 0a 20 20 20 20 20 20 20  -pattern.       
4660: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4670: 20 69 66 20 61 6e 79 28 72 65 2e 73 65 61 72 63   if any(re.searc
4680: 68 28 73 52 65 67 65 78 2c 20 73 4d 6f 72 70 68  h(sRegex, sMorph
4690: 29 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e  )  for sMorph in
46a0: 20 6c 4d 6f 72 70 68 29 3a 0a 20 20 20 20 20 20   lMorph):.      
46b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
46c0: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
46d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
46e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
46f0: 20 65 63 68 6f 28 22 20 20 4d 41 54 43 48 3a 20   echo("  MATCH: 
4700: 40 22 20 2b 20 73 52 65 67 65 78 29 0a 20 20 20  @" + sRegex).   
4710: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4720: 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 7b           yield {
4730: 20 22 69 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65   "iNode1": iNode
4740: 31 2c 20 22 64 4e 6f 64 65 22 3a 20 64 47 72 61  1, "dNode": dGra
4750: 70 68 5b 64 4e 6f 64 65 5b 22 3c 72 65 5f 6d 6f  ph[dNode["<re_mo
4760: 72 70 68 3e 22 5d 5b 73 52 65 67 65 78 5d 5d 20  rph>"][sRegex]] 
4770: 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  }.              
4780: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62 54                bT
4790: 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65  okenFound = True
47a0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
47b0: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
47c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
47d0: 20 20 20 23 20 74 68 65 72 65 20 69 73 20 61 6e     # there is an
47e0: 20 61 6e 74 69 2d 70 61 74 74 65 72 6e 0a 20 20   anti-pattern.  
47f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4800: 20 20 20 20 20 20 73 50 61 74 74 65 72 6e 2c 20        sPattern, 
4810: 73 4e 65 67 50 61 74 74 65 72 6e 20 3d 20 73 52  sNegPattern = sR
4820: 65 67 65 78 2e 73 70 6c 69 74 28 22 c2 ac 22 2c  egex.split("..",
4830: 20 31 29 0a 20 20 20 20 20 20 20 20 20 20 20 20   1).            
4840: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73              if s
4850: 4e 65 67 50 61 74 74 65 72 6e 20 3d 3d 20 22 2a  NegPattern == "*
4860: 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ":.             
4870: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
4880: 20 61 6c 6c 20 6d 6f 72 70 68 6f 6c 6f 67 69 65   all morphologie
4890: 73 20 6d 75 73 74 20 6d 61 74 63 68 20 77 69 74  s must match wit
48a0: 68 20 3c 73 50 61 74 74 65 72 6e 3e 0a 20 20 20  h <sPattern>.   
48b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
48c0: 20 20 20 20 20 20 20 20 20 69 66 20 73 50 61 74           if sPat
48d0: 74 65 72 6e 3a 0a 20 20 20 20 20 20 20 20 20 20  tern:.          
48e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
48f0: 20 20 20 20 20 20 69 66 20 6c 4d 6f 72 70 68 20        if lMorph 
4900: 61 6e 64 20 61 6c 6c 28 72 65 2e 73 65 61 72 63  and all(re.searc
4910: 68 28 73 50 61 74 74 65 72 6e 2c 20 73 4d 6f 72  h(sPattern, sMor
4920: 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70 68 20  ph)  for sMorph 
4930: 69 6e 20 6c 4d 6f 72 70 68 29 3a 0a 20 20 20 20  in lMorph):.    
4940: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4950: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4960: 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20  if bDebug:.     
4970: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4990: 20 20 20 65 63 68 6f 28 22 20 20 4d 41 54 43 48     echo("  MATCH
49a0: 3a 20 40 22 20 2b 20 73 52 65 67 65 78 29 0a 20  : @" + sRegex). 
49b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
49c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
49d0: 20 20 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64     yield { "iNod
49e0: 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e  e1": iNode1, "dN
49f0: 6f 64 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f  ode": dGraph[dNo
4a00: 64 65 5b 22 3c 72 65 5f 6d 6f 72 70 68 3e 22 5d  de["<re_morph>"]
4a10: 5b 73 52 65 67 65 78 5d 5d 20 7d 0a 20 20 20 20  [sRegex]] }.    
4a20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4a30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4a40: 62 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 54 72  bTokenFound = Tr
4a50: 75 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ue.             
4a60: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
4a70: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4a80: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
4a90: 73 4e 65 67 50 61 74 74 65 72 6e 20 61 6e 64 20  sNegPattern and 
4aa0: 61 6e 79 28 72 65 2e 73 65 61 72 63 68 28 73 4e  any(re.search(sN
4ab0: 65 67 50 61 74 74 65 72 6e 2c 20 73 4d 6f 72 70  egPattern, sMorp
4ac0: 68 29 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69  h)  for sMorph i
4ad0: 6e 20 6c 4d 6f 72 70 68 29 3a 0a 20 20 20 20 20  n lMorph):.     
4ae0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4af0: 20 20 20 20 20 20 20 20 20 20 20 63 6f 6e 74 69             conti
4b00: 6e 75 65 0a 20 20 20 20 20 20 20 20 20 20 20 20  nue.            
4b10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4b20: 69 66 20 6e 6f 74 20 73 50 61 74 74 65 72 6e 20  if not sPattern 
4b30: 6f 72 20 61 6e 79 28 72 65 2e 73 65 61 72 63 68  or any(re.search
4b40: 28 73 50 61 74 74 65 72 6e 2c 20 73 4d 6f 72 70  (sPattern, sMorp
4b50: 68 29 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69  h)  for sMorph i
4b60: 6e 20 6c 4d 6f 72 70 68 29 3a 0a 20 20 20 20 20  n lMorph):.     
4b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4b80: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44             if bD
4b90: 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20  ebug:.          
4ba0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4bb0: 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22            echo("
4bc0: 20 20 4d 41 54 43 48 3a 20 40 22 20 2b 20 73 52    MATCH: @" + sR
4bd0: 65 67 65 78 29 0a 20 20 20 20 20 20 20 20 20 20  egex).          
4be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4bf0: 20 20 20 20 20 20 79 69 65 6c 64 20 7b 20 22 69        yield { "i
4c00: 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20  Node1": iNode1, 
4c10: 22 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b  "dNode": dGraph[
4c20: 64 4e 6f 64 65 5b 22 3c 72 65 5f 6d 6f 72 70 68  dNode["<re_morph
4c30: 3e 22 5d 5b 73 52 65 67 65 78 5d 5d 20 7d 0a 20  >"][sRegex]] }. 
4c40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62                 b
4c60: 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75  TokenFound = Tru
4c70: 65 0a 20 20 20 20 20 20 20 20 23 20 74 6f 6b 65  e.        # toke
4c80: 6e 20 74 61 67 73 0a 20 20 20 20 20 20 20 20 69  n tags.        i
4c90: 66 20 22 61 54 61 67 73 22 20 69 6e 20 64 54 6f  f "aTags" in dTo
4ca0: 6b 65 6e 20 61 6e 64 20 22 3c 74 61 67 73 3e 22  ken and "<tags>"
4cb0: 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20 20 20   in dNode:.     
4cc0: 20 20 20 20 20 20 20 66 6f 72 20 73 54 61 67 20         for sTag 
4cd0: 69 6e 20 64 54 6f 6b 65 6e 5b 22 61 54 61 67 73  in dToken["aTags
4ce0: 22 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  "]:.            
4cf0: 20 20 20 20 69 66 20 73 54 61 67 20 69 6e 20 64      if sTag in d
4d00: 4e 6f 64 65 5b 22 3c 74 61 67 73 3e 22 5d 3a 0a  Node["<tags>"]:.
4d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4d20: 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20      if bDebug:. 
4d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4d40: 20 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 4d         echo("  M
4d50: 41 54 43 48 3a 20 2f 22 20 2b 20 73 54 61 67 29  ATCH: /" + sTag)
4d60: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4d70: 20 20 20 20 20 79 69 65 6c 64 20 7b 20 22 69 4e       yield { "iN
4d80: 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22  ode1": iNode1, "
4d90: 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b 64  dNode": dGraph[d
4da0: 4e 6f 64 65 5b 22 3c 74 61 67 73 3e 22 5d 5b 73  Node["<tags>"][s
4db0: 54 61 67 5d 5d 20 7d 0a 20 20 20 20 20 20 20 20  Tag]] }.        
4dc0: 20 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b              bTok
4dd0: 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20  enFound = True. 
4de0: 20 20 20 20 20 20 20 23 20 6d 65 74 61 20 61 72         # meta ar
4df0: 63 20 28 66 6f 72 20 74 6f 6b 65 6e 20 74 79 70  c (for token typ
4e00: 65 29 0a 20 20 20 20 20 20 20 20 69 66 20 22 3c  e).        if "<
4e10: 6d 65 74 61 3e 22 20 69 6e 20 64 4e 6f 64 65 3a  meta>" in dNode:
4e20: 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72  .            for
4e30: 20 73 4d 65 74 61 20 69 6e 20 64 4e 6f 64 65 5b   sMeta in dNode[
4e40: 22 3c 6d 65 74 61 3e 22 5d 3a 0a 20 20 20 20 20  "<meta>"]:.     
4e50: 20 20 20 20 20 20 20 20 20 20 20 23 20 6e 6f 20             # no 
4e60: 72 65 67 65 78 20 68 65 72 65 2c 20 77 65 20 6a  regex here, we j
4e70: 75 73 74 20 73 65 61 72 63 68 20 69 66 20 3c 64  ust search if <d
4e80: 4e 6f 64 65 5b 22 73 54 79 70 65 22 5d 3e 20 65  Node["sType"]> e
4e90: 78 69 73 74 73 20 77 69 74 68 69 6e 20 3c 73 4d  xists within <sM
4ea0: 65 74 61 3e 0a 20 20 20 20 20 20 20 20 20 20 20  eta>.           
4eb0: 20 20 20 20 20 69 66 20 73 4d 65 74 61 20 3d 3d       if sMeta ==
4ec0: 20 22 2a 22 20 6f 72 20 64 54 6f 6b 65 6e 5b 22   "*" or dToken["
4ed0: 73 54 79 70 65 22 5d 20 3d 3d 20 73 4d 65 74 61  sType"] == sMeta
4ee0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
4ef0: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
4f00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4f10: 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 20           echo(" 
4f20: 20 4d 41 54 43 48 3a 20 2a 22 20 2b 20 73 4d 65   MATCH: *" + sMe
4f30: 74 61 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ta).            
4f40: 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 7b 20          yield { 
4f50: 22 69 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31  "iNode1": iNode1
4f60: 2c 20 22 64 4e 6f 64 65 22 3a 20 64 47 72 61 70  , "dNode": dGrap
4f70: 68 5b 64 4e 6f 64 65 5b 22 3c 6d 65 74 61 3e 22  h[dNode["<meta>"
4f80: 5d 5b 73 4d 65 74 61 5d 5d 20 7d 0a 20 20 20 20  ][sMeta]] }.    
4f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4fa0: 62 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 54 72  bTokenFound = Tr
4fb0: 75 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ue.             
4fc0: 20 20 20 65 6c 69 66 20 22 c2 ac 22 20 69 6e 20     elif ".." in 
4fd0: 73 4d 65 74 61 3a 0a 20 20 20 20 20 20 20 20 20  sMeta:.         
4fe0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 64 54             if dT
4ff0: 6f 6b 65 6e 5b 22 73 54 79 70 65 22 5d 20 6e 6f  oken["sType"] no
5000: 74 20 69 6e 20 73 4d 65 74 61 3a 0a 20 20 20 20  t in sMeta:.    
5010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5020: 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20      if bDebug:. 
5030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5040: 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28             echo(
5050: 22 20 20 4d 41 54 43 48 3a 20 2a 22 20 2b 20 73  "  MATCH: *" + s
5060: 4d 65 74 61 29 0a 20 20 20 20 20 20 20 20 20 20  Meta).          
5070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 79 69                yi
5080: 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31 22 3a 20  eld { "iNode1": 
5090: 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64 65 22 3a  iNode1, "dNode":
50a0: 20 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b 22 3c   dGraph[dNode["<
50b0: 6d 65 74 61 3e 22 5d 5b 73 4d 65 74 61 5d 5d 20  meta>"][sMeta]] 
50c0: 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  }.              
50d0: 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b 65 6e            bToken
50e0: 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20 20 20  Found = True.   
50f0: 20 20 20 20 20 69 66 20 6e 6f 74 20 62 54 6f 6b       if not bTok
5100: 65 6e 46 6f 75 6e 64 20 61 6e 64 20 22 62 4b 65  enFound and "bKe
5110: 65 70 22 20 69 6e 20 64 50 6f 69 6e 74 65 72 3a  ep" in dPointer:
5120: 0a 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65  .            yie
5130: 6c 64 20 64 50 6f 69 6e 74 65 72 0a 20 20 20 20  ld dPointer.    
5140: 20 20 20 20 23 20 4a 55 4d 50 0a 20 20 20 20 20      # JUMP.     
5150: 20 20 20 23 20 57 61 72 6e 69 6e 67 21 20 52 65     # Warning! Re
5160: 63 75 72 73 73 69 6f 6e 21 0a 20 20 20 20 20 20  curssion!.      
5170: 20 20 69 66 20 22 3c 3e 22 20 69 6e 20 64 4e 6f    if "<>" in dNo
5180: 64 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  de:.            
5190: 64 50 6f 69 6e 74 65 72 32 20 3d 20 7b 20 22 69  dPointer2 = { "i
51a0: 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20  Node1": iNode1, 
51b0: 22 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b  "dNode": dGraph[
51c0: 64 4e 6f 64 65 5b 22 3c 3e 22 5d 5d 2c 20 22 62  dNode["<>"]], "b
51d0: 4b 65 65 70 22 3a 20 54 72 75 65 20 7d 0a 20 20  Keep": True }.  
51e0: 20 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20            yield 
51f0: 66 72 6f 6d 20 73 65 6c 66 2e 5f 67 65 74 4e 65  from self._getNe
5200: 78 74 50 6f 69 6e 74 65 72 73 28 64 54 6f 6b 65  xtPointers(dToke
5210: 6e 2c 20 64 47 72 61 70 68 2c 20 64 50 6f 69 6e  n, dGraph, dPoin
5220: 74 65 72 32 2c 20 62 44 65 62 75 67 29 0a 0a 20  ter2, bDebug).. 
5230: 20 20 20 64 65 66 20 70 61 72 73 65 47 72 61 70     def parseGrap
5240: 68 20 28 73 65 6c 66 2c 20 64 47 72 61 70 68 2c  h (self, dGraph,
5250: 20 73 43 6f 75 6e 74 72 79 3d 22 24 7b 63 6f 75   sCountry="${cou
5260: 6e 74 72 79 5f 64 65 66 61 75 6c 74 7d 22 2c 20  ntry_default}", 
5270: 64 4f 70 74 69 6f 6e 73 3d 4e 6f 6e 65 2c 20 62  dOptions=None, b
5280: 53 68 6f 77 52 75 6c 65 49 64 3d 46 61 6c 73 65  ShowRuleId=False
5290: 2c 20 62 44 65 62 75 67 3d 46 61 6c 73 65 2c 20  , bDebug=False, 
52a0: 62 43 6f 6e 74 65 78 74 3d 46 61 6c 73 65 29 3a  bContext=False):
52b0: 0a 20 20 20 20 20 20 20 20 22 70 61 72 73 65 20  .        "parse 
52c0: 67 72 61 70 68 20 77 69 74 68 20 74 6f 6b 65 6e  graph with token
52d0: 73 20 66 72 6f 6d 20 74 68 65 20 74 65 78 74 20  s from the text 
52e0: 61 6e 64 20 65 78 65 63 75 74 65 20 61 63 74 69  and execute acti
52f0: 6f 6e 73 20 65 6e 63 6f 75 6e 74 65 72 65 64 22  ons encountered"
5300: 0a 20 20 20 20 20 20 20 20 6c 50 6f 69 6e 74 65  .        lPointe
5310: 72 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 62  r = [].        b
5320: 54 61 67 41 6e 64 52 65 77 72 69 74 65 20 3d 20  TagAndRewrite = 
5330: 46 61 6c 73 65 0a 20 20 20 20 20 20 20 20 66 6f  False.        fo
5340: 72 20 69 54 6f 6b 65 6e 2c 20 64 54 6f 6b 65 6e  r iToken, dToken
5350: 20 69 6e 20 65 6e 75 6d 65 72 61 74 65 28 73 65   in enumerate(se
5360: 6c 66 2e 6c 54 6f 6b 65 6e 29 3a 0a 20 20 20 20  lf.lToken):.    
5370: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
5380: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  g:.             
5390: 20 20 20 65 63 68 6f 28 22 54 4f 4b 45 4e 3a 20     echo("TOKEN: 
53a0: 22 20 2b 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c  " + dToken["sVal
53b0: 75 65 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20  ue"]).          
53c0: 20 20 23 20 63 68 65 63 6b 20 61 72 63 73 20 66    # check arcs f
53d0: 6f 72 20 65 61 63 68 20 65 78 69 73 74 69 6e 67  or each existing
53e0: 20 70 6f 69 6e 74 65 72 0a 20 20 20 20 20 20 20   pointer.       
53f0: 20 20 20 20 20 6c 4e 65 78 74 50 6f 69 6e 74 65       lNextPointe
5400: 72 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 20  r = [].         
5410: 20 20 20 66 6f 72 20 64 50 6f 69 6e 74 65 72 20     for dPointer 
5420: 69 6e 20 6c 50 6f 69 6e 74 65 72 3a 0a 20 20 20  in lPointer:.   
5430: 20 20 20 20 20 20 20 20 20 20 20 20 20 6c 4e 65               lNe
5440: 78 74 50 6f 69 6e 74 65 72 2e 65 78 74 65 6e 64  xtPointer.extend
5450: 28 73 65 6c 66 2e 5f 67 65 74 4e 65 78 74 50 6f  (self._getNextPo
5460: 69 6e 74 65 72 73 28 64 54 6f 6b 65 6e 2c 20 64  inters(dToken, d
5470: 47 72 61 70 68 2c 20 64 50 6f 69 6e 74 65 72 2c  Graph, dPointer,
5480: 20 62 44 65 62 75 67 29 29 0a 20 20 20 20 20 20   bDebug)).      
5490: 20 20 20 20 20 20 6c 50 6f 69 6e 74 65 72 20 3d        lPointer =
54a0: 20 6c 4e 65 78 74 50 6f 69 6e 74 65 72 0a 20 20   lNextPointer.  
54b0: 20 20 20 20 20 20 20 20 20 20 23 20 63 68 65 63            # chec
54c0: 6b 20 61 72 63 73 20 6f 66 20 66 69 72 73 74 20  k arcs of first 
54d0: 6e 6f 64 65 73 0a 20 20 20 20 20 20 20 20 20 20  nodes.          
54e0: 20 20 6c 50 6f 69 6e 74 65 72 2e 65 78 74 65 6e    lPointer.exten
54f0: 64 28 73 65 6c 66 2e 5f 67 65 74 4e 65 78 74 50  d(self._getNextP
5500: 6f 69 6e 74 65 72 73 28 64 54 6f 6b 65 6e 2c 20  ointers(dToken, 
5510: 64 47 72 61 70 68 2c 20 7b 20 22 69 4e 6f 64 65  dGraph, { "iNode
5520: 31 22 3a 20 69 54 6f 6b 65 6e 2c 20 22 64 4e 6f  1": iToken, "dNo
5530: 64 65 22 3a 20 64 47 72 61 70 68 5b 30 5d 20 7d  de": dGraph[0] }
5540: 2c 20 62 44 65 62 75 67 29 29 0a 20 20 20 20 20  , bDebug)).     
5550: 20 20 20 20 20 20 20 23 20 63 68 65 63 6b 20 69         # check i
5560: 66 20 74 68 65 72 65 20 69 73 20 72 75 6c 65 73  f there is rules
5570: 20 74 6f 20 63 68 65 63 6b 20 66 6f 72 20 65 61   to check for ea
5580: 63 68 20 70 6f 69 6e 74 65 72 0a 20 20 20 20 20  ch pointer.     
5590: 20 20 20 20 20 20 20 66 6f 72 20 64 50 6f 69 6e         for dPoin
55a0: 74 65 72 20 69 6e 20 6c 50 6f 69 6e 74 65 72 3a  ter in lPointer:
55b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
55c0: 20 23 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20   #if bDebug:.   
55d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 20               #  
55e0: 20 20 65 63 68 6f 28 22 2b 22 2c 20 64 50 6f 69    echo("+", dPoi
55f0: 6e 74 65 72 29 0a 20 20 20 20 20 20 20 20 20 20  nter).          
5600: 20 20 20 20 20 20 69 66 20 22 3c 72 75 6c 65 73        if "<rules
5610: 3e 22 20 69 6e 20 64 50 6f 69 6e 74 65 72 5b 22  >" in dPointer["
5620: 64 4e 6f 64 65 22 5d 3a 0a 20 20 20 20 20 20 20  dNode"]:.       
5630: 20 20 20 20 20 20 20 20 20 20 20 20 20 62 43 68               bCh
5640: 61 6e 67 65 20 3d 20 73 65 6c 66 2e 5f 65 78 65  ange = self._exe
5650: 63 75 74 65 41 63 74 69 6f 6e 73 28 64 47 72 61  cuteActions(dGra
5660: 70 68 2c 20 64 50 6f 69 6e 74 65 72 5b 22 64 4e  ph, dPointer["dN
5670: 6f 64 65 22 5d 5b 22 3c 72 75 6c 65 73 3e 22 5d  ode"]["<rules>"]
5680: 2c 20 64 50 6f 69 6e 74 65 72 5b 22 69 4e 6f 64  , dPointer["iNod
5690: 65 31 22 5d 2d 31 2c 20 69 54 6f 6b 65 6e 2c 20  e1"]-1, iToken, 
56a0: 64 4f 70 74 69 6f 6e 73 2c 20 73 43 6f 75 6e 74  dOptions, sCount
56b0: 72 79 2c 20 62 53 68 6f 77 52 75 6c 65 49 64 2c  ry, bShowRuleId,
56c0: 20 62 44 65 62 75 67 2c 20 62 43 6f 6e 74 65 78   bDebug, bContex
56d0: 74 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  t).             
56e0: 20 20 20 20 20 20 20 69 66 20 62 43 68 61 6e 67         if bChang
56f0: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
5700: 20 20 20 20 20 20 20 20 20 20 20 62 54 61 67 41             bTagA
5710: 6e 64 52 65 77 72 69 74 65 20 3d 20 54 72 75 65  ndRewrite = True
5720: 0a 20 20 20 20 20 20 20 20 69 66 20 62 54 61 67  .        if bTag
5730: 41 6e 64 52 65 77 72 69 74 65 3a 0a 20 20 20 20  AndRewrite:.    
5740: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 72 65 77          self.rew
5750: 72 69 74 65 46 72 6f 6d 54 61 67 73 28 62 44 65  riteFromTags(bDe
5760: 62 75 67 29 0a 20 20 20 20 20 20 20 20 69 66 20  bug).        if 
5770: 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20  bDebug:.        
5780: 20 20 20 20 65 63 68 6f 28 73 65 6c 66 29 0a 20      echo(self). 
5790: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 73 65         return se
57a0: 6c 66 2e 73 53 65 6e 74 65 6e 63 65 0a 0a 20 20  lf.sSentence..  
57b0: 20 20 64 65 66 20 5f 65 78 65 63 75 74 65 41 63    def _executeAc
57c0: 74 69 6f 6e 73 20 28 73 65 6c 66 2c 20 64 47 72  tions (self, dGr
57d0: 61 70 68 2c 20 64 4e 6f 64 65 2c 20 6e 54 6f 6b  aph, dNode, nTok
57e0: 65 6e 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54  enOffset, nLastT
57f0: 6f 6b 65 6e 2c 20 64 4f 70 74 69 6f 6e 73 2c 20  oken, dOptions, 
5800: 73 43 6f 75 6e 74 72 79 2c 20 62 53 68 6f 77 52  sCountry, bShowR
5810: 75 6c 65 49 64 2c 20 62 44 65 62 75 67 2c 20 62  uleId, bDebug, b
5820: 43 6f 6e 74 65 78 74 29 3a 0a 20 20 20 20 20 20  Context):.      
5830: 20 20 22 65 78 65 63 75 74 65 20 61 63 74 69 6f    "execute actio
5840: 6e 73 20 66 6f 75 6e 64 20 69 6e 20 74 68 65 20  ns found in the 
5850: 44 41 52 47 22 0a 20 20 20 20 20 20 20 20 62 43  DARG".        bC
5860: 68 61 6e 67 65 20 3d 20 46 61 6c 73 65 0a 20 20  hange = False.  
5870: 20 20 20 20 20 20 66 6f 72 20 73 4c 69 6e 65 49        for sLineI
5880: 64 2c 20 6e 65 78 74 4e 6f 64 65 4b 65 79 20 69  d, nextNodeKey i
5890: 6e 20 64 4e 6f 64 65 2e 69 74 65 6d 73 28 29 3a  n dNode.items():
58a0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 62 43 6f  .            bCo
58b0: 6e 64 4d 65 6d 6f 20 3d 20 4e 6f 6e 65 0a 20 20  ndMemo = None.  
58c0: 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 73 52            for sR
58d0: 75 6c 65 49 64 20 69 6e 20 64 47 72 61 70 68 5b  uleId in dGraph[
58e0: 6e 65 78 74 4e 6f 64 65 4b 65 79 5d 3a 0a 20 20  nextNodeKey]:.  
58f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 74 72                tr
5900: 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  y:.             
5910: 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67         if bDebug
5920: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
5930: 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22            echo("
5940: 20 20 20 3e 54 52 59 3a 20 22 20 2b 20 73 52 75     >TRY: " + sRu
5950: 6c 65 49 64 20 2b 20 22 20 22 20 2b 20 73 4c 69  leId + " " + sLi
5960: 6e 65 49 64 29 0a 20 20 20 20 20 20 20 20 20 20  neId).          
5970: 20 20 20 20 20 20 20 20 20 20 73 4f 70 74 69 6f            sOptio
5980: 6e 2c 20 73 46 75 6e 63 43 6f 6e 64 2c 20 63 41  n, sFuncCond, cA
5990: 63 74 69 6f 6e 54 79 70 65 2c 20 73 57 68 61 74  ctionType, sWhat
59a0: 2c 20 2a 65 41 63 74 20 3d 20 5f 72 75 6c 65 73  , *eAct = _rules
59b0: 5f 67 72 61 70 68 2e 64 52 75 6c 65 5b 73 52 75  _graph.dRule[sRu
59c0: 6c 65 49 64 5d 0a 20 20 20 20 20 20 20 20 20 20  leId].          
59d0: 20 20 20 20 20 20 20 20 20 20 23 20 53 75 67 67            # Sugg
59e0: 65 73 74 69 6f 6e 20 20 20 20 5b 20 6f 70 74 69  estion    [ opti
59f0: 6f 6e 2c 20 63 6f 6e 64 69 74 69 6f 6e 2c 20 22  on, condition, "
5a00: 2d 22 2c 20 72 65 70 6c 61 63 65 6d 65 6e 74 2f  -", replacement/
5a10: 73 75 67 67 65 73 74 69 6f 6e 2f 61 63 74 69 6f  suggestion/actio
5a20: 6e 2c 20 69 54 6f 6b 65 6e 53 74 61 72 74 2c 20  n, iTokenStart, 
5a30: 69 54 6f 6b 65 6e 45 6e 64 2c 20 63 53 74 61 72  iTokenEnd, cStar
5a40: 74 4c 69 6d 69 74 2c 20 63 45 6e 64 4c 69 6d 69  tLimit, cEndLimi
5a50: 74 2c 20 62 43 61 73 65 53 76 74 79 2c 20 6e 50  t, bCaseSvty, nP
5a60: 72 69 6f 72 69 74 79 2c 20 73 4d 65 73 73 61 67  riority, sMessag
5a70: 65 2c 20 73 55 52 4c 20 5d 0a 20 20 20 20 20 20  e, sURL ].      
5a80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
5a90: 54 65 78 74 50 72 6f 63 65 73 73 6f 72 20 5b 20  TextProcessor [ 
5aa0: 6f 70 74 69 6f 6e 2c 20 63 6f 6e 64 69 74 69 6f  option, conditio
5ab0: 6e 2c 20 22 7e 22 2c 20 72 65 70 6c 61 63 65 6d  n, "~", replacem
5ac0: 65 6e 74 2f 73 75 67 67 65 73 74 69 6f 6e 2f 61  ent/suggestion/a
5ad0: 63 74 69 6f 6e 2c 20 69 54 6f 6b 65 6e 53 74 61  ction, iTokenSta
5ae0: 72 74 2c 20 69 54 6f 6b 65 6e 45 6e 64 2c 20 62  rt, iTokenEnd, b
5af0: 43 61 73 65 53 76 74 79 20 5d 0a 20 20 20 20 20  CaseSvty ].     
5b00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
5b10: 20 44 69 73 61 6d 62 69 67 75 61 74 6f 72 20 5b   Disambiguator [
5b20: 20 6f 70 74 69 6f 6e 2c 20 63 6f 6e 64 69 74 69   option, conditi
5b30: 6f 6e 2c 20 22 3d 22 2c 20 72 65 70 6c 61 63 65  on, "=", replace
5b40: 6d 65 6e 74 2f 73 75 67 67 65 73 74 69 6f 6e 2f  ment/suggestion/
5b50: 61 63 74 69 6f 6e 20 5d 0a 20 20 20 20 20 20 20  action ].       
5b60: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 54               # T
5b70: 61 67 20 20 20 20 20 20 20 20 20 20 20 5b 20 6f  ag           [ o
5b80: 70 74 69 6f 6e 2c 20 63 6f 6e 64 69 74 69 6f 6e  ption, condition
5b90: 2c 20 22 2f 22 2c 20 72 65 70 6c 61 63 65 6d 65  , "/", replaceme
5ba0: 6e 74 2f 73 75 67 67 65 73 74 69 6f 6e 2f 61 63  nt/suggestion/ac
5bb0: 74 69 6f 6e 2c 20 69 54 6f 6b 65 6e 53 74 61 72  tion, iTokenStar
5bc0: 74 2c 20 69 54 6f 6b 65 6e 45 6e 64 20 5d 0a 20  t, iTokenEnd ]. 
5bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5be0: 20 20 20 23 20 49 6d 6d 75 6e 69 74 79 20 20 20     # Immunity   
5bf0: 20 20 20 5b 20 6f 70 74 69 6f 6e 2c 20 63 6f 6e     [ option, con
5c00: 64 69 74 69 6f 6e 2c 20 22 21 22 2c 20 22 22 2c  dition, "!", "",
5c10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5c20: 20 20 20 20 20 20 20 20 20 20 20 20 69 54 6f 6b              iTok
5c30: 65 6e 53 74 61 72 74 2c 20 69 54 6f 6b 65 6e 45  enStart, iTokenE
5c40: 6e 64 20 5d 0a 20 20 20 20 20 20 20 20 20 20 20  nd ].           
5c50: 20 20 20 20 20 20 20 20 20 23 20 54 65 73 74 20           # Test 
5c60: 20 20 20 20 20 20 20 20 20 5b 20 6f 70 74 69 6f           [ optio
5c70: 6e 2c 20 63 6f 6e 64 69 74 69 6f 6e 2c 20 22 3e  n, condition, ">
5c80: 22 2c 20 22 22 20 5d 0a 20 20 20 20 20 20 20 20  ", "" ].        
5c90: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
5ca0: 6f 74 20 73 4f 70 74 69 6f 6e 20 6f 72 20 64 4f  ot sOption or dO
5cb0: 70 74 69 6f 6e 73 2e 67 65 74 28 73 4f 70 74 69  ptions.get(sOpti
5cc0: 6f 6e 2c 20 46 61 6c 73 65 29 3a 0a 20 20 20 20  on, False):.    
5cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ce0: 20 20 20 20 62 43 6f 6e 64 4d 65 6d 6f 20 3d 20      bCondMemo = 
5cf0: 6e 6f 74 20 73 46 75 6e 63 43 6f 6e 64 20 6f 72  not sFuncCond or
5d00: 20 67 6c 6f 62 61 6c 73 28 29 5b 73 46 75 6e 63   globals()[sFunc
5d10: 43 6f 6e 64 5d 28 73 65 6c 66 2e 6c 54 6f 6b 65  Cond](self.lToke
5d20: 6e 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2c  n, nTokenOffset,
5d30: 20 6e 4c 61 73 74 54 6f 6b 65 6e 2c 20 73 43 6f   nLastToken, sCo
5d40: 75 6e 74 72 79 2c 20 62 43 6f 6e 64 4d 65 6d 6f  untry, bCondMemo
5d50: 2c 20 73 65 6c 66 2e 64 54 61 67 73 2c 20 73 65  , self.dTags, se
5d60: 6c 66 2e 73 53 65 6e 74 65 6e 63 65 2c 20 73 65  lf.sSentence, se
5d70: 6c 66 2e 73 53 65 6e 74 65 6e 63 65 30 29 0a 20  lf.sSentence0). 
5d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5d90: 20 20 20 20 20 20 20 69 66 20 62 43 6f 6e 64 4d         if bCondM
5da0: 65 6d 6f 3a 0a 20 20 20 20 20 20 20 20 20 20 20  emo:.           
5db0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5dc0: 20 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20   if cActionType 
5dd0: 3d 3d 20 22 2d 22 3a 0a 20 20 20 20 20 20 20 20  == "-":.        
5de0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5df0: 20 20 20 20 20 20 20 20 23 20 67 72 61 6d 6d 61          # gramma
5e00: 72 20 65 72 72 6f 72 0a 20 20 20 20 20 20 20 20  r error.        
5e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e20: 20 20 20 20 20 20 20 20 69 54 6f 6b 65 6e 53 74          iTokenSt
5e30: 61 72 74 2c 20 69 54 6f 6b 65 6e 45 6e 64 2c 20  art, iTokenEnd, 
5e40: 63 53 74 61 72 74 4c 69 6d 69 74 2c 20 63 45 6e  cStartLimit, cEn
5e50: 64 4c 69 6d 69 74 2c 20 62 43 61 73 65 53 76 74  dLimit, bCaseSvt
5e60: 79 2c 20 6e 50 72 69 6f 72 69 74 79 2c 20 73 4d  y, nPriority, sM
5e70: 65 73 73 61 67 65 2c 20 73 55 52 4c 20 3d 20 65  essage, sURL = e
5e80: 41 63 74 0a 20 20 20 20 20 20 20 20 20 20 20 20  Act.            
5e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ea0: 20 20 20 20 6e 54 6f 6b 65 6e 45 72 72 6f 72 53      nTokenErrorS
5eb0: 74 61 72 74 20 3d 20 6e 54 6f 6b 65 6e 4f 66 66  tart = nTokenOff
5ec0: 73 65 74 20 2b 20 69 54 6f 6b 65 6e 53 74 61 72  set + iTokenStar
5ed0: 74 20 20 69 66 20 69 54 6f 6b 65 6e 53 74 61 72  t  if iTokenStar
5ee0: 74 20 3e 20 30 20 20 65 6c 73 65 20 6e 4c 61 73  t > 0  else nLas
5ef0: 74 54 6f 6b 65 6e 20 2b 20 69 54 6f 6b 65 6e 53  tToken + iTokenS
5f00: 74 61 72 74 0a 20 20 20 20 20 20 20 20 20 20 20  tart.           
5f10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5f20: 20 20 20 20 20 69 66 20 22 62 49 6d 6d 75 6e 65       if "bImmune
5f30: 22 20 6e 6f 74 20 69 6e 20 73 65 6c 66 2e 6c 54  " not in self.lT
5f40: 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 45 72 72 6f 72  oken[nTokenError
5f50: 53 74 61 72 74 5d 3a 0a 20 20 20 20 20 20 20 20  Start]:.        
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 20 20 20 6e 54 6f 6b              nTok
5f80: 65 6e 45 72 72 6f 72 45 6e 64 20 3d 20 6e 54 6f  enErrorEnd = nTo
5f90: 6b 65 6e 4f 66 66 73 65 74 20 2b 20 69 54 6f 6b  kenOffset + iTok
5fa0: 65 6e 45 6e 64 20 20 69 66 20 69 54 6f 6b 65 6e  enEnd  if iToken
5fb0: 45 6e 64 20 3e 20 30 20 20 65 6c 73 65 20 6e 4c  End > 0  else nL
5fc0: 61 73 74 54 6f 6b 65 6e 20 2b 20 69 54 6f 6b 65  astToken + iToke
5fd0: 6e 45 6e 64 0a 20 20 20 20 20 20 20 20 20 20 20  nEnd.           
5fe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ff0: 20 20 20 20 20 20 20 20 20 6e 45 72 72 6f 72 53           nErrorS
6000: 74 61 72 74 20 3d 20 73 65 6c 66 2e 6e 4f 66 66  tart = self.nOff
6010: 73 65 74 57 69 74 68 69 6e 50 61 72 61 67 72 61  setWithinParagra
6020: 70 68 20 2b 20 28 73 65 6c 66 2e 6c 54 6f 6b 65  ph + (self.lToke
6030: 6e 5b 6e 54 6f 6b 65 6e 45 72 72 6f 72 53 74 61  n[nTokenErrorSta
6040: 72 74 5d 5b 22 6e 53 74 61 72 74 22 5d 20 69 66  rt]["nStart"] if
6050: 20 63 53 74 61 72 74 4c 69 6d 69 74 20 3d 3d 20   cStartLimit == 
6060: 22 3c 22 20 20 65 6c 73 65 20 73 65 6c 66 2e 6c  "<"  else self.l
6070: 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 45 72 72 6f  Token[nTokenErro
6080: 72 53 74 61 72 74 5d 5b 22 6e 45 6e 64 22 5d 29  rStart]["nEnd"])
6090: 0a 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 20 20 20 20 20 20                  
60b0: 20 20 20 20 20 6e 45 72 72 6f 72 45 6e 64 20 3d       nErrorEnd =
60c0: 20 73 65 6c 66 2e 6e 4f 66 66 73 65 74 57 69 74   self.nOffsetWit
60d0: 68 69 6e 50 61 72 61 67 72 61 70 68 20 2b 20 28  hinParagraph + (
60e0: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b  self.lToken[nTok
60f0: 65 6e 45 72 72 6f 72 45 6e 64 5d 5b 22 6e 45 6e  enErrorEnd]["nEn
6100: 64 22 5d 20 69 66 20 63 45 6e 64 4c 69 6d 69 74  d"] if cEndLimit
6110: 20 3d 3d 20 22 3e 22 20 20 65 6c 73 65 20 73 65   == ">"  else se
6120: 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e  lf.lToken[nToken
6130: 45 72 72 6f 72 45 6e 64 5d 5b 22 6e 53 74 61 72  ErrorEnd]["nStar
6140: 74 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20  t"]).           
6150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6160: 20 20 20 20 20 20 20 20 20 69 66 20 6e 45 72 72           if nErr
6170: 6f 72 53 74 61 72 74 20 6e 6f 74 20 69 6e 20 73  orStart not in s
6180: 65 6c 66 2e 64 45 72 72 6f 72 20 6f 72 20 6e 50  elf.dError or nP
6190: 72 69 6f 72 69 74 79 20 3e 20 73 65 6c 66 2e 64  riority > self.d
61a0: 45 72 72 6f 72 50 72 69 6f 72 69 74 79 2e 67 65  ErrorPriority.ge
61b0: 74 28 6e 45 72 72 6f 72 53 74 61 72 74 2c 20 2d  t(nErrorStart, -
61c0: 31 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  1):.            
61d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
61e0: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
61f0: 2e 64 45 72 72 6f 72 5b 6e 45 72 72 6f 72 53 74  .dError[nErrorSt
6200: 61 72 74 5d 20 3d 20 73 65 6c 66 2e 5f 63 72 65  art] = self._cre
6210: 61 74 65 45 72 72 6f 72 46 72 6f 6d 54 6f 6b 65  ateErrorFromToke
6220: 6e 73 28 73 57 68 61 74 2c 20 6e 54 6f 6b 65 6e  ns(sWhat, nToken
6230: 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b  Offset, nLastTok
6240: 65 6e 2c 20 6e 54 6f 6b 65 6e 45 72 72 6f 72 53  en, nTokenErrorS
6250: 74 61 72 74 2c 20 6e 45 72 72 6f 72 53 74 61 72  tart, nErrorStar
6260: 74 2c 20 6e 45 72 72 6f 72 45 6e 64 2c 20 73 4c  t, nErrorEnd, sL
6270: 69 6e 65 49 64 2c 20 73 52 75 6c 65 49 64 2c 20  ineId, sRuleId, 
6280: 62 43 61 73 65 53 76 74 79 2c 20 73 4d 65 73 73  bCaseSvty, sMess
6290: 61 67 65 2c 20 73 55 52 4c 2c 20 62 53 68 6f 77  age, sURL, bShow
62a0: 52 75 6c 65 49 64 2c 20 73 4f 70 74 69 6f 6e 2c  RuleId, sOption,
62b0: 20 62 43 6f 6e 74 65 78 74 29 0a 20 20 20 20 20   bContext).     
62c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
62d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
62e0: 20 20 20 73 65 6c 66 2e 64 45 72 72 6f 72 50 72     self.dErrorPr
62f0: 69 6f 72 69 74 79 5b 6e 45 72 72 6f 72 53 74 61  iority[nErrorSta
6300: 72 74 5d 20 3d 20 6e 50 72 69 6f 72 69 74 79 0a  rt] = nPriority.
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 20 20 20 20 20 20                  
6330: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64 53 65          self.dSe
6340: 6e 74 65 6e 63 65 45 72 72 6f 72 5b 6e 45 72 72  ntenceError[nErr
6350: 6f 72 53 74 61 72 74 5d 20 3d 20 73 65 6c 66 2e  orStart] = self.
6360: 64 45 72 72 6f 72 5b 6e 45 72 72 6f 72 53 74 61  dError[nErrorSta
6370: 72 74 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  rt].            
6380: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6390: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62              if b
63a0: 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20  Debug:.         
63b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
63c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
63d0: 20 20 20 65 63 68 6f 28 22 20 20 20 20 4e 45 57     echo("    NEW
63e0: 5f 45 52 52 4f 52 3a 20 7b 7d 22 2e 66 6f 72 6d  _ERROR: {}".form
63f0: 61 74 28 73 65 6c 66 2e 64 45 72 72 6f 72 5b 6e  at(self.dError[n
6400: 45 72 72 6f 72 53 74 61 72 74 5d 29 29 0a 20 20  ErrorStart])).  
6410: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6420: 20 20 20 20 20 20 20 20 20 20 65 6c 69 66 20 63            elif c
6430: 41 63 74 69 6f 6e 54 79 70 65 20 3d 3d 20 22 7e  ActionType == "~
6440: 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ":.             
6450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6460: 20 20 20 23 20 74 65 78 74 20 70 72 6f 63 65 73     # text proces
6470: 73 6f 72 0a 20 20 20 20 20 20 20 20 20 20 20 20  sor.            
6480: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6490: 20 20 20 20 6e 54 6f 6b 65 6e 53 74 61 72 74 20      nTokenStart 
64a0: 3d 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 20 2b  = nTokenOffset +
64b0: 20 65 41 63 74 5b 30 5d 20 20 69 66 20 65 41 63   eAct[0]  if eAc
64c0: 74 5b 30 5d 20 3e 20 30 20 20 65 6c 73 65 20 6e  t[0] > 0  else n
64d0: 4c 61 73 74 54 6f 6b 65 6e 20 2b 20 65 41 63 74  LastToken + eAct
64e0: 5b 30 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  [0].            
64f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6500: 20 20 20 20 6e 54 6f 6b 65 6e 45 6e 64 20 3d 20      nTokenEnd = 
6510: 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 20 2b 20 65  nTokenOffset + e
6520: 41 63 74 5b 31 5d 20 20 69 66 20 65 41 63 74 5b  Act[1]  if eAct[
6530: 31 5d 20 3e 20 30 20 20 65 6c 73 65 20 6e 4c 61  1] > 0  else nLa
6540: 73 74 54 6f 6b 65 6e 20 2b 20 65 41 63 74 5b 31  stToken + eAct[1
6550: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ].              
6560: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6570: 20 20 73 65 6c 66 2e 5f 74 61 67 41 6e 64 50 72    self._tagAndPr
6580: 65 70 61 72 65 54 6f 6b 65 6e 46 6f 72 52 65 77  epareTokenForRew
6590: 72 69 74 69 6e 67 28 73 57 68 61 74 2c 20 6e 54  riting(sWhat, nT
65a0: 6f 6b 65 6e 53 74 61 72 74 2c 20 6e 54 6f 6b 65  okenStart, nToke
65b0: 6e 45 6e 64 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73  nEnd, nTokenOffs
65c0: 65 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 2c 20  et, nLastToken, 
65d0: 65 41 63 74 5b 32 5d 2c 20 62 44 65 62 75 67 29  eAct[2], bDebug)
65e0: 0a 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 20 20 20                  
6600: 20 62 43 68 61 6e 67 65 20 3d 20 54 72 75 65 0a   bChange = True.
6610: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6620: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6630: 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20  if bDebug:.     
6640: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6650: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
6660: 63 68 6f 28 22 20 20 20 20 54 45 58 54 5f 50 52  cho("    TEXT_PR
6670: 4f 43 45 53 53 4f 52 3a 20 5b 7b 7d 3a 7b 7d 5d  OCESSOR: [{}:{}]
6680: 20 20 3e 20 7b 7d 22 2e 66 6f 72 6d 61 74 28 73    > {}".format(s
6690: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65  elf.lToken[nToke
66a0: 6e 53 74 61 72 74 5d 5b 22 73 56 61 6c 75 65 22  nStart]["sValue"
66b0: 5d 2c 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e  ], self.lToken[n
66c0: 54 6f 6b 65 6e 45 6e 64 5d 5b 22 73 56 61 6c 75  TokenEnd]["sValu
66d0: 65 22 5d 2c 20 73 57 68 61 74 29 29 0a 20 20 20  e"], sWhat)).   
66e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
66f0: 20 20 20 20 20 20 20 20 20 65 6c 69 66 20 63 41           elif cA
6700: 63 74 69 6f 6e 54 79 70 65 20 3d 3d 20 22 3d 22  ctionType == "="
6710: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
6720: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6730: 20 20 23 20 64 69 73 61 6d 62 69 67 75 61 74 69    # disambiguati
6740: 6f 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  on.             
6750: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6760: 20 20 20 67 6c 6f 62 61 6c 73 28 29 5b 73 57 68     globals()[sWh
6770: 61 74 5d 28 73 65 6c 66 2e 6c 54 6f 6b 65 6e 2c  at](self.lToken,
6780: 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 6e   nTokenOffset, n
6790: 4c 61 73 74 54 6f 6b 65 6e 29 0a 20 20 20 20 20  LastToken).     
67a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
67b0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44             if bD
67c0: 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20  ebug:.          
67d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
67e0: 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22            echo("
67f0: 20 20 20 20 44 49 53 41 4d 42 49 47 55 41 54 4f      DISAMBIGUATO
6800: 52 3a 20 28 7b 7d 29 20 20 5b 7b 7d 3a 7b 7d 5d  R: ({})  [{}:{}]
6810: 22 2e 66 6f 72 6d 61 74 28 73 57 68 61 74 2c 20  ".format(sWhat, 
6820: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b  self.lToken[nTok
6830: 65 6e 4f 66 66 73 65 74 2b 31 5d 5b 22 73 56 61  enOffset+1]["sVa
6840: 6c 75 65 22 5d 2c 20 73 65 6c 66 2e 6c 54 6f 6b  lue"], self.lTok
6850: 65 6e 5b 6e 4c 61 73 74 54 6f 6b 65 6e 5d 5b 22  en[nLastToken]["
6860: 73 56 61 6c 75 65 22 5d 29 29 0a 20 20 20 20 20  sValue"])).     
6870: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6880: 20 20 20 20 20 20 20 65 6c 69 66 20 63 41 63 74         elif cAct
6890: 69 6f 6e 54 79 70 65 20 3d 3d 20 22 3e 22 3a 0a  ionType == ">":.
68a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
68b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
68c0: 23 20 77 65 20 64 6f 20 6e 6f 74 68 69 6e 67 2c  # we do nothing,
68d0: 20 74 68 69 73 20 74 65 73 74 20 69 73 20 6a 75   this test is ju
68e0: 73 74 20 61 20 63 6f 6e 64 69 74 69 6f 6e 20 74  st a condition t
68f0: 6f 20 61 70 70 6c 79 20 61 6c 6c 20 66 6f 6c 6c  o apply all foll
6900: 6f 77 69 6e 67 20 61 63 74 69 6f 6e 73 0a 20 20  owing actions.  
6910: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6920: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
6930: 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20   bDebug:.       
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 20 20 65 63 68               ech
6960: 6f 28 22 20 20 20 20 43 4f 4e 44 5f 4f 4b 22 29  o("    COND_OK")
6970: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6980: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69               eli
6990: 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20 3d 3d  f cActionType ==
69a0: 20 22 2f 22 3a 0a 20 20 20 20 20 20 20 20 20 20   "/":.          
69b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
69c0: 20 20 20 20 20 20 23 20 54 61 67 0a 20 20 20 20        # Tag.    
69d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
69e0: 20 20 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b              nTok
69f0: 65 6e 53 74 61 72 74 20 3d 20 6e 54 6f 6b 65 6e  enStart = nToken
6a00: 4f 66 66 73 65 74 20 2b 20 65 41 63 74 5b 30 5d  Offset + eAct[0]
6a10: 20 20 69 66 20 65 41 63 74 5b 30 5d 20 3e 20 30    if eAct[0] > 0
6a20: 20 20 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65    else nLastToke
6a30: 6e 20 2b 20 65 41 63 74 5b 30 5d 0a 20 20 20 20  n + eAct[0].    
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 6e 54 6f 6b              nTok
6a60: 65 6e 45 6e 64 20 3d 20 6e 54 6f 6b 65 6e 4f 66  enEnd = nTokenOf
6a70: 66 73 65 74 20 2b 20 65 41 63 74 5b 31 5d 20 20  fset + eAct[1]  
6a80: 69 66 20 65 41 63 74 5b 31 5d 20 3e 20 30 20 20  if eAct[1] > 0  
6a90: 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20  else nLastToken 
6aa0: 2b 20 65 41 63 74 5b 31 5d 0a 20 20 20 20 20 20  + eAct[1].      
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 66 6f 72 20 69 20            for i 
6ad0: 69 6e 20 72 61 6e 67 65 28 6e 54 6f 6b 65 6e 53  in range(nTokenS
6ae0: 74 61 72 74 2c 20 6e 54 6f 6b 65 6e 45 6e 64 2b  tart, nTokenEnd+
6af0: 31 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  1):.            
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 20 69 66 20 22 61 54 61 67          if "aTag
6b20: 73 22 20 69 6e 20 73 65 6c 66 2e 6c 54 6f 6b 65  s" in self.lToke
6b30: 6e 5b 69 5d 3a 0a 20 20 20 20 20 20 20 20 20 20  n[i]:.          
6b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6b50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
6b60: 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 61 54  lf.lToken[i]["aT
6b70: 61 67 73 22 5d 2e 75 70 64 61 74 65 28 73 57 68  ags"].update(sWh
6b80: 61 74 2e 73 70 6c 69 74 28 22 7c 22 29 29 0a 20  at.split("|")). 
6b90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ba0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6bb0: 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20     else:.       
6bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6be0: 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b   self.lToken[i][
6bf0: 22 61 54 61 67 73 22 5d 20 3d 20 73 65 74 28 73  "aTags"] = set(s
6c00: 57 68 61 74 2e 73 70 6c 69 74 28 22 7c 22 29 29  What.split("|"))
6c10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6c20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c30: 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20   if bDebug:.    
6c40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c60: 65 63 68 6f 28 22 20 20 20 20 54 41 47 3a 20 7b  echo("    TAG: {
6c70: 7d 20 3e 20 20 5b 7b 7d 3a 7b 7d 5d 22 2e 66 6f  } >  [{}:{}]".fo
6c80: 72 6d 61 74 28 73 57 68 61 74 2c 20 73 65 6c 66  rmat(sWhat, self
6c90: 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 53 74  .lToken[nTokenSt
6ca0: 61 72 74 5d 5b 22 73 56 61 6c 75 65 22 5d 2c 20  art]["sValue"], 
6cb0: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b  self.lToken[nTok
6cc0: 65 6e 45 6e 64 5d 5b 22 73 56 61 6c 75 65 22 5d  enEnd]["sValue"]
6cd0: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  )).             
6ce0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6cf0: 20 20 20 69 66 20 73 57 68 61 74 20 6e 6f 74 20     if sWhat not 
6d00: 69 6e 20 73 65 6c 66 2e 64 54 61 67 73 3a 0a 20  in self.dTags:. 
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: 20 20 20 73 65 6c 66 2e 64 54 61 67 73 5b 73 57     self.dTags[sW
6d40: 68 61 74 5d 20 3d 20 5b 6e 54 6f 6b 65 6e 53 74  hat] = [nTokenSt
6d50: 61 72 74 2c 20 6e 54 6f 6b 65 6e 53 74 61 72 74  art, nTokenStart
6d60: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ].              
6d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6d80: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
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 20 73 65 6c 66              self
6db0: 2e 64 54 61 67 73 5b 73 57 68 61 74 5d 5b 30 5d  .dTags[sWhat][0]
6dc0: 20 3d 20 6d 69 6e 28 6e 54 6f 6b 65 6e 53 74 61   = min(nTokenSta
6dd0: 72 74 2c 20 73 65 6c 66 2e 64 54 61 67 73 5b 73  rt, self.dTags[s
6de0: 57 68 61 74 5d 5b 30 5d 29 0a 20 20 20 20 20 20  What][0]).      
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 20 20 20 20 20 73 65                se
6e10: 6c 66 2e 64 54 61 67 73 5b 73 57 68 61 74 5d 5b  lf.dTags[sWhat][
6e20: 31 5d 20 3d 20 6d 61 78 28 6e 54 6f 6b 65 6e 45  1] = max(nTokenE
6e30: 6e 64 2c 20 73 65 6c 66 2e 64 54 61 67 73 5b 73  nd, self.dTags[s
6e40: 57 68 61 74 5d 5b 31 5d 29 0a 20 20 20 20 20 20  What][1]).      
6e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6e60: 20 20 20 20 20 20 65 6c 69 66 20 63 41 63 74 69        elif cActi
6e70: 6f 6e 54 79 70 65 20 3d 3d 20 22 21 22 3a 0a 20  onType == "!":. 
6e80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
6ea0: 20 69 6d 6d 75 6e 69 74 79 0a 20 20 20 20 20 20   immunity.      
6eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ec0: 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65            if bDe
6ed0: 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  bug:.           
6ee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ef0: 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 20           echo(" 
6f00: 20 20 20 49 4d 4d 55 4e 49 54 59 3a 20 22 20 2b     IMMUNITY: " +
6f10: 20 73 4c 69 6e 65 49 64 20 2b 20 22 20 2f 20 22   sLineId + " / "
6f20: 20 2b 20 73 52 75 6c 65 49 64 29 0a 20 20 20 20   + sRuleId).    
6f30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6f40: 20 20 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b              nTok
6f50: 65 6e 53 74 61 72 74 20 3d 20 6e 54 6f 6b 65 6e  enStart = nToken
6f60: 4f 66 66 73 65 74 20 2b 20 65 41 63 74 5b 30 5d  Offset + eAct[0]
6f70: 20 20 69 66 20 65 41 63 74 5b 30 5d 20 3e 20 30    if eAct[0] > 0
6f80: 20 20 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65    else nLastToke
6f90: 6e 20 2b 20 65 41 63 74 5b 30 5d 0a 20 20 20 20  n + eAct[0].    
6fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6fb0: 20 20 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b              nTok
6fc0: 65 6e 45 6e 64 20 3d 20 6e 54 6f 6b 65 6e 4f 66  enEnd = nTokenOf
6fd0: 66 73 65 74 20 2b 20 65 41 63 74 5b 31 5d 20 20  fset + eAct[1]  
6fe0: 69 66 20 65 41 63 74 5b 31 5d 20 3e 20 30 20 20  if eAct[1] > 0  
6ff0: 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20  else nLastToken 
7000: 2b 20 65 41 63 74 5b 31 5d 0a 20 20 20 20 20 20  + eAct[1].      
7010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7020: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 54 6f            if nTo
7030: 6b 65 6e 45 6e 64 20 2d 20 6e 54 6f 6b 65 6e 53  kenEnd - nTokenS
7040: 74 61 72 74 20 3d 3d 20 30 3a 0a 20 20 20 20 20  tart == 0:.     
7050: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7060: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
7070: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65  elf.lToken[nToke
7080: 6e 53 74 61 72 74 5d 5b 22 62 49 6d 6d 75 6e 65  nStart]["bImmune
7090: 22 5d 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20  "] = True.      
70a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
70b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 45                nE
70c0: 72 72 6f 72 53 74 61 72 74 20 3d 20 73 65 6c 66  rrorStart = self
70d0: 2e 6e 4f 66 66 73 65 74 57 69 74 68 69 6e 50 61  .nOffsetWithinPa
70e0: 72 61 67 72 61 70 68 20 2b 20 73 65 6c 66 2e 6c  ragraph + self.l
70f0: 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 53 74 61 72  Token[nTokenStar
7100: 74 5d 5b 22 6e 53 74 61 72 74 22 5d 0a 20 20 20  t]["nStart"].   
7110: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7120: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7130: 20 69 66 20 6e 45 72 72 6f 72 53 74 61 72 74 20   if nErrorStart 
7140: 69 6e 20 73 65 6c 66 2e 64 45 72 72 6f 72 3a 0a  in self.dError:.
7150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7160: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7170: 20 20 20 20 20 20 20 20 64 65 6c 20 73 65 6c 66          del self
7180: 2e 64 45 72 72 6f 72 5b 6e 45 72 72 6f 72 53 74  .dError[nErrorSt
7190: 61 72 74 5d 0a 20 20 20 20 20 20 20 20 20 20 20  art].           
71a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
71b0: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
71c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
71d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66                 f
71e0: 6f 72 20 69 20 69 6e 20 72 61 6e 67 65 28 6e 54  or i in range(nT
71f0: 6f 6b 65 6e 53 74 61 72 74 2c 20 6e 54 6f 6b 65  okenStart, nToke
7200: 6e 45 6e 64 2b 31 29 3a 0a 20 20 20 20 20 20 20  nEnd+1):.       
7210: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7220: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7230: 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b   self.lToken[i][
7240: 22 62 49 6d 6d 75 6e 65 22 5d 20 3d 20 54 72 75  "bImmune"] = Tru
7250: 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e.              
7260: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7270: 20 20 20 20 20 20 20 20 20 20 6e 45 72 72 6f 72            nError
7280: 53 74 61 72 74 20 3d 20 73 65 6c 66 2e 6e 4f 66  Start = self.nOf
7290: 66 73 65 74 57 69 74 68 69 6e 50 61 72 61 67 72  fsetWithinParagr
72a0: 61 70 68 20 2b 20 73 65 6c 66 2e 6c 54 6f 6b 65  aph + self.lToke
72b0: 6e 5b 69 5d 5b 22 6e 53 74 61 72 74 22 5d 0a 20  n[i]["nStart"]. 
72c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
72d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
72e0: 20 20 20 20 20 20 20 69 66 20 6e 45 72 72 6f 72         if nError
72f0: 53 74 61 72 74 20 69 6e 20 73 65 6c 66 2e 64 45  Start in self.dE
7300: 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20 20 20  rror:.          
7310: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7320: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7330: 20 20 64 65 6c 20 73 65 6c 66 2e 64 45 72 72 6f    del self.dErro
7340: 72 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d 0a 20  r[nErrorStart]. 
7350: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7360: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
7370: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
7380: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7390: 20 65 63 68 6f 28 22 23 20 65 72 72 6f 72 3a 20   echo("# error: 
73a0: 75 6e 6b 6e 6f 77 6e 20 61 63 74 69 6f 6e 20 61  unknown action a
73b0: 74 20 22 20 2b 20 73 4c 69 6e 65 49 64 29 0a 20  t " + sLineId). 
73c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
73d0: 20 20 20 20 20 20 20 65 6c 69 66 20 63 41 63 74         elif cAct
73e0: 69 6f 6e 54 79 70 65 20 3d 3d 20 22 3e 22 3a 0a  ionType == ">":.
73f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7400: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62              if b
7410: 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20  Debug:.         
7420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7430: 20 20 20 20 20 20 20 65 63 68 6f 28 22 20 20 20         echo("   
7440: 20 43 4f 4e 44 5f 42 52 45 41 4b 22 29 0a 20 20   COND_BREAK").  
7450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7460: 20 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 0a            break.
7470: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7480: 65 78 63 65 70 74 20 45 78 63 65 70 74 69 6f 6e  except Exception
7490: 20 61 73 20 65 3a 0a 20 20 20 20 20 20 20 20 20   as e:.         
74a0: 20 20 20 20 20 20 20 20 20 20 20 72 61 69 73 65             raise
74b0: 20 45 78 63 65 70 74 69 6f 6e 28 73 74 72 28 65   Exception(str(e
74c0: 29 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c  ), sLineId, sRul
74d0: 65 49 64 2c 20 73 65 6c 66 2e 73 53 65 6e 74 65  eId, self.sSente
74e0: 6e 63 65 29 0a 20 20 20 20 20 20 20 20 72 65 74  nce).        ret
74f0: 75 72 6e 20 62 43 68 61 6e 67 65 0a 0a 20 20 20  urn bChange..   
7500: 20 64 65 66 20 5f 63 72 65 61 74 65 45 72 72 6f   def _createErro
7510: 72 46 72 6f 6d 52 65 67 65 78 20 28 73 65 6c 66  rFromRegex (self
7520: 2c 20 73 54 65 78 74 2c 20 73 54 65 78 74 30 2c  , sText, sText0,
7530: 20 73 52 65 70 6c 2c 20 6e 4f 66 66 73 65 74 2c   sRepl, nOffset,
7540: 20 6d 2c 20 69 47 72 6f 75 70 2c 20 73 4c 69 6e   m, iGroup, sLin
7550: 65 49 64 2c 20 73 52 75 6c 65 49 64 2c 20 62 55  eId, sRuleId, bU
7560: 70 70 65 72 63 61 73 65 2c 20 73 4d 73 67 2c 20  ppercase, sMsg, 
7570: 73 55 52 4c 2c 20 62 53 68 6f 77 52 75 6c 65 49  sURL, bShowRuleI
7580: 64 2c 20 73 4f 70 74 69 6f 6e 2c 20 62 43 6f 6e  d, sOption, bCon
7590: 74 65 78 74 29 3a 0a 20 20 20 20 20 20 20 20 6e  text):.        n
75a0: 53 74 61 72 74 20 3d 20 6e 4f 66 66 73 65 74 20  Start = nOffset 
75b0: 2b 20 6d 2e 73 74 61 72 74 28 69 47 72 6f 75 70  + m.start(iGroup
75c0: 29 0a 20 20 20 20 20 20 20 20 6e 45 6e 64 20 3d  ).        nEnd =
75d0: 20 6e 4f 66 66 73 65 74 20 2b 20 6d 2e 65 6e 64   nOffset + m.end
75e0: 28 69 47 72 6f 75 70 29 0a 20 20 20 20 20 20 20  (iGroup).       
75f0: 20 23 20 73 75 67 67 65 73 74 69 6f 6e 73 0a 20   # suggestions. 
7600: 20 20 20 20 20 20 20 69 66 20 73 52 65 70 6c 5b         if sRepl[
7610: 30 3a 31 5d 20 3d 3d 20 22 3d 22 3a 0a 20 20 20  0:1] == "=":.   
7620: 20 20 20 20 20 20 20 20 20 73 53 75 67 67 20 3d           sSugg =
7630: 20 67 6c 6f 62 61 6c 73 28 29 5b 73 52 65 70 6c   globals()[sRepl
7640: 5b 31 3a 5d 5d 28 73 54 65 78 74 2c 20 6d 29 0a  [1:]](sText, m).
7650: 20 20 20 20 20 20 20 20 20 20 20 20 6c 53 75 67              lSug
7660: 67 20 3d 20 73 53 75 67 67 2e 73 70 6c 69 74 28  g = sSugg.split(
7670: 22 7c 22 29 20 20 69 66 20 73 53 75 67 67 20 20  "|")  if sSugg  
7680: 65 6c 73 65 20 5b 5d 0a 20 20 20 20 20 20 20 20  else [].        
7690: 65 6c 69 66 20 73 52 65 70 6c 20 3d 3d 20 22 5f  elif sRepl == "_
76a0: 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6c  ":.            l
76b0: 53 75 67 67 20 3d 20 5b 5d 0a 20 20 20 20 20 20  Sugg = [].      
76c0: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
76d0: 20 20 20 20 6c 53 75 67 67 20 3d 20 6d 2e 65 78      lSugg = m.ex
76e0: 70 61 6e 64 28 73 52 65 70 6c 29 2e 73 70 6c 69  pand(sRepl).spli
76f0: 74 28 22 7c 22 29 0a 20 20 20 20 20 20 20 20 69  t("|").        i
7700: 66 20 62 55 70 70 65 72 63 61 73 65 20 61 6e 64  f bUppercase and
7710: 20 6c 53 75 67 67 20 61 6e 64 20 6d 2e 67 72 6f   lSugg and m.gro
7720: 75 70 28 69 47 72 6f 75 70 29 5b 30 3a 31 5d 2e  up(iGroup)[0:1].
7730: 69 73 75 70 70 65 72 28 29 3a 0a 20 20 20 20 20  isupper():.     
7740: 20 20 20 20 20 20 20 6c 53 75 67 67 20 3d 20 6c         lSugg = l
7750: 69 73 74 28 6d 61 70 28 6c 61 6d 62 64 61 20 73  ist(map(lambda s
7760: 3a 20 73 5b 30 3a 31 5d 2e 75 70 70 65 72 28 29  : s[0:1].upper()
7770: 2b 73 5b 31 3a 5d 2c 20 6c 53 75 67 67 29 29 0a  +s[1:], lSugg)).
7780: 20 20 20 20 20 20 20 20 23 20 4d 65 73 73 61 67          # Messag
7790: 65 0a 20 20 20 20 20 20 20 20 73 4d 65 73 73 61  e.        sMessa
77a0: 67 65 20 3d 20 67 6c 6f 62 61 6c 73 28 29 5b 73  ge = globals()[s
77b0: 4d 73 67 5b 31 3a 5d 5d 28 73 54 65 78 74 2c 20  Msg[1:]](sText, 
77c0: 6d 29 20 20 69 66 20 73 4d 73 67 5b 30 3a 31 5d  m)  if sMsg[0:1]
77d0: 20 3d 3d 20 22 3d 22 20 20 65 6c 73 65 20 20 6d   == "="  else  m
77e0: 2e 65 78 70 61 6e 64 28 73 4d 73 67 29 0a 20 20  .expand(sMsg).  
77f0: 20 20 20 20 20 20 69 66 20 62 53 68 6f 77 52 75        if bShowRu
7800: 6c 65 49 64 3a 0a 20 20 20 20 20 20 20 20 20 20  leId:.          
7810: 20 20 73 4d 65 73 73 61 67 65 20 2b 3d 20 22 20    sMessage += " 
7820: 20 23 22 20 2b 20 73 4c 69 6e 65 49 64 20 2b 20   #" + sLineId + 
7830: 22 20 2f 20 22 20 2b 20 73 52 75 6c 65 49 64 0a  " / " + sRuleId.
7840: 20 20 20 20 20 20 20 20 23 0a 20 20 20 20 20 20          #.      
7850: 20 20 69 66 20 5f 62 57 72 69 74 65 72 45 72 72    if _bWriterErr
7860: 6f 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  or:.            
7870: 72 65 74 75 72 6e 20 73 65 6c 66 2e 5f 63 72 65  return self._cre
7880: 61 74 65 45 72 72 6f 72 46 6f 72 57 72 69 74 65  ateErrorForWrite
7890: 72 28 6e 53 74 61 72 74 2c 20 6e 45 6e 64 20 2d  r(nStart, nEnd -
78a0: 20 6e 53 74 61 72 74 2c 20 73 52 75 6c 65 49 64   nStart, sRuleId
78b0: 2c 20 73 4f 70 74 69 6f 6e 2c 20 73 4d 65 73 73  , sOption, sMess
78c0: 61 67 65 2c 20 6c 53 75 67 67 2c 20 73 55 52 4c  age, lSugg, sURL
78d0: 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ).        return
78e0: 20 73 65 6c 66 2e 5f 63 72 65 61 74 65 45 72 72   self._createErr
78f0: 6f 72 41 73 44 69 63 74 28 6e 53 74 61 72 74 2c  orAsDict(nStart,
7900: 20 6e 45 6e 64 2c 20 73 4c 69 6e 65 49 64 2c 20   nEnd, sLineId, 
7910: 73 52 75 6c 65 49 64 2c 20 73 4f 70 74 69 6f 6e  sRuleId, sOption
7920: 2c 20 73 4d 65 73 73 61 67 65 2c 20 6c 53 75 67  , sMessage, lSug
7930: 67 2c 20 73 55 52 4c 2c 20 62 43 6f 6e 74 65 78  g, sURL, bContex
7940: 74 29 0a 0a 20 20 20 20 64 65 66 20 5f 63 72 65  t)..    def _cre
7950: 61 74 65 45 72 72 6f 72 46 72 6f 6d 54 6f 6b 65  ateErrorFromToke
7960: 6e 73 20 28 73 65 6c 66 2c 20 73 53 75 67 67 2c  ns (self, sSugg,
7970: 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 6e   nTokenOffset, n
7980: 4c 61 73 74 54 6f 6b 65 6e 2c 20 69 46 69 72 73  LastToken, iFirs
7990: 74 54 6f 6b 65 6e 2c 20 6e 53 74 61 72 74 2c 20  tToken, nStart, 
79a0: 6e 45 6e 64 2c 20 73 4c 69 6e 65 49 64 2c 20 73  nEnd, sLineId, s
79b0: 52 75 6c 65 49 64 2c 20 62 43 61 73 65 53 76 74  RuleId, bCaseSvt
79c0: 79 2c 20 73 4d 73 67 2c 20 73 55 52 4c 2c 20 62  y, sMsg, sURL, b
79d0: 53 68 6f 77 52 75 6c 65 49 64 2c 20 73 4f 70 74  ShowRuleId, sOpt
79e0: 69 6f 6e 2c 20 62 43 6f 6e 74 65 78 74 29 3a 0a  ion, bContext):.
79f0: 20 20 20 20 20 20 20 20 23 20 73 75 67 67 65 73          # sugges
7a00: 74 69 6f 6e 73 0a 20 20 20 20 20 20 20 20 69 66  tions.        if
7a10: 20 73 53 75 67 67 5b 30 3a 31 5d 20 3d 3d 20 22   sSugg[0:1] == "
7a20: 3d 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  =":.            
7a30: 73 53 75 67 67 20 3d 20 67 6c 6f 62 61 6c 73 28  sSugg = globals(
7a40: 29 5b 73 53 75 67 67 5b 31 3a 5d 5d 28 73 65 6c  )[sSugg[1:]](sel
7a50: 66 2e 6c 54 6f 6b 65 6e 2c 20 6e 54 6f 6b 65 6e  f.lToken, nToken
7a60: 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b  Offset, nLastTok
7a70: 65 6e 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  en).            
7a80: 6c 53 75 67 67 20 3d 20 73 53 75 67 67 2e 73 70  lSugg = sSugg.sp
7a90: 6c 69 74 28 22 7c 22 29 20 20 69 66 20 73 53 75  lit("|")  if sSu
7aa0: 67 67 20 20 65 6c 73 65 20 5b 5d 0a 20 20 20 20  gg  else [].    
7ab0: 20 20 20 20 65 6c 69 66 20 73 53 75 67 67 20 3d      elif sSugg =
7ac0: 3d 20 22 5f 22 3a 0a 20 20 20 20 20 20 20 20 20  = "_":.         
7ad0: 20 20 20 6c 53 75 67 67 20 3d 20 5b 5d 0a 20 20     lSugg = [].  
7ae0: 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20        else:.    
7af0: 20 20 20 20 20 20 20 20 6c 53 75 67 67 20 3d 20          lSugg = 
7b00: 73 65 6c 66 2e 5f 65 78 70 61 6e 64 28 73 53 75  self._expand(sSu
7b10: 67 67 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74  gg, nTokenOffset
7b20: 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 29 2e 73 70  , nLastToken).sp
7b30: 6c 69 74 28 22 7c 22 29 0a 20 20 20 20 20 20 20  lit("|").       
7b40: 20 69 66 20 62 43 61 73 65 53 76 74 79 20 61 6e   if bCaseSvty an
7b50: 64 20 6c 53 75 67 67 20 61 6e 64 20 73 65 6c 66  d lSugg and self
7b60: 2e 6c 54 6f 6b 65 6e 5b 69 46 69 72 73 74 54 6f  .lToken[iFirstTo
7b70: 6b 65 6e 5d 5b 22 73 56 61 6c 75 65 22 5d 5b 30  ken]["sValue"][0
7b80: 3a 31 5d 2e 69 73 75 70 70 65 72 28 29 3a 0a 20  :1].isupper():. 
7b90: 20 20 20 20 20 20 20 20 20 20 20 6c 53 75 67 67             lSugg
7ba0: 20 3d 20 6c 69 73 74 28 6d 61 70 28 6c 61 6d 62   = list(map(lamb
7bb0: 64 61 20 73 3a 20 73 5b 30 3a 31 5d 2e 75 70 70  da s: s[0:1].upp
7bc0: 65 72 28 29 2b 73 5b 31 3a 5d 2c 20 6c 53 75 67  er()+s[1:], lSug
7bd0: 67 29 29 0a 20 20 20 20 20 20 20 20 23 20 4d 65  g)).        # Me
7be0: 73 73 61 67 65 0a 20 20 20 20 20 20 20 20 73 4d  ssage.        sM
7bf0: 65 73 73 61 67 65 20 3d 20 67 6c 6f 62 61 6c 73  essage = globals
7c00: 28 29 5b 73 4d 73 67 5b 31 3a 5d 5d 28 73 65 6c  ()[sMsg[1:]](sel
7c10: 66 2e 6c 54 6f 6b 65 6e 2c 20 6e 54 6f 6b 65 6e  f.lToken, nToken
7c20: 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b  Offset, nLastTok
7c30: 65 6e 29 20 20 69 66 20 73 4d 73 67 5b 30 3a 31  en)  if sMsg[0:1
7c40: 5d 20 3d 3d 20 22 3d 22 20 20 65 6c 73 65 20 73  ] == "="  else s
7c50: 65 6c 66 2e 5f 65 78 70 61 6e 64 28 73 4d 73 67  elf._expand(sMsg
7c60: 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2c 20  , nTokenOffset, 
7c70: 6e 4c 61 73 74 54 6f 6b 65 6e 29 0a 20 20 20 20  nLastToken).    
7c80: 20 20 20 20 69 66 20 62 53 68 6f 77 52 75 6c 65      if bShowRule
7c90: 49 64 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  Id:.            
7ca0: 73 4d 65 73 73 61 67 65 20 2b 3d 20 22 20 20 23  sMessage += "  #
7cb0: 22 20 2b 20 73 4c 69 6e 65 49 64 20 2b 20 22 20  " + sLineId + " 
7cc0: 2f 20 22 20 2b 20 73 52 75 6c 65 49 64 0a 20 20  / " + sRuleId.  
7cd0: 20 20 20 20 20 20 23 0a 20 20 20 20 20 20 20 20        #.        
7ce0: 69 66 20 5f 62 57 72 69 74 65 72 45 72 72 6f 72  if _bWriterError
7cf0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  :.            re
7d00: 74 75 72 6e 20 73 65 6c 66 2e 5f 63 72 65 61 74  turn self._creat
7d10: 65 45 72 72 6f 72 46 6f 72 57 72 69 74 65 72 28  eErrorForWriter(
7d20: 6e 53 74 61 72 74 2c 20 6e 45 6e 64 20 2d 20 6e  nStart, nEnd - n
7d30: 53 74 61 72 74 2c 20 73 52 75 6c 65 49 64 2c 20  Start, sRuleId, 
7d40: 73 4f 70 74 69 6f 6e 2c 20 73 4d 65 73 73 61 67  sOption, sMessag
7d50: 65 2c 20 6c 53 75 67 67 2c 20 73 55 52 4c 29 0a  e, lSugg, sURL).
7d60: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 73          return s
7d70: 65 6c 66 2e 5f 63 72 65 61 74 65 45 72 72 6f 72  elf._createError
7d80: 41 73 44 69 63 74 28 6e 53 74 61 72 74 2c 20 6e  AsDict(nStart, n
7d90: 45 6e 64 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52  End, sLineId, sR
7da0: 75 6c 65 49 64 2c 20 73 4f 70 74 69 6f 6e 2c 20  uleId, sOption, 
7db0: 73 4d 65 73 73 61 67 65 2c 20 6c 53 75 67 67 2c  sMessage, lSugg,
7dc0: 20 73 55 52 4c 2c 20 62 43 6f 6e 74 65 78 74 29   sURL, bContext)
7dd0: 0a 0a 20 20 20 20 64 65 66 20 5f 63 72 65 61 74  ..    def _creat
7de0: 65 45 72 72 6f 72 46 6f 72 57 72 69 74 65 72 20  eErrorForWriter 
7df0: 28 73 65 6c 66 2c 20 6e 53 74 61 72 74 2c 20 6e  (self, nStart, n
7e00: 4c 65 6e 2c 20 73 52 75 6c 65 49 64 2c 20 73 4f  Len, sRuleId, sO
7e10: 70 74 69 6f 6e 2c 20 73 4d 65 73 73 61 67 65 2c  ption, sMessage,
7e20: 20 6c 53 75 67 67 2c 20 73 55 52 4c 29 3a 0a 20   lSugg, sURL):. 
7e30: 20 20 20 20 20 20 20 78 45 72 72 20 3d 20 53 69         xErr = Si
7e40: 6e 67 6c 65 50 72 6f 6f 66 72 65 61 64 69 6e 67  ngleProofreading
7e50: 45 72 72 6f 72 28 29 20 20 20 20 23 20 75 6e 6f  Error()    # uno
7e60: 2e 63 72 65 61 74 65 55 6e 6f 53 74 72 75 63 74  .createUnoStruct
7e70: 28 20 22 63 6f 6d 2e 73 75 6e 2e 73 74 61 72 2e  ( "com.sun.star.
7e80: 6c 69 6e 67 75 69 73 74 69 63 32 2e 53 69 6e 67  linguistic2.Sing
7e90: 6c 65 50 72 6f 6f 66 72 65 61 64 69 6e 67 45 72  leProofreadingEr
7ea0: 72 6f 72 22 20 29 0a 20 20 20 20 20 20 20 20 78  ror" ).        x
7eb0: 45 72 72 2e 6e 45 72 72 6f 72 53 74 61 72 74 20  Err.nErrorStart 
7ec0: 3d 20 6e 53 74 61 72 74 0a 20 20 20 20 20 20 20  = nStart.       
7ed0: 20 78 45 72 72 2e 6e 45 72 72 6f 72 4c 65 6e 67   xErr.nErrorLeng
7ee0: 74 68 20 3d 20 6e 4c 65 6e 0a 20 20 20 20 20 20  th = nLen.      
7ef0: 20 20 78 45 72 72 2e 6e 45 72 72 6f 72 54 79 70    xErr.nErrorTyp
7f00: 65 20 3d 20 50 52 4f 4f 46 52 45 41 44 49 4e 47  e = PROOFREADING
7f10: 0a 20 20 20 20 20 20 20 20 78 45 72 72 2e 61 52  .        xErr.aR
7f20: 75 6c 65 49 64 65 6e 74 69 66 69 65 72 20 3d 20  uleIdentifier = 
7f30: 73 52 75 6c 65 49 64 0a 20 20 20 20 20 20 20 20  sRuleId.        
7f40: 78 45 72 72 2e 61 53 68 6f 72 74 43 6f 6d 6d 65  xErr.aShortComme
7f50: 6e 74 20 3d 20 73 4d 65 73 73 61 67 65 20 20 20  nt = sMessage   
7f60: 23 20 73 4d 65 73 73 61 67 65 2e 73 70 6c 69 74  # sMessage.split
7f70: 28 22 7c 22 29 5b 30 5d 20 20 20 20 20 23 20 69  ("|")[0]     # i
7f80: 6e 20 63 6f 6e 74 65 78 74 20 6d 65 6e 75 0a 20  n context menu. 
7f90: 20 20 20 20 20 20 20 78 45 72 72 2e 61 46 75 6c         xErr.aFul
7fa0: 6c 43 6f 6d 6d 65 6e 74 20 3d 20 73 4d 65 73 73  lComment = sMess
7fb0: 61 67 65 20 20 20 20 23 20 73 4d 65 73 73 61 67  age    # sMessag
7fc0: 65 2e 73 70 6c 69 74 28 22 7c 22 29 5b 2d 31 5d  e.split("|")[-1]
7fd0: 20 20 20 20 23 20 69 6e 20 64 69 61 6c 6f 67 0a      # in dialog.
7fe0: 20 20 20 20 20 20 20 20 78 45 72 72 2e 61 53 75          xErr.aSu
7ff0: 67 67 65 73 74 69 6f 6e 73 20 3d 20 74 75 70 6c  ggestions = tupl
8000: 65 28 6c 53 75 67 67 29 0a 20 20 20 20 20 20 20  e(lSugg).       
8010: 20 23 20 50 72 6f 70 65 72 74 69 65 73 0a 20 20   # Properties.  
8020: 20 20 20 20 20 20 6c 50 72 6f 70 65 72 74 69 65        lPropertie
8030: 73 20 3d 20 5b 0a 20 20 20 20 20 20 20 20 20 20  s = [.          
8040: 20 20 50 72 6f 70 65 72 74 79 56 61 6c 75 65 28    PropertyValue(
8050: 4e 61 6d 65 3d 22 4c 69 6e 65 54 79 70 65 22 2c  Name="LineType",
8060: 20 56 61 6c 75 65 3d 31 38 29 2c 20 23 20 57 41   Value=18), # WA
8070: 56 45 3a 20 31 30 2c 20 44 41 53 48 3a 20 35 2c  VE: 10, DASH: 5,
8080: 20 42 4f 4c 44 3a 20 31 32 2c 20 42 4f 4c 44 57   BOLD: 12, BOLDW
8090: 41 56 45 3a 20 31 38 20 68 74 74 70 73 3a 2f 2f  AVE: 18 https://
80a0: 61 70 69 2e 6c 69 62 72 65 6f 66 66 69 63 65 2e  api.libreoffice.
80b0: 6f 72 67 2f 64 6f 63 73 2f 69 64 6c 2f 72 65 66  org/docs/idl/ref
80c0: 2f 46 6f 6e 74 55 6e 64 65 72 6c 69 6e 65 5f 38  /FontUnderline_8
80d0: 69 64 6c 2e 68 74 6d 6c 0a 20 20 20 20 20 20 20  idl.html.       
80e0: 20 20 20 20 20 50 72 6f 70 65 72 74 79 56 61 6c       PropertyVal
80f0: 75 65 28 4e 61 6d 65 3d 22 4c 69 6e 65 43 6f 6c  ue(Name="LineCol
8100: 6f 72 22 2c 20 56 61 6c 75 65 3d 5f 64 4f 70 74  or", Value=_dOpt
8110: 69 6f 6e 73 43 6f 6c 6f 72 73 2e 67 65 74 28 73  ionsColors.get(s
8120: 4f 70 74 69 6f 6e 2c 20 33 33 30 32 33 29 29 0a  Option, 33023)).
8130: 20 20 20 20 20 20 20 20 5d 0a 20 20 20 20 20 20          ].      
8140: 20 20 69 66 20 73 55 52 4c 3a 0a 20 20 20 20 20    if sURL:.     
8150: 20 20 20 20 20 20 20 6c 50 72 6f 70 65 72 74 69         lProperti
8160: 65 73 2e 61 70 70 65 6e 64 28 50 72 6f 70 65 72  es.append(Proper
8170: 74 79 56 61 6c 75 65 28 4e 61 6d 65 3d 22 46 75  tyValue(Name="Fu
8180: 6c 6c 43 6f 6d 6d 65 6e 74 55 52 4c 22 2c 20 56  llCommentURL", V
8190: 61 6c 75 65 3d 73 55 52 4c 29 29 0a 20 20 20 20  alue=sURL)).    
81a0: 20 20 20 20 78 45 72 72 2e 61 50 72 6f 70 65 72      xErr.aProper
81b0: 74 69 65 73 20 3d 20 6c 50 72 6f 70 65 72 74 69  ties = lProperti
81c0: 65 73 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  es.        retur
81d0: 6e 20 78 45 72 72 0a 0a 20 20 20 20 64 65 66 20  n xErr..    def 
81e0: 5f 63 72 65 61 74 65 45 72 72 6f 72 41 73 44 69  _createErrorAsDi
81f0: 63 74 20 28 73 65 6c 66 2c 20 6e 53 74 61 72 74  ct (self, nStart
8200: 2c 20 6e 45 6e 64 2c 20 73 4c 69 6e 65 49 64 2c  , nEnd, sLineId,
8210: 20 73 52 75 6c 65 49 64 2c 20 73 4f 70 74 69 6f   sRuleId, sOptio
8220: 6e 2c 20 73 4d 65 73 73 61 67 65 2c 20 6c 53 75  n, sMessage, lSu
8230: 67 67 2c 20 73 55 52 4c 2c 20 62 43 6f 6e 74 65  gg, sURL, bConte
8240: 78 74 29 3a 0a 20 20 20 20 20 20 20 20 64 45 72  xt):.        dEr
8250: 72 20 3d 20 7b 0a 20 20 20 20 20 20 20 20 20 20  r = {.          
8260: 20 20 22 6e 53 74 61 72 74 22 3a 20 6e 53 74 61    "nStart": nSta
8270: 72 74 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  rt,.            
8280: 22 6e 45 6e 64 22 3a 20 6e 45 6e 64 2c 0a 20 20  "nEnd": nEnd,.  
8290: 20 20 20 20 20 20 20 20 20 20 22 73 4c 69 6e 65            "sLine
82a0: 49 64 22 3a 20 73 4c 69 6e 65 49 64 2c 0a 20 20  Id": sLineId,.  
82b0: 20 20 20 20 20 20 20 20 20 20 22 73 52 75 6c 65            "sRule
82c0: 49 64 22 3a 20 73 52 75 6c 65 49 64 2c 0a 20 20  Id": sRuleId,.  
82d0: 20 20 20 20 20 20 20 20 20 20 22 73 54 79 70 65            "sType
82e0: 22 3a 20 73 4f 70 74 69 6f 6e 20 20 69 66 20 73  ": sOption  if s
82f0: 4f 70 74 69 6f 6e 20 20 65 6c 73 65 20 22 6e 6f  Option  else "no
8300: 74 79 70 65 22 2c 0a 20 20 20 20 20 20 20 20 20  type",.         
8310: 20 20 20 22 61 43 6f 6c 6f 72 22 3a 20 5f 64 4f     "aColor": _dO
8320: 70 74 69 6f 6e 73 43 6f 6c 6f 72 73 2e 67 65 74  ptionsColors.get
8330: 28 73 4f 70 74 69 6f 6e 2c 20 4e 6f 6e 65 29 2c  (sOption, None),
8340: 0a 20 20 20 20 20 20 20 20 20 20 20 20 22 73 4d  .            "sM
8350: 65 73 73 61 67 65 22 3a 20 73 4d 65 73 73 61 67  essage": sMessag
8360: 65 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 22  e,.            "
8370: 61 53 75 67 67 65 73 74 69 6f 6e 73 22 3a 20 6c  aSuggestions": l
8380: 53 75 67 67 2c 0a 20 20 20 20 20 20 20 20 20 20  Sugg,.          
8390: 20 20 22 55 52 4c 22 3a 20 73 55 52 4c 0a 20 20    "URL": sURL.  
83a0: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 20 20        }.        
83b0: 69 66 20 62 43 6f 6e 74 65 78 74 3a 0a 20 20 20  if bContext:.   
83c0: 20 20 20 20 20 20 20 20 20 64 45 72 72 5b 27 73           dErr['s
83d0: 55 6e 64 65 72 6c 69 6e 65 64 27 5d 20 3d 20 73  Underlined'] = s
83e0: 65 6c 66 2e 73 54 65 78 74 30 5b 6e 53 74 61 72  elf.sText0[nStar
83f0: 74 3a 6e 45 6e 64 5d 0a 20 20 20 20 20 20 20 20  t:nEnd].        
8400: 20 20 20 20 64 45 72 72 5b 27 73 42 65 66 6f 72      dErr['sBefor
8410: 65 27 5d 20 3d 20 73 65 6c 66 2e 73 54 65 78 74  e'] = self.sText
8420: 30 5b 6d 61 78 28 30 2c 6e 53 74 61 72 74 2d 38  0[max(0,nStart-8
8430: 30 29 3a 6e 53 74 61 72 74 5d 0a 20 20 20 20 20  0):nStart].     
8440: 20 20 20 20 20 20 20 64 45 72 72 5b 27 73 41 66         dErr['sAf
8450: 74 65 72 27 5d 20 3d 20 73 65 6c 66 2e 73 54 65  ter'] = self.sTe
8460: 78 74 30 5b 6e 45 6e 64 3a 6e 45 6e 64 2b 38 30  xt0[nEnd:nEnd+80
8470: 5d 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ].        return
8480: 20 64 45 72 72 0a 0a 20 20 20 20 64 65 66 20 5f   dErr..    def _
8490: 65 78 70 61 6e 64 20 28 73 65 6c 66 2c 20 73 54  expand (self, sT
84a0: 65 78 74 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65  ext, nTokenOffse
84b0: 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 29 3a 0a  t, nLastToken):.
84c0: 20 20 20 20 20 20 20 20 66 6f 72 20 6d 20 69 6e          for m in
84d0: 20 72 65 2e 66 69 6e 64 69 74 65 72 28 72 22 5c   re.finditer(r"\
84e0: 5c 28 2d 3f 5b 30 2d 39 5d 2b 29 22 2c 20 73 54  \(-?[0-9]+)", sT
84f0: 65 78 74 29 3a 0a 20 20 20 20 20 20 20 20 20 20  ext):.          
8500: 20 20 69 66 20 6d 2e 67 72 6f 75 70 28 31 29 5b    if m.group(1)[
8510: 30 3a 31 5d 20 3d 3d 20 22 2d 22 3a 0a 20 20 20  0:1] == "-":.   
8520: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 54 65               sTe
8530: 78 74 20 3d 20 73 54 65 78 74 2e 72 65 70 6c 61  xt = sText.repla
8540: 63 65 28 6d 2e 67 72 6f 75 70 28 30 29 2c 20 73  ce(m.group(0), s
8550: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 4c 61 73 74  elf.lToken[nLast
8560: 54 6f 6b 65 6e 2b 69 6e 74 28 6d 2e 67 72 6f 75  Token+int(m.grou
8570: 70 28 31 29 29 2b 31 5d 5b 22 73 56 61 6c 75 65  p(1))+1]["sValue
8580: 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  "]).            
8590: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
85a0: 20 20 20 20 20 20 73 54 65 78 74 20 3d 20 73 54        sText = sT
85b0: 65 78 74 2e 72 65 70 6c 61 63 65 28 6d 2e 67 72  ext.replace(m.gr
85c0: 6f 75 70 28 30 29 2c 20 73 65 6c 66 2e 6c 54 6f  oup(0), self.lTo
85d0: 6b 65 6e 5b 6e 54 6f 6b 65 6e 4f 66 66 73 65 74  ken[nTokenOffset
85e0: 2b 69 6e 74 28 6d 2e 67 72 6f 75 70 28 31 29 29  +int(m.group(1))
85f0: 5d 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20  ]["sValue"]).   
8600: 20 20 20 20 20 72 65 74 75 72 6e 20 73 54 65 78       return sTex
8610: 74 0a 0a 20 20 20 20 64 65 66 20 72 65 77 72 69  t..    def rewri
8620: 74 65 54 65 78 74 20 28 73 65 6c 66 2c 20 73 54  teText (self, sT
8630: 65 78 74 2c 20 73 52 65 70 6c 2c 20 69 47 72 6f  ext, sRepl, iGro
8640: 75 70 2c 20 6d 2c 20 62 55 70 70 65 72 63 61 73  up, m, bUppercas
8650: 65 29 3a 0a 20 20 20 20 20 20 20 20 22 74 65 78  e):.        "tex
8660: 74 20 70 72 6f 63 65 73 73 6f 72 3a 20 77 72 69  t processor: wri
8670: 74 65 20 3c 73 52 65 70 6c 3e 20 69 6e 20 3c 73  te <sRepl> in <s
8680: 54 65 78 74 3e 20 61 74 20 3c 69 47 72 6f 75 70  Text> at <iGroup
8690: 3e 20 70 6f 73 69 74 69 6f 6e 22 0a 20 20 20 20  > position".    
86a0: 20 20 20 20 6e 4c 65 6e 20 3d 20 6d 2e 65 6e 64      nLen = m.end
86b0: 28 69 47 72 6f 75 70 29 20 2d 20 6d 2e 73 74 61  (iGroup) - m.sta
86c0: 72 74 28 69 47 72 6f 75 70 29 0a 20 20 20 20 20  rt(iGroup).     
86d0: 20 20 20 69 66 20 73 52 65 70 6c 20 3d 3d 20 22     if sRepl == "
86e0: 2a 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  *":.            
86f0: 73 4e 65 77 20 3d 20 22 20 22 20 2a 20 6e 4c 65  sNew = " " * nLe
8700: 6e 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 73  n.        elif s
8710: 52 65 70 6c 20 3d 3d 20 22 5f 22 3a 0a 20 20 20  Repl == "_":.   
8720: 20 20 20 20 20 20 20 20 20 73 4e 65 77 20 3d 20           sNew = 
8730: 22 5f 22 20 2a 20 6e 4c 65 6e 0a 20 20 20 20 20  "_" * nLen.     
8740: 20 20 20 65 6c 69 66 20 73 52 65 70 6c 20 3d 3d     elif sRepl ==
8750: 20 22 40 22 3a 0a 20 20 20 20 20 20 20 20 20 20   "@":.          
8760: 20 20 73 4e 65 77 20 3d 20 22 40 22 20 2a 20 6e    sNew = "@" * n
8770: 4c 65 6e 0a 20 20 20 20 20 20 20 20 65 6c 69 66  Len.        elif
8780: 20 73 52 65 70 6c 5b 30 3a 31 5d 20 3d 3d 20 22   sRepl[0:1] == "
8790: 3d 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  =":.            
87a0: 73 4e 65 77 20 3d 20 67 6c 6f 62 61 6c 73 28 29  sNew = globals()
87b0: 5b 73 52 65 70 6c 5b 31 3a 5d 5d 28 73 54 65 78  [sRepl[1:]](sTex
87c0: 74 2c 20 6d 29 0a 20 20 20 20 20 20 20 20 20 20  t, m).          
87d0: 20 20 73 4e 65 77 20 3d 20 73 4e 65 77 20 2b 20    sNew = sNew + 
87e0: 22 20 22 20 2a 20 28 6e 4c 65 6e 2d 6c 65 6e 28  " " * (nLen-len(
87f0: 73 4e 65 77 29 29 0a 20 20 20 20 20 20 20 20 20  sNew)).         
8800: 20 20 20 69 66 20 62 55 70 70 65 72 63 61 73 65     if bUppercase
8810: 20 61 6e 64 20 6d 2e 67 72 6f 75 70 28 69 47 72   and m.group(iGr
8820: 6f 75 70 29 5b 30 3a 31 5d 2e 69 73 75 70 70 65  oup)[0:1].isuppe
8830: 72 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  r():.           
8840: 20 20 20 20 20 73 4e 65 77 20 3d 20 73 4e 65 77       sNew = sNew
8850: 2e 63 61 70 69 74 61 6c 69 7a 65 28 29 0a 20 20  .capitalize().  
8860: 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20        else:.    
8870: 20 20 20 20 20 20 20 20 73 4e 65 77 20 3d 20 6d          sNew = m
8880: 2e 65 78 70 61 6e 64 28 73 52 65 70 6c 29 0a 20  .expand(sRepl). 
8890: 20 20 20 20 20 20 20 20 20 20 20 73 4e 65 77 20             sNew 
88a0: 3d 20 73 4e 65 77 20 2b 20 22 20 22 20 2a 20 28  = sNew + " " * (
88b0: 6e 4c 65 6e 2d 6c 65 6e 28 73 4e 65 77 29 29 0a  nLen-len(sNew)).
88c0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 73          return s
88d0: 54 65 78 74 5b 30 3a 6d 2e 73 74 61 72 74 28 69  Text[0:m.start(i
88e0: 47 72 6f 75 70 29 5d 20 2b 20 73 4e 65 77 20 2b  Group)] + sNew +
88f0: 20 73 54 65 78 74 5b 6d 2e 65 6e 64 28 69 47 72   sText[m.end(iGr
8900: 6f 75 70 29 3a 5d 0a 0a 20 20 20 20 64 65 66 20  oup):]..    def 
8910: 5f 74 61 67 41 6e 64 50 72 65 70 61 72 65 54 6f  _tagAndPrepareTo
8920: 6b 65 6e 46 6f 72 52 65 77 72 69 74 69 6e 67 20  kenForRewriting 
8930: 28 73 65 6c 66 2c 20 73 57 68 61 74 2c 20 6e 54  (self, sWhat, nT
8940: 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72 74  okenRewriteStart
8950: 2c 20 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 45  , nTokenRewriteE
8960: 6e 64 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74  nd, nTokenOffset
8970: 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 2c 20 62 43  , nLastToken, bC
8980: 61 73 65 53 76 74 79 2c 20 62 44 65 62 75 67 29  aseSvty, bDebug)
8990: 3a 0a 20 20 20 20 20 20 20 20 22 74 65 78 74 20  :.        "text 
89a0: 70 72 6f 63 65 73 73 6f 72 3a 20 72 65 77 72 69  processor: rewri
89b0: 74 65 20 74 6f 6b 65 6e 73 20 62 65 74 77 65 65  te tokens betwee
89c0: 6e 20 3c 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65  n <nTokenRewrite
89d0: 53 74 61 72 74 3e 20 61 6e 64 20 3c 6e 54 6f 6b  Start> and <nTok
89e0: 65 6e 52 65 77 72 69 74 65 45 6e 64 3e 20 70 6f  enRewriteEnd> po
89f0: 73 69 74 69 6f 6e 22 0a 20 20 20 20 20 20 20 20  sition".        
8a00: 69 66 20 73 57 68 61 74 20 3d 3d 20 22 2a 22 3a  if sWhat == "*":
8a10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 20 70  .            # p
8a20: 75 72 67 65 20 74 65 78 74 0a 20 20 20 20 20 20  urge text.      
8a30: 20 20 20 20 20 20 69 66 20 6e 54 6f 6b 65 6e 52        if nTokenR
8a40: 65 77 72 69 74 65 45 6e 64 20 2d 20 6e 54 6f 6b  ewriteEnd - nTok
8a50: 65 6e 52 65 77 72 69 74 65 53 74 61 72 74 20 3d  enRewriteStart =
8a60: 3d 20 30 3a 0a 20 20 20 20 20 20 20 20 20 20 20  = 0:.           
8a70: 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e       self.lToken
8a80: 5b 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74  [nTokenRewriteSt
8a90: 61 72 74 5d 5b 22 62 54 6f 52 65 6d 6f 76 65 22  art]["bToRemove"
8aa0: 5d 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20  ] = True.       
8ab0: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
8ac0: 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 69             for i
8ad0: 20 69 6e 20 72 61 6e 67 65 28 6e 54 6f 6b 65 6e   in range(nToken
8ae0: 52 65 77 72 69 74 65 53 74 61 72 74 2c 20 6e 54  RewriteStart, nT
8af0: 6f 6b 65 6e 52 65 77 72 69 74 65 45 6e 64 2b 31  okenRewriteEnd+1
8b00: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
8b10: 20 20 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b         self.lTok
8b20: 65 6e 5b 69 5d 5b 22 62 54 6f 52 65 6d 6f 76 65  en[i]["bToRemove
8b30: 22 5d 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20  "] = True.      
8b40: 20 20 65 6c 69 66 20 73 57 68 61 74 20 3d 3d 20    elif sWhat == 
8b50: 22 e2 90 a3 22 3a 0a 20 20 20 20 20 20 20 20 20  "...":.         
8b60: 20 20 20 23 20 6d 65 72 67 65 20 74 6f 6b 65 6e     # merge token
8b70: 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 65  s.            se
8b80: 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e  lf.lToken[nToken
8b90: 52 65 77 72 69 74 65 53 74 61 72 74 5d 5b 22 6e  RewriteStart]["n
8ba0: 4d 65 72 67 65 55 6e 74 69 6c 22 5d 20 3d 20 6e  MergeUntil"] = n
8bb0: 54 6f 6b 65 6e 52 65 77 72 69 74 65 45 6e 64 0a  TokenRewriteEnd.
8bc0: 20 20 20 20 20 20 20 20 65 6c 69 66 20 73 57 68          elif sWh
8bd0: 61 74 20 3d 3d 20 22 5f 22 3a 0a 20 20 20 20 20  at == "_":.     
8be0: 20 20 20 20 20 20 20 23 20 6e 65 75 74 72 61 6c         # neutral
8bf0: 69 7a 65 64 20 74 6f 6b 65 6e 0a 20 20 20 20 20  ized token.     
8c00: 20 20 20 20 20 20 20 69 66 20 6e 54 6f 6b 65 6e         if nToken
8c10: 52 65 77 72 69 74 65 45 6e 64 20 2d 20 6e 54 6f  RewriteEnd - nTo
8c20: 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72 74 20  kenRewriteStart 
8c30: 3d 3d 20 30 3a 0a 20 20 20 20 20 20 20 20 20 20  == 0:.          
8c40: 20 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65        self.lToke
8c50: 6e 5b 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53  n[nTokenRewriteS
8c60: 74 61 72 74 5d 5b 22 73 4e 65 77 56 61 6c 75 65  tart]["sNewValue
8c70: 22 5d 20 3d 20 22 5f 22 0a 20 20 20 20 20 20 20  "] = "_".       
8c80: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
8c90: 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 69             for i
8ca0: 20 69 6e 20 72 61 6e 67 65 28 6e 54 6f 6b 65 6e   in range(nToken
8cb0: 52 65 77 72 69 74 65 53 74 61 72 74 2c 20 6e 54  RewriteStart, nT
8cc0: 6f 6b 65 6e 52 65 77 72 69 74 65 45 6e 64 2b 31  okenRewriteEnd+1
8cd0: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
8ce0: 20 20 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b         self.lTok
8cf0: 65 6e 5b 69 5d 5b 22 73 4e 65 77 56 61 6c 75 65  en[i]["sNewValue
8d00: 22 5d 20 3d 20 22 5f 22 0a 20 20 20 20 20 20 20  "] = "_".       
8d10: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
8d20: 20 20 20 69 66 20 73 57 68 61 74 2e 73 74 61 72     if sWhat.star
8d30: 74 73 77 69 74 68 28 22 3d 22 29 3a 0a 20 20 20  tswith("="):.   
8d40: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 57 68               sWh
8d50: 61 74 20 3d 20 67 6c 6f 62 61 6c 73 28 29 5b 73  at = globals()[s
8d60: 57 68 61 74 5b 31 3a 5d 5d 28 73 65 6c 66 2e 6c  What[1:]](self.l
8d70: 54 6f 6b 65 6e 2c 20 6e 54 6f 6b 65 6e 4f 66 66  Token, nTokenOff
8d80: 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 29  set, nLastToken)
8d90: 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73  .            els
8da0: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
8db0: 20 20 20 73 57 68 61 74 20 3d 20 73 65 6c 66 2e     sWhat = self.
8dc0: 5f 65 78 70 61 6e 64 28 73 57 68 61 74 2c 20 6e  _expand(sWhat, n
8dd0: 54 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 6e 4c 61  TokenOffset, nLa
8de0: 73 74 54 6f 6b 65 6e 29 0a 20 20 20 20 20 20 20  stToken).       
8df0: 20 20 20 20 20 62 55 70 70 65 72 63 61 73 65 20       bUppercase 
8e00: 3d 20 62 43 61 73 65 53 76 74 79 20 61 6e 64 20  = bCaseSvty and 
8e10: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b  self.lToken[nTok
8e20: 65 6e 52 65 77 72 69 74 65 53 74 61 72 74 5d 5b  enRewriteStart][
8e30: 22 73 56 61 6c 75 65 22 5d 5b 30 3a 31 5d 2e 69  "sValue"][0:1].i
8e40: 73 75 70 70 65 72 28 29 0a 20 20 20 20 20 20 20  supper().       
8e50: 20 20 20 20 20 69 66 20 6e 54 6f 6b 65 6e 52 65       if nTokenRe
8e60: 77 72 69 74 65 45 6e 64 20 2d 20 6e 54 6f 6b 65  writeEnd - nToke
8e70: 6e 52 65 77 72 69 74 65 53 74 61 72 74 20 3d 3d  nRewriteStart ==
8e80: 20 30 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20   0:.            
8e90: 20 20 20 20 23 20 6f 6e 65 20 74 6f 6b 65 6e 0a      # one token.
8ea0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8eb0: 69 66 20 62 55 70 70 65 72 63 61 73 65 3a 0a 20  if bUppercase:. 
8ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8ed0: 20 20 20 73 57 68 61 74 20 3d 20 73 57 68 61 74     sWhat = sWhat
8ee0: 5b 30 3a 31 5d 2e 75 70 70 65 72 28 29 20 2b 20  [0:1].upper() + 
8ef0: 73 57 68 61 74 5b 31 3a 5d 0a 20 20 20 20 20 20  sWhat[1:].      
8f00: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c            self.l
8f10: 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 52 65 77 72  Token[nTokenRewr
8f20: 69 74 65 53 74 61 72 74 5d 5b 22 73 4e 65 77 56  iteStart]["sNewV
8f30: 61 6c 75 65 22 5d 20 3d 20 73 57 68 61 74 0a 20  alue"] = sWhat. 
8f40: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
8f50: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8f60: 20 23 20 73 65 76 65 72 61 6c 20 74 6f 6b 65 6e   # several token
8f70: 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  s.              
8f80: 20 20 6c 54 6f 6b 65 6e 56 61 6c 75 65 20 3d 20    lTokenValue = 
8f90: 73 57 68 61 74 2e 73 70 6c 69 74 28 22 7c 22 29  sWhat.split("|")
8fa0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8fb0: 20 69 66 20 6c 65 6e 28 6c 54 6f 6b 65 6e 56 61   if len(lTokenVa
8fc0: 6c 75 65 29 20 21 3d 20 28 6e 54 6f 6b 65 6e 52  lue) != (nTokenR
8fd0: 65 77 72 69 74 65 45 6e 64 20 2d 20 6e 54 6f 6b  ewriteEnd - nTok
8fe0: 65 6e 52 65 77 72 69 74 65 53 74 61 72 74 20 2b  enRewriteStart +
8ff0: 20 31 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20   1):.           
9000: 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 45           echo("E
9010: 72 72 6f 72 2e 20 54 65 78 74 20 70 72 6f 63 65  rror. Text proce
9020: 73 73 6f 72 3a 20 6e 75 6d 62 65 72 20 6f 66 20  ssor: number of 
9030: 72 65 70 6c 61 63 65 6d 65 6e 74 73 20 21 3d 20  replacements != 
9040: 6e 75 6d 62 65 72 20 6f 66 20 74 6f 6b 65 6e 73  number of tokens
9050: 2e 22 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  .").            
9060: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 0a 20          return. 
9070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66                 f
9080: 6f 72 20 69 2c 20 73 56 61 6c 75 65 20 69 6e 20  or i, sValue in 
9090: 7a 69 70 28 72 61 6e 67 65 28 6e 54 6f 6b 65 6e  zip(range(nToken
90a0: 52 65 77 72 69 74 65 53 74 61 72 74 2c 20 6e 54  RewriteStart, nT
90b0: 6f 6b 65 6e 52 65 77 72 69 74 65 45 6e 64 2b 31  okenRewriteEnd+1
90c0: 29 2c 20 6c 54 6f 6b 65 6e 56 61 6c 75 65 29 3a  ), lTokenValue):
90d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
90e0: 20 20 20 20 20 69 66 20 6e 6f 74 20 73 56 61 6c       if not sVal
90f0: 75 65 20 6f 72 20 73 56 61 6c 75 65 20 3d 3d 20  ue or sValue == 
9100: 22 2a 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20  "*":.           
9110: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c               sel
9120: 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 62 54 6f  f.lToken[i]["bTo
9130: 52 65 6d 6f 76 65 22 5d 20 3d 20 54 72 75 65 0a  Remove"] = True.
9140: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9150: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
9160: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9170: 20 20 69 66 20 62 55 70 70 65 72 63 61 73 65 3a    if bUppercase:
9180: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9190: 20 20 20 20 20 20 20 20 20 20 20 20 20 73 56 61               sVa
91a0: 6c 75 65 20 3d 20 73 56 61 6c 75 65 5b 30 3a 31  lue = sValue[0:1
91b0: 5d 2e 75 70 70 65 72 28 29 20 2b 20 73 56 61 6c  ].upper() + sVal
91c0: 75 65 5b 31 3a 5d 0a 20 20 20 20 20 20 20 20 20  ue[1:].         
91d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
91e0: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 73  elf.lToken[i]["s
91f0: 4e 65 77 56 61 6c 75 65 22 5d 20 3d 20 73 56 61  NewValue"] = sVa
9200: 6c 75 65 0a 0a 20 20 20 20 64 65 66 20 72 65 77  lue..    def rew
9210: 72 69 74 65 46 72 6f 6d 54 61 67 73 20 28 73 65  riteFromTags (se
9220: 6c 66 2c 20 62 44 65 62 75 67 3d 46 61 6c 73 65  lf, bDebug=False
9230: 29 3a 0a 20 20 20 20 20 20 20 20 22 72 65 77 72  ):.        "rewr
9240: 69 74 65 20 74 68 65 20 73 65 6e 74 65 6e 63 65  ite the sentence
9250: 2c 20 6d 6f 64 69 66 79 20 74 6f 6b 65 6e 73 2c  , modify tokens,
9260: 20 70 75 72 67 65 20 74 68 65 20 74 6f 6b 65 6e   purge the token
9270: 20 6c 69 73 74 22 0a 20 20 20 20 20 20 20 20 69   list".        i
9280: 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20  f bDebug:.      
9290: 20 20 20 20 20 20 65 63 68 6f 28 22 52 45 57 52        echo("REWR
92a0: 49 54 45 22 29 0a 20 20 20 20 20 20 20 20 6c 4e  ITE").        lN
92b0: 65 77 54 6f 6b 65 6e 20 3d 20 5b 5d 0a 20 20 20  ewToken = [].   
92c0: 20 20 20 20 20 6e 4d 65 72 67 65 55 6e 74 69 6c       nMergeUntil
92d0: 20 3d 20 30 0a 20 20 20 20 20 20 20 20 64 54 6f   = 0.        dTo
92e0: 6b 65 6e 4d 65 72 67 65 72 20 3d 20 7b 7d 0a 20  kenMerger = {}. 
92f0: 20 20 20 20 20 20 20 66 6f 72 20 69 54 6f 6b 65         for iToke
9300: 6e 2c 20 64 54 6f 6b 65 6e 20 69 6e 20 65 6e 75  n, dToken in enu
9310: 6d 65 72 61 74 65 28 73 65 6c 66 2e 6c 54 6f 6b  merate(self.lTok
9320: 65 6e 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  en):.           
9330: 20 62 4b 65 65 70 54 6f 6b 65 6e 20 3d 20 54 72   bKeepToken = Tr
9340: 75 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  ue.            i
9350: 66 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70 65 22  f dToken["sType"
9360: 5d 20 21 3d 20 22 49 4e 46 4f 22 3a 0a 20 20 20  ] != "INFO":.   
9370: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
9380: 6e 4d 65 72 67 65 55 6e 74 69 6c 20 61 6e 64 20  nMergeUntil and 
9390: 69 54 6f 6b 65 6e 20 3c 3d 20 6e 4d 65 72 67 65  iToken <= nMerge
93a0: 55 6e 74 69 6c 3a 0a 20 20 20 20 20 20 20 20 20  Until:.         
93b0: 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65             dToke
93c0: 6e 4d 65 72 67 65 72 5b 22 73 56 61 6c 75 65 22  nMerger["sValue"
93d0: 5d 20 2b 3d 20 22 20 22 20 2a 20 28 64 54 6f 6b  ] += " " * (dTok
93e0: 65 6e 5b 22 6e 53 74 61 72 74 22 5d 20 2d 20 64  en["nStart"] - d
93f0: 54 6f 6b 65 6e 4d 65 72 67 65 72 5b 22 6e 45 6e  TokenMerger["nEn
9400: 64 22 5d 29 20 2b 20 64 54 6f 6b 65 6e 5b 22 73  d"]) + dToken["s
9410: 56 61 6c 75 65 22 5d 0a 20 20 20 20 20 20 20 20  Value"].        
9420: 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b              dTok
9430: 65 6e 4d 65 72 67 65 72 5b 22 6e 45 6e 64 22 5d  enMerger["nEnd"]
9440: 20 3d 20 64 54 6f 6b 65 6e 5b 22 6e 45 6e 64 22   = dToken["nEnd"
9450: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ].              
9460: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
9470: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9480: 20 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 20           echo(" 
9490: 20 4d 45 52 47 45 44 20 54 4f 4b 45 4e 3a 20 22   MERGED TOKEN: "
94a0: 20 2b 20 64 54 6f 6b 65 6e 4d 65 72 67 65 72 5b   + dTokenMerger[
94b0: 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20 20  "sValue"]).     
94c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62                 b
94d0: 4b 65 65 70 54 6f 6b 65 6e 20 3d 20 46 61 6c 73  KeepToken = Fals
94e0: 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e.              
94f0: 20 20 69 66 20 22 6e 4d 65 72 67 65 55 6e 74 69    if "nMergeUnti
9500: 6c 22 20 69 6e 20 64 54 6f 6b 65 6e 3a 0a 20 20  l" in dToken:.  
9510: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9520: 20 20 69 66 20 69 54 6f 6b 65 6e 20 3e 20 6e 4d    if iToken > nM
9530: 65 72 67 65 55 6e 74 69 6c 3a 20 23 20 74 68 69  ergeUntil: # thi
9540: 73 20 74 6f 6b 65 6e 20 69 73 20 6e 6f 74 20 61  s token is not a
9550: 6c 72 65 61 64 79 20 6d 65 72 67 65 64 20 77 69  lready merged wi
9560: 74 68 20 61 20 70 72 65 76 69 6f 75 73 20 74 6f  th a previous to
9570: 6b 65 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20  ken.            
9580: 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b              dTok
9590: 65 6e 4d 65 72 67 65 72 20 3d 20 64 54 6f 6b 65  enMerger = dToke
95a0: 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  n.              
95b0: 20 20 20 20 20 20 69 66 20 64 54 6f 6b 65 6e 5b        if dToken[
95c0: 22 6e 4d 65 72 67 65 55 6e 74 69 6c 22 5d 20 3e  "nMergeUntil"] >
95d0: 20 6e 4d 65 72 67 65 55 6e 74 69 6c 3a 0a 20 20   nMergeUntil:.  
95e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
95f0: 20 20 20 20 20 20 6e 4d 65 72 67 65 55 6e 74 69        nMergeUnti
9600: 6c 20 3d 20 64 54 6f 6b 65 6e 5b 22 6e 4d 65 72  l = dToken["nMer
9610: 67 65 55 6e 74 69 6c 22 5d 0a 20 20 20 20 20 20  geUntil"].      
9620: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64 65                de
9630: 6c 20 64 54 6f 6b 65 6e 5b 22 6e 4d 65 72 67 65  l dToken["nMerge
9640: 55 6e 74 69 6c 22 5d 0a 20 20 20 20 20 20 20 20  Until"].        
9650: 20 20 20 20 20 20 20 20 65 6c 69 66 20 22 62 54          elif "bT
9660: 6f 52 65 6d 6f 76 65 22 20 69 6e 20 64 54 6f 6b  oRemove" in dTok
9670: 65 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  en:.            
9680: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
9690: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  g:.             
96a0: 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28             echo(
96b0: 22 20 20 52 45 4d 4f 56 45 44 3a 20 22 20 2b 20  "  REMOVED: " + 
96c0: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
96d0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
96e0: 20 20 20 20 20 20 73 65 6c 66 2e 73 53 65 6e 74        self.sSent
96f0: 65 6e 63 65 20 3d 20 73 65 6c 66 2e 73 53 65 6e  ence = self.sSen
9700: 74 65 6e 63 65 5b 3a 64 54 6f 6b 65 6e 5b 22 6e  tence[:dToken["n
9710: 53 74 61 72 74 22 5d 5d 20 2b 20 22 20 22 20 2a  Start"]] + " " *
9720: 20 28 64 54 6f 6b 65 6e 5b 22 6e 45 6e 64 22 5d   (dToken["nEnd"]
9730: 20 2d 20 64 54 6f 6b 65 6e 5b 22 6e 53 74 61 72   - dToken["nStar
9740: 74 22 5d 29 20 2b 20 73 65 6c 66 2e 73 53 65 6e  t"]) + self.sSen
9750: 74 65 6e 63 65 5b 64 54 6f 6b 65 6e 5b 22 6e 45  tence[dToken["nE
9760: 6e 64 22 5d 3a 5d 0a 20 20 20 20 20 20 20 20 20  nd"]:].         
9770: 20 20 20 20 20 20 20 20 20 20 20 62 4b 65 65 70             bKeep
9780: 54 6f 6b 65 6e 20 3d 20 46 61 6c 73 65 0a 20 20  Token = False.  
9790: 20 20 20 20 20 20 20 20 20 20 23 0a 20 20 20 20            #.    
97a0: 20 20 20 20 20 20 20 20 69 66 20 62 4b 65 65 70          if bKeep
97b0: 54 6f 6b 65 6e 3a 0a 20 20 20 20 20 20 20 20 20  Token:.         
97c0: 20 20 20 20 20 20 20 6c 4e 65 77 54 6f 6b 65 6e         lNewToken
97d0: 2e 61 70 70 65 6e 64 28 64 54 6f 6b 65 6e 29 0a  .append(dToken).
97e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
97f0: 69 66 20 22 73 4e 65 77 56 61 6c 75 65 22 20 69  if "sNewValue" i
9800: 6e 20 64 54 6f 6b 65 6e 3a 0a 20 20 20 20 20 20  n dToken:.      
9810: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
9820: 72 65 77 72 69 74 65 20 74 6f 6b 65 6e 20 61 6e  rewrite token an
9830: 64 20 73 65 6e 74 65 6e 63 65 0a 20 20 20 20 20  d sentence.     
9840: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
9850: 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20  f bDebug:.      
9860: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9870: 20 20 65 63 68 6f 28 64 54 6f 6b 65 6e 5b 22 73    echo(dToken["s
9880: 56 61 6c 75 65 22 5d 20 2b 20 22 20 2d 3e 20 22  Value"] + " -> "
9890: 20 2b 20 64 54 6f 6b 65 6e 5b 22 73 4e 65 77 56   + dToken["sNewV
98a0: 61 6c 75 65 22 5d 29 0a 20 20 20 20 20 20 20 20  alue"]).        
98b0: 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b              dTok
98c0: 65 6e 5b 22 73 52 65 61 6c 56 61 6c 75 65 22 5d  en["sRealValue"]
98d0: 20 3d 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75   = dToken["sValu
98e0: 65 22 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  e"].            
98f0: 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22          dToken["
9900: 73 56 61 6c 75 65 22 5d 20 3d 20 64 54 6f 6b 65  sValue"] = dToke
9910: 6e 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d 0a 20  n["sNewValue"]. 
9920: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9930: 20 20 20 6e 44 69 66 66 4c 65 6e 20 3d 20 6c 65     nDiffLen = le
9940: 6e 28 64 54 6f 6b 65 6e 5b 22 73 52 65 61 6c 56  n(dToken["sRealV
9950: 61 6c 75 65 22 5d 29 20 2d 20 6c 65 6e 28 64 54  alue"]) - len(dT
9960: 6f 6b 65 6e 5b 22 73 4e 65 77 56 61 6c 75 65 22  oken["sNewValue"
9970: 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]).             
9980: 20 20 20 20 20 20 20 73 4e 65 77 52 65 70 6c 20         sNewRepl 
9990: 3d 20 28 64 54 6f 6b 65 6e 5b 22 73 4e 65 77 56  = (dToken["sNewV
99a0: 61 6c 75 65 22 5d 20 2b 20 22 20 22 20 2a 20 6e  alue"] + " " * n
99b0: 44 69 66 66 4c 65 6e 29 20 20 69 66 20 6e 44 69  DiffLen)  if nDi
99c0: 66 66 4c 65 6e 20 3e 3d 20 30 20 20 65 6c 73 65  ffLen >= 0  else
99d0: 20 64 54 6f 6b 65 6e 5b 22 73 4e 65 77 56 61 6c   dToken["sNewVal
99e0: 75 65 22 5d 5b 3a 6c 65 6e 28 64 54 6f 6b 65 6e  ue"][:len(dToken
99f0: 5b 22 73 52 65 61 6c 56 61 6c 75 65 22 5d 29 5d  ["sRealValue"])]
9a00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9a10: 20 20 20 20 20 73 65 6c 66 2e 73 53 65 6e 74 65       self.sSente
9a20: 6e 63 65 20 3d 20 73 65 6c 66 2e 73 53 65 6e 74  nce = self.sSent
9a30: 65 6e 63 65 5b 3a 64 54 6f 6b 65 6e 5b 22 6e 53  ence[:dToken["nS
9a40: 74 61 72 74 22 5d 5d 20 2b 20 73 4e 65 77 52 65  tart"]] + sNewRe
9a50: 70 6c 20 2b 20 73 65 6c 66 2e 73 53 65 6e 74 65  pl + self.sSente
9a60: 6e 63 65 5b 64 54 6f 6b 65 6e 5b 22 6e 45 6e 64  nce[dToken["nEnd
9a70: 22 5d 3a 5d 0a 20 20 20 20 20 20 20 20 20 20 20  "]:].           
9a80: 20 20 20 20 20 20 20 20 20 64 65 6c 20 64 54 6f           del dTo
9a90: 6b 65 6e 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d  ken["sNewValue"]
9aa0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73  .            els
9ab0: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
9ac0: 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20     try:.        
9ad0: 20 20 20 20 20 20 20 20 20 20 20 20 64 65 6c 20              del 
9ae0: 73 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f 73 5b 64  self.dTokenPos[d
9af0: 54 6f 6b 65 6e 5b 22 6e 53 74 61 72 74 22 5d 5d  Token["nStart"]]
9b00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9b10: 20 65 78 63 65 70 74 20 4b 65 79 45 72 72 6f 72   except KeyError
9b20: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
9b30: 20 20 20 20 20 20 65 63 68 6f 28 73 65 6c 66 29        echo(self)
9b40: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9b50: 20 20 20 20 20 65 63 68 6f 28 64 54 6f 6b 65 6e       echo(dToken
9b60: 29 0a 20 20 20 20 20 20 20 20 69 66 20 62 44 65  ).        if bDe
9b70: 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  bug:.           
9b80: 20 65 63 68 6f 28 22 20 20 54 45 58 54 20 52 45   echo("  TEXT RE
9b90: 57 52 49 54 45 44 3a 20 22 20 2b 20 73 65 6c 66  WRITED: " + self
9ba0: 2e 73 53 65 6e 74 65 6e 63 65 29 0a 20 20 20 20  .sSentence).    
9bb0: 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 2e      self.lToken.
9bc0: 63 6c 65 61 72 28 29 0a 20 20 20 20 20 20 20 20  clear().        
9bd0: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 3d 20 6c 4e  self.lToken = lN
9be0: 65 77 54 6f 6b 65 6e 0a 0a 0a 23 23 23 23 20 63  ewToken...#### c
9bf0: 6f 6d 6d 6f 6e 20 66 75 6e 63 74 69 6f 6e 73 0a  ommon functions.
9c00: 0a 64 65 66 20 6f 70 74 69 6f 6e 20 28 73 4f 70  .def option (sOp
9c10: 74 29 3a 0a 20 20 20 20 22 72 65 74 75 72 6e 20  t):.    "return 
9c20: 54 72 75 65 20 69 66 20 6f 70 74 69 6f 6e 20 3c  True if option <
9c30: 73 4f 70 74 3e 20 69 73 20 61 63 74 69 76 65 22  sOpt> is active"
9c40: 0a 20 20 20 20 72 65 74 75 72 6e 20 5f 64 4f 70  .    return _dOp
9c50: 74 69 6f 6e 73 2e 67 65 74 28 73 4f 70 74 2c 20  tions.get(sOpt, 
9c60: 46 61 6c 73 65 29 0a 0a 0a 23 23 23 23 20 46 75  False)...#### Fu
9c70: 6e 63 74 69 6f 6e 73 20 74 6f 20 67 65 74 20 74  nctions to get t
9c80: 65 78 74 20 6f 75 74 73 69 64 65 20 70 61 74 74  ext outside patt
9c90: 65 72 6e 20 73 63 6f 70 65 0a 0a 23 20 77 61 72  ern scope..# war
9ca0: 6e 69 6e 67 3a 20 63 68 65 63 6b 20 63 6f 6d 70  ning: check comp
9cb0: 69 6c 65 5f 72 75 6c 65 73 2e 70 79 20 74 6f 20  ile_rules.py to 
9cc0: 75 6e 64 65 72 73 74 61 6e 64 20 68 6f 77 20 69  understand how i
9cd0: 74 20 77 6f 72 6b 73 0a 0a 5f 7a 4e 65 78 74 57  t works.._zNextW
9ce0: 6f 72 64 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65  ord = re.compile
9cf0: 28 72 22 20 2b 28 5c 77 5b 5c 77 2d 5d 2a 29 22  (r" +(\w[\w-]*)"
9d00: 29 0a 5f 7a 50 72 65 76 57 6f 72 64 20 3d 20 72  )._zPrevWord = r
9d10: 65 2e 63 6f 6d 70 69 6c 65 28 72 22 28 5c 77 5b  e.compile(r"(\w[
9d20: 5c 77 2d 5d 2a 29 20 2b 24 22 29 0a 0a 64 65 66  \w-]*) +$")..def
9d30: 20 6e 65 78 74 77 6f 72 64 20 28 73 2c 20 69 53   nextword (s, iS
9d40: 74 61 72 74 2c 20 6e 29 3a 0a 20 20 20 20 22 67  tart, n):.    "g
9d50: 65 74 20 74 68 65 20 6e 74 68 20 77 6f 72 64 20  et the nth word 
9d60: 6f 66 20 74 68 65 20 69 6e 70 75 74 20 73 74 72  of the input str
9d70: 69 6e 67 20 6f 72 20 65 6d 70 74 79 20 73 74 72  ing or empty str
9d80: 69 6e 67 22 0a 20 20 20 20 6d 20 3d 20 72 65 2e  ing".    m = re.
9d90: 6d 61 74 63 68 28 22 28 3f 3a 20 2b 5b 5c 5c 77  match("(?: +[\\w
9da0: 25 2d 5d 2b 29 7b 22 20 2b 20 73 74 72 28 6e 2d  %-]+){" + str(n-
9db0: 31 29 20 2b 20 22 7d 20 2b 28 5b 5c 5c 77 25 2d  1) + "} +([\\w%-
9dc0: 5d 2b 29 22 2c 20 73 5b 69 53 74 61 72 74 3a 5d  ]+)", s[iStart:]
9dd0: 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6d 3a 0a  ).    if not m:.
9de0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 4e          return N
9df0: 6f 6e 65 0a 20 20 20 20 72 65 74 75 72 6e 20 28  one.    return (
9e00: 69 53 74 61 72 74 2b 6d 2e 73 74 61 72 74 28 31  iStart+m.start(1
9e10: 29 2c 20 6d 2e 67 72 6f 75 70 28 31 29 29 0a 0a  ), m.group(1))..
9e20: 0a 64 65 66 20 70 72 65 76 77 6f 72 64 20 28 73  .def prevword (s
9e30: 2c 20 69 45 6e 64 2c 20 6e 29 3a 0a 20 20 20 20  , iEnd, n):.    
9e40: 22 67 65 74 20 74 68 65 20 28 2d 29 6e 74 68 20  "get the (-)nth 
9e50: 77 6f 72 64 20 6f 66 20 74 68 65 20 69 6e 70 75  word of the inpu
9e60: 74 20 73 74 72 69 6e 67 20 6f 72 20 65 6d 70 74  t string or empt
9e70: 79 20 73 74 72 69 6e 67 22 0a 20 20 20 20 6d 20  y string".    m 
9e80: 3d 20 72 65 2e 73 65 61 72 63 68 28 22 28 5b 5c  = re.search("([\
9e90: 5c 77 25 2d 5d 2b 29 20 2b 28 3f 3a 5b 5c 5c 77  \w%-]+) +(?:[\\w
9ea0: 25 2d 5d 2b 20 2b 29 7b 22 20 2b 20 73 74 72 28  %-]+ +){" + str(
9eb0: 6e 2d 31 29 20 2b 20 22 7d 24 22 2c 20 73 5b 3a  n-1) + "}$", s[:
9ec0: 69 45 6e 64 5d 29 0a 20 20 20 20 69 66 20 6e 6f  iEnd]).    if no
9ed0: 74 20 6d 3a 0a 20 20 20 20 20 20 20 20 72 65 74  t m:.        ret
9ee0: 75 72 6e 20 4e 6f 6e 65 0a 20 20 20 20 72 65 74  urn None.    ret
9ef0: 75 72 6e 20 28 6d 2e 73 74 61 72 74 28 31 29 2c  urn (m.start(1),
9f00: 20 6d 2e 67 72 6f 75 70 28 31 29 29 0a 0a 0a 64   m.group(1))...d
9f10: 65 66 20 6e 65 78 74 77 6f 72 64 31 20 28 73 2c  ef nextword1 (s,
9f20: 20 69 53 74 61 72 74 29 3a 0a 20 20 20 20 22 67   iStart):.    "g
9f30: 65 74 20 6e 65 78 74 20 77 6f 72 64 20 28 6f 70  et next word (op
9f40: 74 69 6d 69 7a 61 74 69 6f 6e 29 22 0a 20 20 20  timization)".   
9f50: 20 6d 20 3d 20 5f 7a 4e 65 78 74 57 6f 72 64 2e   m = _zNextWord.
9f60: 6d 61 74 63 68 28 73 5b 69 53 74 61 72 74 3a 5d  match(s[iStart:]
9f70: 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6d 3a 0a  ).    if not m:.
9f80: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 4e          return N
9f90: 6f 6e 65 0a 20 20 20 20 72 65 74 75 72 6e 20 28  one.    return (
9fa0: 69 53 74 61 72 74 2b 6d 2e 73 74 61 72 74 28 31  iStart+m.start(1
9fb0: 29 2c 20 6d 2e 67 72 6f 75 70 28 31 29 29 0a 0a  ), m.group(1))..
9fc0: 0a 64 65 66 20 70 72 65 76 77 6f 72 64 31 20 28  .def prevword1 (
9fd0: 73 2c 20 69 45 6e 64 29 3a 0a 20 20 20 20 22 67  s, iEnd):.    "g
9fe0: 65 74 20 70 72 65 76 69 6f 75 73 20 77 6f 72 64  et previous word
9ff0: 20 28 6f 70 74 69 6d 69 7a 61 74 69 6f 6e 29 22   (optimization)"
a000: 0a 20 20 20 20 6d 20 3d 20 5f 7a 50 72 65 76 57  .    m = _zPrevW
a010: 6f 72 64 2e 73 65 61 72 63 68 28 73 5b 3a 69 45  ord.search(s[:iE
a020: 6e 64 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20  nd]).    if not 
a030: 6d 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  m:.        retur
a040: 6e 20 4e 6f 6e 65 0a 20 20 20 20 72 65 74 75 72  n None.    retur
a050: 6e 20 28 6d 2e 73 74 61 72 74 28 31 29 2c 20 6d  n (m.start(1), m
a060: 2e 67 72 6f 75 70 28 31 29 29 0a 0a 0a 64 65 66  .group(1))...def
a070: 20 6c 6f 6f 6b 20 28 73 2c 20 73 50 61 74 74 65   look (s, sPatte
a080: 72 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 3d  rn, sNegPattern=
a090: 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 73 65 65 6b  None):.    "seek
a0a0: 20 73 50 61 74 74 65 72 6e 20 69 6e 20 73 20 28   sPattern in s (
a0b0: 62 65 66 6f 72 65 2f 61 66 74 65 72 2f 66 75 6c  before/after/ful
a0c0: 6c 74 65 78 74 29 2c 20 69 66 20 73 4e 65 67 50  ltext), if sNegP
a0d0: 61 74 74 65 72 6e 20 6e 6f 74 20 69 6e 20 73 22  attern not in s"
a0e0: 0a 20 20 20 20 69 66 20 73 4e 65 67 50 61 74 74  .    if sNegPatt
a0f0: 65 72 6e 20 61 6e 64 20 72 65 2e 73 65 61 72 63  ern and re.searc
a100: 68 28 73 4e 65 67 50 61 74 74 65 72 6e 2c 20 73  h(sNegPattern, s
a110: 29 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  ):.        retur
a120: 6e 20 46 61 6c 73 65 0a 20 20 20 20 69 66 20 72  n False.    if r
a130: 65 2e 73 65 61 72 63 68 28 73 50 61 74 74 65 72  e.search(sPatter
a140: 6e 2c 20 73 29 3a 0a 20 20 20 20 20 20 20 20 72  n, s):.        r
a150: 65 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 72  eturn True.    r
a160: 65 74 75 72 6e 20 46 61 6c 73 65 0a 0a 0a 64 65  eturn False...de
a170: 66 20 6c 6f 6f 6b 5f 63 68 6b 31 20 28 64 54 6f  f look_chk1 (dTo
a180: 6b 65 6e 50 6f 73 2c 20 73 2c 20 6e 4f 66 66 73  kenPos, s, nOffs
a190: 65 74 2c 20 73 50 61 74 74 65 72 6e 2c 20 73 50  et, sPattern, sP
a1a0: 61 74 74 65 72 6e 47 72 6f 75 70 31 2c 20 73 4e  atternGroup1, sN
a1b0: 65 67 50 61 74 74 65 72 6e 47 72 6f 75 70 31 3d  egPatternGroup1=
a1c0: 22 22 29 3a 0a 20 20 20 20 22 72 65 74 75 72 6e  ""):.    "return
a1d0: 73 20 54 72 75 65 20 69 66 20 73 20 68 61 73 20  s True if s has 
a1e0: 70 61 74 74 65 72 6e 20 73 50 61 74 74 65 72 6e  pattern sPattern
a1f0: 20 61 6e 64 20 6d 2e 67 72 6f 75 70 28 31 29 20   and m.group(1) 
a200: 68 61 73 20 70 61 74 74 65 72 6e 20 73 50 61 74  has pattern sPat
a210: 74 65 72 6e 47 72 6f 75 70 31 22 0a 20 20 20 20  ternGroup1".    
a220: 6d 20 3d 20 72 65 2e 73 65 61 72 63 68 28 73 50  m = re.search(sP
a230: 61 74 74 65 72 6e 2c 20 73 29 0a 20 20 20 20 69  attern, s).    i
a240: 66 20 6e 6f 74 20 6d 3a 0a 20 20 20 20 20 20 20  f not m:.       
a250: 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20   return False.  
a260: 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 73    try:.        s
a270: 57 6f 72 64 20 3d 20 6d 2e 67 72 6f 75 70 28 31  Word = m.group(1
a280: 29 0a 20 20 20 20 20 20 20 20 6e 50 6f 73 20 3d  ).        nPos =
a290: 20 6d 2e 73 74 61 72 74 28 31 29 20 2b 20 6e 4f   m.start(1) + nO
a2a0: 66 66 73 65 74 0a 20 20 20 20 65 78 63 65 70 74  ffset.    except
a2b0: 20 49 6e 64 65 78 45 72 72 6f 72 3a 0a 20 20 20   IndexError:.   
a2c0: 20 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73       return Fals
a2d0: 65 0a 20 20 20 20 72 65 74 75 72 6e 20 6d 6f 72  e.    return mor
a2e0: 70 68 28 64 54 6f 6b 65 6e 50 6f 73 2c 20 28 6e  ph(dTokenPos, (n
a2f0: 50 6f 73 2c 20 73 57 6f 72 64 29 2c 20 73 50 61  Pos, sWord), sPa
a300: 74 74 65 72 6e 47 72 6f 75 70 31 2c 20 73 4e 65  tternGroup1, sNe
a310: 67 50 61 74 74 65 72 6e 47 72 6f 75 70 31 29 0a  gPatternGroup1).
a320: 0a 0a 0a 23 23 23 23 20 41 6e 61 6c 79 73 65 20  ...#### Analyse 
a330: 67 72 6f 75 70 73 20 66 6f 72 20 72 65 67 65 78  groups for regex
a340: 20 72 75 6c 65 73 0a 0a 64 65 66 20 64 69 73 70   rules..def disp
a350: 6c 61 79 49 6e 66 6f 20 28 64 54 6f 6b 65 6e 50  layInfo (dTokenP
a360: 6f 73 2c 20 74 57 6f 72 64 29 3a 0a 20 20 20 20  os, tWord):.    
a370: 22 66 6f 72 20 64 65 62 75 67 67 69 6e 67 3a 20  "for debugging: 
a380: 72 65 74 72 69 65 76 65 20 69 6e 66 6f 20 6f 66  retrieve info of
a390: 20 77 6f 72 64 22 0a 20 20 20 20 69 66 20 6e 6f   word".    if no
a3a0: 74 20 74 57 6f 72 64 3a 0a 20 20 20 20 20 20 20  t tWord:.       
a3b0: 20 65 63 68 6f 28 22 3e 20 6e 6f 74 68 69 6e 67   echo("> nothing
a3c0: 20 74 6f 20 66 69 6e 64 22 29 0a 20 20 20 20 20   to find").     
a3d0: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
a3e0: 20 20 20 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53 70     lMorph = _oSp
a3f0: 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f  ellChecker.getMo
a400: 72 70 68 28 74 57 6f 72 64 5b 31 5d 29 0a 20 20  rph(tWord[1]).  
a410: 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 3a    if not lMorph:
a420: 0a 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 3e  .        echo(">
a430: 20 6e 6f 74 20 69 6e 20 64 69 63 74 69 6f 6e 61   not in dictiona
a440: 72 79 22 29 0a 20 20 20 20 20 20 20 20 72 65 74  ry").        ret
a450: 75 72 6e 20 54 72 75 65 0a 20 20 20 20 65 63 68  urn True.    ech
a460: 6f 28 22 54 4f 4b 45 4e 53 3a 22 2c 20 64 54 6f  o("TOKENS:", dTo
a470: 6b 65 6e 50 6f 73 29 0a 20 20 20 20 69 66 20 74  kenPos).    if t
a480: 57 6f 72 64 5b 30 5d 20 69 6e 20 64 54 6f 6b 65  Word[0] in dToke
a490: 6e 50 6f 73 20 61 6e 64 20 22 6c 4d 6f 72 70 68  nPos and "lMorph
a4a0: 22 20 69 6e 20 64 54 6f 6b 65 6e 50 6f 73 5b 74  " in dTokenPos[t
a4b0: 57 6f 72 64 5b 30 5d 5d 3a 0a 20 20 20 20 20 20  Word[0]]:.      
a4c0: 20 20 65 63 68 6f 28 22 44 41 3a 20 22 20 2b 20    echo("DA: " + 
a4d0: 73 74 72 28 64 54 6f 6b 65 6e 50 6f 73 5b 74 57  str(dTokenPos[tW
a4e0: 6f 72 64 5b 30 5d 5d 5b 22 6c 4d 6f 72 70 68 22  ord[0]]["lMorph"
a4f0: 5d 29 29 0a 20 20 20 20 65 63 68 6f 28 22 46 53  ])).    echo("FS
a500: 41 3a 20 22 20 2b 20 73 74 72 28 6c 4d 6f 72 70  A: " + str(lMorp
a510: 68 29 29 0a 20 20 20 20 72 65 74 75 72 6e 20 54  h)).    return T
a520: 72 75 65 0a 0a 0a 64 65 66 20 6d 6f 72 70 68 20  rue...def morph 
a530: 28 64 54 6f 6b 65 6e 50 6f 73 2c 20 74 57 6f 72  (dTokenPos, tWor
a540: 64 2c 20 73 50 61 74 74 65 72 6e 2c 20 73 4e 65  d, sPattern, sNe
a550: 67 50 61 74 74 65 72 6e 3d 22 22 2c 20 62 4e 6f  gPattern="", bNo
a560: 57 6f 72 64 3d 46 61 6c 73 65 29 3a 0a 20 20 20  Word=False):.   
a570: 20 22 61 6e 61 6c 79 73 65 20 61 20 74 75 70 6c   "analyse a tupl
a580: 65 20 28 70 6f 73 69 74 69 6f 6e 2c 20 77 6f 72  e (position, wor
a590: 64 29 2c 20 72 65 74 75 72 6e 73 20 54 72 75 65  d), returns True
a5a0: 20 69 66 20 6e 6f 74 20 73 4e 65 67 50 61 74 74   if not sNegPatt
a5b0: 65 72 6e 20 69 6e 20 77 6f 72 64 20 6d 6f 72 70  ern in word morp
a5c0: 68 6f 6c 6f 67 69 65 73 20 61 6e 64 20 73 50 61  hologies and sPa
a5d0: 74 74 65 72 6e 20 69 6e 20 77 6f 72 64 20 6d 6f  ttern in word mo
a5e0: 72 70 68 6f 6c 6f 67 69 65 73 20 28 64 69 73 61  rphologies (disa
a5f0: 6d 62 69 67 75 61 74 69 6f 6e 20 6f 6e 29 22 0a  mbiguation on)".
a600: 20 20 20 20 69 66 20 6e 6f 74 20 74 57 6f 72 64      if not tWord
a610: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
a620: 20 62 4e 6f 57 6f 72 64 0a 20 20 20 20 6c 4d 6f   bNoWord.    lMo
a630: 72 70 68 20 3d 20 64 54 6f 6b 65 6e 50 6f 73 5b  rph = dTokenPos[
a640: 74 57 6f 72 64 5b 30 5d 5d 5b 22 6c 4d 6f 72 70  tWord[0]]["lMorp
a650: 68 22 5d 20 20 69 66 20 74 57 6f 72 64 5b 30 5d  h"]  if tWord[0]
a660: 20 69 6e 20 64 54 6f 6b 65 6e 50 6f 73 20 61 6e   in dTokenPos an
a670: 64 20 22 6c 4d 6f 72 70 68 22 20 69 6e 20 64 54  d "lMorph" in dT
a680: 6f 6b 65 6e 50 6f 73 5b 74 57 6f 72 64 5b 30 5d  okenPos[tWord[0]
a690: 5d 20 20 65 6c 73 65 20 5f 6f 53 70 65 6c 6c 43  ]  else _oSpellC
a6a0: 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28  hecker.getMorph(
a6b0: 74 57 6f 72 64 5b 31 5d 29 0a 20 20 20 20 69 66  tWord[1]).    if
a6c0: 20 6e 6f 74 20 6c 4d 6f 72 70 68 3a 0a 20 20 20   not lMorph:.   
a6d0: 20 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73       return Fals
a6e0: 65 0a 20 20 20 20 23 20 63 68 65 63 6b 20 6e 65  e.    # check ne
a6f0: 67 61 74 69 76 65 20 63 6f 6e 64 69 74 69 6f 6e  gative condition
a700: 0a 20 20 20 20 69 66 20 73 4e 65 67 50 61 74 74  .    if sNegPatt
a710: 65 72 6e 3a 0a 20 20 20 20 20 20 20 20 69 66 20  ern:.        if 
a720: 73 4e 65 67 50 61 74 74 65 72 6e 20 3d 3d 20 22  sNegPattern == "
a730: 2a 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  *":.            
a740: 23 20 61 6c 6c 20 6d 6f 72 70 68 20 6d 75 73 74  # all morph must
a750: 20 6d 61 74 63 68 20 73 50 61 74 74 65 72 6e 0a   match sPattern.
a760: 20 20 20 20 20 20 20 20 20 20 20 20 7a 50 61 74              zPat
a770: 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c  tern = re.compil
a780: 65 28 73 50 61 74 74 65 72 6e 29 0a 20 20 20 20  e(sPattern).    
a790: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 61          return a
a7a0: 6c 6c 28 7a 50 61 74 74 65 72 6e 2e 73 65 61 72  ll(zPattern.sear
a7b0: 63 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72 20  ch(sMorph)  for 
a7c0: 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68  sMorph in lMorph
a7d0: 29 0a 20 20 20 20 20 20 20 20 7a 4e 65 67 50 61  ).        zNegPa
a7e0: 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69  ttern = re.compi
a7f0: 6c 65 28 73 4e 65 67 50 61 74 74 65 72 6e 29 0a  le(sNegPattern).
a800: 20 20 20 20 20 20 20 20 69 66 20 61 6e 79 28 7a          if any(z
a810: 4e 65 67 50 61 74 74 65 72 6e 2e 73 65 61 72 63  NegPattern.searc
a820: 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72 20 73  h(sMorph)  for s
a830: 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29  Morph in lMorph)
a840: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  :.            re
a850: 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 23  turn False.    #
a860: 20 73 65 61 72 63 68 20 73 50 61 74 74 65 72 6e   search sPattern
a870: 0a 20 20 20 20 7a 50 61 74 74 65 72 6e 20 3d 20  .    zPattern = 
a880: 72 65 2e 63 6f 6d 70 69 6c 65 28 73 50 61 74 74  re.compile(sPatt
a890: 65 72 6e 29 0a 20 20 20 20 72 65 74 75 72 6e 20  ern).    return 
a8a0: 61 6e 79 28 7a 50 61 74 74 65 72 6e 2e 73 65 61  any(zPattern.sea
a8b0: 72 63 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72  rch(sMorph)  for
a8c0: 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70   sMorph in lMorp
a8d0: 68 29 0a 0a 0a 64 65 66 20 61 6e 61 6c 79 73 65  h)...def analyse
a8e0: 20 28 73 57 6f 72 64 2c 20 73 50 61 74 74 65 72   (sWord, sPatter
a8f0: 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 3d 22  n, sNegPattern="
a900: 22 29 3a 0a 20 20 20 20 22 61 6e 61 6c 79 73 65  "):.    "analyse
a910: 20 61 20 77 6f 72 64 2c 20 72 65 74 75 72 6e 73   a word, returns
a920: 20 54 72 75 65 20 69 66 20 6e 6f 74 20 73 4e 65   True if not sNe
a930: 67 50 61 74 74 65 72 6e 20 69 6e 20 77 6f 72 64  gPattern in word
a940: 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 61 6e   morphologies an
a950: 64 20 73 50 61 74 74 65 72 6e 20 69 6e 20 77 6f  d sPattern in wo
a960: 72 64 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20  rd morphologies 
a970: 28 64 69 73 61 6d 62 69 67 75 61 74 69 6f 6e 20  (disambiguation 
a980: 6f 66 66 29 22 0a 20 20 20 20 6c 4d 6f 72 70 68  off)".    lMorph
a990: 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65   = _oSpellChecke
a9a0: 72 2e 67 65 74 4d 6f 72 70 68 28 73 57 6f 72 64  r.getMorph(sWord
a9b0: 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f  ).    if not lMo
a9c0: 72 70 68 3a 0a 20 20 20 20 20 20 20 20 72 65 74  rph:.        ret
a9d0: 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 23 20  urn False.    # 
a9e0: 63 68 65 63 6b 20 6e 65 67 61 74 69 76 65 20 63  check negative c
a9f0: 6f 6e 64 69 74 69 6f 6e 0a 20 20 20 20 69 66 20  ondition.    if 
aa00: 73 4e 65 67 50 61 74 74 65 72 6e 3a 0a 20 20 20  sNegPattern:.   
aa10: 20 20 20 20 20 69 66 20 73 4e 65 67 50 61 74 74       if sNegPatt
aa20: 65 72 6e 20 3d 3d 20 22 2a 22 3a 0a 20 20 20 20  ern == "*":.    
aa30: 20 20 20 20 20 20 20 20 7a 50 61 74 74 65 72 6e          zPattern
aa40: 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 50   = re.compile(sP
aa50: 61 74 74 65 72 6e 29 0a 20 20 20 20 20 20 20 20  attern).        
aa60: 20 20 20 20 72 65 74 75 72 6e 20 61 6c 6c 28 7a      return all(z
aa70: 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73  Pattern.search(s
aa80: 4d 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72  Morph)  for sMor
aa90: 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29 0a 20 20  ph in lMorph).  
aaa0: 20 20 20 20 20 20 7a 4e 65 67 50 61 74 74 65 72        zNegPatter
aab0: 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73  n = re.compile(s
aac0: 4e 65 67 50 61 74 74 65 72 6e 29 0a 20 20 20 20  NegPattern).    
aad0: 20 20 20 20 69 66 20 61 6e 79 28 7a 4e 65 67 50      if any(zNegP
aae0: 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73 4d  attern.search(sM
aaf0: 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70  orph)  for sMorp
ab00: 68 20 69 6e 20 6c 4d 6f 72 70 68 29 3a 0a 20 20  h in lMorph):.  
ab10: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
ab20: 20 46 61 6c 73 65 0a 20 20 20 20 23 20 73 65 61   False.    # sea
ab30: 72 63 68 20 73 50 61 74 74 65 72 6e 0a 20 20 20  rch sPattern.   
ab40: 20 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63   zPattern = re.c
ab50: 6f 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29  ompile(sPattern)
ab60: 0a 20 20 20 20 72 65 74 75 72 6e 20 61 6e 79 28  .    return any(
ab70: 7a 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28  zPattern.search(
ab80: 73 4d 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f  sMorph)  for sMo
ab90: 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29 0a 0a  rph in lMorph)..
aba0: 0a 23 23 23 23 20 41 6e 61 6c 79 73 65 20 74 6f  .#### Analyse to
abb0: 6b 65 6e 73 20 66 6f 72 20 67 72 61 70 68 20 72  kens for graph r
abc0: 75 6c 65 73 0a 0a 64 65 66 20 67 5f 76 61 6c 75  ules..def g_valu
abd0: 65 20 28 64 54 6f 6b 65 6e 2c 20 73 56 61 6c 75  e (dToken, sValu
abe0: 65 73 2c 20 6e 4c 65 66 74 3d 4e 6f 6e 65 2c 20  es, nLeft=None, 
abf0: 6e 52 69 67 68 74 3d 4e 6f 6e 65 29 3a 0a 20 20  nRight=None):.  
ac00: 20 20 22 74 65 73 74 20 69 66 20 3c 64 54 6f 6b    "test if <dTok
ac10: 65 6e 5b 27 73 56 61 6c 75 65 27 5d 3e 20 69 73  en['sValue']> is
ac20: 20 69 6e 20 73 56 61 6c 75 65 73 20 28 65 61 63   in sValues (eac
ac30: 68 20 76 61 6c 75 65 20 73 68 6f 75 6c 64 20 62  h value should b
ac40: 65 20 73 65 70 61 72 61 74 65 64 20 77 69 74 68  e separated with
ac50: 20 7c 29 22 0a 20 20 20 20 73 56 61 6c 75 65 20   |)".    sValue 
ac60: 3d 20 22 7c 22 2b 64 54 6f 6b 65 6e 5b 22 73 56  = "|"+dToken["sV
ac70: 61 6c 75 65 22 5d 2b 22 7c 22 20 20 69 66 20 6e  alue"]+"|"  if n
ac80: 4c 65 66 74 20 69 73 20 4e 6f 6e 65 20 20 65 6c  Left is None  el
ac90: 73 65 20 22 7c 22 2b 64 54 6f 6b 65 6e 5b 22 73  se "|"+dToken["s
aca0: 56 61 6c 75 65 22 5d 5b 73 6c 69 63 65 28 6e 4c  Value"][slice(nL
acb0: 65 66 74 2c 20 6e 52 69 67 68 74 29 5d 2b 22 7c  eft, nRight)]+"|
acc0: 22 0a 20 20 20 20 69 66 20 73 56 61 6c 75 65 20  ".    if sValue 
acd0: 69 6e 20 73 56 61 6c 75 65 73 3a 0a 20 20 20 20  in sValues:.    
ace0: 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a      return True.
acf0: 20 20 20 20 69 66 20 64 54 6f 6b 65 6e 5b 22 73      if dToken["s
ad00: 56 61 6c 75 65 22 5d 5b 30 3a 32 5d 2e 69 73 74  Value"][0:2].ist
ad10: 69 74 6c 65 28 29 3a 20 23 20 77 65 20 74 65 73  itle(): # we tes
ad20: 74 20 6f 6e 6c 79 20 32 20 66 69 72 73 74 20 63  t only 2 first c
ad30: 68 61 72 73 2c 20 74 6f 20 6d 61 6b 65 20 76 61  hars, to make va
ad40: 6c 69 64 20 77 6f 72 64 73 20 73 75 63 68 20 61  lid words such a
ad50: 73 20 22 4c 61 69 73 73 65 7a 2d 6c 65 73 22 2c  s "Laissez-les",
ad60: 20 22 50 61 73 73 65 2d 70 61 72 74 6f 75 74 22   "Passe-partout"
ad70: 2e 0a 20 20 20 20 20 20 20 20 69 66 20 73 56 61  ..        if sVa
ad80: 6c 75 65 2e 6c 6f 77 65 72 28 29 20 69 6e 20 73  lue.lower() in s
ad90: 56 61 6c 75 65 73 3a 0a 20 20 20 20 20 20 20 20  Values:.        
ada0: 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a      return True.
adb0: 20 20 20 20 65 6c 69 66 20 64 54 6f 6b 65 6e 5b      elif dToken[
adc0: 22 73 56 61 6c 75 65 22 5d 2e 69 73 75 70 70 65  "sValue"].isuppe
add0: 72 28 29 3a 0a 20 20 20 20 20 20 20 20 23 69 66  r():.        #if
ade0: 20 73 56 61 6c 75 65 2e 6c 6f 77 65 72 28 29 20   sValue.lower() 
adf0: 69 6e 20 73 56 61 6c 75 65 73 3a 0a 20 20 20 20  in sValues:.    
ae00: 20 20 20 20 23 20 20 20 20 72 65 74 75 72 6e 20      #    return 
ae10: 54 72 75 65 0a 20 20 20 20 20 20 20 20 73 56 61  True.        sVa
ae20: 6c 75 65 20 3d 20 22 7c 22 2b 73 56 61 6c 75 65  lue = "|"+sValue
ae30: 5b 31 3a 5d 2e 63 61 70 69 74 61 6c 69 7a 65 28  [1:].capitalize(
ae40: 29 0a 20 20 20 20 20 20 20 20 69 66 20 73 56 61  ).        if sVa
ae50: 6c 75 65 20 69 6e 20 73 56 61 6c 75 65 73 3a 0a  lue in sValues:.
ae60: 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
ae70: 72 6e 20 54 72 75 65 0a 20 20 20 20 20 20 20 20  rn True.        
ae80: 73 56 61 6c 75 65 20 3d 20 73 56 61 6c 75 65 2e  sValue = sValue.
ae90: 6c 6f 77 65 72 28 29 0a 20 20 20 20 20 20 20 20  lower().        
aea0: 69 66 20 73 56 61 6c 75 65 20 69 6e 20 73 56 61  if sValue in sVa
aeb0: 6c 75 65 73 3a 0a 20 20 20 20 20 20 20 20 20 20  lues:.          
aec0: 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20 20    return True.  
aed0: 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 0a    return False..
aee0: 0a 64 65 66 20 67 5f 6d 6f 72 70 68 20 28 64 54  .def g_morph (dT
aef0: 6f 6b 65 6e 2c 20 73 50 61 74 74 65 72 6e 2c 20  oken, sPattern, 
af00: 73 4e 65 67 50 61 74 74 65 72 6e 3d 22 22 2c 20  sNegPattern="", 
af10: 6e 4c 65 66 74 3d 4e 6f 6e 65 2c 20 6e 52 69 67  nLeft=None, nRig
af20: 68 74 3d 4e 6f 6e 65 2c 20 62 4d 65 6d 6f 72 69  ht=None, bMemori
af30: 7a 65 4d 6f 72 70 68 3d 54 72 75 65 29 3a 0a 20  zeMorph=True):. 
af40: 20 20 20 22 61 6e 61 6c 79 73 65 20 61 20 74 6f     "analyse a to
af50: 6b 65 6e 2c 20 72 65 74 75 72 6e 20 54 72 75 65  ken, return True
af60: 20 69 66 20 3c 73 4e 65 67 50 61 74 74 65 72 6e   if <sNegPattern
af70: 3e 20 6e 6f 74 20 69 6e 20 6d 6f 72 70 68 6f 6c  > not in morphol
af80: 6f 67 69 65 73 20 61 6e 64 20 3c 73 50 61 74 74  ogies and <sPatt
af90: 65 72 6e 3e 20 69 6e 20 6d 6f 72 70 68 6f 6c 6f  ern> in morpholo
afa0: 67 69 65 73 22 0a 20 20 20 20 69 66 20 22 6c 4d  gies".    if "lM
afb0: 6f 72 70 68 22 20 69 6e 20 64 54 6f 6b 65 6e 3a  orph" in dToken:
afc0: 0a 20 20 20 20 20 20 20 20 6c 4d 6f 72 70 68 20  .        lMorph 
afd0: 3d 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68  = dToken["lMorph
afe0: 22 5d 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20 20  "].    else:.   
aff0: 20 20 20 20 20 69 66 20 6e 4c 65 66 74 20 69 73       if nLeft is
b000: 20 6e 6f 74 20 4e 6f 6e 65 3a 0a 20 20 20 20 20   not None:.     
b010: 20 20 20 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20         lMorph = 
b020: 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67  _oSpellChecker.g
b030: 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e 5b 22  etMorph(dToken["
b040: 73 56 61 6c 75 65 22 5d 5b 73 6c 69 63 65 28 6e  sValue"][slice(n
b050: 4c 65 66 74 2c 20 6e 52 69 67 68 74 29 5d 29 0a  Left, nRight)]).
b060: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62              if b
b070: 4d 65 6d 6f 72 69 7a 65 4d 6f 72 70 68 3a 0a 20  MemorizeMorph:. 
b080: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64                 d
b090: 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20  Token["lMorph"] 
b0a0: 3d 20 6c 4d 6f 72 70 68 0a 20 20 20 20 20 20 20  = lMorph.       
b0b0: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
b0c0: 20 20 20 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53 70     lMorph = _oSp
b0d0: 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f  ellChecker.getMo
b0e0: 72 70 68 28 64 54 6f 6b 65 6e 5b 22 73 56 61 6c  rph(dToken["sVal
b0f0: 75 65 22 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74  ue"]).    if not
b100: 20 6c 4d 6f 72 70 68 3a 0a 20 20 20 20 20 20 20   lMorph:.       
b110: 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20   return False.  
b120: 20 20 23 20 63 68 65 63 6b 20 6e 65 67 61 74 69    # check negati
b130: 76 65 20 63 6f 6e 64 69 74 69 6f 6e 0a 20 20 20  ve condition.   
b140: 20 69 66 20 73 4e 65 67 50 61 74 74 65 72 6e 3a   if sNegPattern:
b150: 0a 20 20 20 20 20 20 20 20 69 66 20 73 4e 65 67  .        if sNeg
b160: 50 61 74 74 65 72 6e 20 3d 3d 20 22 2a 22 3a 0a  Pattern == "*":.
b170: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 61 6c              # al
b180: 6c 20 6d 6f 72 70 68 20 6d 75 73 74 20 6d 61 74  l morph must mat
b190: 63 68 20 73 50 61 74 74 65 72 6e 0a 20 20 20 20  ch sPattern.    
b1a0: 20 20 20 20 20 20 20 20 7a 50 61 74 74 65 72 6e          zPattern
b1b0: 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 50   = re.compile(sP
b1c0: 61 74 74 65 72 6e 29 0a 20 20 20 20 20 20 20 20  attern).        
b1d0: 20 20 20 20 72 65 74 75 72 6e 20 61 6c 6c 28 7a      return all(z
b1e0: 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73  Pattern.search(s
b1f0: 4d 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72  Morph)  for sMor
b200: 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29 0a 20 20  ph in lMorph).  
b210: 20 20 20 20 20 20 7a 4e 65 67 50 61 74 74 65 72        zNegPatter
b220: 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73  n = re.compile(s
b230: 4e 65 67 50 61 74 74 65 72 6e 29 0a 20 20 20 20  NegPattern).    
b240: 20 20 20 20 69 66 20 61 6e 79 28 7a 4e 65 67 50      if any(zNegP
b250: 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73 4d  attern.search(sM
b260: 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70  orph)  for sMorp
b270: 68 20 69 6e 20 6c 4d 6f 72 70 68 29 3a 0a 20 20  h in lMorph):.  
b280: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
b290: 20 46 61 6c 73 65 0a 20 20 20 20 23 20 73 65 61   False.    # sea
b2a0: 72 63 68 20 73 50 61 74 74 65 72 6e 0a 20 20 20  rch sPattern.   
b2b0: 20 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63   zPattern = re.c
b2c0: 6f 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29  ompile(sPattern)
b2d0: 0a 20 20 20 20 72 65 74 75 72 6e 20 61 6e 79 28  .    return any(
b2e0: 7a 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28  zPattern.search(
b2f0: 73 4d 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f  sMorph)  for sMo
b300: 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29 0a 0a  rph in lMorph)..
b310: 0a 64 65 66 20 67 5f 61 6e 61 6c 79 73 65 20 28  .def g_analyse (
b320: 64 54 6f 6b 65 6e 2c 20 73 50 61 74 74 65 72 6e  dToken, sPattern
b330: 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 3d 22 22  , sNegPattern=""
b340: 2c 20 6e 4c 65 66 74 3d 4e 6f 6e 65 2c 20 6e 52  , nLeft=None, nR
b350: 69 67 68 74 3d 4e 6f 6e 65 2c 20 62 4d 65 6d 6f  ight=None, bMemo
b360: 72 69 7a 65 4d 6f 72 70 68 3d 54 72 75 65 29 3a  rizeMorph=True):
b370: 0a 20 20 20 20 22 61 6e 61 6c 79 73 65 20 61 20  .    "analyse a 
b380: 74 6f 6b 65 6e 2c 20 72 65 74 75 72 6e 20 54 72  token, return Tr
b390: 75 65 20 69 66 20 3c 73 4e 65 67 50 61 74 74 65  ue if <sNegPatte
b3a0: 72 6e 3e 20 6e 6f 74 20 69 6e 20 6d 6f 72 70 68  rn> not in morph
b3b0: 6f 6c 6f 67 69 65 73 20 61 6e 64 20 3c 73 50 61  ologies and <sPa
b3c0: 74 74 65 72 6e 3e 20 69 6e 20 6d 6f 72 70 68 6f  ttern> in morpho
b3d0: 6c 6f 67 69 65 73 20 28 64 69 73 61 6d 62 69 67  logies (disambig
b3e0: 75 61 74 69 6f 6e 20 6f 66 66 29 22 0a 20 20 20  uation off)".   
b3f0: 20 69 66 20 6e 4c 65 66 74 20 69 73 20 6e 6f 74   if nLeft is not
b400: 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 6c   None:.        l
b410: 4d 6f 72 70 68 20 3d 20 5f 6f 53 70 65 6c 6c 43  Morph = _oSpellC
b420: 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28  hecker.getMorph(
b430: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
b440: 5b 73 6c 69 63 65 28 6e 4c 65 66 74 2c 20 6e 52  [slice(nLeft, nR
b450: 69 67 68 74 29 5d 29 0a 20 20 20 20 20 20 20 20  ight)]).        
b460: 69 66 20 62 4d 65 6d 6f 72 69 7a 65 4d 6f 72 70  if bMemorizeMorp
b470: 68 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  h:.            d
b480: 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20  Token["lMorph"] 
b490: 3d 20 6c 4d 6f 72 70 68 0a 20 20 20 20 65 6c 73  = lMorph.    els
b4a0: 65 3a 0a 20 20 20 20 20 20 20 20 6c 4d 6f 72 70  e:.        lMorp
b4b0: 68 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b  h = _oSpellCheck
b4c0: 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b  er.getMorph(dTok
b4d0: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20  en["sValue"]).  
b4e0: 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 3a    if not lMorph:
b4f0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
b500: 46 61 6c 73 65 0a 20 20 20 20 23 20 63 68 65 63  False.    # chec
b510: 6b 20 6e 65 67 61 74 69 76 65 20 63 6f 6e 64 69  k negative condi
b520: 74 69 6f 6e 0a 20 20 20 20 69 66 20 73 4e 65 67  tion.    if sNeg
b530: 50 61 74 74 65 72 6e 3a 0a 20 20 20 20 20 20 20  Pattern:.       
b540: 20 69 66 20 73 4e 65 67 50 61 74 74 65 72 6e 20   if sNegPattern 
b550: 3d 3d 20 22 2a 22 3a 0a 20 20 20 20 20 20 20 20  == "*":.        
b560: 20 20 20 20 23 20 61 6c 6c 20 6d 6f 72 70 68 20      # all morph 
b570: 6d 75 73 74 20 6d 61 74 63 68 20 73 50 61 74 74  must match sPatt
b580: 65 72 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20  ern.            
b590: 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f  zPattern = re.co
b5a0: 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29 0a  mpile(sPattern).
b5b0: 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
b5c0: 72 6e 20 61 6c 6c 28 7a 50 61 74 74 65 72 6e 2e  rn all(zPattern.
b5d0: 73 65 61 72 63 68 28 73 4d 6f 72 70 68 29 20 20  search(sMorph)  
b5e0: 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d  for sMorph in lM
b5f0: 6f 72 70 68 29 0a 20 20 20 20 20 20 20 20 7a 4e  orph).        zN
b600: 65 67 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63  egPattern = re.c
b610: 6f 6d 70 69 6c 65 28 73 4e 65 67 50 61 74 74 65  ompile(sNegPatte
b620: 72 6e 29 0a 20 20 20 20 20 20 20 20 69 66 20 61  rn).        if a
b630: 6e 79 28 7a 4e 65 67 50 61 74 74 65 72 6e 2e 73  ny(zNegPattern.s
b640: 65 61 72 63 68 28 73 4d 6f 72 70 68 29 20 20 66  earch(sMorph)  f
b650: 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f  or sMorph in lMo
b660: 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20  rph):.          
b670: 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20    return False. 
b680: 20 20 20 23 20 73 65 61 72 63 68 20 73 50 61 74     # search sPat
b690: 74 65 72 6e 0a 20 20 20 20 7a 50 61 74 74 65 72  tern.    zPatter
b6a0: 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73  n = re.compile(s
b6b0: 50 61 74 74 65 72 6e 29 0a 20 20 20 20 72 65 74  Pattern).    ret
b6c0: 75 72 6e 20 61 6e 79 28 7a 50 61 74 74 65 72 6e  urn any(zPattern
b6d0: 2e 73 65 61 72 63 68 28 73 4d 6f 72 70 68 29 20  .search(sMorph) 
b6e0: 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c   for sMorph in l
b6f0: 4d 6f 72 70 68 29 0a 0a 0a 64 65 66 20 67 5f 6d  Morph)...def g_m
b700: 65 72 67 65 64 5f 61 6e 61 6c 79 73 65 20 28 64  erged_analyse (d
b710: 54 6f 6b 65 6e 31 2c 20 64 54 6f 6b 65 6e 32 2c  Token1, dToken2,
b720: 20 63 4d 65 72 67 65 72 2c 20 73 50 61 74 74 65   cMerger, sPatte
b730: 72 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 3d  rn, sNegPattern=
b740: 22 22 2c 20 62 53 65 74 4d 6f 72 70 68 3d 54 72  "", bSetMorph=Tr
b750: 75 65 29 3a 0a 20 20 20 20 22 6d 65 72 67 65 20  ue):.    "merge 
b760: 74 77 6f 20 74 6f 6b 65 6e 20 76 61 6c 75 65 73  two token values
b770: 2c 20 72 65 74 75 72 6e 20 54 72 75 65 20 69 66  , return True if
b780: 20 3c 73 4e 65 67 50 61 74 74 65 72 6e 3e 20 6e   <sNegPattern> n
b790: 6f 74 20 69 6e 20 6d 6f 72 70 68 6f 6c 6f 67 69  ot in morphologi
b7a0: 65 73 20 61 6e 64 20 3c 73 50 61 74 74 65 72 6e  es and <sPattern
b7b0: 3e 20 69 6e 20 6d 6f 72 70 68 6f 6c 6f 67 69 65  > in morphologie
b7c0: 73 20 28 64 69 73 61 6d 62 69 67 75 61 74 69 6f  s (disambiguatio
b7d0: 6e 20 6f 66 66 29 22 0a 20 20 20 20 6c 4d 6f 72  n off)".    lMor
b7e0: 70 68 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63  ph = _oSpellChec
b7f0: 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f  ker.getMorph(dTo
b800: 6b 65 6e 31 5b 22 73 56 61 6c 75 65 22 5d 20 2b  ken1["sValue"] +
b810: 20 63 4d 65 72 67 65 72 20 2b 20 64 54 6f 6b 65   cMerger + dToke
b820: 6e 32 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20  n2["sValue"]).  
b830: 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 3a    if not lMorph:
b840: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
b850: 46 61 6c 73 65 0a 20 20 20 20 23 20 63 68 65 63  False.    # chec
b860: 6b 20 6e 65 67 61 74 69 76 65 20 63 6f 6e 64 69  k negative condi
b870: 74 69 6f 6e 0a 20 20 20 20 69 66 20 73 4e 65 67  tion.    if sNeg
b880: 50 61 74 74 65 72 6e 3a 0a 20 20 20 20 20 20 20  Pattern:.       
b890: 20 69 66 20 73 4e 65 67 50 61 74 74 65 72 6e 20   if sNegPattern 
b8a0: 3d 3d 20 22 2a 22 3a 0a 20 20 20 20 20 20 20 20  == "*":.        
b8b0: 20 20 20 20 23 20 61 6c 6c 20 6d 6f 72 70 68 20      # all morph 
b8c0: 6d 75 73 74 20 6d 61 74 63 68 20 73 50 61 74 74  must match sPatt
b8d0: 65 72 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20  ern.            
b8e0: 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f  zPattern = re.co
b8f0: 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29 0a  mpile(sPattern).
b900: 20 20 20 20 20 20 20 20 20 20 20 20 62 52 65 73              bRes
b910: 75 6c 74 20 3d 20 61 6c 6c 28 7a 50 61 74 74 65  ult = all(zPatte
b920: 72 6e 2e 73 65 61 72 63 68 28 73 4d 6f 72 70 68  rn.search(sMorph
b930: 29 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e  )  for sMorph in
b940: 20 6c 4d 6f 72 70 68 29 0a 20 20 20 20 20 20 20   lMorph).       
b950: 20 20 20 20 20 69 66 20 62 52 65 73 75 6c 74 20       if bResult 
b960: 61 6e 64 20 62 53 65 74 4d 6f 72 70 68 3a 0a 20  and bSetMorph:. 
b970: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64                 d
b980: 54 6f 6b 65 6e 31 5b 22 6c 4d 6f 72 70 68 22 5d  Token1["lMorph"]
b990: 20 3d 20 6c 4d 6f 72 70 68 0a 20 20 20 20 20 20   = lMorph.      
b9a0: 20 20 20 20 20 20 72 65 74 75 72 6e 20 62 52 65        return bRe
b9b0: 73 75 6c 74 0a 20 20 20 20 20 20 20 20 7a 4e 65  sult.        zNe
b9c0: 67 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f  gPattern = re.co
b9d0: 6d 70 69 6c 65 28 73 4e 65 67 50 61 74 74 65 72  mpile(sNegPatter
b9e0: 6e 29 0a 20 20 20 20 20 20 20 20 69 66 20 61 6e  n).        if an
b9f0: 79 28 7a 4e 65 67 50 61 74 74 65 72 6e 2e 73 65  y(zNegPattern.se
ba00: 61 72 63 68 28 73 4d 6f 72 70 68 29 20 20 66 6f  arch(sMorph)  fo
ba10: 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72  r sMorph in lMor
ba20: 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ph):.           
ba30: 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20   return False.  
ba40: 20 20 23 20 73 65 61 72 63 68 20 73 50 61 74 74    # search sPatt
ba50: 65 72 6e 0a 20 20 20 20 7a 50 61 74 74 65 72 6e  ern.    zPattern
ba60: 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 50   = re.compile(sP
ba70: 61 74 74 65 72 6e 29 0a 20 20 20 20 62 52 65 73  attern).    bRes
ba80: 75 6c 74 20 3d 20 61 6e 79 28 7a 50 61 74 74 65  ult = any(zPatte
ba90: 72 6e 2e 73 65 61 72 63 68 28 73 4d 6f 72 70 68  rn.search(sMorph
baa0: 29 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e  )  for sMorph in
bab0: 20 6c 4d 6f 72 70 68 29 0a 20 20 20 20 69 66 20   lMorph).    if 
bac0: 62 52 65 73 75 6c 74 20 61 6e 64 20 62 53 65 74  bResult and bSet
bad0: 4d 6f 72 70 68 3a 0a 20 20 20 20 20 20 20 20 64  Morph:.        d
bae0: 54 6f 6b 65 6e 31 5b 22 6c 4d 6f 72 70 68 22 5d  Token1["lMorph"]
baf0: 20 3d 20 6c 4d 6f 72 70 68 0a 20 20 20 20 72 65   = lMorph.    re
bb00: 74 75 72 6e 20 62 52 65 73 75 6c 74 0a 0a 0a 64  turn bResult...d
bb10: 65 66 20 67 5f 74 61 67 5f 62 65 66 6f 72 65 20  ef g_tag_before 
bb20: 28 64 54 6f 6b 65 6e 2c 20 64 54 61 67 73 2c 20  (dToken, dTags, 
bb30: 73 54 61 67 29 3a 0a 20 20 20 20 22 72 65 74 75  sTag):.    "retu
bb40: 72 6e 73 20 54 72 75 65 20 69 66 20 3c 73 54 61  rns True if <sTa
bb50: 67 3e 20 69 73 20 70 72 65 73 65 6e 74 20 6f 6e  g> is present on
bb60: 20 74 6f 6b 65 6e 73 20 62 65 66 6f 72 65 20 3c   tokens before <
bb70: 64 54 6f 6b 65 6e 3e 22 0a 20 20 20 20 69 66 20  dToken>".    if 
bb80: 73 54 61 67 20 6e 6f 74 20 69 6e 20 64 54 61 67  sTag not in dTag
bb90: 73 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  s:.        retur
bba0: 6e 20 46 61 6c 73 65 0a 20 20 20 20 69 66 20 64  n False.    if d
bbb0: 54 6f 6b 65 6e 5b 22 69 22 5d 20 3e 20 64 54 61  Token["i"] > dTa
bbc0: 67 73 5b 73 54 61 67 5d 5b 30 5d 3a 0a 20 20 20  gs[sTag][0]:.   
bbd0: 20 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65       return True
bbe0: 0a 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73  .    return Fals
bbf0: 65 0a 0a 0a 64 65 66 20 67 5f 74 61 67 5f 61 66  e...def g_tag_af
bc00: 74 65 72 20 28 64 54 6f 6b 65 6e 2c 20 64 54 61  ter (dToken, dTa
bc10: 67 73 2c 20 73 54 61 67 29 3a 0a 20 20 20 20 22  gs, sTag):.    "
bc20: 72 65 74 75 72 6e 73 20 54 72 75 65 20 69 66 20  returns True if 
bc30: 3c 73 54 61 67 3e 20 69 73 20 70 72 65 73 65 6e  <sTag> is presen
bc40: 74 20 6f 6e 20 74 6f 6b 65 6e 73 20 61 66 74 65  t on tokens afte
bc50: 72 20 3c 64 54 6f 6b 65 6e 3e 22 0a 20 20 20 20  r <dToken>".    
bc60: 69 66 20 73 54 61 67 20 6e 6f 74 20 69 6e 20 64  if sTag not in d
bc70: 54 61 67 73 3a 0a 20 20 20 20 20 20 20 20 72 65  Tags:.        re
bc80: 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 69  turn False.    i
bc90: 66 20 64 54 6f 6b 65 6e 5b 22 69 22 5d 20 3c 20  f dToken["i"] < 
bca0: 64 54 61 67 73 5b 73 54 61 67 5d 5b 31 5d 3a 0a  dTags[sTag][1]:.
bcb0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54          return T
bcc0: 72 75 65 0a 20 20 20 20 72 65 74 75 72 6e 20 46  rue.    return F
bcd0: 61 6c 73 65 0a 0a 0a 64 65 66 20 67 5f 74 61 67  alse...def g_tag
bce0: 20 28 64 54 6f 6b 65 6e 2c 20 73 54 61 67 29 3a   (dToken, sTag):
bcf0: 0a 20 20 20 20 22 72 65 74 75 72 6e 73 20 54 72  .    "returns Tr
bd00: 75 65 20 69 66 20 3c 73 54 61 67 3e 20 69 73 20  ue if <sTag> is 
bd10: 70 72 65 73 65 6e 74 20 6f 6e 20 74 6f 6b 65 6e  present on token
bd20: 20 3c 64 54 6f 6b 65 6e 3e 22 0a 20 20 20 20 72   <dToken>".    r
bd30: 65 74 75 72 6e 20 22 61 54 61 67 73 22 20 69 6e  eturn "aTags" in
bd40: 20 64 54 6f 6b 65 6e 20 61 6e 64 20 73 54 61 67   dToken and sTag
bd50: 20 69 6e 20 64 54 6f 6b 65 6e 5b 22 61 54 61 67   in dToken["aTag
bd60: 73 22 5d 0a 0a 0a 64 65 66 20 67 5f 73 70 61 63  s"]...def g_spac
bd70: 65 5f 62 65 74 77 65 65 6e 5f 74 6f 6b 65 6e 73  e_between_tokens
bd80: 20 28 64 54 6f 6b 65 6e 31 2c 20 64 54 6f 6b 65   (dToken1, dToke
bd90: 6e 32 2c 20 6e 4d 69 6e 2c 20 6e 4d 61 78 3d 4e  n2, nMin, nMax=N
bda0: 6f 6e 65 29 3a 0a 20 20 20 20 22 63 68 65 63 6b  one):.    "check
bdb0: 73 20 69 66 20 73 70 61 63 65 73 20 62 65 74 77  s if spaces betw
bdc0: 65 65 6e 20 74 6f 6b 65 6e 73 20 69 73 20 3e 3d  een tokens is >=
bdd0: 20 3c 6e 4d 69 6e 3e 20 61 6e 64 20 3c 3d 20 3c   <nMin> and <= <
bde0: 6e 4d 61 78 3e 22 0a 20 20 20 20 6e 53 70 61 63  nMax>".    nSpac
bdf0: 65 20 3d 20 64 54 6f 6b 65 6e 32 5b 22 6e 53 74  e = dToken2["nSt
be00: 61 72 74 22 5d 20 2d 20 64 54 6f 6b 65 6e 31 5b  art"] - dToken1[
be10: 22 6e 45 6e 64 22 5d 0a 20 20 20 20 69 66 20 6e  "nEnd"].    if n
be20: 53 70 61 63 65 20 3c 20 6e 4d 69 6e 3a 0a 20 20  Space < nMin:.  
be30: 20 20 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c        return Fal
be40: 73 65 0a 20 20 20 20 69 66 20 6e 4d 61 78 20 69  se.    if nMax i
be50: 73 20 6e 6f 74 20 4e 6f 6e 65 20 61 6e 64 20 6e  s not None and n
be60: 53 70 61 63 65 20 3e 20 6e 4d 61 78 3a 0a 20 20  Space > nMax:.  
be70: 20 20 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c        return Fal
be80: 73 65 0a 20 20 20 20 72 65 74 75 72 6e 20 54 72  se.    return Tr
be90: 75 65 0a 0a 0a 64 65 66 20 67 5f 74 6f 6b 65 6e  ue...def g_token
bea0: 20 28 6c 54 6f 6b 65 6e 2c 20 69 29 3a 0a 20 20   (lToken, i):.  
beb0: 20 20 22 72 65 74 75 72 6e 20 74 6f 6b 65 6e 20    "return token 
bec0: 61 74 20 69 6e 64 65 78 20 3c 69 3e 20 69 6e 20  at index <i> in 
bed0: 6c 54 6f 6b 65 6e 20 28 6f 72 20 74 68 65 20 63  lToken (or the c
bee0: 6c 6f 73 65 73 74 20 6f 6e 65 29 22 0a 20 20 20  losest one)".   
bef0: 20 69 66 20 69 20 3c 20 30 3a 0a 20 20 20 20 20   if i < 0:.     
bf00: 20 20 20 72 65 74 75 72 6e 20 6c 54 6f 6b 65 6e     return lToken
bf10: 5b 30 5d 0a 20 20 20 20 69 66 20 69 20 3e 3d 20  [0].    if i >= 
bf20: 6c 65 6e 28 6c 54 6f 6b 65 6e 29 3a 0a 20 20 20  len(lToken):.   
bf30: 20 20 20 20 20 72 65 74 75 72 6e 20 6c 54 6f 6b       return lTok
bf40: 65 6e 5b 2d 31 5d 0a 20 20 20 20 72 65 74 75 72  en[-1].    retur
bf50: 6e 20 6c 54 6f 6b 65 6e 5b 69 5d 0a 0a 0a 0a 23  n lToken[i]....#
bf60: 23 23 23 20 44 69 73 61 6d 62 69 67 75 61 74 6f  ### Disambiguato
bf70: 72 20 66 6f 72 20 72 65 67 65 78 20 72 75 6c 65  r for regex rule
bf80: 73 0a 0a 64 65 66 20 73 65 6c 65 63 74 20 28 64  s..def select (d
bf90: 54 6f 6b 65 6e 50 6f 73 2c 20 6e 50 6f 73 2c 20  TokenPos, nPos, 
bfa0: 73 57 6f 72 64 2c 20 73 50 61 74 74 65 72 6e 2c  sWord, sPattern,
bfb0: 20 6c 44 65 66 61 75 6c 74 3d 4e 6f 6e 65 29 3a   lDefault=None):
bfc0: 0a 20 20 20 20 22 44 69 73 61 6d 62 69 67 75 61  .    "Disambigua
bfd0: 74 69 6f 6e 3a 20 73 65 6c 65 63 74 20 6d 6f 72  tion: select mor
bfe0: 70 68 6f 6c 6f 67 69 65 73 20 6f 66 20 3c 73 57  phologies of <sW
bff0: 6f 72 64 3e 20 6d 61 74 63 68 69 6e 67 20 3c 73  ord> matching <s
c000: 50 61 74 74 65 72 6e 3e 22 0a 20 20 20 20 69 66  Pattern>".    if
c010: 20 6e 6f 74 20 73 57 6f 72 64 3a 0a 20 20 20 20   not sWord:.    
c020: 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a      return True.
c030: 20 20 20 20 69 66 20 6e 50 6f 73 20 6e 6f 74 20      if nPos not 
c040: 69 6e 20 64 54 6f 6b 65 6e 50 6f 73 3a 0a 20 20  in dTokenPos:.  
c050: 20 20 20 20 20 20 65 63 68 6f 28 22 45 72 72 6f        echo("Erro
c060: 72 2e 20 54 68 65 72 65 20 73 68 6f 75 6c 64 20  r. There should 
c070: 62 65 20 61 20 74 6f 6b 65 6e 20 61 74 20 74 68  be a token at th
c080: 69 73 20 70 6f 73 69 74 69 6f 6e 3a 20 22 2c 20  is position: ", 
c090: 6e 50 6f 73 29 0a 20 20 20 20 20 20 20 20 72 65  nPos).        re
c0a0: 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 6c 4d  turn True.    lM
c0b0: 6f 72 70 68 20 3d 20 5f 6f 53 70 65 6c 6c 43 68  orph = _oSpellCh
c0c0: 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 73  ecker.getMorph(s
c0d0: 57 6f 72 64 29 0a 20 20 20 20 69 66 20 6e 6f 74  Word).    if not
c0e0: 20 6c 4d 6f 72 70 68 20 6f 72 20 6c 65 6e 28 6c   lMorph or len(l
c0f0: 4d 6f 72 70 68 29 20 3d 3d 20 31 3a 0a 20 20 20  Morph) == 1:.   
c100: 20 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65       return True
c110: 0a 20 20 20 20 6c 53 65 6c 65 63 74 20 3d 20 5b  .    lSelect = [
c120: 20 73 4d 6f 72 70 68 20 20 66 6f 72 20 73 4d 6f   sMorph  for sMo
c130: 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68 20 20 69  rph in lMorph  i
c140: 66 20 72 65 2e 73 65 61 72 63 68 28 73 50 61 74  f re.search(sPat
c150: 74 65 72 6e 2c 20 73 4d 6f 72 70 68 29 20 5d 0a  tern, sMorph) ].
c160: 20 20 20 20 69 66 20 6c 53 65 6c 65 63 74 3a 0a      if lSelect:.
c170: 20 20 20 20 20 20 20 20 69 66 20 6c 65 6e 28 6c          if len(l
c180: 53 65 6c 65 63 74 29 20 21 3d 20 6c 65 6e 28 6c  Select) != len(l
c190: 4d 6f 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20  Morph):.        
c1a0: 20 20 20 20 64 54 6f 6b 65 6e 50 6f 73 5b 6e 50      dTokenPos[nP
c1b0: 6f 73 5d 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20  os]["lMorph"] = 
c1c0: 6c 53 65 6c 65 63 74 0a 20 20 20 20 65 6c 69 66  lSelect.    elif
c1d0: 20 6c 44 65 66 61 75 6c 74 3a 0a 20 20 20 20 20   lDefault:.     
c1e0: 20 20 20 64 54 6f 6b 65 6e 50 6f 73 5b 6e 50 6f     dTokenPos[nPo
c1f0: 73 5d 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c  s]["lMorph"] = l
c200: 44 65 66 61 75 6c 74 0a 20 20 20 20 72 65 74 75  Default.    retu
c210: 72 6e 20 54 72 75 65 0a 0a 0a 64 65 66 20 65 78  rn True...def ex
c220: 63 6c 75 64 65 20 28 64 54 6f 6b 65 6e 50 6f 73  clude (dTokenPos
c230: 2c 20 6e 50 6f 73 2c 20 73 57 6f 72 64 2c 20 73  , nPos, sWord, s
c240: 50 61 74 74 65 72 6e 2c 20 6c 44 65 66 61 75 6c  Pattern, lDefaul
c250: 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 44 69  t=None):.    "Di
c260: 73 61 6d 62 69 67 75 61 74 69 6f 6e 3a 20 65 78  sambiguation: ex
c270: 63 6c 75 64 65 20 6d 6f 72 70 68 6f 6c 6f 67 69  clude morphologi
c280: 65 73 20 6f 66 20 3c 73 57 6f 72 64 3e 20 6d 61  es of <sWord> ma
c290: 74 63 68 69 6e 67 20 3c 73 50 61 74 74 65 72 6e  tching <sPattern
c2a0: 3e 22 0a 20 20 20 20 69 66 20 6e 6f 74 20 73 57  >".    if not sW
c2b0: 6f 72 64 3a 0a 20 20 20 20 20 20 20 20 72 65 74  ord:.        ret
c2c0: 75 72 6e 20 54 72 75 65 0a 20 20 20 20 69 66 20  urn True.    if 
c2d0: 6e 50 6f 73 20 6e 6f 74 20 69 6e 20 64 54 6f 6b  nPos not in dTok
c2e0: 65 6e 50 6f 73 3a 0a 20 20 20 20 20 20 20 20 65  enPos:.        e
c2f0: 63 68 6f 28 22 45 72 72 6f 72 2e 20 54 68 65 72  cho("Error. Ther
c300: 65 20 73 68 6f 75 6c 64 20 62 65 20 61 20 74 6f  e should be a to
c310: 6b 65 6e 20 61 74 20 74 68 69 73 20 70 6f 73 69  ken at this posi
c320: 74 69 6f 6e 3a 20 22 2c 20 6e 50 6f 73 29 0a 20  tion: ", nPos). 
c330: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54 72         return Tr
c340: 75 65 0a 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20  ue.    lMorph = 
c350: 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67  _oSpellChecker.g
c360: 65 74 4d 6f 72 70 68 28 73 57 6f 72 64 29 0a 20  etMorph(sWord). 
c370: 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68     if not lMorph
c380: 20 6f 72 20 6c 65 6e 28 6c 4d 6f 72 70 68 29 20   or len(lMorph) 
c390: 3d 3d 20 31 3a 0a 20 20 20 20 20 20 20 20 72 65  == 1:.        re
c3a0: 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 6c 53  turn True.    lS
c3b0: 65 6c 65 63 74 20 3d 20 5b 20 73 4d 6f 72 70 68  elect = [ sMorph
c3c0: 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20    for sMorph in 
c3d0: 6c 4d 6f 72 70 68 20 20 69 66 20 6e 6f 74 20 72  lMorph  if not r
c3e0: 65 2e 73 65 61 72 63 68 28 73 50 61 74 74 65 72  e.search(sPatter
c3f0: 6e 2c 20 73 4d 6f 72 70 68 29 20 5d 0a 20 20 20  n, sMorph) ].   
c400: 20 69 66 20 6c 53 65 6c 65 63 74 3a 0a 20 20 20   if lSelect:.   
c410: 20 20 20 20 20 69 66 20 6c 65 6e 28 6c 53 65 6c       if len(lSel
c420: 65 63 74 29 20 21 3d 20 6c 65 6e 28 6c 4d 6f 72  ect) != len(lMor
c430: 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ph):.           
c440: 20 64 54 6f 6b 65 6e 50 6f 73 5b 6e 50 6f 73 5d   dTokenPos[nPos]
c450: 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 53 65  ["lMorph"] = lSe
c460: 6c 65 63 74 0a 20 20 20 20 65 6c 69 66 20 6c 44  lect.    elif lD
c470: 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 20 20  efault:.        
c480: 64 54 6f 6b 65 6e 50 6f 73 5b 6e 50 6f 73 5d 5b  dTokenPos[nPos][
c490: 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 44 65 66  "lMorph"] = lDef
c4a0: 61 75 6c 74 0a 20 20 20 20 72 65 74 75 72 6e 20  ault.    return 
c4b0: 54 72 75 65 0a 0a 0a 64 65 66 20 64 65 66 69 6e  True...def defin
c4c0: 65 20 28 64 54 6f 6b 65 6e 50 6f 73 2c 20 6e 50  e (dTokenPos, nP
c4d0: 6f 73 2c 20 6c 4d 6f 72 70 68 29 3a 0a 20 20 20  os, lMorph):.   
c4e0: 20 22 44 69 73 61 6d 62 69 67 75 61 74 69 6f 6e   "Disambiguation
c4f0: 3a 20 73 65 74 20 6d 6f 72 70 68 6f 6c 6f 67 69  : set morphologi
c500: 65 73 20 6f 66 20 74 6f 6b 65 6e 20 61 74 20 3c  es of token at <
c510: 6e 50 6f 73 3e 20 77 69 74 68 20 3c 6c 4d 6f 72  nPos> with <lMor
c520: 70 68 3e 22 0a 20 20 20 20 69 66 20 6e 50 6f 73  ph>".    if nPos
c530: 20 6e 6f 74 20 69 6e 20 64 54 6f 6b 65 6e 50 6f   not in dTokenPo
c540: 73 3a 0a 20 20 20 20 20 20 20 20 65 63 68 6f 28  s:.        echo(
c550: 22 45 72 72 6f 72 2e 20 54 68 65 72 65 20 73 68  "Error. There sh
c560: 6f 75 6c 64 20 62 65 20 61 20 74 6f 6b 65 6e 20  ould be a token 
c570: 61 74 20 74 68 69 73 20 70 6f 73 69 74 69 6f 6e  at this position
c580: 3a 20 22 2c 20 6e 50 6f 73 29 0a 20 20 20 20 20  : ", nPos).     
c590: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
c5a0: 20 20 20 64 54 6f 6b 65 6e 50 6f 73 5b 6e 50 6f     dTokenPos[nPo
c5b0: 73 5d 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c  s]["lMorph"] = l
c5c0: 4d 6f 72 70 68 0a 20 20 20 20 72 65 74 75 72 6e  Morph.    return
c5d0: 20 54 72 75 65 0a 0a 0a 23 23 23 23 20 44 69 73   True...#### Dis
c5e0: 61 6d 62 69 67 75 61 74 69 6f 6e 20 66 6f 72 20  ambiguation for 
c5f0: 67 72 61 70 68 20 72 75 6c 65 73 0a 0a 64 65 66  graph rules..def
c600: 20 67 5f 73 65 6c 65 63 74 20 28 64 54 6f 6b 65   g_select (dToke
c610: 6e 2c 20 73 50 61 74 74 65 72 6e 2c 20 6c 44 65  n, sPattern, lDe
c620: 66 61 75 6c 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20  fault=None):.   
c630: 20 22 73 65 6c 65 63 74 20 6d 6f 72 70 68 6f 6c   "select morphol
c640: 6f 67 69 65 73 20 66 6f 72 20 3c 64 54 6f 6b 65  ogies for <dToke
c650: 6e 3e 20 61 63 63 6f 72 64 69 6e 67 20 74 6f 20  n> according to 
c660: 3c 73 50 61 74 74 65 72 6e 3e 2c 20 61 6c 77 61  <sPattern>, alwa
c670: 79 73 20 72 65 74 75 72 6e 20 54 72 75 65 22 0a  ys return True".
c680: 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20 64 54 6f      lMorph = dTo
c690: 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 20 69  ken["lMorph"]  i
c6a0: 66 20 22 6c 4d 6f 72 70 68 22 20 69 6e 20 64 54  f "lMorph" in dT
c6b0: 6f 6b 65 6e 20 20 65 6c 73 65 20 5f 6f 53 70 65  oken  else _oSpe
c6c0: 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72  llChecker.getMor
c6d0: 70 68 28 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  ph(dToken["sValu
c6e0: 65 22 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20  e"]).    if not 
c6f0: 6c 4d 6f 72 70 68 20 6f 72 20 6c 65 6e 28 6c 4d  lMorph or len(lM
c700: 6f 72 70 68 29 20 3d 3d 20 31 3a 0a 20 20 20 20  orph) == 1:.    
c710: 20 20 20 20 69 66 20 6c 44 65 66 61 75 6c 74 3a      if lDefault:
c720: 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f  .            dTo
c730: 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20  ken["lMorph"] = 
c740: 6c 44 65 66 61 75 6c 74 0a 20 20 20 20 20 20 20  lDefault.       
c750: 20 20 20 20 20 23 65 63 68 6f 28 22 44 41 3a 22       #echo("DA:"
c760: 2c 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65  , dToken["sValue
c770: 22 5d 2c 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72  "], dToken["lMor
c780: 70 68 22 5d 29 0a 20 20 20 20 20 20 20 20 72 65  ph"]).        re
c790: 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 6c 53  turn True.    lS
c7a0: 65 6c 65 63 74 20 3d 20 5b 20 73 4d 6f 72 70 68  elect = [ sMorph
c7b0: 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20    for sMorph in 
c7c0: 6c 4d 6f 72 70 68 20 20 69 66 20 72 65 2e 73 65  lMorph  if re.se
c7d0: 61 72 63 68 28 73 50 61 74 74 65 72 6e 2c 20 73  arch(sPattern, s
c7e0: 4d 6f 72 70 68 29 20 5d 0a 20 20 20 20 69 66 20  Morph) ].    if 
c7f0: 6c 53 65 6c 65 63 74 3a 0a 20 20 20 20 20 20 20  lSelect:.       
c800: 20 69 66 20 6c 65 6e 28 6c 53 65 6c 65 63 74 29   if len(lSelect)
c810: 20 21 3d 20 6c 65 6e 28 6c 4d 6f 72 70 68 29 3a   != len(lMorph):
c820: 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f  .            dTo
c830: 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20  ken["lMorph"] = 
c840: 6c 53 65 6c 65 63 74 0a 20 20 20 20 65 6c 69 66  lSelect.    elif
c850: 20 6c 44 65 66 61 75 6c 74 3a 0a 20 20 20 20 20   lDefault:.     
c860: 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70     dToken["lMorp
c870: 68 22 5d 20 3d 20 6c 44 65 66 61 75 6c 74 0a 20  h"] = lDefault. 
c880: 20 20 20 23 65 63 68 6f 28 22 44 41 3a 22 2c 20     #echo("DA:", 
c890: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
c8a0: 2c 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68  , dToken["lMorph
c8b0: 22 5d 29 0a 20 20 20 20 72 65 74 75 72 6e 20 54  "]).    return T
c8c0: 72 75 65 0a 0a 0a 64 65 66 20 67 5f 65 78 63 6c  rue...def g_excl
c8d0: 75 64 65 20 28 64 54 6f 6b 65 6e 2c 20 73 50 61  ude (dToken, sPa
c8e0: 74 74 65 72 6e 2c 20 6c 44 65 66 61 75 6c 74 3d  ttern, lDefault=
c8f0: 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 73 65 6c 65  None):.    "sele
c900: 63 74 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20  ct morphologies 
c910: 66 6f 72 20 3c 64 54 6f 6b 65 6e 3e 20 61 63 63  for <dToken> acc
c920: 6f 72 64 69 6e 67 20 74 6f 20 3c 73 50 61 74 74  ording to <sPatt
c930: 65 72 6e 3e 2c 20 61 6c 77 61 79 73 20 72 65 74  ern>, always ret
c940: 75 72 6e 20 54 72 75 65 22 0a 20 20 20 20 6c 4d  urn True".    lM
c950: 6f 72 70 68 20 3d 20 64 54 6f 6b 65 6e 5b 22 6c  orph = dToken["l
c960: 4d 6f 72 70 68 22 5d 20 20 69 66 20 22 6c 4d 6f  Morph"]  if "lMo
c970: 72 70 68 22 20 69 6e 20 64 54 6f 6b 65 6e 20 20  rph" in dToken  
c980: 65 6c 73 65 20 5f 6f 53 70 65 6c 6c 43 68 65 63  else _oSpellChec
c990: 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f  ker.getMorph(dTo
c9a0: 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20  ken["sValue"]). 
c9b0: 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68     if not lMorph
c9c0: 20 6f 72 20 6c 65 6e 28 6c 4d 6f 72 70 68 29 20   or len(lMorph) 
c9d0: 3d 3d 20 31 3a 0a 20 20 20 20 20 20 20 20 69 66  == 1:.        if
c9e0: 20 6c 44 65 66 61 75 6c 74 3a 0a 20 20 20 20 20   lDefault:.     
c9f0: 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22 6c         dToken["l
ca00: 4d 6f 72 70 68 22 5d 20 3d 20 6c 44 65 66 61 75  Morph"] = lDefau
ca10: 6c 74 0a 20 20 20 20 20 20 20 20 20 20 20 20 23  lt.            #
ca20: 65 63 68 6f 28 22 44 41 3a 22 2c 20 64 54 6f 6b  echo("DA:", dTok
ca30: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2c 20 64 54  en["sValue"], dT
ca40: 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 29 0a  oken["lMorph"]).
ca50: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54          return T
ca60: 72 75 65 0a 20 20 20 20 6c 53 65 6c 65 63 74 20  rue.    lSelect 
ca70: 3d 20 5b 20 73 4d 6f 72 70 68 20 20 66 6f 72 20  = [ sMorph  for 
ca80: 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68  sMorph in lMorph
ca90: 20 20 69 66 20 6e 6f 74 20 72 65 2e 73 65 61 72    if not re.sear
caa0: 63 68 28 73 50 61 74 74 65 72 6e 2c 20 73 4d 6f  ch(sPattern, sMo
cab0: 72 70 68 29 20 5d 0a 20 20 20 20 69 66 20 6c 53  rph) ].    if lS
cac0: 65 6c 65 63 74 3a 0a 20 20 20 20 20 20 20 20 69  elect:.        i
cad0: 66 20 6c 65 6e 28 6c 53 65 6c 65 63 74 29 20 21  f len(lSelect) !
cae0: 3d 20 6c 65 6e 28 6c 4d 6f 72 70 68 29 3a 0a 20  = len(lMorph):. 
caf0: 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65             dToke
cb00: 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 53  n["lMorph"] = lS
cb10: 65 6c 65 63 74 0a 20 20 20 20 65 6c 69 66 20 6c  elect.    elif l
cb20: 44 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 20  Default:.       
cb30: 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22   dToken["lMorph"
cb40: 5d 20 3d 20 6c 44 65 66 61 75 6c 74 0a 20 20 20  ] = lDefault.   
cb50: 20 23 65 63 68 6f 28 22 44 41 3a 22 2c 20 64 54   #echo("DA:", dT
cb60: 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2c 20  oken["sValue"], 
cb70: 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d  dToken["lMorph"]
cb80: 29 0a 20 20 20 20 72 65 74 75 72 6e 20 54 72 75  ).    return Tru
cb90: 65 0a 0a 0a 64 65 66 20 67 5f 64 65 66 69 6e 65  e...def g_define
cba0: 20 28 64 54 6f 6b 65 6e 2c 20 6c 4d 6f 72 70 68   (dToken, lMorph
cbb0: 29 3a 0a 20 20 20 20 22 73 65 74 20 6d 6f 72 70  ):.    "set morp
cbc0: 68 6f 6c 6f 67 69 65 73 20 6f 66 20 3c 64 54 6f  hologies of <dTo
cbd0: 6b 65 6e 3e 2c 20 61 6c 77 61 79 73 20 72 65 74  ken>, always ret
cbe0: 75 72 6e 20 54 72 75 65 22 0a 20 20 20 20 64 54  urn True".    dT
cbf0: 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d  oken["lMorph"] =
cc00: 20 6c 4d 6f 72 70 68 0a 20 20 20 20 23 65 63 68   lMorph.    #ech
cc10: 6f 28 22 44 41 3a 22 2c 20 64 54 6f 6b 65 6e 5b  o("DA:", dToken[
cc20: 22 73 56 61 6c 75 65 22 5d 2c 20 6c 4d 6f 72 70  "sValue"], lMorp
cc30: 68 29 0a 20 20 20 20 72 65 74 75 72 6e 20 54 72  h).    return Tr
cc40: 75 65 0a 0a 0a 64 65 66 20 67 5f 64 65 66 69 6e  ue...def g_defin
cc50: 65 5f 66 72 6f 6d 20 28 64 54 6f 6b 65 6e 2c 20  e_from (dToken, 
cc60: 6e 4c 65 66 74 3d 4e 6f 6e 65 2c 20 6e 52 69 67  nLeft=None, nRig
cc70: 68 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 73  ht=None):.    "s
cc80: 65 74 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20  et morphologies 
cc90: 6f 66 20 3c 64 54 6f 6b 65 6e 3e 20 77 69 74 68  of <dToken> with
cca0: 20 73 6c 69 63 69 6e 67 20 69 74 73 20 76 61 6c   slicing its val
ccb0: 75 65 20 77 69 74 68 20 3c 6e 4c 65 66 74 3e 20  ue with <nLeft> 
ccc0: 61 6e 64 20 3c 6e 52 69 67 68 74 3e 22 0a 20 20  and <nRight>".  
ccd0: 20 20 69 66 20 6e 4c 65 66 74 20 69 73 20 6e 6f    if nLeft is no
cce0: 74 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20  t None:.        
ccf0: 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d  dToken["lMorph"]
cd00: 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65   = _oSpellChecke
cd10: 72 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65  r.getMorph(dToke
cd20: 6e 5b 22 73 56 61 6c 75 65 22 5d 5b 73 6c 69 63  n["sValue"][slic
cd30: 65 28 6e 4c 65 66 74 2c 20 6e 52 69 67 68 74 29  e(nLeft, nRight)
cd40: 5d 29 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20 20  ]).    else:.   
cd50: 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f       dToken["lMo
cd60: 72 70 68 22 5d 20 3d 20 5f 6f 53 70 65 6c 6c 43  rph"] = _oSpellC
cd70: 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28  hecker.getMorph(
cd80: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
cd90: 29 0a 20 20 20 20 72 65 74 75 72 6e 20 54 72 75  ).    return Tru
cda0: 65 0a 0a 0a 0a 23 23 23 23 20 47 52 41 4d 4d 41  e....#### GRAMMA
cdb0: 52 20 43 48 45 43 4b 45 52 20 50 4c 55 47 49 4e  R CHECKER PLUGIN
cdc0: 53 0a 0a 24 7b 70 6c 75 67 69 6e 73 7d 0a 0a 0a  S..${plugins}...
cdd0: 23 23 23 23 20 43 41 4c 4c 41 42 4c 45 53 20 46  #### CALLABLES F
cde0: 4f 52 20 52 45 47 45 58 20 52 55 4c 45 53 20 28  OR REGEX RULES (
cdf0: 67 65 6e 65 72 61 74 65 64 20 63 6f 64 65 29 0a  generated code).
ce00: 0a 24 7b 63 61 6c 6c 61 62 6c 65 73 7d 0a 0a 0a  .${callables}...
ce10: 23 23 23 23 20 43 41 4c 4c 41 42 4c 45 53 20 46  #### CALLABLES F
ce20: 4f 52 20 47 52 41 50 48 20 52 55 4c 45 53 20 28  OR GRAPH RULES (
ce30: 67 65 6e 65 72 61 74 65 64 20 63 6f 64 65 29 0a  generated code).
ce40: 0a 24 7b 67 72 61 70 68 5f 63 61 6c 6c 61 62 6c  .${graph_callabl
ce50: 65 73 7d 0a                                      es}.