Grammalecte  Hex Artifact Content

Artifact f034e8dbe915b0fd5c32177314fff8143270508b699ba80178e897ee2f0c2467:


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 73 79 73  rt re.import sys
0040: 0a 69 6d 70 6f 72 74 20 6f 73 0a 69 6d 70 6f 72  .import os.impor
0050: 74 20 74 72 61 63 65 62 61 63 6b 0a 23 69 6d 70  t traceback.#imp
0060: 6f 72 74 20 75 6e 69 63 6f 64 65 64 61 74 61 0a  ort unicodedata.
0070: 66 72 6f 6d 20 69 74 65 72 74 6f 6f 6c 73 20 69  from itertools i
0080: 6d 70 6f 72 74 20 63 68 61 69 6e 0a 0a 66 72 6f  mport chain..fro
0090: 6d 20 2e 2e 67 72 61 70 68 73 70 65 6c 6c 2e 73  m ..graphspell.s
00a0: 70 65 6c 6c 63 68 65 63 6b 65 72 20 69 6d 70 6f  pellchecker impo
00b0: 72 74 20 53 70 65 6c 6c 43 68 65 63 6b 65 72 0a  rt SpellChecker.
00c0: 66 72 6f 6d 20 2e 2e 67 72 61 70 68 73 70 65 6c  from ..graphspel
00d0: 6c 2e 65 63 68 6f 20 69 6d 70 6f 72 74 20 65 63  l.echo import ec
00e0: 68 6f 0a 66 72 6f 6d 20 2e 20 69 6d 70 6f 72 74  ho.from . import
00f0: 20 67 63 5f 6f 70 74 69 6f 6e 73 0a 0a 66 72 6f   gc_options..fro
0100: 6d 20 2e 2e 67 72 61 70 68 73 70 65 6c 6c 2e 74  m ..graphspell.t
0110: 6f 6b 65 6e 69 7a 65 72 20 69 6d 70 6f 72 74 20  okenizer import 
0120: 54 6f 6b 65 6e 69 7a 65 72 0a 66 72 6f 6d 20 2e  Tokenizer.from .
0130: 67 63 5f 72 75 6c 65 73 5f 67 72 61 70 68 20 69  gc_rules_graph i
0140: 6d 70 6f 72 74 20 64 41 6c 6c 47 72 61 70 68 2c  mport dAllGraph,
0150: 20 64 52 75 6c 65 0a 0a 74 72 79 3a 0a 20 20 20   dRule..try:.   
0160: 20 23 20 4c 69 62 72 65 4f 66 66 69 63 65 20 2f   # LibreOffice /
0170: 20 4f 70 65 6e 4f 66 66 69 63 65 0a 20 20 20 20   OpenOffice.    
0180: 66 72 6f 6d 20 63 6f 6d 2e 73 75 6e 2e 73 74 61  from com.sun.sta
0190: 72 2e 6c 69 6e 67 75 69 73 74 69 63 32 20 69 6d  r.linguistic2 im
01a0: 70 6f 72 74 20 53 69 6e 67 6c 65 50 72 6f 6f 66  port SingleProof
01b0: 72 65 61 64 69 6e 67 45 72 72 6f 72 0a 20 20 20  readingError.   
01c0: 20 66 72 6f 6d 20 63 6f 6d 2e 73 75 6e 2e 73 74   from com.sun.st
01d0: 61 72 2e 74 65 78 74 2e 54 65 78 74 4d 61 72 6b  ar.text.TextMark
01e0: 75 70 54 79 70 65 20 69 6d 70 6f 72 74 20 50 52  upType import PR
01f0: 4f 4f 46 52 45 41 44 49 4e 47 0a 20 20 20 20 66  OOFREADING.    f
0200: 72 6f 6d 20 63 6f 6d 2e 73 75 6e 2e 73 74 61 72  rom com.sun.star
0210: 2e 62 65 61 6e 73 20 69 6d 70 6f 72 74 20 50 72  .beans import Pr
0220: 6f 70 65 72 74 79 56 61 6c 75 65 0a 20 20 20 20  opertyValue.    
0230: 23 69 6d 70 6f 72 74 20 6c 69 67 68 74 70 72 6f  #import lightpro
0240: 6f 66 5f 68 61 6e 64 6c 65 72 5f 24 7b 69 6d 70  of_handler_${imp
0250: 6c 6e 61 6d 65 7d 20 61 73 20 6f 70 74 0a 20 20  lname} as opt.  
0260: 20 20 5f 62 57 72 69 74 65 72 45 72 72 6f 72 20    _bWriterError 
0270: 3d 20 54 72 75 65 0a 65 78 63 65 70 74 20 49 6d  = True.except Im
0280: 70 6f 72 74 45 72 72 6f 72 3a 0a 20 20 20 20 5f  portError:.    _
0290: 62 57 72 69 74 65 72 45 72 72 6f 72 20 3d 20 46  bWriterError = F
02a0: 61 6c 73 65 0a 0a 0a 5f 5f 61 6c 6c 5f 5f 20 3d  alse...__all__ =
02b0: 20 5b 20 22 6c 61 6e 67 22 2c 20 22 6c 6f 63 61   [ "lang", "loca
02c0: 6c 65 73 22 2c 20 22 70 6b 67 22 2c 20 22 6e 61  les", "pkg", "na
02d0: 6d 65 22 2c 20 22 76 65 72 73 69 6f 6e 22 2c 20  me", "version", 
02e0: 22 61 75 74 68 6f 72 22 2c 20 5c 0a 20 20 20 20  "author", \.    
02f0: 20 20 20 20 20 20 20 20 22 6c 6f 61 64 22 2c 20          "load", 
0300: 22 70 61 72 73 65 22 2c 20 22 67 65 74 53 70 65  "parse", "getSpe
0310: 6c 6c 43 68 65 63 6b 65 72 22 2c 20 5c 0a 20 20  llChecker", \.  
0320: 20 20 20 20 20 20 20 20 20 20 22 73 65 74 4f 70            "setOp
0330: 74 69 6f 6e 22 2c 20 22 73 65 74 4f 70 74 69 6f  tion", "setOptio
0340: 6e 73 22 2c 20 22 67 65 74 4f 70 74 69 6f 6e 73  ns", "getOptions
0350: 22 2c 20 22 67 65 74 44 65 66 61 75 6c 74 4f 70  ", "getDefaultOp
0360: 74 69 6f 6e 73 22 2c 20 22 67 65 74 4f 70 74 69  tions", "getOpti
0370: 6f 6e 73 4c 61 62 65 6c 73 22 2c 20 22 72 65 73  onsLabels", "res
0380: 65 74 4f 70 74 69 6f 6e 73 22 2c 20 22 64 69 73  etOptions", "dis
0390: 70 6c 61 79 4f 70 74 69 6f 6e 73 22 2c 20 5c 0a  playOptions", \.
03a0: 20 20 20 20 20 20 20 20 20 20 20 20 22 69 67 6e              "ign
03b0: 6f 72 65 52 75 6c 65 22 2c 20 22 72 65 73 65 74  oreRule", "reset
03c0: 49 67 6e 6f 72 65 52 75 6c 65 73 22 2c 20 22 72  IgnoreRules", "r
03d0: 65 61 63 74 69 76 61 74 65 52 75 6c 65 22 2c 20  eactivateRule", 
03e0: 22 6c 69 73 74 52 75 6c 65 73 22 2c 20 22 64 69  "listRules", "di
03f0: 73 70 6c 61 79 52 75 6c 65 73 22 20 5d 0a 0a 5f  splayRules" ].._
0400: 5f 76 65 72 73 69 6f 6e 5f 5f 20 3d 20 22 24 7b  _version__ = "${
0410: 76 65 72 73 69 6f 6e 7d 22 0a 0a 0a 6c 61 6e 67  version}"...lang
0420: 20 3d 20 22 24 7b 6c 61 6e 67 7d 22 0a 6c 6f 63   = "${lang}".loc
0430: 61 6c 65 73 20 3d 20 24 7b 6c 6f 63 7d 0a 70 6b  ales = ${loc}.pk
0440: 67 20 3d 20 22 24 7b 69 6d 70 6c 6e 61 6d 65 7d  g = "${implname}
0450: 22 0a 6e 61 6d 65 20 3d 20 22 24 7b 6e 61 6d 65  ".name = "${name
0460: 7d 22 0a 76 65 72 73 69 6f 6e 20 3d 20 22 24 7b  }".version = "${
0470: 76 65 72 73 69 6f 6e 7d 22 0a 61 75 74 68 6f 72  version}".author
0480: 20 3d 20 22 24 7b 61 75 74 68 6f 72 7d 22 0a 0a   = "${author}"..
0490: 5f 72 75 6c 65 73 20 3d 20 4e 6f 6e 65 20 20 20  _rules = None   
04a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
04b0: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 6d 6f              # mo
04c0: 64 75 6c 65 20 67 63 5f 72 75 6c 65 73 0a 0a 23  dule gc_rules..#
04d0: 20 64 61 74 61 0a 5f 73 41 70 70 43 6f 6e 74 65   data._sAppConte
04e0: 78 74 20 3d 20 22 22 20 20 20 20 20 20 20 20 20  xt = ""         
04f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0500: 20 20 23 20 77 68 61 74 20 73 6f 66 74 77 61 72    # what softwar
0510: 65 20 69 73 20 72 75 6e 6e 69 6e 67 0a 5f 64 4f  e is running._dO
0520: 70 74 69 6f 6e 73 20 3d 20 4e 6f 6e 65 0a 5f 6f  ptions = None._o
0530: 53 70 65 6c 6c 43 68 65 63 6b 65 72 20 3d 20 4e  SpellChecker = N
0540: 6f 6e 65 0a 5f 6f 54 6f 6b 65 6e 69 7a 65 72 20  one._oTokenizer 
0550: 3d 20 4e 6f 6e 65 0a 5f 61 49 67 6e 6f 72 65 64  = None._aIgnored
0560: 52 75 6c 65 73 20 3d 20 73 65 74 28 29 0a 0a 23  Rules = set()..#
0570: 20 66 75 6e 63 74 69 6f 6e 73 0a 5f 63 72 65 61   functions._crea
0580: 74 65 52 65 67 65 78 45 72 72 6f 72 20 3d 20 4e  teRegexError = N
0590: 6f 6e 65 0a 0a 0a 23 23 23 23 20 49 6e 69 74 69  one...#### Initi
05a0: 61 6c 69 7a 61 74 69 6f 6e 0a 0a 64 65 66 20 6c  alization..def l
05b0: 6f 61 64 20 28 73 43 6f 6e 74 65 78 74 3d 22 50  oad (sContext="P
05c0: 79 74 68 6f 6e 22 29 3a 0a 20 20 20 20 22 69 6e  ython"):.    "in
05d0: 69 74 69 61 6c 69 7a 61 74 69 6f 6e 20 6f 66 20  itialization of 
05e0: 74 68 65 20 67 72 61 6d 6d 61 72 20 63 68 65 63  the grammar chec
05f0: 6b 65 72 22 0a 20 20 20 20 67 6c 6f 62 61 6c 20  ker".    global 
0600: 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 0a 20  _oSpellChecker. 
0610: 20 20 20 67 6c 6f 62 61 6c 20 5f 73 41 70 70 43     global _sAppC
0620: 6f 6e 74 65 78 74 0a 20 20 20 20 67 6c 6f 62 61  ontext.    globa
0630: 6c 20 5f 64 4f 70 74 69 6f 6e 73 0a 20 20 20 20  l _dOptions.    
0640: 67 6c 6f 62 61 6c 20 5f 6f 54 6f 6b 65 6e 69 7a  global _oTokeniz
0650: 65 72 0a 20 20 20 20 67 6c 6f 62 61 6c 20 5f 63  er.    global _c
0660: 72 65 61 74 65 52 65 67 65 78 45 72 72 6f 72 0a  reateRegexError.
0670: 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20      try:.       
0680: 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 20   _oSpellChecker 
0690: 3d 20 53 70 65 6c 6c 43 68 65 63 6b 65 72 28 22  = SpellChecker("
06a0: 24 7b 6c 61 6e 67 7d 22 2c 20 22 24 7b 64 69 63  ${lang}", "${dic
06b0: 5f 6d 61 69 6e 5f 66 69 6c 65 6e 61 6d 65 5f 70  _main_filename_p
06c0: 79 7d 22 2c 20 22 24 7b 64 69 63 5f 65 78 74 65  y}", "${dic_exte
06d0: 6e 64 65 64 5f 66 69 6c 65 6e 61 6d 65 5f 70 79  nded_filename_py
06e0: 7d 22 2c 20 22 24 7b 64 69 63 5f 63 6f 6d 6d 75  }", "${dic_commu
06f0: 6e 69 74 79 5f 66 69 6c 65 6e 61 6d 65 5f 70 79  nity_filename_py
0700: 7d 22 2c 20 22 24 7b 64 69 63 5f 70 65 72 73 6f  }", "${dic_perso
0710: 6e 61 6c 5f 66 69 6c 65 6e 61 6d 65 5f 70 79 7d  nal_filename_py}
0720: 22 29 0a 20 20 20 20 20 20 20 20 5f 73 41 70 70  ").        _sApp
0730: 43 6f 6e 74 65 78 74 20 3d 20 73 43 6f 6e 74 65  Context = sConte
0740: 78 74 0a 20 20 20 20 20 20 20 20 5f 64 4f 70 74  xt.        _dOpt
0750: 69 6f 6e 73 20 3d 20 64 69 63 74 28 67 63 5f 6f  ions = dict(gc_o
0760: 70 74 69 6f 6e 73 2e 67 65 74 4f 70 74 69 6f 6e  ptions.getOption
0770: 73 28 73 43 6f 6e 74 65 78 74 29 29 20 20 20 23  s(sContext))   #
0780: 20 64 75 70 6c 69 63 61 74 69 6f 6e 20 6e 65 63   duplication nec
0790: 65 73 73 61 72 79 2c 20 74 6f 20 62 65 20 61 62  essary, to be ab
07a0: 6c 65 20 74 6f 20 72 65 73 65 74 20 74 6f 20 64  le to reset to d
07b0: 65 66 61 75 6c 74 0a 20 20 20 20 20 20 20 20 5f  efault.        _
07c0: 6f 54 6f 6b 65 6e 69 7a 65 72 20 3d 20 5f 6f 53  oTokenizer = _oS
07d0: 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 54  pellChecker.getT
07e0: 6f 6b 65 6e 69 7a 65 72 28 29 0a 20 20 20 20 20  okenizer().     
07f0: 20 20 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65     _oSpellChecke
0800: 72 2e 61 63 74 69 76 61 74 65 53 74 6f 72 61 67  r.activateStorag
0810: 65 28 29 0a 20 20 20 20 20 20 20 20 5f 63 72 65  e().        _cre
0820: 61 74 65 52 65 67 65 78 45 72 72 6f 72 20 3d 20  ateRegexError = 
0830: 5f 63 72 65 61 74 65 52 65 67 65 78 57 72 69 74  _createRegexWrit
0840: 65 72 45 72 72 6f 72 20 20 69 66 20 5f 62 57 72  erError  if _bWr
0850: 69 74 65 72 45 72 72 6f 72 20 20 65 6c 73 65 20  iterError  else 
0860: 5f 63 72 65 61 74 65 52 65 67 65 78 44 69 63 74  _createRegexDict
0870: 45 72 72 6f 72 0a 20 20 20 20 65 78 63 65 70 74  Error.    except
0880: 3a 0a 20 20 20 20 20 20 20 20 74 72 61 63 65 62  :.        traceb
0890: 61 63 6b 2e 70 72 69 6e 74 5f 65 78 63 28 29 0a  ack.print_exc().
08a0: 0a 0a 64 65 66 20 5f 67 65 74 52 75 6c 65 73 20  ..def _getRules 
08b0: 28 62 50 61 72 61 67 72 61 70 68 29 3a 0a 20 20  (bParagraph):.  
08c0: 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 69    try:.        i
08d0: 66 20 6e 6f 74 20 62 50 61 72 61 67 72 61 70 68  f not bParagraph
08e0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  :.            re
08f0: 74 75 72 6e 20 5f 72 75 6c 65 73 2e 6c 53 65 6e  turn _rules.lSen
0900: 74 65 6e 63 65 52 75 6c 65 73 0a 20 20 20 20 20  tenceRules.     
0910: 20 20 20 72 65 74 75 72 6e 20 5f 72 75 6c 65 73     return _rules
0920: 2e 6c 50 61 72 61 67 72 61 70 68 52 75 6c 65 73  .lParagraphRules
0930: 0a 20 20 20 20 65 78 63 65 70 74 3a 0a 20 20 20  .    except:.   
0940: 20 20 20 20 20 5f 6c 6f 61 64 52 75 6c 65 73 28       _loadRules(
0950: 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 62 50 61  ).    if not bPa
0960: 72 61 67 72 61 70 68 3a 0a 20 20 20 20 20 20 20  ragraph:.       
0970: 20 72 65 74 75 72 6e 20 5f 72 75 6c 65 73 2e 6c   return _rules.l
0980: 53 65 6e 74 65 6e 63 65 52 75 6c 65 73 0a 20 20  SentenceRules.  
0990: 20 20 72 65 74 75 72 6e 20 5f 72 75 6c 65 73 2e    return _rules.
09a0: 6c 50 61 72 61 67 72 61 70 68 52 75 6c 65 73 0a  lParagraphRules.
09b0: 0a 0a 64 65 66 20 5f 6c 6f 61 64 52 75 6c 65 73  ..def _loadRules
09c0: 20 28 29 3a 0a 20 20 20 20 66 72 6f 6d 20 2e 20   ():.    from . 
09d0: 69 6d 70 6f 72 74 20 67 63 5f 72 75 6c 65 73 0a  import gc_rules.
09e0: 20 20 20 20 67 6c 6f 62 61 6c 20 5f 72 75 6c 65      global _rule
09f0: 73 0a 20 20 20 20 5f 72 75 6c 65 73 20 3d 20 67  s.    _rules = g
0a00: 63 5f 72 75 6c 65 73 0a 20 20 20 20 23 20 63 6f  c_rules.    # co
0a10: 6d 70 69 6c 65 20 72 75 6c 65 73 20 72 65 67 65  mpile rules rege
0a20: 78 0a 20 20 20 20 66 6f 72 20 73 4f 70 74 69 6f  x.    for sOptio
0a30: 6e 2c 20 6c 52 75 6c 65 47 72 6f 75 70 20 69 6e  n, lRuleGroup in
0a40: 20 63 68 61 69 6e 28 5f 72 75 6c 65 73 2e 6c 50   chain(_rules.lP
0a50: 61 72 61 67 72 61 70 68 52 75 6c 65 73 2c 20 5f  aragraphRules, _
0a60: 72 75 6c 65 73 2e 6c 53 65 6e 74 65 6e 63 65 52  rules.lSentenceR
0a70: 75 6c 65 73 29 3a 0a 20 20 20 20 20 20 20 20 69  ules):.        i
0a80: 66 20 73 4f 70 74 69 6f 6e 20 21 3d 20 22 40 40  f sOption != "@@
0a90: 40 40 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20  @@":.           
0aa0: 20 66 6f 72 20 61 52 75 6c 65 20 69 6e 20 6c 52   for aRule in lR
0ab0: 75 6c 65 47 72 6f 75 70 3a 0a 20 20 20 20 20 20  uleGroup:.      
0ac0: 20 20 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20            try:. 
0ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ae0: 20 20 20 61 52 75 6c 65 5b 30 5d 20 3d 20 72 65     aRule[0] = re
0af0: 2e 63 6f 6d 70 69 6c 65 28 61 52 75 6c 65 5b 30  .compile(aRule[0
0b00: 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]).             
0b10: 20 20 20 65 78 63 65 70 74 3a 0a 20 20 20 20 20     except:.     
0b20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
0b30: 63 68 6f 28 22 42 61 64 20 72 65 67 75 6c 61 72  cho("Bad regular
0b40: 20 65 78 70 72 65 73 73 69 6f 6e 20 69 6e 20 23   expression in #
0b50: 20 22 20 2b 20 73 74 72 28 61 52 75 6c 65 5b 32   " + str(aRule[2
0b60: 5d 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ])).            
0b70: 20 20 20 20 20 20 20 20 61 52 75 6c 65 5b 30 5d          aRule[0]
0b80: 20 3d 20 22 28 3f 69 29 3c 47 72 61 6d 6d 61 6c   = "(?i)<Grammal
0b90: 65 63 74 65 3e 22 0a 0a 0a 23 23 23 23 20 50 61  ecte>"...#### Pa
0ba0: 72 73 69 6e 67 0a 0a 5f 7a 45 6e 64 4f 66 53 65  rsing.._zEndOfSe
0bb0: 6e 74 65 6e 63 65 20 3d 20 72 65 2e 63 6f 6d 70  ntence = re.comp
0bc0: 69 6c 65 28 72 27 28 5b 2e 3f 21 3a 3b e2 80 a6  ile(r'([.?!:;...
0bd0: 5d 5b 20 2e 3f 21 e2 80 a6 20 c2 bb e2 80 9d 22  ][ .?!... ....."
0be0: 29 5d 2a 7c 2e 24 29 27 29 0a 5f 7a 42 65 67 69  )]*|.$)')._zBegi
0bf0: 6e 4f 66 50 61 72 61 67 72 61 70 68 20 3d 20 72  nOfParagraph = r
0c00: 65 2e 63 6f 6d 70 69 6c 65 28 72 22 5e 5c 57 2a  e.compile(r"^\W*
0c10: 22 29 0a 5f 7a 45 6e 64 4f 66 50 61 72 61 67 72  ")._zEndOfParagr
0c20: 61 70 68 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65  aph = re.compile
0c30: 28 72 22 5c 57 2a 24 22 29 0a 0a 64 65 66 20 5f  (r"\W*$")..def _
0c40: 67 65 74 53 65 6e 74 65 6e 63 65 42 6f 75 6e 64  getSentenceBound
0c50: 61 72 69 65 73 20 28 73 54 65 78 74 29 3a 0a 20  aries (sText):. 
0c60: 20 20 20 69 53 74 61 72 74 20 3d 20 5f 7a 42 65     iStart = _zBe
0c70: 67 69 6e 4f 66 50 61 72 61 67 72 61 70 68 2e 6d  ginOfParagraph.m
0c80: 61 74 63 68 28 73 54 65 78 74 29 2e 65 6e 64 28  atch(sText).end(
0c90: 29 0a 20 20 20 20 66 6f 72 20 6d 20 69 6e 20 5f  ).    for m in _
0ca0: 7a 45 6e 64 4f 66 53 65 6e 74 65 6e 63 65 2e 66  zEndOfSentence.f
0cb0: 69 6e 64 69 74 65 72 28 73 54 65 78 74 29 3a 0a  inditer(sText):.
0cc0: 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 28 69          yield (i
0cd0: 53 74 61 72 74 2c 20 6d 2e 65 6e 64 28 29 29 0a  Start, m.end()).
0ce0: 20 20 20 20 20 20 20 20 69 53 74 61 72 74 20 3d          iStart =
0cf0: 20 6d 2e 65 6e 64 28 29 0a 0a 0a 64 65 66 20 70   m.end()...def p
0d00: 61 72 73 65 20 28 73 54 65 78 74 2c 20 73 43 6f  arse (sText, sCo
0d10: 75 6e 74 72 79 3d 22 24 7b 63 6f 75 6e 74 72 79  untry="${country
0d20: 5f 64 65 66 61 75 6c 74 7d 22 2c 20 62 44 65 62  _default}", bDeb
0d30: 75 67 3d 46 61 6c 73 65 2c 20 64 4f 70 74 69 6f  ug=False, dOptio
0d40: 6e 73 3d 4e 6f 6e 65 2c 20 62 43 6f 6e 74 65 78  ns=None, bContex
0d50: 74 3d 46 61 6c 73 65 29 3a 0a 20 20 20 20 22 61  t=False):.    "a
0d60: 6e 61 6c 79 73 65 73 20 74 68 65 20 70 61 72 61  nalyses the para
0d70: 67 72 61 70 68 20 73 54 65 78 74 20 61 6e 64 20  graph sText and 
0d80: 72 65 74 75 72 6e 73 20 6c 69 73 74 20 6f 66 20  returns list of 
0d90: 65 72 72 6f 72 73 22 0a 20 20 20 20 23 73 54 65  errors".    #sTe
0da0: 78 74 20 3d 20 75 6e 69 63 6f 64 65 64 61 74 61  xt = unicodedata
0db0: 2e 6e 6f 72 6d 61 6c 69 7a 65 28 22 4e 46 43 22  .normalize("NFC"
0dc0: 2c 20 73 54 65 78 74 29 0a 20 20 20 20 61 45 72  , sText).    aEr
0dd0: 72 6f 72 73 20 3d 20 4e 6f 6e 65 0a 20 20 20 20  rors = None.    
0de0: 73 52 65 61 6c 54 65 78 74 20 3d 20 73 54 65 78  sRealText = sTex
0df0: 74 0a 20 20 20 20 64 50 72 69 6f 72 69 74 79 20  t.    dPriority 
0e00: 3d 20 7b 7d 20 20 23 20 4b 65 79 20 3d 20 70 6f  = {}  # Key = po
0e10: 73 69 74 69 6f 6e 3b 20 76 61 6c 75 65 20 3d 20  sition; value = 
0e20: 70 72 69 6f 72 69 74 79 0a 20 20 20 20 64 4f 70  priority.    dOp
0e30: 74 20 3d 20 5f 64 4f 70 74 69 6f 6e 73 20 20 69  t = _dOptions  i
0e40: 66 20 6e 6f 74 20 64 4f 70 74 69 6f 6e 73 20 20  f not dOptions  
0e50: 65 6c 73 65 20 64 4f 70 74 69 6f 6e 73 0a 20 20  else dOptions.  
0e60: 20 20 62 53 68 6f 77 52 75 6c 65 49 64 20 3d 20    bShowRuleId = 
0e70: 6f 70 74 69 6f 6e 28 27 69 64 72 75 6c 65 27 29  option('idrule')
0e80: 0a 0a 20 20 20 20 23 20 70 61 72 73 65 20 70 61  ..    # parse pa
0e90: 72 61 67 72 61 70 68 0a 20 20 20 20 74 72 79 3a  ragraph.    try:
0ea0: 0a 20 20 20 20 20 20 20 20 73 4e 65 77 2c 20 61  .        sNew, a
0eb0: 45 72 72 6f 72 73 20 3d 20 5f 70 72 6f 6f 66 72  Errors = _proofr
0ec0: 65 61 64 28 4e 6f 6e 65 2c 20 73 54 65 78 74 2c  ead(None, sText,
0ed0: 20 73 52 65 61 6c 54 65 78 74 2c 20 30 2c 20 54   sRealText, 0, T
0ee0: 72 75 65 2c 20 64 50 72 69 6f 72 69 74 79 2c 20  rue, dPriority, 
0ef0: 73 43 6f 75 6e 74 72 79 2c 20 64 4f 70 74 2c 20  sCountry, dOpt, 
0f00: 62 53 68 6f 77 52 75 6c 65 49 64 2c 20 62 44 65  bShowRuleId, bDe
0f10: 62 75 67 2c 20 62 43 6f 6e 74 65 78 74 29 0a 20  bug, bContext). 
0f20: 20 20 20 20 20 20 20 69 66 20 73 4e 65 77 3a 0a         if sNew:.
0f30: 20 20 20 20 20 20 20 20 20 20 20 20 73 54 65 78              sTex
0f40: 74 20 3d 20 73 4e 65 77 0a 20 20 20 20 65 78 63  t = sNew.    exc
0f50: 65 70 74 3a 0a 20 20 20 20 20 20 20 20 72 61 69  ept:.        rai
0f60: 73 65 0a 0a 20 20 20 20 23 20 63 6c 65 61 6e 75  se..    # cleanu
0f70: 70 0a 20 20 20 20 69 66 20 22 c2 a0 22 20 69 6e  p.    if ".." in
0f80: 20 73 54 65 78 74 3a 0a 20 20 20 20 20 20 20 20   sText:.        
0f90: 73 54 65 78 74 20 3d 20 73 54 65 78 74 2e 72 65  sText = sText.re
0fa0: 70 6c 61 63 65 28 22 c2 a0 22 2c 20 27 20 27 29  place("..", ' ')
0fb0: 20 23 20 6e 62 73 70 0a 20 20 20 20 69 66 20 22   # nbsp.    if "
0fc0: e2 80 af 22 20 69 6e 20 73 54 65 78 74 3a 0a 20  ..." in sText:. 
0fd0: 20 20 20 20 20 20 20 73 54 65 78 74 20 3d 20 73         sText = s
0fe0: 54 65 78 74 2e 72 65 70 6c 61 63 65 28 22 e2 80  Text.replace("..
0ff0: af 22 2c 20 27 20 27 29 20 23 20 6e 6e 62 73 70  .", ' ') # nnbsp
1000: 0a 20 20 20 20 69 66 20 22 27 22 20 69 6e 20 73  .    if "'" in s
1010: 54 65 78 74 3a 0a 20 20 20 20 20 20 20 20 73 54  Text:.        sT
1020: 65 78 74 20 3d 20 73 54 65 78 74 2e 72 65 70 6c  ext = sText.repl
1030: 61 63 65 28 22 27 22 2c 20 22 e2 80 99 22 29 0a  ace("'", "...").
1040: 20 20 20 20 69 66 20 22 e2 80 91 22 20 69 6e 20      if "..." in 
1050: 73 54 65 78 74 3a 0a 20 20 20 20 20 20 20 20 73  sText:.        s
1060: 54 65 78 74 20 3d 20 73 54 65 78 74 2e 72 65 70  Text = sText.rep
1070: 6c 61 63 65 28 22 e2 80 91 22 2c 20 22 2d 22 29  lace("...", "-")
1080: 20 23 20 6e 6f 62 72 65 61 6b 64 61 73 68 0a 0a   # nobreakdash..
1090: 20 20 20 20 23 20 70 61 72 73 65 20 73 65 6e 74      # parse sent
10a0: 65 6e 63 65 73 0a 20 20 20 20 66 6f 72 20 69 53  ences.    for iS
10b0: 74 61 72 74 2c 20 69 45 6e 64 20 69 6e 20 5f 67  tart, iEnd in _g
10c0: 65 74 53 65 6e 74 65 6e 63 65 42 6f 75 6e 64 61  etSentenceBounda
10d0: 72 69 65 73 28 73 54 65 78 74 29 3a 0a 20 20 20  ries(sText):.   
10e0: 20 20 20 20 20 69 66 20 34 20 3c 20 28 69 45 6e       if 4 < (iEn
10f0: 64 20 2d 20 69 53 74 61 72 74 29 20 3c 20 32 30  d - iStart) < 20
1100: 30 30 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  00:.            
1110: 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20  try:.           
1120: 20 20 20 20 20 6f 53 65 6e 74 65 6e 63 65 20 3d       oSentence =
1130: 20 54 6f 6b 65 6e 53 65 6e 74 65 6e 63 65 28 73   TokenSentence(s
1140: 54 65 78 74 5b 69 53 74 61 72 74 3a 69 45 6e 64  Text[iStart:iEnd
1150: 5d 2c 20 73 52 65 61 6c 54 65 78 74 5b 69 53 74  ], sRealText[iSt
1160: 61 72 74 3a 69 45 6e 64 5d 2c 20 69 53 74 61 72  art:iEnd], iStar
1170: 74 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  t).             
1180: 20 20 20 5f 2c 20 65 72 72 73 20 3d 20 5f 70 72     _, errs = _pr
1190: 6f 6f 66 72 65 61 64 28 6f 53 65 6e 74 65 6e 63  oofread(oSentenc
11a0: 65 2c 20 73 54 65 78 74 5b 69 53 74 61 72 74 3a  e, sText[iStart:
11b0: 69 45 6e 64 5d 2c 20 73 52 65 61 6c 54 65 78 74  iEnd], sRealText
11c0: 5b 69 53 74 61 72 74 3a 69 45 6e 64 5d 2c 20 69  [iStart:iEnd], i
11d0: 53 74 61 72 74 2c 20 46 61 6c 73 65 2c 20 64 50  Start, False, dP
11e0: 72 69 6f 72 69 74 79 2c 20 73 43 6f 75 6e 74 72  riority, sCountr
11f0: 79 2c 20 64 4f 70 74 2c 20 62 53 68 6f 77 52 75  y, dOpt, bShowRu
1200: 6c 65 49 64 2c 20 62 44 65 62 75 67 2c 20 62 43  leId, bDebug, bC
1210: 6f 6e 74 65 78 74 29 0a 20 20 20 20 20 20 20 20  ontext).        
1220: 20 20 20 20 20 20 20 20 61 45 72 72 6f 72 73 2e          aErrors.
1230: 75 70 64 61 74 65 28 65 72 72 73 29 0a 20 20 20  update(errs).   
1240: 20 20 20 20 20 20 20 20 20 65 78 63 65 70 74 3a           except:
1250: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1260: 20 72 61 69 73 65 0a 20 20 20 20 72 65 74 75 72   raise.    retur
1270: 6e 20 61 45 72 72 6f 72 73 2e 76 61 6c 75 65 73  n aErrors.values
1280: 28 29 20 23 20 74 68 69 73 20 69 73 20 61 20 76  () # this is a v
1290: 69 65 77 20 28 69 74 65 72 61 62 6c 65 29 0a 0a  iew (iterable)..
12a0: 0a 64 65 66 20 5f 70 72 6f 6f 66 72 65 61 64 20  .def _proofread 
12b0: 28 6f 53 65 6e 74 65 6e 63 65 2c 20 73 2c 20 73  (oSentence, s, s
12c0: 78 2c 20 6e 4f 66 66 73 65 74 2c 20 62 50 61 72  x, nOffset, bPar
12d0: 61 67 72 61 70 68 2c 20 64 50 72 69 6f 72 69 74  agraph, dPriorit
12e0: 79 2c 20 73 43 6f 75 6e 74 72 79 2c 20 64 4f 70  y, sCountry, dOp
12f0: 74 69 6f 6e 73 2c 20 62 53 68 6f 77 52 75 6c 65  tions, bShowRule
1300: 49 64 2c 20 62 44 65 62 75 67 2c 20 62 43 6f 6e  Id, bDebug, bCon
1310: 74 65 78 74 29 3a 0a 20 20 20 20 64 45 72 72 73  text):.    dErrs
1320: 20 3d 20 7b 7d 0a 20 20 20 20 62 50 61 72 61 67   = {}.    bParag
1330: 72 61 70 68 43 68 61 6e 67 65 20 3d 20 46 61 6c  raphChange = Fal
1340: 73 65 0a 20 20 20 20 62 53 65 6e 74 65 6e 63 65  se.    bSentence
1350: 43 68 61 6e 67 65 20 3d 20 46 61 6c 73 65 0a 20  Change = False. 
1360: 20 20 20 64 54 6f 6b 65 6e 50 6f 73 20 3d 20 6f     dTokenPos = o
1370: 53 65 6e 74 65 6e 63 65 2e 64 54 6f 6b 65 6e 50  Sentence.dTokenP
1380: 6f 73 20 69 66 20 6f 53 65 6e 74 65 6e 63 65 20  os if oSentence 
1390: 65 6c 73 65 20 7b 7d 0a 20 20 20 20 66 6f 72 20  else {}.    for 
13a0: 73 4f 70 74 69 6f 6e 2c 20 6c 52 75 6c 65 47 72  sOption, lRuleGr
13b0: 6f 75 70 20 69 6e 20 5f 67 65 74 52 75 6c 65 73  oup in _getRules
13c0: 28 62 50 61 72 61 67 72 61 70 68 29 3a 0a 20 20  (bParagraph):.  
13d0: 20 20 20 20 20 20 69 66 20 73 4f 70 74 69 6f 6e        if sOption
13e0: 20 3d 3d 20 22 40 40 40 40 22 3a 0a 20 20 20 20   == "@@@@":.    
13f0: 20 20 20 20 20 20 20 20 23 20 67 72 61 70 68 20          # graph 
1400: 72 75 6c 65 73 0a 20 20 20 20 20 20 20 20 20 20  rules.          
1410: 20 20 69 66 20 6e 6f 74 20 62 50 61 72 61 67 72    if not bParagr
1420: 61 70 68 20 61 6e 64 20 62 53 65 6e 74 65 6e 63  aph and bSentenc
1430: 65 43 68 61 6e 67 65 3a 0a 20 20 20 20 20 20 20  eChange:.       
1440: 20 20 20 20 20 20 20 20 20 6f 53 65 6e 74 65 6e           oSenten
1450: 63 65 2e 75 70 64 61 74 65 28 73 29 0a 20 20 20  ce.update(s).   
1460: 20 20 20 20 20 20 20 20 20 20 20 20 20 62 53 65               bSe
1470: 6e 74 65 6e 63 65 43 68 61 6e 67 65 20 3d 20 46  ntenceChange = F
1480: 61 6c 73 65 0a 20 20 20 20 20 20 20 20 20 20 20  alse.           
1490: 20 66 6f 72 20 73 47 72 61 70 68 4e 61 6d 65 2c   for sGraphName,
14a0: 20 73 4c 69 6e 65 49 64 20 69 6e 20 6c 52 75 6c   sLineId in lRul
14b0: 65 47 72 6f 75 70 3a 0a 20 20 20 20 20 20 20 20  eGroup:.        
14c0: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
14d0: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  g:.             
14e0: 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 5c 6e         print("\n
14f0: 3e 3e 3e 3e 20 47 52 41 50 48 3a 22 2c 20 73 47  >>>> GRAPH:", sG
1500: 72 61 70 68 4e 61 6d 65 2c 20 73 4c 69 6e 65 49  raphName, sLineI
1510: 64 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  d).             
1520: 20 20 20 62 50 61 72 61 67 72 61 70 68 43 68 61     bParagraphCha
1530: 6e 67 65 2c 20 73 20 3d 20 6f 53 65 6e 74 65 6e  nge, s = oSenten
1540: 63 65 2e 70 61 72 73 65 28 64 41 6c 6c 47 72 61  ce.parse(dAllGra
1550: 70 68 5b 73 47 72 61 70 68 4e 61 6d 65 5d 2c 20  ph[sGraphName], 
1560: 64 50 72 69 6f 72 69 74 79 2c 20 73 43 6f 75 6e  dPriority, sCoun
1570: 74 72 79 2c 20 64 4f 70 74 69 6f 6e 73 2c 20 62  try, dOptions, b
1580: 53 68 6f 77 52 75 6c 65 49 64 2c 20 62 44 65 62  ShowRuleId, bDeb
1590: 75 67 2c 20 62 43 6f 6e 74 65 78 74 29 0a 20 20  ug, bContext).  
15a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64 45                dE
15b0: 72 72 73 2e 75 70 64 61 74 65 28 6f 53 65 6e 74  rrs.update(oSent
15c0: 65 6e 63 65 2e 64 45 72 72 6f 72 29 0a 20 20 20  ence.dError).   
15d0: 20 20 20 20 20 65 6c 69 66 20 6e 6f 74 20 73 4f       elif not sO
15e0: 70 74 69 6f 6e 20 6f 72 20 64 4f 70 74 69 6f 6e  ption or dOption
15f0: 73 2e 67 65 74 28 73 4f 70 74 69 6f 6e 2c 20 46  s.get(sOption, F
1600: 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20 20 20  alse):.         
1610: 20 20 20 23 20 72 65 67 65 78 20 72 75 6c 65 73     # regex rules
1620: 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72  .            for
1630: 20 7a 52 65 67 65 78 2c 20 62 55 70 70 65 72 63   zRegex, bUpperc
1640: 61 73 65 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52  ase, sLineId, sR
1650: 75 6c 65 49 64 2c 20 6e 50 72 69 6f 72 69 74 79  uleId, nPriority
1660: 2c 20 6c 41 63 74 69 6f 6e 73 20 69 6e 20 6c 52  , lActions in lR
1670: 75 6c 65 47 72 6f 75 70 3a 0a 20 20 20 20 20 20  uleGroup:.      
1680: 20 20 20 20 20 20 20 20 20 20 69 66 20 73 52 75            if sRu
1690: 6c 65 49 64 20 6e 6f 74 20 69 6e 20 5f 61 49 67  leId not in _aIg
16a0: 6e 6f 72 65 64 52 75 6c 65 73 3a 0a 20 20 20 20  noredRules:.    
16b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
16c0: 66 6f 72 20 6d 20 69 6e 20 7a 52 65 67 65 78 2e  for m in zRegex.
16d0: 66 69 6e 64 69 74 65 72 28 73 29 3a 0a 20 20 20  finditer(s):.   
16e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
16f0: 20 20 20 20 20 62 43 6f 6e 64 4d 65 6d 6f 20 3d       bCondMemo =
1700: 20 4e 6f 6e 65 0a 20 20 20 20 20 20 20 20 20 20   None.          
1710: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f                fo
1720: 72 20 73 46 75 6e 63 43 6f 6e 64 2c 20 63 41 63  r sFuncCond, cAc
1730: 74 69 6f 6e 54 79 70 65 2c 20 73 57 68 61 74 2c  tionType, sWhat,
1740: 20 2a 65 41 63 74 20 69 6e 20 6c 41 63 74 69 6f   *eAct in lActio
1750: 6e 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ns:.            
1760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1770: 23 20 61 63 74 69 6f 6e 20 69 6e 20 6c 41 63 74  # action in lAct
1780: 69 6f 6e 73 3a 20 5b 20 63 6f 6e 64 69 74 69 6f  ions: [ conditio
1790: 6e 2c 20 61 63 74 69 6f 6e 20 74 79 70 65 2c 20  n, action type, 
17a0: 72 65 70 6c 61 63 65 6d 65 6e 74 2f 73 75 67 67  replacement/sugg
17b0: 65 73 74 69 6f 6e 2f 61 63 74 69 6f 6e 5b 2c 20  estion/action[, 
17c0: 69 47 72 6f 75 70 5b 2c 20 6d 65 73 73 61 67 65  iGroup[, message
17d0: 2c 20 55 52 4c 5d 5d 20 5d 0a 20 20 20 20 20 20  , URL]] ].      
17e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
17f0: 20 20 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20        try:.     
1800: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1810: 20 20 20 20 20 20 20 20 20 20 20 62 43 6f 6e 64             bCond
1820: 4d 65 6d 6f 20 3d 20 6e 6f 74 20 73 46 75 6e 63  Memo = not sFunc
1830: 43 6f 6e 64 20 6f 72 20 67 6c 6f 62 61 6c 73 28  Cond or globals(
1840: 29 5b 73 46 75 6e 63 43 6f 6e 64 5d 28 73 2c 20  )[sFuncCond](s, 
1850: 73 78 2c 20 6d 2c 20 64 54 6f 6b 65 6e 50 6f 73  sx, m, dTokenPos
1860: 2c 20 73 43 6f 75 6e 74 72 79 2c 20 62 43 6f 6e  , sCountry, bCon
1870: 64 4d 65 6d 6f 29 0a 20 20 20 20 20 20 20 20 20  dMemo).         
1880: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1890: 20 20 20 20 20 20 20 69 66 20 62 43 6f 6e 64 4d         if bCondM
18a0: 65 6d 6f 3a 0a 20 20 20 20 20 20 20 20 20 20 20  emo:.           
18b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
18c0: 20 20 20 20 20 20 20 20 20 69 66 20 63 41 63 74           if cAct
18d0: 69 6f 6e 54 79 70 65 20 3d 3d 20 22 2d 22 3a 0a  ionType == "-":.
18e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
18f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1900: 20 20 20 20 20 20 20 20 23 20 67 72 61 6d 6d 61          # gramma
1910: 72 20 65 72 72 6f 72 0a 20 20 20 20 20 20 20 20  r error.        
1920: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1940: 6e 45 72 72 6f 72 53 74 61 72 74 20 3d 20 6e 4f  nErrorStart = nO
1950: 66 66 73 65 74 20 2b 20 6d 2e 73 74 61 72 74 28  ffset + m.start(
1960: 65 41 63 74 5b 30 5d 29 0a 20 20 20 20 20 20 20  eAct[0]).       
1970: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1990: 20 69 66 20 6e 45 72 72 6f 72 53 74 61 72 74 20   if nErrorStart 
19a0: 6e 6f 74 20 69 6e 20 64 45 72 72 73 20 6f 72 20  not in dErrs or 
19b0: 6e 50 72 69 6f 72 69 74 79 20 3e 20 64 50 72 69  nPriority > dPri
19c0: 6f 72 69 74 79 2e 67 65 74 28 6e 45 72 72 6f 72  ority.get(nError
19d0: 53 74 61 72 74 2c 20 2d 31 29 3a 0a 20 20 20 20  Start, -1):.    
19e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
19f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1a00: 20 20 20 20 20 20 20 20 64 45 72 72 73 5b 6e 45          dErrs[nE
1a10: 72 72 6f 72 53 74 61 72 74 5d 20 3d 20 5f 63 72  rrorStart] = _cr
1a20: 65 61 74 65 52 65 67 65 78 45 72 72 6f 72 28 73  eateRegexError(s
1a30: 2c 20 73 78 2c 20 73 57 68 61 74 2c 20 6e 4f 66  , sx, sWhat, nOf
1a40: 66 73 65 74 2c 20 6d 2c 20 65 41 63 74 5b 30 5d  fset, m, eAct[0]
1a50: 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65  , sLineId, sRule
1a60: 49 64 2c 20 62 55 70 70 65 72 63 61 73 65 2c 20  Id, bUppercase, 
1a70: 65 41 63 74 5b 31 5d 2c 20 65 41 63 74 5b 32 5d  eAct[1], eAct[2]
1a80: 2c 20 62 53 68 6f 77 52 75 6c 65 49 64 2c 20 73  , bShowRuleId, s
1a90: 4f 70 74 69 6f 6e 2c 20 62 43 6f 6e 74 65 78 74  Option, bContext
1aa0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
1ab0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ac0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64 50                dP
1ad0: 72 69 6f 72 69 74 79 5b 6e 45 72 72 6f 72 53 74  riority[nErrorSt
1ae0: 61 72 74 5d 20 3d 20 6e 50 72 69 6f 72 69 74 79  art] = nPriority
1af0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1b00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b10: 20 20 20 20 20 65 6c 69 66 20 63 41 63 74 69 6f       elif cActio
1b20: 6e 54 79 70 65 20 3d 3d 20 22 7e 22 3a 0a 20 20  nType == "~":.  
1b30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b50: 20 20 20 20 20 20 23 20 74 65 78 74 20 70 72 6f        # text pro
1b60: 63 65 73 73 6f 72 0a 20 20 20 20 20 20 20 20 20  cessor.         
1b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
1b90: 20 3d 20 5f 72 65 77 72 69 74 65 28 73 2c 20 73   = _rewrite(s, s
1ba0: 57 68 61 74 2c 20 65 41 63 74 5b 30 5d 2c 20 6d  What, eAct[0], m
1bb0: 2c 20 62 55 70 70 65 72 63 61 73 65 29 0a 20 20  , bUppercase).  
1bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1be0: 20 20 20 20 20 20 62 50 61 72 61 67 72 61 70 68        bParagraph
1bf0: 43 68 61 6e 67 65 20 3d 20 54 72 75 65 0a 20 20  Change = True.  
1c00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c20: 20 20 20 20 20 20 62 53 65 6e 74 65 6e 63 65 43        bSentenceC
1c30: 68 61 6e 67 65 20 3d 20 54 72 75 65 0a 20 20 20  hange = True.   
1c40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c60: 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a       if bDebug:.
1c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c90: 20 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f              echo
1ca0: 28 22 7e 20 22 20 2b 20 73 20 2b 20 22 20 20 2d  ("~ " + s + "  -
1cb0: 2d 20 22 20 2b 20 6d 2e 67 72 6f 75 70 28 65 41  - " + m.group(eA
1cc0: 63 74 5b 30 5d 29 20 2b 20 22 20 20 23 20 22 20  ct[0]) + "  # " 
1cd0: 2b 20 73 4c 69 6e 65 49 64 29 0a 20 20 20 20 20  + sLineId).     
1ce0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1cf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
1d00: 6c 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20  lif cActionType 
1d10: 3d 3d 20 22 3d 22 3a 0a 20 20 20 20 20 20 20 20  == "=":.        
1d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d40: 23 20 64 69 73 61 6d 62 69 67 75 61 74 69 6f 6e  # disambiguation
1d50: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1d60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d70: 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20           if not 
1d80: 62 50 61 72 61 67 72 61 70 68 3a 0a 20 20 20 20  bParagraph:.    
1d90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1da0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1db0: 20 20 20 20 20 20 20 20 67 6c 6f 62 61 6c 73 28          globals(
1dc0: 29 5b 73 57 68 61 74 5d 28 73 2c 20 6d 2c 20 64  )[sWhat](s, m, d
1dd0: 54 6f 6b 65 6e 50 6f 73 29 0a 20 20 20 20 20 20  TokenPos).      
1de0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1df0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e00: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
1e10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e40: 20 65 63 68 6f 28 22 3d 20 22 20 2b 20 6d 2e 67   echo("= " + m.g
1e50: 72 6f 75 70 28 30 29 20 2b 20 22 20 20 23 20 22  roup(0) + "  # "
1e60: 20 2b 20 73 4c 69 6e 65 49 64 29 0a 20 20 20 20   + sLineId).    
1e70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e90: 65 6c 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65  elif cActionType
1ea0: 20 3d 3d 20 22 3e 22 3a 0a 20 20 20 20 20 20 20   == ">":.       
1eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ed0: 20 23 20 77 65 20 64 6f 20 6e 6f 74 68 69 6e 67   # we do nothing
1ee0: 2c 20 74 68 69 73 20 74 65 73 74 20 69 73 20 6a  , this test is j
1ef0: 75 73 74 20 61 20 63 6f 6e 64 69 74 69 6f 6e 20  ust a condition 
1f00: 74 6f 20 61 70 70 6c 79 20 61 6c 6c 20 66 6f 6c  to apply all fol
1f10: 6c 6f 77 69 6e 67 20 61 63 74 69 6f 6e 73 0a 20  lowing actions. 
1f20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f40: 20 20 20 20 20 20 20 70 61 73 73 0a 20 20 20 20         pass.    
1f50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f70: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
1f80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 63                ec
1fa0: 68 6f 28 22 23 20 65 72 72 6f 72 3a 20 75 6e 6b  ho("# error: unk
1fb0: 6e 6f 77 6e 20 61 63 74 69 6f 6e 20 61 74 20 22  nown action at "
1fc0: 20 2b 20 73 4c 69 6e 65 49 64 29 0a 20 20 20 20   + sLineId).    
1fd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1fe0: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66              elif
1ff0: 20 63 41 63 74 69 6f 6e 54 79 70 65 20 3d 3d 20   cActionType == 
2000: 22 3e 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ">":.           
2010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2020: 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 0a 20           break. 
2030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2040: 20 20 20 20 20 20 20 20 20 20 20 65 78 63 65 70             excep
2050: 74 20 45 78 63 65 70 74 69 6f 6e 20 61 73 20 65  t Exception as e
2060: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
2070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2080: 20 20 72 61 69 73 65 20 45 78 63 65 70 74 69 6f    raise Exceptio
2090: 6e 28 73 74 72 28 65 29 2c 20 22 23 20 22 20 2b  n(str(e), "# " +
20a0: 20 73 4c 69 6e 65 49 64 20 2b 20 22 20 23 20 22   sLineId + " # "
20b0: 20 2b 20 73 52 75 6c 65 49 64 29 0a 20 20 20 20   + sRuleId).    
20c0: 69 66 20 62 50 61 72 61 67 72 61 70 68 43 68 61  if bParagraphCha
20d0: 6e 67 65 3a 0a 20 20 20 20 20 20 20 20 72 65 74  nge:.        ret
20e0: 75 72 6e 20 28 73 2c 20 64 45 72 72 73 29 0a 20  urn (s, dErrs). 
20f0: 20 20 20 72 65 74 75 72 6e 20 28 46 61 6c 73 65     return (False
2100: 2c 20 64 45 72 72 73 29 0a 0a 0a 64 65 66 20 5f  , dErrs)...def _
2110: 63 72 65 61 74 65 52 65 67 65 78 57 72 69 74 65  createRegexWrite
2120: 72 45 72 72 6f 72 20 28 73 2c 20 73 78 2c 20 73  rError (s, sx, s
2130: 52 65 70 6c 2c 20 6e 4f 66 66 73 65 74 2c 20 6d  Repl, nOffset, m
2140: 2c 20 69 47 72 6f 75 70 2c 20 73 4c 69 6e 65 49  , iGroup, sLineI
2150: 64 2c 20 73 52 75 6c 65 49 64 2c 20 62 55 70 70  d, sRuleId, bUpp
2160: 65 72 63 61 73 65 2c 20 73 4d 73 67 2c 20 73 55  ercase, sMsg, sU
2170: 52 4c 2c 20 62 53 68 6f 77 52 75 6c 65 49 64 2c  RL, bShowRuleId,
2180: 20 73 4f 70 74 69 6f 6e 2c 20 62 43 6f 6e 74 65   sOption, bConte
2190: 78 74 29 3a 0a 20 20 20 20 22 65 72 72 6f 72 20  xt):.    "error 
21a0: 66 6f 72 20 57 72 69 74 65 72 20 28 4c 4f 2f 4f  for Writer (LO/O
21b0: 4f 29 22 0a 20 20 20 20 78 45 72 72 20 3d 20 53  O)".    xErr = S
21c0: 69 6e 67 6c 65 50 72 6f 6f 66 72 65 61 64 69 6e  ingleProofreadin
21d0: 67 45 72 72 6f 72 28 29 0a 20 20 20 20 23 78 45  gError().    #xE
21e0: 72 72 20 3d 20 75 6e 6f 2e 63 72 65 61 74 65 55  rr = uno.createU
21f0: 6e 6f 53 74 72 75 63 74 28 20 22 63 6f 6d 2e 73  noStruct( "com.s
2200: 75 6e 2e 73 74 61 72 2e 6c 69 6e 67 75 69 73 74  un.star.linguist
2210: 69 63 32 2e 53 69 6e 67 6c 65 50 72 6f 6f 66 72  ic2.SingleProofr
2220: 65 61 64 69 6e 67 45 72 72 6f 72 22 20 29 0a 20  eadingError" ). 
2230: 20 20 20 78 45 72 72 2e 6e 45 72 72 6f 72 53 74     xErr.nErrorSt
2240: 61 72 74 20 3d 20 6e 4f 66 66 73 65 74 20 2b 20  art = nOffset + 
2250: 6d 2e 73 74 61 72 74 28 69 47 72 6f 75 70 29 0a  m.start(iGroup).
2260: 20 20 20 20 78 45 72 72 2e 6e 45 72 72 6f 72 4c      xErr.nErrorL
2270: 65 6e 67 74 68 20 3d 20 6d 2e 65 6e 64 28 69 47  ength = m.end(iG
2280: 72 6f 75 70 29 20 2d 20 6d 2e 73 74 61 72 74 28  roup) - m.start(
2290: 69 47 72 6f 75 70 29 0a 20 20 20 20 78 45 72 72  iGroup).    xErr
22a0: 2e 6e 45 72 72 6f 72 54 79 70 65 20 3d 20 50 52  .nErrorType = PR
22b0: 4f 4f 46 52 45 41 44 49 4e 47 0a 20 20 20 20 78  OOFREADING.    x
22c0: 45 72 72 2e 61 52 75 6c 65 49 64 65 6e 74 69 66  Err.aRuleIdentif
22d0: 69 65 72 20 3d 20 73 52 75 6c 65 49 64 0a 20 20  ier = sRuleId.  
22e0: 20 20 23 20 73 75 67 67 65 73 74 69 6f 6e 73 0a    # suggestions.
22f0: 20 20 20 20 69 66 20 73 52 65 70 6c 5b 30 3a 31      if sRepl[0:1
2300: 5d 20 3d 3d 20 22 3d 22 3a 0a 20 20 20 20 20 20  ] == "=":.      
2310: 20 20 73 75 67 67 20 3d 20 67 6c 6f 62 61 6c 73    sugg = globals
2320: 28 29 5b 73 52 65 70 6c 5b 31 3a 5d 5d 28 73 2c  ()[sRepl[1:]](s,
2330: 20 6d 29 0a 20 20 20 20 20 20 20 20 69 66 20 73   m).        if s
2340: 75 67 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ugg:.           
2350: 20 69 66 20 62 55 70 70 65 72 63 61 73 65 20 61   if bUppercase a
2360: 6e 64 20 6d 2e 67 72 6f 75 70 28 69 47 72 6f 75  nd m.group(iGrou
2370: 70 29 5b 30 3a 31 5d 2e 69 73 75 70 70 65 72 28  p)[0:1].isupper(
2380: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
2390: 20 20 20 78 45 72 72 2e 61 53 75 67 67 65 73 74     xErr.aSuggest
23a0: 69 6f 6e 73 20 3d 20 74 75 70 6c 65 28 6d 61 70  ions = tuple(map
23b0: 28 73 74 72 2e 63 61 70 69 74 61 6c 69 7a 65 2c  (str.capitalize,
23c0: 20 73 75 67 67 2e 73 70 6c 69 74 28 22 7c 22 29   sugg.split("|")
23d0: 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 65  )).            e
23e0: 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  lse:.           
23f0: 20 20 20 20 20 78 45 72 72 2e 61 53 75 67 67 65       xErr.aSugge
2400: 73 74 69 6f 6e 73 20 3d 20 74 75 70 6c 65 28 73  stions = tuple(s
2410: 75 67 67 2e 73 70 6c 69 74 28 22 7c 22 29 29 0a  ugg.split("|")).
2420: 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20          else:.  
2430: 20 20 20 20 20 20 20 20 20 20 78 45 72 72 2e 61            xErr.a
2440: 53 75 67 67 65 73 74 69 6f 6e 73 20 3d 20 28 29  Suggestions = ()
2450: 0a 20 20 20 20 65 6c 69 66 20 73 52 65 70 6c 20  .    elif sRepl 
2460: 3d 3d 20 22 5f 22 3a 0a 20 20 20 20 20 20 20 20  == "_":.        
2470: 78 45 72 72 2e 61 53 75 67 67 65 73 74 69 6f 6e  xErr.aSuggestion
2480: 73 20 3d 20 28 29 0a 20 20 20 20 65 6c 73 65 3a  s = ().    else:
2490: 0a 20 20 20 20 20 20 20 20 69 66 20 62 55 70 70  .        if bUpp
24a0: 65 72 63 61 73 65 20 61 6e 64 20 6d 2e 67 72 6f  ercase and m.gro
24b0: 75 70 28 69 47 72 6f 75 70 29 5b 30 3a 31 5d 2e  up(iGroup)[0:1].
24c0: 69 73 75 70 70 65 72 28 29 3a 0a 20 20 20 20 20  isupper():.     
24d0: 20 20 20 20 20 20 20 78 45 72 72 2e 61 53 75 67         xErr.aSug
24e0: 67 65 73 74 69 6f 6e 73 20 3d 20 74 75 70 6c 65  gestions = tuple
24f0: 28 6d 61 70 28 73 74 72 2e 63 61 70 69 74 61 6c  (map(str.capital
2500: 69 7a 65 2c 20 6d 2e 65 78 70 61 6e 64 28 73 52  ize, m.expand(sR
2510: 65 70 6c 29 2e 73 70 6c 69 74 28 22 7c 22 29 29  epl).split("|"))
2520: 29 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a  ).        else:.
2530: 20 20 20 20 20 20 20 20 20 20 20 20 78 45 72 72              xErr
2540: 2e 61 53 75 67 67 65 73 74 69 6f 6e 73 20 3d 20  .aSuggestions = 
2550: 74 75 70 6c 65 28 6d 2e 65 78 70 61 6e 64 28 73  tuple(m.expand(s
2560: 52 65 70 6c 29 2e 73 70 6c 69 74 28 22 7c 22 29  Repl).split("|")
2570: 29 0a 20 20 20 20 23 20 4d 65 73 73 61 67 65 0a  ).    # Message.
2580: 20 20 20 20 73 4d 65 73 73 61 67 65 20 3d 20 67      sMessage = g
2590: 6c 6f 62 61 6c 73 28 29 5b 73 4d 73 67 5b 31 3a  lobals()[sMsg[1:
25a0: 5d 5d 28 73 2c 20 6d 29 20 20 69 66 20 73 4d 73  ]](s, m)  if sMs
25b0: 67 5b 30 3a 31 5d 20 3d 3d 20 22 3d 22 20 20 65  g[0:1] == "="  e
25c0: 6c 73 65 20 20 6d 2e 65 78 70 61 6e 64 28 73 4d  lse  m.expand(sM
25d0: 73 67 29 0a 20 20 20 20 78 45 72 72 2e 61 53 68  sg).    xErr.aSh
25e0: 6f 72 74 43 6f 6d 6d 65 6e 74 20 3d 20 73 4d 65  ortComment = sMe
25f0: 73 73 61 67 65 20 20 20 23 20 73 4d 65 73 73 61  ssage   # sMessa
2600: 67 65 2e 73 70 6c 69 74 28 22 7c 22 29 5b 30 5d  ge.split("|")[0]
2610: 20 20 20 20 20 23 20 69 6e 20 63 6f 6e 74 65 78       # in contex
2620: 74 20 6d 65 6e 75 0a 20 20 20 20 78 45 72 72 2e  t menu.    xErr.
2630: 61 46 75 6c 6c 43 6f 6d 6d 65 6e 74 20 3d 20 73  aFullComment = s
2640: 4d 65 73 73 61 67 65 20 20 20 23 20 73 4d 65 73  Message   # sMes
2650: 73 61 67 65 2e 73 70 6c 69 74 28 22 7c 22 29 5b  sage.split("|")[
2660: 2d 31 5d 20 20 20 20 23 20 69 6e 20 64 69 61 6c  -1]    # in dial
2670: 6f 67 0a 20 20 20 20 69 66 20 62 53 68 6f 77 52  og.    if bShowR
2680: 75 6c 65 49 64 3a 0a 20 20 20 20 20 20 20 20 78  uleId:.        x
2690: 45 72 72 2e 61 53 68 6f 72 74 43 6f 6d 6d 65 6e  Err.aShortCommen
26a0: 74 20 2b 3d 20 22 20 20 23 20 22 20 2b 20 73 4c  t += "  # " + sL
26b0: 69 6e 65 49 64 20 2b 20 22 20 23 20 22 20 2b 20  ineId + " # " + 
26c0: 73 52 75 6c 65 49 64 0a 20 20 20 20 23 20 55 52  sRuleId.    # UR
26d0: 4c 0a 20 20 20 20 69 66 20 73 55 52 4c 3a 0a 20  L.    if sURL:. 
26e0: 20 20 20 20 20 20 20 78 50 72 6f 70 65 72 74 79         xProperty
26f0: 20 3d 20 50 72 6f 70 65 72 74 79 56 61 6c 75 65   = PropertyValue
2700: 28 29 0a 20 20 20 20 20 20 20 20 78 50 72 6f 70  ().        xProp
2710: 65 72 74 79 2e 4e 61 6d 65 20 3d 20 22 46 75 6c  erty.Name = "Ful
2720: 6c 43 6f 6d 6d 65 6e 74 55 52 4c 22 0a 20 20 20  lCommentURL".   
2730: 20 20 20 20 20 78 50 72 6f 70 65 72 74 79 2e 56       xProperty.V
2740: 61 6c 75 65 20 3d 20 73 55 52 4c 0a 20 20 20 20  alue = sURL.    
2750: 20 20 20 20 78 45 72 72 2e 61 50 72 6f 70 65 72      xErr.aProper
2760: 74 69 65 73 20 3d 20 28 78 50 72 6f 70 65 72 74  ties = (xPropert
2770: 79 2c 29 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20  y,).    else:.  
2780: 20 20 20 20 20 20 78 45 72 72 2e 61 50 72 6f 70        xErr.aProp
2790: 65 72 74 69 65 73 20 3d 20 28 29 0a 20 20 20 20  erties = ().    
27a0: 72 65 74 75 72 6e 20 78 45 72 72 0a 0a 0a 64 65  return xErr...de
27b0: 66 20 5f 63 72 65 61 74 65 52 65 67 65 78 44 69  f _createRegexDi
27c0: 63 74 45 72 72 6f 72 20 28 73 2c 20 73 78 2c 20  ctError (s, sx, 
27d0: 73 52 65 70 6c 2c 20 6e 4f 66 66 73 65 74 2c 20  sRepl, nOffset, 
27e0: 6d 2c 20 69 47 72 6f 75 70 2c 20 73 4c 69 6e 65  m, iGroup, sLine
27f0: 49 64 2c 20 73 52 75 6c 65 49 64 2c 20 62 55 70  Id, sRuleId, bUp
2800: 70 65 72 63 61 73 65 2c 20 73 4d 73 67 2c 20 73  percase, sMsg, s
2810: 55 52 4c 2c 20 62 53 68 6f 77 52 75 6c 65 49 64  URL, bShowRuleId
2820: 2c 20 73 4f 70 74 69 6f 6e 2c 20 62 43 6f 6e 74  , sOption, bCont
2830: 65 78 74 29 3a 0a 20 20 20 20 22 65 72 72 6f 72  ext):.    "error
2840: 20 61 73 20 61 20 64 69 63 74 69 6f 6e 61 72 79   as a dictionary
2850: 22 0a 20 20 20 20 64 45 72 72 20 3d 20 7b 7d 0a  ".    dErr = {}.
2860: 20 20 20 20 64 45 72 72 5b 22 6e 53 74 61 72 74      dErr["nStart
2870: 22 5d 20 3d 20 6e 4f 66 66 73 65 74 20 2b 20 6d  "] = nOffset + m
2880: 2e 73 74 61 72 74 28 69 47 72 6f 75 70 29 0a 20  .start(iGroup). 
2890: 20 20 20 64 45 72 72 5b 22 6e 45 6e 64 22 5d 20     dErr["nEnd"] 
28a0: 3d 20 6e 4f 66 66 73 65 74 20 2b 20 6d 2e 65 6e  = nOffset + m.en
28b0: 64 28 69 47 72 6f 75 70 29 0a 20 20 20 20 64 45  d(iGroup).    dE
28c0: 72 72 5b 22 73 4c 69 6e 65 49 64 22 5d 20 3d 20  rr["sLineId"] = 
28d0: 73 4c 69 6e 65 49 64 0a 20 20 20 20 64 45 72 72  sLineId.    dErr
28e0: 5b 22 73 52 75 6c 65 49 64 22 5d 20 3d 20 73 52  ["sRuleId"] = sR
28f0: 75 6c 65 49 64 0a 20 20 20 20 64 45 72 72 5b 22  uleId.    dErr["
2900: 73 54 79 70 65 22 5d 20 3d 20 73 4f 70 74 69 6f  sType"] = sOptio
2910: 6e 20 20 69 66 20 73 4f 70 74 69 6f 6e 20 20 65  n  if sOption  e
2920: 6c 73 65 20 22 6e 6f 74 79 70 65 22 0a 20 20 20  lse "notype".   
2930: 20 23 20 73 75 67 67 65 73 74 69 6f 6e 73 0a 20   # suggestions. 
2940: 20 20 20 69 66 20 73 52 65 70 6c 5b 30 3a 31 5d     if sRepl[0:1]
2950: 20 3d 3d 20 22 3d 22 3a 0a 20 20 20 20 20 20 20   == "=":.       
2960: 20 73 75 67 67 20 3d 20 67 6c 6f 62 61 6c 73 28   sugg = globals(
2970: 29 5b 73 52 65 70 6c 5b 31 3a 5d 5d 28 73 2c 20  )[sRepl[1:]](s, 
2980: 6d 29 0a 20 20 20 20 20 20 20 20 69 66 20 73 75  m).        if su
2990: 67 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  gg:.            
29a0: 69 66 20 62 55 70 70 65 72 63 61 73 65 20 61 6e  if bUppercase an
29b0: 64 20 6d 2e 67 72 6f 75 70 28 69 47 72 6f 75 70  d m.group(iGroup
29c0: 29 5b 30 3a 31 5d 2e 69 73 75 70 70 65 72 28 29  )[0:1].isupper()
29d0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
29e0: 20 20 64 45 72 72 5b 22 61 53 75 67 67 65 73 74    dErr["aSuggest
29f0: 69 6f 6e 73 22 5d 20 3d 20 6c 69 73 74 28 6d 61  ions"] = list(ma
2a00: 70 28 73 74 72 2e 63 61 70 69 74 61 6c 69 7a 65  p(str.capitalize
2a10: 2c 20 73 75 67 67 2e 73 70 6c 69 74 28 22 7c 22  , sugg.split("|"
2a20: 29 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ))).            
2a30: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
2a40: 20 20 20 20 20 20 64 45 72 72 5b 22 61 53 75 67        dErr["aSug
2a50: 67 65 73 74 69 6f 6e 73 22 5d 20 3d 20 73 75 67  gestions"] = sug
2a60: 67 2e 73 70 6c 69 74 28 22 7c 22 29 0a 20 20 20  g.split("|").   
2a70: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
2a80: 20 20 20 20 20 20 20 64 45 72 72 5b 22 61 53 75         dErr["aSu
2a90: 67 67 65 73 74 69 6f 6e 73 22 5d 20 3d 20 5b 5d  ggestions"] = []
2aa0: 0a 20 20 20 20 65 6c 69 66 20 73 52 65 70 6c 20  .    elif sRepl 
2ab0: 3d 3d 20 22 5f 22 3a 0a 20 20 20 20 20 20 20 20  == "_":.        
2ac0: 64 45 72 72 5b 22 61 53 75 67 67 65 73 74 69 6f  dErr["aSuggestio
2ad0: 6e 73 22 5d 20 3d 20 5b 5d 0a 20 20 20 20 65 6c  ns"] = [].    el
2ae0: 73 65 3a 0a 20 20 20 20 20 20 20 20 69 66 20 62  se:.        if b
2af0: 55 70 70 65 72 63 61 73 65 20 61 6e 64 20 6d 2e  Uppercase and m.
2b00: 67 72 6f 75 70 28 69 47 72 6f 75 70 29 5b 30 3a  group(iGroup)[0:
2b10: 31 5d 2e 69 73 75 70 70 65 72 28 29 3a 0a 20 20  1].isupper():.  
2b20: 20 20 20 20 20 20 20 20 20 20 64 45 72 72 5b 22            dErr["
2b30: 61 53 75 67 67 65 73 74 69 6f 6e 73 22 5d 20 3d  aSuggestions"] =
2b40: 20 6c 69 73 74 28 6d 61 70 28 73 74 72 2e 63 61   list(map(str.ca
2b50: 70 69 74 61 6c 69 7a 65 2c 20 6d 2e 65 78 70 61  pitalize, m.expa
2b60: 6e 64 28 73 52 65 70 6c 29 2e 73 70 6c 69 74 28  nd(sRepl).split(
2b70: 22 7c 22 29 29 29 0a 20 20 20 20 20 20 20 20 65  "|"))).        e
2b80: 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  lse:.           
2b90: 20 64 45 72 72 5b 22 61 53 75 67 67 65 73 74 69   dErr["aSuggesti
2ba0: 6f 6e 73 22 5d 20 3d 20 6d 2e 65 78 70 61 6e 64  ons"] = m.expand
2bb0: 28 73 52 65 70 6c 29 2e 73 70 6c 69 74 28 22 7c  (sRepl).split("|
2bc0: 22 29 0a 20 20 20 20 23 20 4d 65 73 73 61 67 65  ").    # Message
2bd0: 0a 20 20 20 20 64 45 72 72 5b 22 73 4d 65 73 73  .    dErr["sMess
2be0: 61 67 65 22 5d 20 3d 20 67 6c 6f 62 61 6c 73 28  age"] = globals(
2bf0: 29 5b 73 4d 73 67 5b 31 3a 5d 5d 28 73 2c 20 6d  )[sMsg[1:]](s, m
2c00: 29 20 20 69 66 20 73 4d 73 67 5b 30 3a 31 5d 20  )  if sMsg[0:1] 
2c10: 3d 3d 20 22 3d 22 20 20 65 6c 73 65 20 20 6d 2e  == "="  else  m.
2c20: 65 78 70 61 6e 64 28 73 4d 73 67 29 0a 20 20 20  expand(sMsg).   
2c30: 20 69 66 20 62 53 68 6f 77 52 75 6c 65 49 64 3a   if bShowRuleId:
2c40: 0a 20 20 20 20 20 20 20 20 64 45 72 72 5b 22 73  .        dErr["s
2c50: 4d 65 73 73 61 67 65 22 5d 20 2b 3d 20 22 20 20  Message"] += "  
2c60: 23 20 22 20 2b 20 73 4c 69 6e 65 49 64 20 2b 20  # " + sLineId + 
2c70: 22 20 23 20 22 20 2b 20 73 52 75 6c 65 49 64 0a  " # " + sRuleId.
2c80: 20 20 20 20 23 20 55 52 4c 0a 20 20 20 20 64 45      # URL.    dE
2c90: 72 72 5b 22 55 52 4c 22 5d 20 3d 20 73 55 52 4c  rr["URL"] = sURL
2ca0: 20 20 69 66 20 73 55 52 4c 20 20 65 6c 73 65 20    if sURL  else 
2cb0: 22 22 0a 20 20 20 20 23 20 43 6f 6e 74 65 78 74  "".    # Context
2cc0: 0a 20 20 20 20 69 66 20 62 43 6f 6e 74 65 78 74  .    if bContext
2cd0: 3a 0a 20 20 20 20 20 20 20 20 64 45 72 72 5b 27  :.        dErr['
2ce0: 73 55 6e 64 65 72 6c 69 6e 65 64 27 5d 20 3d 20  sUnderlined'] = 
2cf0: 73 78 5b 6d 2e 73 74 61 72 74 28 69 47 72 6f 75  sx[m.start(iGrou
2d00: 70 29 3a 6d 2e 65 6e 64 28 69 47 72 6f 75 70 29  p):m.end(iGroup)
2d10: 5d 0a 20 20 20 20 20 20 20 20 64 45 72 72 5b 27  ].        dErr['
2d20: 73 42 65 66 6f 72 65 27 5d 20 3d 20 73 78 5b 6d  sBefore'] = sx[m
2d30: 61 78 28 30 2c 6d 2e 73 74 61 72 74 28 69 47 72  ax(0,m.start(iGr
2d40: 6f 75 70 29 2d 38 30 29 3a 6d 2e 73 74 61 72 74  oup)-80):m.start
2d50: 28 69 47 72 6f 75 70 29 5d 0a 20 20 20 20 20 20  (iGroup)].      
2d60: 20 20 64 45 72 72 5b 27 73 41 66 74 65 72 27 5d    dErr['sAfter']
2d70: 20 3d 20 73 78 5b 6d 2e 65 6e 64 28 69 47 72 6f   = sx[m.end(iGro
2d80: 75 70 29 3a 6d 2e 65 6e 64 28 69 47 72 6f 75 70  up):m.end(iGroup
2d90: 29 2b 38 30 5d 0a 20 20 20 20 72 65 74 75 72 6e  )+80].    return
2da0: 20 64 45 72 72 0a 0a 0a 64 65 66 20 5f 72 65 77   dErr...def _rew
2db0: 72 69 74 65 20 28 73 53 65 6e 74 65 6e 63 65 2c  rite (sSentence,
2dc0: 20 73 52 65 70 6c 2c 20 69 47 72 6f 75 70 2c 20   sRepl, iGroup, 
2dd0: 6d 2c 20 62 55 70 70 65 72 63 61 73 65 29 3a 0a  m, bUppercase):.
2de0: 20 20 20 20 22 74 65 78 74 20 70 72 6f 63 65 73      "text proces
2df0: 73 6f 72 3a 20 77 72 69 74 65 20 3c 73 52 65 70  sor: write <sRep
2e00: 6c 3e 20 69 6e 20 3c 73 53 65 6e 74 65 6e 63 65  l> in <sSentence
2e10: 3e 20 61 74 20 3c 69 47 72 6f 75 70 3e 20 70 6f  > at <iGroup> po
2e20: 73 69 74 69 6f 6e 22 0a 20 20 20 20 6e 4c 65 6e  sition".    nLen
2e30: 20 3d 20 6d 2e 65 6e 64 28 69 47 72 6f 75 70 29   = m.end(iGroup)
2e40: 20 2d 20 6d 2e 73 74 61 72 74 28 69 47 72 6f 75   - m.start(iGrou
2e50: 70 29 0a 20 20 20 20 69 66 20 73 52 65 70 6c 20  p).    if sRepl 
2e60: 3d 3d 20 22 2a 22 3a 0a 20 20 20 20 20 20 20 20  == "*":.        
2e70: 73 4e 65 77 20 3d 20 22 20 22 20 2a 20 6e 4c 65  sNew = " " * nLe
2e80: 6e 0a 20 20 20 20 65 6c 69 66 20 73 52 65 70 6c  n.    elif sRepl
2e90: 20 3d 3d 20 22 5f 22 3a 0a 20 20 20 20 20 20 20   == "_":.       
2ea0: 20 73 4e 65 77 20 3d 20 73 52 65 70 6c 20 2b 20   sNew = sRepl + 
2eb0: 22 20 22 20 2a 20 28 6e 4c 65 6e 2d 31 29 0a 20  " " * (nLen-1). 
2ec0: 20 20 20 65 6c 69 66 20 73 52 65 70 6c 5b 30 3a     elif sRepl[0:
2ed0: 31 5d 20 3d 3d 20 22 3d 22 3a 0a 20 20 20 20 20  1] == "=":.     
2ee0: 20 20 20 73 4e 65 77 20 3d 20 67 6c 6f 62 61 6c     sNew = global
2ef0: 73 28 29 5b 73 52 65 70 6c 5b 31 3a 5d 5d 28 73  s()[sRepl[1:]](s
2f00: 53 65 6e 74 65 6e 63 65 2c 20 6d 29 0a 20 20 20  Sentence, m).   
2f10: 20 20 20 20 20 73 4e 65 77 20 3d 20 73 4e 65 77       sNew = sNew
2f20: 20 2b 20 22 20 22 20 2a 20 28 6e 4c 65 6e 2d 6c   + " " * (nLen-l
2f30: 65 6e 28 73 4e 65 77 29 29 0a 20 20 20 20 20 20  en(sNew)).      
2f40: 20 20 69 66 20 62 55 70 70 65 72 63 61 73 65 20    if bUppercase 
2f50: 61 6e 64 20 6d 2e 67 72 6f 75 70 28 69 47 72 6f  and m.group(iGro
2f60: 75 70 29 5b 30 3a 31 5d 2e 69 73 75 70 70 65 72  up)[0:1].isupper
2f70: 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ():.            
2f80: 73 4e 65 77 20 3d 20 73 4e 65 77 2e 63 61 70 69  sNew = sNew.capi
2f90: 74 61 6c 69 7a 65 28 29 0a 20 20 20 20 65 6c 73  talize().    els
2fa0: 65 3a 0a 20 20 20 20 20 20 20 20 73 4e 65 77 20  e:.        sNew 
2fb0: 3d 20 6d 2e 65 78 70 61 6e 64 28 73 52 65 70 6c  = m.expand(sRepl
2fc0: 29 0a 20 20 20 20 20 20 20 20 73 4e 65 77 20 3d  ).        sNew =
2fd0: 20 73 4e 65 77 20 2b 20 22 20 22 20 2a 20 28 6e   sNew + " " * (n
2fe0: 4c 65 6e 2d 6c 65 6e 28 73 4e 65 77 29 29 0a 20  Len-len(sNew)). 
2ff0: 20 20 20 72 65 74 75 72 6e 20 73 53 65 6e 74 65     return sSente
3000: 6e 63 65 5b 30 3a 6d 2e 73 74 61 72 74 28 69 47  nce[0:m.start(iG
3010: 72 6f 75 70 29 5d 20 2b 20 73 4e 65 77 20 2b 20  roup)] + sNew + 
3020: 73 53 65 6e 74 65 6e 63 65 5b 6d 2e 65 6e 64 28  sSentence[m.end(
3030: 69 47 72 6f 75 70 29 3a 5d 0a 0a 0a 64 65 66 20  iGroup):]...def 
3040: 69 67 6e 6f 72 65 52 75 6c 65 20 28 73 52 75 6c  ignoreRule (sRul
3050: 65 49 64 29 3a 0a 20 20 20 20 22 64 69 73 61 62  eId):.    "disab
3060: 6c 65 20 72 75 6c 65 20 3c 73 52 75 6c 65 49 64  le rule <sRuleId
3070: 3e 22 0a 20 20 20 20 5f 61 49 67 6e 6f 72 65 64  >".    _aIgnored
3080: 52 75 6c 65 73 2e 61 64 64 28 73 52 75 6c 65 49  Rules.add(sRuleI
3090: 64 29 0a 0a 0a 64 65 66 20 72 65 73 65 74 49 67  d)...def resetIg
30a0: 6e 6f 72 65 52 75 6c 65 73 20 28 29 3a 0a 20 20  noreRules ():.  
30b0: 20 20 22 63 6c 65 61 72 20 61 6c 6c 20 69 67 6e    "clear all ign
30c0: 6f 72 65 64 20 72 75 6c 65 73 22 0a 20 20 20 20  ored rules".    
30d0: 5f 61 49 67 6e 6f 72 65 64 52 75 6c 65 73 2e 63  _aIgnoredRules.c
30e0: 6c 65 61 72 28 29 0a 0a 0a 64 65 66 20 72 65 61  lear()...def rea
30f0: 63 74 69 76 61 74 65 52 75 6c 65 20 28 73 52 75  ctivateRule (sRu
3100: 6c 65 49 64 29 3a 0a 20 20 20 20 22 28 72 65 29  leId):.    "(re)
3110: 61 63 74 69 76 61 74 65 20 72 75 6c 65 20 3c 73  activate rule <s
3120: 52 75 6c 65 49 64 3e 22 0a 20 20 20 20 5f 61 49  RuleId>".    _aI
3130: 67 6e 6f 72 65 64 52 75 6c 65 73 2e 64 69 73 63  gnoredRules.disc
3140: 61 72 64 28 73 52 75 6c 65 49 64 29 0a 0a 0a 64  ard(sRuleId)...d
3150: 65 66 20 6c 69 73 74 52 75 6c 65 73 20 28 73 46  ef listRules (sF
3160: 69 6c 74 65 72 3d 4e 6f 6e 65 29 3a 0a 20 20 20  ilter=None):.   
3170: 20 22 67 65 6e 65 72 61 74 6f 72 3a 20 72 65 74   "generator: ret
3180: 75 72 6e 73 20 74 79 70 6c 65 20 28 73 4f 70 74  urns typle (sOpt
3190: 69 6f 6e 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52  ion, sLineId, sR
31a0: 75 6c 65 49 64 29 22 0a 20 20 20 20 69 66 20 73  uleId)".    if s
31b0: 46 69 6c 74 65 72 3a 0a 20 20 20 20 20 20 20 20  Filter:.        
31c0: 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20  try:.           
31d0: 20 7a 46 69 6c 74 65 72 20 3d 20 72 65 2e 63 6f   zFilter = re.co
31e0: 6d 70 69 6c 65 28 73 46 69 6c 74 65 72 29 0a 20  mpile(sFilter). 
31f0: 20 20 20 20 20 20 20 65 78 63 65 70 74 3a 0a 20         except:. 
3200: 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28             echo(
3210: 22 23 20 45 72 72 6f 72 2e 20 4c 69 73 74 20 72  "# Error. List r
3220: 75 6c 65 73 3a 20 77 72 6f 6e 67 20 72 65 67 65  ules: wrong rege
3230: 78 2e 22 29 0a 20 20 20 20 20 20 20 20 20 20 20  x.").           
3240: 20 73 46 69 6c 74 65 72 20 3d 20 4e 6f 6e 65 0a   sFilter = None.
3250: 20 20 20 20 66 6f 72 20 73 4f 70 74 69 6f 6e 2c      for sOption,
3260: 20 6c 52 75 6c 65 47 72 6f 75 70 20 69 6e 20 63   lRuleGroup in c
3270: 68 61 69 6e 28 5f 67 65 74 52 75 6c 65 73 28 54  hain(_getRules(T
3280: 72 75 65 29 2c 20 5f 67 65 74 52 75 6c 65 73 28  rue), _getRules(
3290: 46 61 6c 73 65 29 29 3a 0a 20 20 20 20 20 20 20  False)):.       
32a0: 20 69 66 20 73 4f 70 74 69 6f 6e 20 21 3d 20 22   if sOption != "
32b0: 40 40 40 40 22 3a 0a 20 20 20 20 20 20 20 20 20  @@@@":.         
32c0: 20 20 20 66 6f 72 20 5f 2c 20 5f 2c 20 73 4c 69     for _, _, sLi
32d0: 6e 65 49 64 2c 20 73 52 75 6c 65 49 64 2c 20 5f  neId, sRuleId, _
32e0: 2c 20 5f 20 69 6e 20 6c 52 75 6c 65 47 72 6f 75  , _ in lRuleGrou
32f0: 70 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  p:.             
3300: 20 20 20 69 66 20 6e 6f 74 20 73 46 69 6c 74 65     if not sFilte
3310: 72 20 6f 72 20 7a 46 69 6c 74 65 72 2e 73 65 61  r or zFilter.sea
3320: 72 63 68 28 73 52 75 6c 65 49 64 29 3a 0a 20 20  rch(sRuleId):.  
3330: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3340: 20 20 79 69 65 6c 64 20 28 73 4f 70 74 69 6f 6e    yield (sOption
3350: 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65  , sLineId, sRule
3360: 49 64 29 0a 0a 0a 64 65 66 20 64 69 73 70 6c 61  Id)...def displa
3370: 79 52 75 6c 65 73 20 28 73 46 69 6c 74 65 72 3d  yRules (sFilter=
3380: 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 64 69 73 70  None):.    "disp
3390: 6c 61 79 20 74 68 65 20 6e 61 6d 65 20 6f 66 20  lay the name of 
33a0: 72 75 6c 65 73 2c 20 77 69 74 68 20 74 68 65 20  rules, with the 
33b0: 66 69 6c 74 65 72 20 3c 73 46 69 6c 74 65 72 3e  filter <sFilter>
33c0: 22 0a 20 20 20 20 65 63 68 6f 28 22 4c 69 73 74  ".    echo("List
33d0: 20 6f 66 20 72 75 6c 65 73 2e 20 46 69 6c 74 65   of rules. Filte
33e0: 72 3a 20 3c 3c 20 22 20 2b 20 73 74 72 28 73 46  r: << " + str(sF
33f0: 69 6c 74 65 72 29 20 2b 20 22 20 3e 3e 22 29 0a  ilter) + " >>").
3400: 20 20 20 20 66 6f 72 20 73 4f 70 74 69 6f 6e 2c      for sOption,
3410: 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65 49   sLineId, sRuleI
3420: 64 20 69 6e 20 6c 69 73 74 52 75 6c 65 73 28 73  d in listRules(s
3430: 46 69 6c 74 65 72 29 3a 0a 20 20 20 20 20 20 20  Filter):.       
3440: 20 65 63 68 6f 28 22 7b 3a 3c 31 30 7d 20 7b 3a   echo("{:<10} {:
3450: 3c 31 30 7d 20 7b 7d 22 2e 66 6f 72 6d 61 74 28  <10} {}".format(
3460: 73 4f 70 74 69 6f 6e 2c 20 73 4c 69 6e 65 49 64  sOption, sLineId
3470: 2c 20 73 52 75 6c 65 49 64 29 29 0a 0a 0a 64 65  , sRuleId))...de
3480: 66 20 73 65 74 4f 70 74 69 6f 6e 20 28 73 4f 70  f setOption (sOp
3490: 74 2c 20 62 56 61 6c 29 3a 0a 20 20 20 20 22 73  t, bVal):.    "s
34a0: 65 74 20 6f 70 74 69 6f 6e 20 3c 73 4f 70 74 3e  et option <sOpt>
34b0: 20 77 69 74 68 20 3c 62 56 61 6c 3e 20 69 66 20   with <bVal> if 
34c0: 69 74 20 65 78 69 73 74 73 22 0a 20 20 20 20 69  it exists".    i
34d0: 66 20 73 4f 70 74 20 69 6e 20 5f 64 4f 70 74 69  f sOpt in _dOpti
34e0: 6f 6e 73 3a 0a 20 20 20 20 20 20 20 20 5f 64 4f  ons:.        _dO
34f0: 70 74 69 6f 6e 73 5b 73 4f 70 74 5d 20 3d 20 62  ptions[sOpt] = b
3500: 56 61 6c 0a 0a 0a 64 65 66 20 73 65 74 4f 70 74  Val...def setOpt
3510: 69 6f 6e 73 20 28 64 4f 70 74 29 3a 0a 20 20 20  ions (dOpt):.   
3520: 20 22 75 70 64 61 74 65 20 74 68 65 20 64 69 63   "update the dic
3530: 74 69 6f 6e 61 72 79 20 6f 66 20 6f 70 74 69 6f  tionary of optio
3540: 6e 73 20 77 69 74 68 20 3c 64 4f 70 74 3e 22 0a  ns with <dOpt>".
3550: 20 20 20 20 66 6f 72 20 73 4b 65 79 2c 20 62 56      for sKey, bV
3560: 61 6c 20 69 6e 20 64 4f 70 74 2e 69 74 65 6d 73  al in dOpt.items
3570: 28 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20 73  ():.        if s
3580: 4b 65 79 20 69 6e 20 5f 64 4f 70 74 69 6f 6e 73  Key in _dOptions
3590: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 5f 64  :.            _d
35a0: 4f 70 74 69 6f 6e 73 5b 73 4b 65 79 5d 20 3d 20  Options[sKey] = 
35b0: 62 56 61 6c 0a 0a 0a 64 65 66 20 67 65 74 4f 70  bVal...def getOp
35c0: 74 69 6f 6e 73 20 28 29 3a 0a 20 20 20 20 22 72  tions ():.    "r
35d0: 65 74 75 72 6e 20 74 68 65 20 64 69 63 74 69 6f  eturn the dictio
35e0: 6e 61 72 79 20 6f 66 20 63 75 72 72 65 6e 74 20  nary of current 
35f0: 6f 70 74 69 6f 6e 73 22 0a 20 20 20 20 72 65 74  options".    ret
3600: 75 72 6e 20 5f 64 4f 70 74 69 6f 6e 73 0a 0a 0a  urn _dOptions...
3610: 64 65 66 20 67 65 74 44 65 66 61 75 6c 74 4f 70  def getDefaultOp
3620: 74 69 6f 6e 73 20 28 29 3a 0a 20 20 20 20 22 72  tions ():.    "r
3630: 65 74 75 72 6e 20 74 68 65 20 64 69 63 74 69 6f  eturn the dictio
3640: 6e 61 72 79 20 6f 66 20 64 65 66 61 75 6c 74 20  nary of default 
3650: 6f 70 74 69 6f 6e 73 22 0a 20 20 20 20 72 65 74  options".    ret
3660: 75 72 6e 20 64 69 63 74 28 67 63 5f 6f 70 74 69  urn dict(gc_opti
3670: 6f 6e 73 2e 67 65 74 4f 70 74 69 6f 6e 73 28 5f  ons.getOptions(_
3680: 73 41 70 70 43 6f 6e 74 65 78 74 29 29 0a 0a 0a  sAppContext))...
3690: 64 65 66 20 67 65 74 4f 70 74 69 6f 6e 73 4c 61  def getOptionsLa
36a0: 62 65 6c 73 20 28 73 4c 61 6e 67 29 3a 0a 20 20  bels (sLang):.  
36b0: 20 20 22 72 65 74 75 72 6e 20 6f 70 74 69 6f 6e    "return option
36c0: 73 20 6c 61 62 65 6c 73 22 0a 20 20 20 20 72 65  s labels".    re
36d0: 74 75 72 6e 20 67 63 5f 6f 70 74 69 6f 6e 73 2e  turn gc_options.
36e0: 67 65 74 55 49 28 73 4c 61 6e 67 29 0a 0a 0a 64  getUI(sLang)...d
36f0: 65 66 20 64 69 73 70 6c 61 79 4f 70 74 69 6f 6e  ef displayOption
3700: 73 20 28 73 4c 61 6e 67 29 3a 0a 20 20 20 20 22  s (sLang):.    "
3710: 64 69 73 70 6c 61 79 20 74 68 65 20 6c 69 73 74  display the list
3720: 20 6f 66 20 67 72 61 6d 6d 61 72 20 63 68 65 63   of grammar chec
3730: 6b 69 6e 67 20 6f 70 74 69 6f 6e 73 22 0a 20 20  king options".  
3740: 20 20 65 63 68 6f 28 22 4c 69 73 74 20 6f 66 20    echo("List of 
3750: 6f 70 74 69 6f 6e 73 22 29 0a 20 20 20 20 65 63  options").    ec
3760: 68 6f 28 22 5c 6e 22 2e 6a 6f 69 6e 28 20 5b 20  ho("\n".join( [ 
3770: 6b 2b 22 3a 5c 74 22 2b 73 74 72 28 76 29 2b 22  k+":\t"+str(v)+"
3780: 5c 74 22 2b 67 63 5f 6f 70 74 69 6f 6e 73 2e 67  \t"+gc_options.g
3790: 65 74 55 49 28 73 4c 61 6e 67 29 2e 67 65 74 28  etUI(sLang).get(
37a0: 6b 2c 20 28 22 3f 22 2c 20 22 22 29 29 5b 30 5d  k, ("?", ""))[0]
37b0: 20 20 66 6f 72 20 6b 2c 20 76 20 20 69 6e 20 73    for k, v  in s
37c0: 6f 72 74 65 64 28 5f 64 4f 70 74 69 6f 6e 73 2e  orted(_dOptions.
37d0: 69 74 65 6d 73 28 29 29 20 5d 20 29 29 0a 20 20  items()) ] )).  
37e0: 20 20 65 63 68 6f 28 22 22 29 0a 0a 0a 64 65 66    echo("")...def
37f0: 20 72 65 73 65 74 4f 70 74 69 6f 6e 73 20 28 29   resetOptions ()
3800: 3a 0a 20 20 20 20 22 73 65 74 20 6f 70 74 69 6f  :.    "set optio
3810: 6e 73 20 74 6f 20 64 65 66 61 75 6c 74 20 76 61  ns to default va
3820: 6c 75 65 73 22 0a 20 20 20 20 67 6c 6f 62 61 6c  lues".    global
3830: 20 5f 64 4f 70 74 69 6f 6e 73 0a 20 20 20 20 5f   _dOptions.    _
3840: 64 4f 70 74 69 6f 6e 73 20 3d 20 64 69 63 74 28  dOptions = dict(
3850: 67 63 5f 6f 70 74 69 6f 6e 73 2e 67 65 74 4f 70  gc_options.getOp
3860: 74 69 6f 6e 73 28 5f 73 41 70 70 43 6f 6e 74 65  tions(_sAppConte
3870: 78 74 29 29 0a 0a 0a 64 65 66 20 67 65 74 53 70  xt))...def getSp
3880: 65 6c 6c 43 68 65 63 6b 65 72 20 28 29 3a 0a 20  ellChecker ():. 
3890: 20 20 20 22 72 65 74 75 72 6e 20 74 68 65 20 73     "return the s
38a0: 70 65 6c 6c 63 68 65 63 6b 65 72 20 6f 62 6a 65  pellchecker obje
38b0: 63 74 22 0a 20 20 20 20 72 65 74 75 72 6e 20 5f  ct".    return _
38c0: 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 0a 0a 0a  oSpellChecker...
38d0: 64 65 66 20 5f 67 65 74 50 61 74 68 20 28 29 3a  def _getPath ():
38e0: 0a 20 20 20 20 72 65 74 75 72 6e 20 6f 73 2e 70  .    return os.p
38f0: 61 74 68 2e 6a 6f 69 6e 28 6f 73 2e 70 61 74 68  ath.join(os.path
3900: 2e 64 69 72 6e 61 6d 65 28 73 79 73 2e 6d 6f 64  .dirname(sys.mod
3910: 75 6c 65 73 5b 5f 5f 6e 61 6d 65 5f 5f 5d 2e 5f  ules[__name__]._
3920: 5f 66 69 6c 65 5f 5f 29 2c 20 5f 5f 6e 61 6d 65  _file__), __name
3930: 5f 5f 20 2b 20 22 2e 70 79 22 29 0a 0a 0a 0a 23  __ + ".py")....#
3940: 23 23 23 20 63 6f 6d 6d 6f 6e 20 66 75 6e 63 74  ### common funct
3950: 69 6f 6e 73 0a 0a 64 65 66 20 6f 70 74 69 6f 6e  ions..def option
3960: 20 28 73 4f 70 74 29 3a 0a 20 20 20 20 22 72 65   (sOpt):.    "re
3970: 74 75 72 6e 20 54 72 75 65 20 69 66 20 6f 70 74  turn True if opt
3980: 69 6f 6e 20 3c 73 4f 70 74 3e 20 69 73 20 61 63  ion <sOpt> is ac
3990: 74 69 76 65 22 0a 20 20 20 20 72 65 74 75 72 6e  tive".    return
39a0: 20 5f 64 4f 70 74 69 6f 6e 73 2e 67 65 74 28 73   _dOptions.get(s
39b0: 4f 70 74 2c 20 46 61 6c 73 65 29 0a 0a 0a 64 65  Opt, False)...de
39c0: 66 20 64 69 73 70 6c 61 79 49 6e 66 6f 20 28 64  f displayInfo (d
39d0: 54 6f 6b 65 6e 50 6f 73 2c 20 74 57 6f 72 64 29  TokenPos, tWord)
39e0: 3a 0a 20 20 20 20 22 66 6f 72 20 64 65 62 75 67  :.    "for debug
39f0: 67 69 6e 67 3a 20 72 65 74 72 69 65 76 65 20 69  ging: retrieve i
3a00: 6e 66 6f 20 6f 66 20 77 6f 72 64 22 0a 20 20 20  nfo of word".   
3a10: 20 69 66 20 6e 6f 74 20 74 57 6f 72 64 3a 0a 20   if not tWord:. 
3a20: 20 20 20 20 20 20 20 65 63 68 6f 28 22 3e 20 6e         echo("> n
3a30: 6f 74 68 69 6e 67 20 74 6f 20 66 69 6e 64 22 29  othing to find")
3a40: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
3a50: 54 72 75 65 0a 20 20 20 20 6c 4d 6f 72 70 68 20  True.    lMorph 
3a60: 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72  = _oSpellChecker
3a70: 2e 67 65 74 4d 6f 72 70 68 28 74 57 6f 72 64 5b  .getMorph(tWord[
3a80: 31 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c  1]).    if not l
3a90: 4d 6f 72 70 68 3a 0a 20 20 20 20 20 20 20 20 65  Morph:.        e
3aa0: 63 68 6f 28 22 3e 20 6e 6f 74 20 69 6e 20 64 69  cho("> not in di
3ab0: 63 74 69 6f 6e 61 72 79 22 29 0a 20 20 20 20 20  ctionary").     
3ac0: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
3ad0: 20 20 20 69 66 20 74 57 6f 72 64 5b 30 5d 20 69     if tWord[0] i
3ae0: 6e 20 64 54 6f 6b 65 6e 50 6f 73 20 61 6e 64 20  n dTokenPos and 
3af0: 22 6c 4d 6f 72 70 68 22 20 69 6e 20 64 54 6f 6b  "lMorph" in dTok
3b00: 65 6e 50 6f 73 5b 74 57 6f 72 64 5b 30 5d 5d 3a  enPos[tWord[0]]:
3b10: 0a 20 20 20 20 20 20 20 20 65 63 68 6f 28 22 44  .        echo("D
3b20: 41 3a 20 22 20 2b 20 73 74 72 28 64 54 6f 6b 65  A: " + str(dToke
3b30: 6e 50 6f 73 5b 74 57 6f 72 64 5b 30 5d 5d 5b 22  nPos[tWord[0]]["
3b40: 6c 4d 6f 72 70 68 22 5d 29 29 0a 20 20 20 20 65  lMorph"])).    e
3b50: 63 68 6f 28 22 46 53 41 3a 20 22 20 2b 20 73 74  cho("FSA: " + st
3b60: 72 28 6c 4d 6f 72 70 68 29 29 0a 20 20 20 20 72  r(lMorph)).    r
3b70: 65 74 75 72 6e 20 54 72 75 65 0a 0a 0a 64 65 66  eturn True...def
3b80: 20 6d 6f 72 70 68 20 28 64 54 6f 6b 65 6e 50 6f   morph (dTokenPo
3b90: 73 2c 20 74 57 6f 72 64 2c 20 73 50 61 74 74 65  s, tWord, sPatte
3ba0: 72 6e 2c 20 62 53 74 72 69 63 74 3d 54 72 75 65  rn, bStrict=True
3bb0: 2c 20 62 4e 6f 57 6f 72 64 3d 46 61 6c 73 65 29  , bNoWord=False)
3bc0: 3a 0a 20 20 20 20 22 61 6e 61 6c 79 73 65 20 61  :.    "analyse a
3bd0: 20 74 75 70 6c 65 20 28 70 6f 73 69 74 69 6f 6e   tuple (position
3be0: 2c 20 77 6f 72 64 29 2c 20 72 65 74 75 72 6e 20  , word), return 
3bf0: 54 72 75 65 20 69 66 20 73 50 61 74 74 65 72 6e  True if sPattern
3c00: 20 69 6e 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73   in morphologies
3c10: 20 28 64 69 73 61 6d 62 69 67 75 61 74 69 6f 6e   (disambiguation
3c20: 20 6f 6e 29 22 0a 20 20 20 20 69 66 20 6e 6f 74   on)".    if not
3c30: 20 74 57 6f 72 64 3a 0a 20 20 20 20 20 20 20 20   tWord:.        
3c40: 72 65 74 75 72 6e 20 62 4e 6f 57 6f 72 64 0a 20  return bNoWord. 
3c50: 20 20 20 6c 4d 6f 72 70 68 20 3d 20 64 54 6f 6b     lMorph = dTok
3c60: 65 6e 50 6f 73 5b 74 57 6f 72 64 5b 30 5d 5d 5b  enPos[tWord[0]][
3c70: 22 6c 4d 6f 72 70 68 22 5d 20 20 69 66 20 74 57  "lMorph"]  if tW
3c80: 6f 72 64 5b 30 5d 20 69 6e 20 64 54 6f 6b 65 6e  ord[0] in dToken
3c90: 50 6f 73 20 61 6e 64 20 22 6c 4d 6f 72 70 68 22  Pos and "lMorph"
3ca0: 20 69 6e 20 64 54 6f 6b 65 6e 50 6f 73 5b 74 57   in dTokenPos[tW
3cb0: 6f 72 64 5b 30 5d 5d 20 20 65 6c 73 65 20 5f 6f  ord[0]]  else _o
3cc0: 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74  SpellChecker.get
3cd0: 4d 6f 72 70 68 28 74 57 6f 72 64 5b 31 5d 29 0a  Morph(tWord[1]).
3ce0: 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70      if not lMorp
3cf0: 68 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  h:.        retur
3d00: 6e 20 46 61 6c 73 65 0a 20 20 20 20 7a 50 61 74  n False.    zPat
3d10: 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c  tern = re.compil
3d20: 65 28 73 50 61 74 74 65 72 6e 29 0a 20 20 20 20  e(sPattern).    
3d30: 69 66 20 62 53 74 72 69 63 74 3a 0a 20 20 20 20  if bStrict:.    
3d40: 20 20 20 20 72 65 74 75 72 6e 20 61 6c 6c 28 7a      return all(z
3d50: 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73  Pattern.search(s
3d60: 29 20 20 66 6f 72 20 73 20 69 6e 20 6c 4d 6f 72  )  for s in lMor
3d70: 70 68 29 0a 20 20 20 20 72 65 74 75 72 6e 20 61  ph).    return a
3d80: 6e 79 28 7a 50 61 74 74 65 72 6e 2e 73 65 61 72  ny(zPattern.sear
3d90: 63 68 28 73 29 20 20 66 6f 72 20 73 20 69 6e 20  ch(s)  for s in 
3da0: 6c 4d 6f 72 70 68 29 0a 0a 0a 64 65 66 20 6d 6f  lMorph)...def mo
3db0: 72 70 68 65 78 20 28 64 54 6f 6b 65 6e 50 6f 73  rphex (dTokenPos
3dc0: 2c 20 74 57 6f 72 64 2c 20 73 50 61 74 74 65 72  , tWord, sPatter
3dd0: 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 2c 20  n, sNegPattern, 
3de0: 62 4e 6f 57 6f 72 64 3d 46 61 6c 73 65 29 3a 0a  bNoWord=False):.
3df0: 20 20 20 20 22 61 6e 61 6c 79 73 65 20 61 20 74      "analyse a t
3e00: 75 70 6c 65 20 28 70 6f 73 69 74 69 6f 6e 2c 20  uple (position, 
3e10: 77 6f 72 64 29 2c 20 72 65 74 75 72 6e 73 20 54  word), returns T
3e20: 72 75 65 20 69 66 20 6e 6f 74 20 73 4e 65 67 50  rue if not sNegP
3e30: 61 74 74 65 72 6e 20 69 6e 20 77 6f 72 64 20 6d  attern in word m
3e40: 6f 72 70 68 6f 6c 6f 67 69 65 73 20 61 6e 64 20  orphologies and 
3e50: 73 50 61 74 74 65 72 6e 20 69 6e 20 77 6f 72 64  sPattern in word
3e60: 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 28 64   morphologies (d
3e70: 69 73 61 6d 62 69 67 75 61 74 69 6f 6e 20 6f 6e  isambiguation on
3e80: 29 22 0a 20 20 20 20 69 66 20 6e 6f 74 20 74 57  )".    if not tW
3e90: 6f 72 64 3a 0a 20 20 20 20 20 20 20 20 72 65 74  ord:.        ret
3ea0: 75 72 6e 20 62 4e 6f 57 6f 72 64 0a 20 20 20 20  urn bNoWord.    
3eb0: 6c 4d 6f 72 70 68 20 3d 20 64 54 6f 6b 65 6e 50  lMorph = dTokenP
3ec0: 6f 73 5b 74 57 6f 72 64 5b 30 5d 5d 5b 22 6c 4d  os[tWord[0]]["lM
3ed0: 6f 72 70 68 22 5d 20 20 69 66 20 74 57 6f 72 64  orph"]  if tWord
3ee0: 5b 30 5d 20 69 6e 20 64 54 6f 6b 65 6e 50 6f 73  [0] in dTokenPos
3ef0: 20 61 6e 64 20 22 6c 4d 6f 72 70 68 22 20 69 6e   and "lMorph" in
3f00: 20 64 54 6f 6b 65 6e 50 6f 73 5b 74 57 6f 72 64   dTokenPos[tWord
3f10: 5b 30 5d 5d 20 20 65 6c 73 65 20 5f 6f 53 70 65  [0]]  else _oSpe
3f20: 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72  llChecker.getMor
3f30: 70 68 28 74 57 6f 72 64 5b 31 5d 29 0a 20 20 20  ph(tWord[1]).   
3f40: 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 3a 0a   if not lMorph:.
3f50: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 46          return F
3f60: 61 6c 73 65 0a 20 20 20 20 23 20 63 68 65 63 6b  alse.    # check
3f70: 20 6e 65 67 61 74 69 76 65 20 63 6f 6e 64 69 74   negative condit
3f80: 69 6f 6e 0a 20 20 20 20 7a 4e 65 67 50 61 74 74  ion.    zNegPatt
3f90: 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65  ern = re.compile
3fa0: 28 73 4e 65 67 50 61 74 74 65 72 6e 29 0a 20 20  (sNegPattern).  
3fb0: 20 20 69 66 20 61 6e 79 28 7a 4e 65 67 50 61 74    if any(zNegPat
3fc0: 74 65 72 6e 2e 73 65 61 72 63 68 28 73 29 20 20  tern.search(s)  
3fd0: 66 6f 72 20 73 20 69 6e 20 6c 4d 6f 72 70 68 29  for s in lMorph)
3fe0: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
3ff0: 20 46 61 6c 73 65 0a 20 20 20 20 23 20 73 65 61   False.    # sea
4000: 72 63 68 20 73 50 61 74 74 65 72 6e 0a 20 20 20  rch sPattern.   
4010: 20 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63   zPattern = re.c
4020: 6f 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29  ompile(sPattern)
4030: 0a 20 20 20 20 72 65 74 75 72 6e 20 61 6e 79 28  .    return any(
4040: 7a 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28  zPattern.search(
4050: 73 29 20 20 66 6f 72 20 73 20 69 6e 20 6c 4d 6f  s)  for s in lMo
4060: 72 70 68 29 0a 0a 0a 64 65 66 20 61 6e 61 6c 79  rph)...def analy
4070: 73 65 20 28 73 57 6f 72 64 2c 20 73 50 61 74 74  se (sWord, sPatt
4080: 65 72 6e 2c 20 62 53 74 72 69 63 74 3d 54 72 75  ern, bStrict=Tru
4090: 65 29 3a 0a 20 20 20 20 22 61 6e 61 6c 79 73 65  e):.    "analyse
40a0: 20 61 20 77 6f 72 64 2c 20 72 65 74 75 72 6e 20   a word, return 
40b0: 54 72 75 65 20 69 66 20 73 50 61 74 74 65 72 6e  True if sPattern
40c0: 20 69 6e 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73   in morphologies
40d0: 20 28 64 69 73 61 6d 62 69 67 75 61 74 69 6f 6e   (disambiguation
40e0: 20 6f 66 66 29 22 0a 20 20 20 20 6c 4d 6f 72 70   off)".    lMorp
40f0: 68 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b  h = _oSpellCheck
4100: 65 72 2e 67 65 74 4d 6f 72 70 68 28 73 57 6f 72  er.getMorph(sWor
4110: 64 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d  d).    if not lM
4120: 6f 72 70 68 3a 0a 20 20 20 20 20 20 20 20 72 65  orph:.        re
4130: 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 7a  turn False.    z
4140: 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d  Pattern = re.com
4150: 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29 0a 20  pile(sPattern). 
4160: 20 20 20 69 66 20 62 53 74 72 69 63 74 3a 0a 20     if bStrict:. 
4170: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 61 6c         return al
4180: 6c 28 7a 50 61 74 74 65 72 6e 2e 73 65 61 72 63  l(zPattern.searc
4190: 68 28 73 29 20 20 66 6f 72 20 73 20 69 6e 20 6c  h(s)  for s in l
41a0: 4d 6f 72 70 68 29 0a 20 20 20 20 72 65 74 75 72  Morph).    retur
41b0: 6e 20 61 6e 79 28 7a 50 61 74 74 65 72 6e 2e 73  n any(zPattern.s
41c0: 65 61 72 63 68 28 73 29 20 20 66 6f 72 20 73 20  earch(s)  for s 
41d0: 69 6e 20 6c 4d 6f 72 70 68 29 0a 0a 0a 64 65 66  in lMorph)...def
41e0: 20 61 6e 61 6c 79 73 65 78 20 28 73 57 6f 72 64   analysex (sWord
41f0: 2c 20 73 50 61 74 74 65 72 6e 2c 20 73 4e 65 67  , sPattern, sNeg
4200: 50 61 74 74 65 72 6e 29 3a 0a 20 20 20 20 22 61  Pattern):.    "a
4210: 6e 61 6c 79 73 65 20 61 20 77 6f 72 64 2c 20 72  nalyse a word, r
4220: 65 74 75 72 6e 73 20 54 72 75 65 20 69 66 20 6e  eturns True if n
4230: 6f 74 20 73 4e 65 67 50 61 74 74 65 72 6e 20 69  ot sNegPattern i
4240: 6e 20 77 6f 72 64 20 6d 6f 72 70 68 6f 6c 6f 67  n word morpholog
4250: 69 65 73 20 61 6e 64 20 73 50 61 74 74 65 72 6e  ies and sPattern
4260: 20 69 6e 20 77 6f 72 64 20 6d 6f 72 70 68 6f 6c   in word morphol
4270: 6f 67 69 65 73 20 28 64 69 73 61 6d 62 69 67 75  ogies (disambigu
4280: 61 74 69 6f 6e 20 6f 66 66 29 22 0a 20 20 20 20  ation off)".    
4290: 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53 70 65 6c 6c  lMorph = _oSpell
42a0: 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68  Checker.getMorph
42b0: 28 73 57 6f 72 64 29 0a 20 20 20 20 69 66 20 6e  (sWord).    if n
42c0: 6f 74 20 6c 4d 6f 72 70 68 3a 0a 20 20 20 20 20  ot lMorph:.     
42d0: 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a     return False.
42e0: 20 20 20 20 23 20 63 68 65 63 6b 20 6e 65 67 61      # check nega
42f0: 74 69 76 65 20 63 6f 6e 64 69 74 69 6f 6e 0a 20  tive condition. 
4300: 20 20 20 7a 4e 65 67 50 61 74 74 65 72 6e 20 3d     zNegPattern =
4310: 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 4e 65 67   re.compile(sNeg
4320: 50 61 74 74 65 72 6e 29 0a 20 20 20 20 69 66 20  Pattern).    if 
4330: 61 6e 79 28 7a 4e 65 67 50 61 74 74 65 72 6e 2e  any(zNegPattern.
4340: 73 65 61 72 63 68 28 73 29 20 20 66 6f 72 20 73  search(s)  for s
4350: 20 69 6e 20 6c 4d 6f 72 70 68 29 3a 0a 20 20 20   in lMorph):.   
4360: 20 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73       return Fals
4370: 65 0a 20 20 20 20 23 20 73 65 61 72 63 68 20 73  e.    # search s
4380: 50 61 74 74 65 72 6e 0a 20 20 20 20 7a 50 61 74  Pattern.    zPat
4390: 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c  tern = re.compil
43a0: 65 28 73 50 61 74 74 65 72 6e 29 0a 20 20 20 20  e(sPattern).    
43b0: 72 65 74 75 72 6e 20 61 6e 79 28 7a 50 61 74 74  return any(zPatt
43c0: 65 72 6e 2e 73 65 61 72 63 68 28 73 29 20 20 66  ern.search(s)  f
43d0: 6f 72 20 73 20 69 6e 20 6c 4d 6f 72 70 68 29 0a  or s in lMorph).
43e0: 0a 0a 0a 23 23 20 66 75 6e 63 74 69 6f 6e 73 20  ...## functions 
43f0: 74 6f 20 67 65 74 20 74 65 78 74 20 6f 75 74 73  to get text outs
4400: 69 64 65 20 70 61 74 74 65 72 6e 20 73 63 6f 70  ide pattern scop
4410: 65 0a 0a 23 20 77 61 72 6e 69 6e 67 3a 20 63 68  e..# warning: ch
4420: 65 63 6b 20 63 6f 6d 70 69 6c 65 5f 72 75 6c 65  eck compile_rule
4430: 73 2e 70 79 20 74 6f 20 75 6e 64 65 72 73 74 61  s.py to understa
4440: 6e 64 20 68 6f 77 20 69 74 20 77 6f 72 6b 73 0a  nd how it works.
4450: 0a 5f 7a 4e 65 78 74 57 6f 72 64 20 3d 20 72 65  ._zNextWord = re
4460: 2e 63 6f 6d 70 69 6c 65 28 72 22 20 2b 28 5c 77  .compile(r" +(\w
4470: 5b 5c 77 2d 5d 2a 29 22 29 0a 5f 7a 50 72 65 76  [\w-]*)")._zPrev
4480: 57 6f 72 64 20 3d 20 72 65 2e 63 6f 6d 70 69 6c  Word = re.compil
4490: 65 28 72 22 28 5c 77 5b 5c 77 2d 5d 2a 29 20 2b  e(r"(\w[\w-]*) +
44a0: 24 22 29 0a 0a 64 65 66 20 6e 65 78 74 77 6f 72  $")..def nextwor
44b0: 64 20 28 73 2c 20 69 53 74 61 72 74 2c 20 6e 29  d (s, iStart, n)
44c0: 3a 0a 20 20 20 20 22 67 65 74 20 74 68 65 20 6e  :.    "get the n
44d0: 74 68 20 77 6f 72 64 20 6f 66 20 74 68 65 20 69  th word of the i
44e0: 6e 70 75 74 20 73 74 72 69 6e 67 20 6f 72 20 65  nput string or e
44f0: 6d 70 74 79 20 73 74 72 69 6e 67 22 0a 20 20 20  mpty string".   
4500: 20 6d 20 3d 20 72 65 2e 6d 61 74 63 68 28 22 28   m = re.match("(
4510: 3f 3a 20 2b 5b 5c 5c 77 25 2d 5d 2b 29 7b 22 20  ?: +[\\w%-]+){" 
4520: 2b 20 73 74 72 28 6e 2d 31 29 20 2b 20 22 7d 20  + str(n-1) + "} 
4530: 2b 28 5b 5c 5c 77 25 2d 5d 2b 29 22 2c 20 73 5b  +([\\w%-]+)", s[
4540: 69 53 74 61 72 74 3a 5d 29 0a 20 20 20 20 69 66  iStart:]).    if
4550: 20 6e 6f 74 20 6d 3a 0a 20 20 20 20 20 20 20 20   not m:.        
4560: 72 65 74 75 72 6e 20 4e 6f 6e 65 0a 20 20 20 20  return None.    
4570: 72 65 74 75 72 6e 20 28 69 53 74 61 72 74 2b 6d  return (iStart+m
4580: 2e 73 74 61 72 74 28 31 29 2c 20 6d 2e 67 72 6f  .start(1), m.gro
4590: 75 70 28 31 29 29 0a 0a 0a 64 65 66 20 70 72 65  up(1))...def pre
45a0: 76 77 6f 72 64 20 28 73 2c 20 69 45 6e 64 2c 20  vword (s, iEnd, 
45b0: 6e 29 3a 0a 20 20 20 20 22 67 65 74 20 74 68 65  n):.    "get the
45c0: 20 28 2d 29 6e 74 68 20 77 6f 72 64 20 6f 66 20   (-)nth word of 
45d0: 74 68 65 20 69 6e 70 75 74 20 73 74 72 69 6e 67  the input string
45e0: 20 6f 72 20 65 6d 70 74 79 20 73 74 72 69 6e 67   or empty string
45f0: 22 0a 20 20 20 20 6d 20 3d 20 72 65 2e 73 65 61  ".    m = re.sea
4600: 72 63 68 28 22 28 5b 5c 5c 77 25 2d 5d 2b 29 20  rch("([\\w%-]+) 
4610: 2b 28 3f 3a 5b 5c 5c 77 25 2d 5d 2b 20 2b 29 7b  +(?:[\\w%-]+ +){
4620: 22 20 2b 20 73 74 72 28 6e 2d 31 29 20 2b 20 22  " + str(n-1) + "
4630: 7d 24 22 2c 20 73 5b 3a 69 45 6e 64 5d 29 0a 20  }$", s[:iEnd]). 
4640: 20 20 20 69 66 20 6e 6f 74 20 6d 3a 0a 20 20 20     if not m:.   
4650: 20 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e 65       return None
4660: 0a 20 20 20 20 72 65 74 75 72 6e 20 28 6d 2e 73  .    return (m.s
4670: 74 61 72 74 28 31 29 2c 20 6d 2e 67 72 6f 75 70  tart(1), m.group
4680: 28 31 29 29 0a 0a 0a 64 65 66 20 6e 65 78 74 77  (1))...def nextw
4690: 6f 72 64 31 20 28 73 2c 20 69 53 74 61 72 74 29  ord1 (s, iStart)
46a0: 3a 0a 20 20 20 20 22 67 65 74 20 6e 65 78 74 20  :.    "get next 
46b0: 77 6f 72 64 20 28 6f 70 74 69 6d 69 7a 61 74 69  word (optimizati
46c0: 6f 6e 29 22 0a 20 20 20 20 6d 20 3d 20 5f 7a 4e  on)".    m = _zN
46d0: 65 78 74 57 6f 72 64 2e 6d 61 74 63 68 28 73 5b  extWord.match(s[
46e0: 69 53 74 61 72 74 3a 5d 29 0a 20 20 20 20 69 66  iStart:]).    if
46f0: 20 6e 6f 74 20 6d 3a 0a 20 20 20 20 20 20 20 20   not m:.        
4700: 72 65 74 75 72 6e 20 4e 6f 6e 65 0a 20 20 20 20  return None.    
4710: 72 65 74 75 72 6e 20 28 69 53 74 61 72 74 2b 6d  return (iStart+m
4720: 2e 73 74 61 72 74 28 31 29 2c 20 6d 2e 67 72 6f  .start(1), m.gro
4730: 75 70 28 31 29 29 0a 0a 0a 64 65 66 20 70 72 65  up(1))...def pre
4740: 76 77 6f 72 64 31 20 28 73 2c 20 69 45 6e 64 29  vword1 (s, iEnd)
4750: 3a 0a 20 20 20 20 22 67 65 74 20 70 72 65 76 69  :.    "get previ
4760: 6f 75 73 20 77 6f 72 64 20 28 6f 70 74 69 6d 69  ous word (optimi
4770: 7a 61 74 69 6f 6e 29 22 0a 20 20 20 20 6d 20 3d  zation)".    m =
4780: 20 5f 7a 50 72 65 76 57 6f 72 64 2e 73 65 61 72   _zPrevWord.sear
4790: 63 68 28 73 5b 3a 69 45 6e 64 5d 29 0a 20 20 20  ch(s[:iEnd]).   
47a0: 20 69 66 20 6e 6f 74 20 6d 3a 0a 20 20 20 20 20   if not m:.     
47b0: 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e 65 0a 20     return None. 
47c0: 20 20 20 72 65 74 75 72 6e 20 28 6d 2e 73 74 61     return (m.sta
47d0: 72 74 28 31 29 2c 20 6d 2e 67 72 6f 75 70 28 31  rt(1), m.group(1
47e0: 29 29 0a 0a 0a 64 65 66 20 6c 6f 6f 6b 20 28 73  ))...def look (s
47f0: 2c 20 73 50 61 74 74 65 72 6e 2c 20 73 4e 65 67  , sPattern, sNeg
4800: 50 61 74 74 65 72 6e 3d 4e 6f 6e 65 29 3a 0a 20  Pattern=None):. 
4810: 20 20 20 22 73 65 65 6b 20 73 50 61 74 74 65 72     "seek sPatter
4820: 6e 20 69 6e 20 73 20 28 62 65 66 6f 72 65 2f 61  n in s (before/a
4830: 66 74 65 72 2f 66 75 6c 6c 74 65 78 74 29 2c 20  fter/fulltext), 
4840: 69 66 20 73 4e 65 67 50 61 74 74 65 72 6e 20 6e  if sNegPattern n
4850: 6f 74 20 69 6e 20 73 22 0a 20 20 20 20 69 66 20  ot in s".    if 
4860: 73 4e 65 67 50 61 74 74 65 72 6e 20 61 6e 64 20  sNegPattern and 
4870: 72 65 2e 73 65 61 72 63 68 28 73 4e 65 67 50 61  re.search(sNegPa
4880: 74 74 65 72 6e 2c 20 73 29 3a 0a 20 20 20 20 20  ttern, s):.     
4890: 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a     return False.
48a0: 20 20 20 20 69 66 20 72 65 2e 73 65 61 72 63 68      if re.search
48b0: 28 73 50 61 74 74 65 72 6e 2c 20 73 29 3a 0a 20  (sPattern, s):. 
48c0: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54 72         return Tr
48d0: 75 65 0a 20 20 20 20 72 65 74 75 72 6e 20 46 61  ue.    return Fa
48e0: 6c 73 65 0a 0a 0a 64 65 66 20 6c 6f 6f 6b 5f 63  lse...def look_c
48f0: 68 6b 31 20 28 64 54 6f 6b 65 6e 50 6f 73 2c 20  hk1 (dTokenPos, 
4900: 73 2c 20 6e 4f 66 66 73 65 74 2c 20 73 50 61 74  s, nOffset, sPat
4910: 74 65 72 6e 2c 20 73 50 61 74 74 65 72 6e 47 72  tern, sPatternGr
4920: 6f 75 70 31 2c 20 73 4e 65 67 50 61 74 74 65 72  oup1, sNegPatter
4930: 6e 47 72 6f 75 70 31 3d 4e 6f 6e 65 29 3a 0a 20  nGroup1=None):. 
4940: 20 20 20 22 72 65 74 75 72 6e 73 20 54 72 75 65     "returns True
4950: 20 69 66 20 73 20 68 61 73 20 70 61 74 74 65 72   if s has patter
4960: 6e 20 73 50 61 74 74 65 72 6e 20 61 6e 64 20 6d  n sPattern and m
4970: 2e 67 72 6f 75 70 28 31 29 20 68 61 73 20 70 61  .group(1) has pa
4980: 74 74 65 72 6e 20 73 50 61 74 74 65 72 6e 47 72  ttern sPatternGr
4990: 6f 75 70 31 22 0a 20 20 20 20 6d 20 3d 20 72 65  oup1".    m = re
49a0: 2e 73 65 61 72 63 68 28 73 50 61 74 74 65 72 6e  .search(sPattern
49b0: 2c 20 73 29 0a 20 20 20 20 69 66 20 6e 6f 74 20  , s).    if not 
49c0: 6d 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  m:.        retur
49d0: 6e 20 46 61 6c 73 65 0a 20 20 20 20 74 72 79 3a  n False.    try:
49e0: 0a 20 20 20 20 20 20 20 20 73 57 6f 72 64 20 3d  .        sWord =
49f0: 20 6d 2e 67 72 6f 75 70 28 31 29 0a 20 20 20 20   m.group(1).    
4a00: 20 20 20 20 6e 50 6f 73 20 3d 20 6d 2e 73 74 61      nPos = m.sta
4a10: 72 74 28 31 29 20 2b 20 6e 4f 66 66 73 65 74 0a  rt(1) + nOffset.
4a20: 20 20 20 20 65 78 63 65 70 74 3a 0a 20 20 20 20      except:.    
4a30: 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65      return False
4a40: 0a 20 20 20 20 69 66 20 73 4e 65 67 50 61 74 74  .    if sNegPatt
4a50: 65 72 6e 47 72 6f 75 70 31 3a 0a 20 20 20 20 20  ernGroup1:.     
4a60: 20 20 20 72 65 74 75 72 6e 20 6d 6f 72 70 68 65     return morphe
4a70: 78 28 64 54 6f 6b 65 6e 50 6f 73 2c 20 28 6e 50  x(dTokenPos, (nP
4a80: 6f 73 2c 20 73 57 6f 72 64 29 2c 20 73 50 61 74  os, sWord), sPat
4a90: 74 65 72 6e 47 72 6f 75 70 31 2c 20 73 4e 65 67  ternGroup1, sNeg
4aa0: 50 61 74 74 65 72 6e 47 72 6f 75 70 31 29 0a 20  PatternGroup1). 
4ab0: 20 20 20 72 65 74 75 72 6e 20 6d 6f 72 70 68 28     return morph(
4ac0: 64 54 6f 6b 65 6e 50 6f 73 2c 20 28 6e 50 6f 73  dTokenPos, (nPos
4ad0: 2c 20 73 57 6f 72 64 29 2c 20 73 50 61 74 74 65  , sWord), sPatte
4ae0: 72 6e 47 72 6f 75 70 31 2c 20 46 61 6c 73 65 29  rnGroup1, False)
4af0: 0a 0a 0a 23 23 23 23 20 44 69 73 61 6d 62 69 67  ...#### Disambig
4b00: 75 61 74 6f 72 0a 0a 64 65 66 20 73 65 6c 65 63  uator..def selec
4b10: 74 20 28 64 54 6f 6b 65 6e 50 6f 73 2c 20 6e 50  t (dTokenPos, nP
4b20: 6f 73 2c 20 73 57 6f 72 64 2c 20 73 50 61 74 74  os, sWord, sPatt
4b30: 65 72 6e 2c 20 6c 44 65 66 61 75 6c 74 3d 4e 6f  ern, lDefault=No
4b40: 6e 65 29 3a 0a 20 20 20 20 22 44 69 73 61 6d 62  ne):.    "Disamb
4b50: 69 67 75 61 74 69 6f 6e 3a 20 73 65 6c 65 63 74  iguation: select
4b60: 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 6f 66   morphologies of
4b70: 20 3c 73 57 6f 72 64 3e 20 6d 61 74 63 68 69 6e   <sWord> matchin
4b80: 67 20 3c 73 50 61 74 74 65 72 6e 3e 22 0a 20 20  g <sPattern>".  
4b90: 20 20 69 66 20 6e 6f 74 20 73 57 6f 72 64 3a 0a    if not sWord:.
4ba0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54          return T
4bb0: 72 75 65 0a 20 20 20 20 69 66 20 6e 50 6f 73 20  rue.    if nPos 
4bc0: 6e 6f 74 20 69 6e 20 64 54 6f 6b 65 6e 50 6f 73  not in dTokenPos
4bd0: 3a 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28  :.        print(
4be0: 22 45 72 72 6f 72 2e 20 54 68 65 72 65 20 73 68  "Error. There sh
4bf0: 6f 75 6c 64 20 62 65 20 61 20 74 6f 6b 65 6e 20  ould be a token 
4c00: 61 74 20 74 68 69 73 20 70 6f 73 69 74 69 6f 6e  at this position
4c10: 3a 20 22 2c 20 6e 50 6f 73 29 0a 20 20 20 20 20  : ", nPos).     
4c20: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
4c30: 20 20 20 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53 70     lMorph = _oSp
4c40: 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f  ellChecker.getMo
4c50: 72 70 68 28 73 57 6f 72 64 29 0a 20 20 20 20 69  rph(sWord).    i
4c60: 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 20 6f 72 20  f not lMorph or 
4c70: 6c 65 6e 28 6c 4d 6f 72 70 68 29 20 3d 3d 20 31  len(lMorph) == 1
4c80: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
4c90: 20 54 72 75 65 0a 20 20 20 20 6c 53 65 6c 65 63   True.    lSelec
4ca0: 74 20 3d 20 5b 20 73 4d 6f 72 70 68 20 20 66 6f  t = [ sMorph  fo
4cb0: 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72  r sMorph in lMor
4cc0: 70 68 20 20 69 66 20 72 65 2e 73 65 61 72 63 68  ph  if re.search
4cd0: 28 73 50 61 74 74 65 72 6e 2c 20 73 4d 6f 72 70  (sPattern, sMorp
4ce0: 68 29 20 5d 0a 20 20 20 20 69 66 20 6c 53 65 6c  h) ].    if lSel
4cf0: 65 63 74 3a 0a 20 20 20 20 20 20 20 20 69 66 20  ect:.        if 
4d00: 6c 65 6e 28 6c 53 65 6c 65 63 74 29 20 21 3d 20  len(lSelect) != 
4d10: 6c 65 6e 28 6c 4d 6f 72 70 68 29 3a 0a 20 20 20  len(lMorph):.   
4d20: 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 50           dTokenP
4d30: 6f 73 5b 6e 50 6f 73 5d 5b 22 6c 4d 6f 72 70 68  os[nPos]["lMorph
4d40: 22 5d 20 3d 20 6c 53 65 6c 65 63 74 0a 20 20 20  "] = lSelect.   
4d50: 20 65 6c 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a   elif lDefault:.
4d60: 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 50 6f          dTokenPo
4d70: 73 5b 6e 50 6f 73 5d 5b 22 6c 4d 6f 72 70 68 22  s[nPos]["lMorph"
4d80: 5d 20 3d 20 6c 44 65 66 61 75 6c 74 0a 20 20 20  ] = lDefault.   
4d90: 20 72 65 74 75 72 6e 20 54 72 75 65 0a 0a 0a 64   return True...d
4da0: 65 66 20 65 78 63 6c 75 64 65 20 28 64 54 6f 6b  ef exclude (dTok
4db0: 65 6e 50 6f 73 2c 20 6e 50 6f 73 2c 20 73 57 6f  enPos, nPos, sWo
4dc0: 72 64 2c 20 73 50 61 74 74 65 72 6e 2c 20 6c 44  rd, sPattern, lD
4dd0: 65 66 61 75 6c 74 3d 4e 6f 6e 65 29 3a 0a 20 20  efault=None):.  
4de0: 20 20 22 44 69 73 61 6d 62 69 67 75 61 74 69 6f    "Disambiguatio
4df0: 6e 3a 20 65 78 63 6c 75 64 65 20 6d 6f 72 70 68  n: exclude morph
4e00: 6f 6c 6f 67 69 65 73 20 6f 66 20 3c 73 57 6f 72  ologies of <sWor
4e10: 64 3e 20 6d 61 74 63 68 69 6e 67 20 3c 73 50 61  d> matching <sPa
4e20: 74 74 65 72 6e 3e 22 0a 20 20 20 20 69 66 20 6e  ttern>".    if n
4e30: 6f 74 20 73 57 6f 72 64 3a 0a 20 20 20 20 20 20  ot sWord:.      
4e40: 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20 20    return True.  
4e50: 20 20 69 66 20 6e 50 6f 73 20 6e 6f 74 20 69 6e    if nPos not in
4e60: 20 64 54 6f 6b 65 6e 50 6f 73 3a 0a 20 20 20 20   dTokenPos:.    
4e70: 20 20 20 20 70 72 69 6e 74 28 22 45 72 72 6f 72      print("Error
4e80: 2e 20 54 68 65 72 65 20 73 68 6f 75 6c 64 20 62  . There should b
4e90: 65 20 61 20 74 6f 6b 65 6e 20 61 74 20 74 68 69  e a token at thi
4ea0: 73 20 70 6f 73 69 74 69 6f 6e 3a 20 22 2c 20 6e  s position: ", n
4eb0: 50 6f 73 29 0a 20 20 20 20 20 20 20 20 72 65 74  Pos).        ret
4ec0: 75 72 6e 20 54 72 75 65 0a 20 20 20 20 6c 4d 6f  urn True.    lMo
4ed0: 72 70 68 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65  rph = _oSpellChe
4ee0: 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 73 57  cker.getMorph(sW
4ef0: 6f 72 64 29 0a 20 20 20 20 69 66 20 6e 6f 74 20  ord).    if not 
4f00: 6c 4d 6f 72 70 68 20 6f 72 20 6c 65 6e 28 6c 4d  lMorph or len(lM
4f10: 6f 72 70 68 29 20 3d 3d 20 31 3a 0a 20 20 20 20  orph) == 1:.    
4f20: 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a      return True.
4f30: 20 20 20 20 6c 53 65 6c 65 63 74 20 3d 20 5b 20      lSelect = [ 
4f40: 73 4d 6f 72 70 68 20 20 66 6f 72 20 73 4d 6f 72  sMorph  for sMor
4f50: 70 68 20 69 6e 20 6c 4d 6f 72 70 68 20 20 69 66  ph in lMorph  if
4f60: 20 6e 6f 74 20 72 65 2e 73 65 61 72 63 68 28 73   not re.search(s
4f70: 50 61 74 74 65 72 6e 2c 20 73 4d 6f 72 70 68 29  Pattern, sMorph)
4f80: 20 5d 0a 20 20 20 20 69 66 20 6c 53 65 6c 65 63   ].    if lSelec
4f90: 74 3a 0a 20 20 20 20 20 20 20 20 69 66 20 6c 65  t:.        if le
4fa0: 6e 28 6c 53 65 6c 65 63 74 29 20 21 3d 20 6c 65  n(lSelect) != le
4fb0: 6e 28 6c 4d 6f 72 70 68 29 3a 0a 20 20 20 20 20  n(lMorph):.     
4fc0: 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 50 6f 73         dTokenPos
4fd0: 5b 6e 50 6f 73 5d 5b 22 6c 4d 6f 72 70 68 22 5d  [nPos]["lMorph"]
4fe0: 20 3d 20 6c 53 65 6c 65 63 74 0a 20 20 20 20 65   = lSelect.    e
4ff0: 6c 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a 20 20  lif lDefault:.  
5000: 20 20 20 20 20 20 64 54 6f 6b 65 6e 50 6f 73 5b        dTokenPos[
5010: 6e 50 6f 73 5d 5b 22 6c 4d 6f 72 70 68 22 5d 20  nPos]["lMorph"] 
5020: 3d 20 6c 44 65 66 61 75 6c 74 0a 20 20 20 20 72  = lDefault.    r
5030: 65 74 75 72 6e 20 54 72 75 65 0a 0a 0a 64 65 66  eturn True...def
5040: 20 64 65 66 69 6e 65 20 28 64 54 6f 6b 65 6e 50   define (dTokenP
5050: 6f 73 2c 20 6e 50 6f 73 2c 20 6c 4d 6f 72 70 68  os, nPos, lMorph
5060: 29 3a 0a 20 20 20 20 22 44 69 73 61 6d 62 69 67  ):.    "Disambig
5070: 75 61 74 69 6f 6e 3a 20 73 65 74 20 6d 6f 72 70  uation: set morp
5080: 68 6f 6c 6f 67 69 65 73 20 6f 66 20 74 6f 6b 65  hologies of toke
5090: 6e 20 61 74 20 3c 6e 50 6f 73 3e 20 77 69 74 68  n at <nPos> with
50a0: 20 3c 6c 4d 6f 72 70 68 3e 22 0a 20 20 20 20 69   <lMorph>".    i
50b0: 66 20 6e 50 6f 73 20 6e 6f 74 20 69 6e 20 64 54  f nPos not in dT
50c0: 6f 6b 65 6e 50 6f 73 3a 0a 20 20 20 20 20 20 20  okenPos:.       
50d0: 20 70 72 69 6e 74 28 22 45 72 72 6f 72 2e 20 54   print("Error. T
50e0: 68 65 72 65 20 73 68 6f 75 6c 64 20 62 65 20 61  here should be a
50f0: 20 74 6f 6b 65 6e 20 61 74 20 74 68 69 73 20 70   token at this p
5100: 6f 73 69 74 69 6f 6e 3a 20 22 2c 20 6e 50 6f 73  osition: ", nPos
5110: 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ).        return
5120: 20 54 72 75 65 0a 20 20 20 20 64 54 6f 6b 65 6e   True.    dToken
5130: 50 6f 73 5b 6e 50 6f 73 5d 5b 22 6c 4d 6f 72 70  Pos[nPos]["lMorp
5140: 68 22 5d 20 3d 20 6c 4d 6f 72 70 68 0a 20 20 20  h"] = lMorph.   
5150: 20 72 65 74 75 72 6e 20 54 72 75 65 0a 0a 0a 0a   return True....
5160: 0a 23 23 23 23 20 54 4f 4b 45 4e 20 53 45 4e 54  .#### TOKEN SENT
5170: 45 4e 43 45 20 43 48 45 43 4b 45 52 0a 0a 63 6c  ENCE CHECKER..cl
5180: 61 73 73 20 54 6f 6b 65 6e 53 65 6e 74 65 6e 63  ass TokenSentenc
5190: 65 3a 0a 20 20 20 20 22 54 65 78 74 20 70 61 72  e:.    "Text par
51a0: 73 65 72 22 0a 0a 20 20 20 20 64 65 66 20 5f 5f  ser"..    def __
51b0: 69 6e 69 74 5f 5f 20 28 73 65 6c 66 2c 20 73 53  init__ (self, sS
51c0: 65 6e 74 65 6e 63 65 2c 20 73 53 65 6e 74 65 6e  entence, sSenten
51d0: 63 65 30 2c 20 6e 4f 66 66 73 65 74 29 3a 0a 20  ce0, nOffset):. 
51e0: 20 20 20 20 20 20 20 73 65 6c 66 2e 73 53 65 6e         self.sSen
51f0: 74 65 6e 63 65 20 3d 20 73 53 65 6e 74 65 6e 63  tence = sSentenc
5200: 65 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 73  e.        self.s
5210: 53 65 6e 74 65 6e 63 65 30 20 3d 20 73 53 65 6e  Sentence0 = sSen
5220: 74 65 6e 63 65 30 0a 20 20 20 20 20 20 20 20 73  tence0.        s
5230: 65 6c 66 2e 6e 4f 66 66 73 65 74 57 69 74 68 69  elf.nOffsetWithi
5240: 6e 50 61 72 61 67 72 61 70 68 20 3d 20 6e 4f 66  nParagraph = nOf
5250: 66 73 65 74 0a 20 20 20 20 20 20 20 20 73 65 6c  fset.        sel
5260: 66 2e 6c 54 6f 6b 65 6e 20 3d 20 6c 69 73 74 28  f.lToken = list(
5270: 5f 6f 54 6f 6b 65 6e 69 7a 65 72 2e 67 65 6e 54  _oTokenizer.genT
5280: 6f 6b 65 6e 73 28 73 53 65 6e 74 65 6e 63 65 2c  okens(sSentence,
5290: 20 54 72 75 65 29 29 0a 20 20 20 20 20 20 20 20   True)).        
52a0: 73 65 6c 66 2e 64 54 6f 6b 65 6e 50 6f 73 20 3d  self.dTokenPos =
52b0: 20 7b 20 64 54 6f 6b 65 6e 5b 22 6e 53 74 61 72   { dToken["nStar
52c0: 74 22 5d 3a 20 64 54 6f 6b 65 6e 20 20 66 6f 72  t"]: dToken  for
52d0: 20 64 54 6f 6b 65 6e 20 69 6e 20 73 65 6c 66 2e   dToken in self.
52e0: 6c 54 6f 6b 65 6e 20 7d 0a 20 20 20 20 20 20 20  lToken }.       
52f0: 20 73 65 6c 66 2e 64 54 61 67 73 20 3d 20 7b 7d   self.dTags = {}
5300: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64 45  .        self.dE
5310: 72 72 6f 72 20 3d 20 7b 7d 0a 20 20 20 20 20 20  rror = {}.      
5320: 20 20 73 65 6c 66 2e 63 72 65 61 74 65 45 72 72    self.createErr
5330: 6f 72 20 3d 20 73 65 6c 66 2e 5f 63 72 65 61 74  or = self._creat
5340: 65 57 72 69 74 65 72 45 72 72 6f 72 20 20 69 66  eWriterError  if
5350: 20 5f 62 57 72 69 74 65 72 45 72 72 6f 72 20 20   _bWriterError  
5360: 65 6c 73 65 20 73 65 6c 66 2e 5f 63 72 65 61 74  else self._creat
5370: 65 44 69 63 74 45 72 72 6f 72 0a 0a 20 20 20 20  eDictError..    
5380: 64 65 66 20 75 70 64 61 74 65 20 28 73 65 6c 66  def update (self
5390: 2c 20 73 53 65 6e 74 65 6e 63 65 29 3a 0a 20 20  , sSentence):.  
53a0: 20 20 20 20 20 20 22 75 70 64 61 74 65 20 3c 73        "update <s
53b0: 53 65 6e 74 65 6e 63 65 3e 20 61 6e 64 20 72 65  Sentence> and re
53c0: 74 6f 6b 65 6e 69 7a 65 22 0a 20 20 20 20 20 20  tokenize".      
53d0: 20 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65    self.sSentence
53e0: 20 3d 20 73 53 65 6e 74 65 6e 63 65 0a 20 20 20   = sSentence.   
53f0: 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e       self.lToken
5400: 20 3d 20 6c 69 73 74 28 5f 6f 54 6f 6b 65 6e 69   = list(_oTokeni
5410: 7a 65 72 2e 67 65 6e 54 6f 6b 65 6e 73 28 73 53  zer.genTokens(sS
5420: 65 6e 74 65 6e 63 65 2c 20 54 72 75 65 29 29 0a  entence, True)).
5430: 0a 20 20 20 20 64 65 66 20 5f 67 65 74 4e 65 78  .    def _getNex
5440: 74 4d 61 74 63 68 69 6e 67 4e 6f 64 65 73 20 28  tMatchingNodes (
5450: 73 65 6c 66 2c 20 64 54 6f 6b 65 6e 2c 20 64 47  self, dToken, dG
5460: 72 61 70 68 2c 20 64 4e 6f 64 65 2c 20 62 44 65  raph, dNode, bDe
5470: 62 75 67 3d 46 61 6c 73 65 29 3a 0a 20 20 20 20  bug=False):.    
5480: 20 20 20 20 22 67 65 6e 65 72 61 74 6f 72 3a 20      "generator: 
5490: 72 65 74 75 72 6e 20 6e 6f 64 65 73 20 77 68 65  return nodes whe
54a0: 72 65 20 3c 64 54 6f 6b 65 6e 3e 20 e2 80 9c 76  re <dToken> ...v
54b0: 61 6c 75 65 73 e2 80 9d 20 6d 61 74 63 68 20 3c  alues... match <
54c0: 64 4e 6f 64 65 3e 20 61 72 63 73 22 0a 20 20 20  dNode> arcs".   
54d0: 20 20 20 20 20 23 20 74 6f 6b 65 6e 20 76 61 6c       # token val
54e0: 75 65 0a 20 20 20 20 20 20 20 20 69 66 20 64 54  ue.        if dT
54f0: 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 20 69  oken["sValue"] i
5500: 6e 20 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20  n dNode:.       
5510: 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a       if bDebug:.
5520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5530: 70 72 69 6e 74 28 22 20 20 4d 41 54 43 48 3a 22  print("  MATCH:"
5540: 2c 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65  , dToken["sValue
5550: 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  "]).            
5560: 79 69 65 6c 64 20 64 47 72 61 70 68 5b 64 4e 6f  yield dGraph[dNo
5570: 64 65 5b 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  de[dToken["sValu
5580: 65 22 5d 5d 5d 0a 20 20 20 20 20 20 20 20 69 66  e"]]].        if
5590: 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22   dToken["sValue"
55a0: 5d 5b 30 3a 32 5d 2e 69 73 74 69 74 6c 65 28 29  ][0:2].istitle()
55b0: 3a 20 23 20 77 65 20 74 65 73 74 20 6f 6e 6c 79  : # we test only
55c0: 20 32 20 66 69 72 73 74 20 63 68 61 72 73 2c 20   2 first chars, 
55d0: 74 6f 20 6d 61 6b 65 20 76 61 6c 69 64 20 77 6f  to make valid wo
55e0: 72 64 73 20 73 75 63 68 20 61 73 20 22 4c 61 69  rds such as "Lai
55f0: 73 73 65 7a 2d 6c 65 73 22 2c 20 22 50 61 73 73  ssez-les", "Pass
5600: 65 2d 70 61 72 74 6f 75 74 22 2e 0a 20 20 20 20  e-partout"..    
5610: 20 20 20 20 20 20 20 20 73 56 61 6c 75 65 20 3d          sValue =
5620: 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22   dToken["sValue"
5630: 5d 2e 6c 6f 77 65 72 28 29 0a 20 20 20 20 20 20  ].lower().      
5640: 20 20 20 20 20 20 69 66 20 73 56 61 6c 75 65 20        if sValue 
5650: 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20  in dNode:.      
5660: 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65            if bDe
5670: 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  bug:.           
5680: 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22           print("
5690: 20 20 4d 41 54 43 48 3a 22 2c 20 73 56 61 6c 75    MATCH:", sValu
56a0: 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e).             
56b0: 20 20 20 79 69 65 6c 64 20 64 47 72 61 70 68 5b     yield dGraph[
56c0: 64 4e 6f 64 65 5b 73 56 61 6c 75 65 5d 5d 0a 20  dNode[sValue]]. 
56d0: 20 20 20 20 20 20 20 65 6c 69 66 20 64 54 6f 6b         elif dTok
56e0: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2e 69 73 75  en["sValue"].isu
56f0: 70 70 65 72 28 29 3a 0a 20 20 20 20 20 20 20 20  pper():.        
5700: 20 20 20 20 73 56 61 6c 75 65 20 3d 20 64 54 6f      sValue = dTo
5710: 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2e 6c 6f  ken["sValue"].lo
5720: 77 65 72 28 29 0a 20 20 20 20 20 20 20 20 20 20  wer().          
5730: 20 20 69 66 20 73 56 61 6c 75 65 20 69 6e 20 64    if sValue in d
5740: 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20 20 20  Node:.          
5750: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
5760: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5770: 20 20 20 20 20 70 72 69 6e 74 28 22 20 20 4d 41       print("  MA
5780: 54 43 48 3a 22 2c 20 73 56 61 6c 75 65 29 0a 20  TCH:", sValue). 
5790: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 79                 y
57a0: 69 65 6c 64 20 64 47 72 61 70 68 5b 64 4e 6f 64  ield dGraph[dNod
57b0: 65 5b 73 56 61 6c 75 65 5d 5d 0a 20 20 20 20 20  e[sValue]].     
57c0: 20 20 20 20 20 20 20 73 56 61 6c 75 65 20 3d 20         sValue = 
57d0: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
57e0: 2e 63 61 70 69 74 61 6c 69 7a 65 28 29 0a 20 20  .capitalize().  
57f0: 20 20 20 20 20 20 20 20 20 20 69 66 20 73 56 61            if sVa
5800: 6c 75 65 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20  lue in dNode:.  
5810: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
5820: 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20   bDebug:.       
5830: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69               pri
5840: 6e 74 28 22 20 20 4d 41 54 43 48 3a 22 2c 20 73  nt("  MATCH:", s
5850: 56 61 6c 75 65 29 0a 20 20 20 20 20 20 20 20 20  Value).         
5860: 20 20 20 20 20 20 20 79 69 65 6c 64 20 64 47 72         yield dGr
5870: 61 70 68 5b 64 4e 6f 64 65 5b 73 56 61 6c 75 65  aph[dNode[sValue
5880: 5d 5d 0a 20 20 20 20 20 20 20 20 23 20 74 6f 6b  ]].        # tok
5890: 65 6e 20 6c 65 6d 6d 61 73 0a 20 20 20 20 20 20  en lemmas.      
58a0: 20 20 69 66 20 22 3c 6c 65 6d 6d 61 73 3e 22 20    if "<lemmas>" 
58b0: 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20  in dNode:.      
58c0: 20 20 20 20 20 20 66 6f 72 20 73 4c 65 6d 6d 61        for sLemma
58d0: 20 69 6e 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b   in _oSpellCheck
58e0: 65 72 2e 67 65 74 4c 65 6d 6d 61 28 64 54 6f 6b  er.getLemma(dTok
58f0: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 3a 0a 20  en["sValue"]):. 
5900: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
5910: 66 20 73 4c 65 6d 6d 61 20 69 6e 20 64 4e 6f 64  f sLemma in dNod
5920: 65 5b 22 3c 6c 65 6d 6d 61 73 3e 22 5d 3a 0a 20  e["<lemmas>"]:. 
5930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5940: 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20     if bDebug:.  
5950: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5960: 20 20 20 20 20 20 70 72 69 6e 74 28 22 20 20 4d        print("  M
5970: 41 54 43 48 3a 20 3e 22 20 2b 20 73 4c 65 6d 6d  ATCH: >" + sLemm
5980: 61 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  a).             
5990: 20 20 20 20 20 20 20 79 69 65 6c 64 20 64 47 72         yield dGr
59a0: 61 70 68 5b 64 4e 6f 64 65 5b 22 3c 6c 65 6d 6d  aph[dNode["<lemm
59b0: 61 73 3e 22 5d 5b 73 4c 65 6d 6d 61 5d 5d 0a 20  as>"][sLemma]]. 
59c0: 20 20 20 20 20 20 20 23 20 72 65 67 65 78 20 76         # regex v
59d0: 61 6c 75 65 20 61 72 63 73 0a 20 20 20 20 20 20  alue arcs.      
59e0: 20 20 69 66 20 22 3c 72 65 5f 76 61 6c 75 65 3e    if "<re_value>
59f0: 22 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20 20  " in dNode:.    
5a00: 20 20 20 20 20 20 20 20 66 6f 72 20 73 52 65 67          for sReg
5a10: 65 78 20 69 6e 20 64 4e 6f 64 65 5b 22 3c 72 65  ex in dNode["<re
5a20: 5f 76 61 6c 75 65 3e 22 5d 3a 0a 20 20 20 20 20  _value>"]:.     
5a30: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 22 c2             if ".
5a40: ac 22 20 6e 6f 74 20 69 6e 20 73 52 65 67 65 78  ." not in sRegex
5a50: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
5a60: 20 20 20 20 20 20 23 20 6e 6f 20 61 6e 74 69 2d        # no anti-
5a70: 70 61 74 74 65 72 6e 0a 20 20 20 20 20 20 20 20  pattern.        
5a80: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 72              if r
5a90: 65 2e 73 65 61 72 63 68 28 73 52 65 67 65 78 2c  e.search(sRegex,
5aa0: 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22   dToken["sValue"
5ab0: 5d 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ]):.            
5ac0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62              if b
5ad0: 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20  Debug:.         
5ae0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5af0: 20 20 20 70 72 69 6e 74 28 22 20 20 4d 41 54 43     print("  MATC
5b00: 48 3a 20 7e 22 20 2b 20 73 52 65 67 65 78 29 0a  H: ~" + sRegex).
5b10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5b20: 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 64 47          yield dG
5b30: 72 61 70 68 5b 64 4e 6f 64 65 5b 22 3c 72 65 5f  raph[dNode["<re_
5b40: 76 61 6c 75 65 3e 22 5d 5b 73 52 65 67 65 78 5d  value>"][sRegex]
5b50: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ].              
5b60: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
5b70: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 74 68              # th
5b80: 65 72 65 20 69 73 20 61 6e 20 61 6e 74 69 2d 70  ere is an anti-p
5b90: 61 74 74 65 72 6e 0a 20 20 20 20 20 20 20 20 20  attern.         
5ba0: 20 20 20 20 20 20 20 20 20 20 20 73 50 61 74 74             sPatt
5bb0: 65 72 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e  ern, sNegPattern
5bc0: 20 3d 20 73 52 65 67 65 78 2e 73 70 6c 69 74 28   = sRegex.split(
5bd0: 22 c2 ac 22 2c 20 31 29 0a 20 20 20 20 20 20 20  "..", 1).       
5be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
5bf0: 73 4e 65 67 50 61 74 74 65 72 6e 20 61 6e 64 20  sNegPattern and 
5c00: 72 65 2e 73 65 61 72 63 68 28 73 4e 65 67 50 61  re.search(sNegPa
5c10: 74 74 65 72 6e 2c 20 64 54 6f 6b 65 6e 5b 22 73  ttern, dToken["s
5c20: 56 61 6c 75 65 22 5d 29 3a 0a 20 20 20 20 20 20  Value"]):.      
5c30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5c40: 20 20 63 6f 6e 74 69 6e 75 65 0a 20 20 20 20 20    continue.     
5c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
5c60: 66 20 6e 6f 74 20 73 50 61 74 74 65 72 6e 20 6f  f not sPattern o
5c70: 72 20 72 65 2e 73 65 61 72 63 68 28 73 50 61 74  r re.search(sPat
5c80: 74 65 72 6e 2c 20 64 54 6f 6b 65 6e 5b 22 73 56  tern, dToken["sV
5c90: 61 6c 75 65 22 5d 29 3a 0a 20 20 20 20 20 20 20  alue"]):.       
5ca0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5cb0: 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20   if bDebug:.    
5cc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5cd0: 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 20          print(" 
5ce0: 20 4d 41 54 43 48 3a 20 7e 22 20 2b 20 73 52 65   MATCH: ~" + sRe
5cf0: 67 65 78 29 0a 20 20 20 20 20 20 20 20 20 20 20  gex).           
5d00: 20 20 20 20 20 20 20 20 20 20 20 20 20 79 69 65               yie
5d10: 6c 64 20 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b  ld dGraph[dNode[
5d20: 22 3c 72 65 5f 76 61 6c 75 65 3e 22 5d 5b 73 52  "<re_value>"][sR
5d30: 65 67 65 78 5d 5d 0a 20 20 20 20 20 20 20 20 23  egex]].        #
5d40: 20 72 65 67 65 78 20 6d 6f 72 70 68 20 61 72 63   regex morph arc
5d50: 73 0a 20 20 20 20 20 20 20 20 69 66 20 22 3c 72  s.        if "<r
5d60: 65 5f 6d 6f 72 70 68 3e 22 20 69 6e 20 64 4e 6f  e_morph>" in dNo
5d70: 64 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  de:.            
5d80: 66 6f 72 20 73 52 65 67 65 78 20 69 6e 20 64 4e  for sRegex in dN
5d90: 6f 64 65 5b 22 3c 72 65 5f 6d 6f 72 70 68 3e 22  ode["<re_morph>"
5da0: 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]:.             
5db0: 20 20 20 69 66 20 22 c2 ac 22 20 6e 6f 74 20 69     if ".." not i
5dc0: 6e 20 73 52 65 67 65 78 3a 0a 20 20 20 20 20 20  n sRegex:.      
5dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
5de0: 6e 6f 20 61 6e 74 69 2d 70 61 74 74 65 72 6e 0a  no anti-pattern.
5df0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e00: 20 20 20 20 69 66 20 61 6e 79 28 72 65 2e 73 65      if any(re.se
5e10: 61 72 63 68 28 73 52 65 67 65 78 2c 20 73 4d 6f  arch(sRegex, sMo
5e20: 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70 68  rph)  for sMorph
5e30: 20 69 6e 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b   in _oSpellCheck
5e40: 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b  er.getMorph(dTok
5e50: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 29 3a 0a  en["sValue"])):.
5e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e70: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
5e80: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  g:.             
5e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
5ea0: 72 69 6e 74 28 22 20 20 4d 41 54 43 48 3a 20 40  rint("  MATCH: @
5eb0: 22 20 2b 20 73 52 65 67 65 78 29 0a 20 20 20 20  " + sRegex).    
5ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ed0: 20 20 20 20 79 69 65 6c 64 20 64 47 72 61 70 68      yield dGraph
5ee0: 5b 64 4e 6f 64 65 5b 22 3c 72 65 5f 6d 6f 72 70  [dNode["<re_morp
5ef0: 68 3e 22 5d 5b 73 52 65 67 65 78 5d 5d 0a 20 20  h>"][sRegex]].  
5f00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c                el
5f10: 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
5f20: 20 20 20 20 20 20 20 20 23 20 74 68 65 72 65 20          # there 
5f30: 69 73 20 61 6e 20 61 6e 74 69 2d 70 61 74 74 65  is an anti-patte
5f40: 72 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  rn.             
5f50: 20 20 20 20 20 20 20 73 50 61 74 74 65 72 6e 2c         sPattern,
5f60: 20 73 4e 65 67 50 61 74 74 65 72 6e 20 3d 20 73   sNegPattern = s
5f70: 52 65 67 65 78 2e 73 70 6c 69 74 28 22 c2 ac 22  Regex.split(".."
5f80: 2c 20 31 29 0a 20 20 20 20 20 20 20 20 20 20 20  , 1).           
5f90: 20 20 20 20 20 20 20 20 20 69 66 20 73 4e 65 67           if sNeg
5fa0: 50 61 74 74 65 72 6e 20 3d 3d 20 22 2a 22 3a 0a  Pattern == "*":.
5fb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5fc0: 20 20 20 20 20 20 20 20 23 20 61 6c 6c 20 6d 6f          # all mo
5fd0: 72 70 68 6f 6c 6f 67 69 65 73 20 6d 75 73 74 20  rphologies must 
5fe0: 6d 61 74 63 68 20 77 69 74 68 20 3c 73 50 61 74  match with <sPat
5ff0: 74 65 72 6e 3e 0a 20 20 20 20 20 20 20 20 20 20  tern>.          
6000: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
6010: 20 73 50 61 74 74 65 72 6e 20 61 6e 64 20 61 6c   sPattern and al
6020: 6c 28 72 65 2e 73 65 61 72 63 68 28 73 50 61 74  l(re.search(sPat
6030: 74 65 72 6e 2c 20 73 4d 6f 72 70 68 29 20 20 66  tern, sMorph)  f
6040: 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 5f 6f 53  or sMorph in _oS
6050: 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d  pellChecker.getM
6060: 6f 72 70 68 28 64 54 6f 6b 65 6e 5b 22 73 56 61  orph(dToken["sVa
6070: 6c 75 65 22 5d 29 29 3a 0a 20 20 20 20 20 20 20  lue"])):.       
6080: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6090: 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a       if bDebug:.
60a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
60b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
60c0: 70 72 69 6e 74 28 22 20 20 4d 41 54 43 48 3a 20  print("  MATCH: 
60d0: 40 22 20 2b 20 73 52 65 67 65 78 29 0a 20 20 20  @" + sRegex).   
60e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
60f0: 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 64           yield d
6100: 47 72 61 70 68 5b 64 4e 6f 64 65 5b 22 3c 72 65  Graph[dNode["<re
6110: 5f 6d 6f 72 70 68 3e 22 5d 5b 73 52 65 67 65 78  _morph>"][sRegex
6120: 5d 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]].             
6130: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
6140: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6150: 20 20 20 20 20 69 66 20 73 4e 65 67 50 61 74 74       if sNegPatt
6160: 65 72 6e 20 61 6e 64 20 61 6e 79 28 72 65 2e 73  ern and any(re.s
6170: 65 61 72 63 68 28 73 4e 65 67 50 61 74 74 65 72  earch(sNegPatter
6180: 6e 2c 20 73 4d 6f 72 70 68 29 20 20 66 6f 72 20  n, sMorph)  for 
6190: 73 4d 6f 72 70 68 20 69 6e 20 5f 6f 53 70 65 6c  sMorph in _oSpel
61a0: 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70  lChecker.getMorp
61b0: 68 28 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65  h(dToken["sValue
61c0: 22 5d 29 29 3a 0a 20 20 20 20 20 20 20 20 20 20  "])):.          
61d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
61e0: 20 20 63 6f 6e 74 69 6e 75 65 0a 20 20 20 20 20    continue.     
61f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6200: 20 20 20 69 66 20 6e 6f 74 20 73 50 61 74 74 65     if not sPatte
6210: 72 6e 20 6f 72 20 61 6e 79 28 72 65 2e 73 65 61  rn or any(re.sea
6220: 72 63 68 28 73 50 61 74 74 65 72 6e 2c 20 73 4d  rch(sPattern, sM
6230: 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70  orph)  for sMorp
6240: 68 20 69 6e 20 5f 6f 53 70 65 6c 6c 43 68 65 63  h in _oSpellChec
6250: 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f  ker.getMorph(dTo
6260: 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 29 3a  ken["sValue"])):
6270: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6280: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
6290: 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20  bDebug:.        
62a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
62b0: 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 20          print(" 
62c0: 20 4d 41 54 43 48 3a 20 40 22 20 2b 20 73 52 65   MATCH: @" + sRe
62d0: 67 65 78 29 0a 20 20 20 20 20 20 20 20 20 20 20  gex).           
62e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
62f0: 20 79 69 65 6c 64 20 64 47 72 61 70 68 5b 64 4e   yield dGraph[dN
6300: 6f 64 65 5b 22 3c 72 65 5f 6d 6f 72 70 68 3e 22  ode["<re_morph>"
6310: 5d 5b 73 52 65 67 65 78 5d 5d 0a 20 20 20 20 20  ][sRegex]].     
6320: 20 20 20 23 20 6d 65 74 61 20 61 72 63 20 28 66     # meta arc (f
6330: 6f 72 20 74 6f 6b 65 6e 20 74 79 70 65 29 0a 20  or token type). 
6340: 20 20 20 20 20 20 20 69 66 20 22 3c 6d 65 74 61         if "<meta
6350: 3e 22 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20  >" in dNode:.   
6360: 20 20 20 20 20 20 20 20 20 66 6f 72 20 73 4d 65           for sMe
6370: 74 61 20 69 6e 20 64 4e 6f 64 65 5b 22 3c 6d 65  ta in dNode["<me
6380: 74 61 3e 22 5d 3a 0a 20 20 20 20 20 20 20 20 20  ta>"]:.         
6390: 20 20 20 20 20 20 20 23 20 6e 6f 74 20 72 65 67         # not reg
63a0: 65 78 20 68 65 72 65 2c 20 77 65 20 6a 75 73 74  ex here, we just
63b0: 20 73 65 61 72 63 68 20 69 66 20 3c 64 4e 6f 64   search if <dNod
63c0: 65 5b 22 73 54 79 70 65 22 5d 3e 20 65 78 69 73  e["sType"]> exis
63d0: 74 73 20 77 69 74 68 69 6e 20 3c 73 4d 65 74 61  ts within <sMeta
63e0: 3e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  >.              
63f0: 20 20 69 66 20 73 4d 65 74 61 20 3d 3d 20 22 2a    if sMeta == "*
6400: 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ":.             
6410: 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67         if bDebug
6420: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
6430: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28            print(
6440: 22 20 20 4d 41 54 43 48 3a 20 2a 22 20 2b 20 73  "  MATCH: *" + s
6450: 4d 65 74 61 29 0a 20 20 20 20 20 20 20 20 20 20  Meta).          
6460: 20 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20            yield 
6470: 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b 22 3c 6d  dGraph[dNode["<m
6480: 65 74 61 3e 22 5d 5b 22 2a 22 5d 5d 0a 20 20 20  eta>"]["*"]].   
6490: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69               eli
64a0: 66 20 22 c2 ac 22 20 69 6e 20 73 4d 65 74 61 3a  f ".." in sMeta:
64b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
64c0: 20 20 20 20 20 69 66 20 64 4e 6f 64 65 5b 22 73       if dNode["s
64d0: 54 79 70 65 22 5d 20 6e 6f 74 20 69 6e 20 73 4d  Type"] not in sM
64e0: 65 74 61 3a 0a 20 20 20 20 20 20 20 20 20 20 20  eta:.           
64f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
6500: 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20  bDebug:.        
6510: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6520: 20 20 20 20 70 72 69 6e 74 28 22 20 20 4d 41 54      print("  MAT
6530: 43 48 3a 20 2a 22 20 2b 20 73 4d 65 74 61 29 0a  CH: *" + sMeta).
6540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6550: 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 64 47          yield dG
6560: 72 61 70 68 5b 64 4e 6f 64 65 5b 22 3c 6d 65 74  raph[dNode["<met
6570: 61 3e 22 5d 5b 73 4d 65 74 61 5d 5d 0a 20 20 20  a>"][sMeta]].   
6580: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69               eli
6590: 66 20 64 4e 6f 64 65 5b 22 73 54 79 70 65 22 5d  f dNode["sType"]
65a0: 20 69 6e 20 73 4d 65 74 61 3a 0a 20 20 20 20 20   in sMeta:.     
65b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
65c0: 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20  f bDebug:.      
65d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
65e0: 20 20 70 72 69 6e 74 28 22 20 20 4d 41 54 43 48    print("  MATCH
65f0: 3a 20 2a 22 20 2b 20 73 4d 65 74 61 29 0a 20 20  : *" + sMeta).  
6600: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6610: 20 20 79 69 65 6c 64 20 64 47 72 61 70 68 5b 64    yield dGraph[d
6620: 4e 6f 64 65 5b 22 3c 6d 65 74 61 3e 22 5d 5b 73  Node["<meta>"][s
6630: 4d 65 74 61 5d 5d 0a 0a 0a 20 20 20 20 64 65 66  Meta]]...    def
6640: 20 70 61 72 73 65 20 28 73 65 6c 66 2c 20 64 47   parse (self, dG
6650: 72 61 70 68 2c 20 64 50 72 69 6f 72 69 74 79 2c  raph, dPriority,
6660: 20 73 43 6f 75 6e 74 72 79 3d 22 24 7b 63 6f 75   sCountry="${cou
6670: 6e 74 72 79 5f 64 65 66 61 75 6c 74 7d 22 2c 20  ntry_default}", 
6680: 64 4f 70 74 69 6f 6e 73 3d 4e 6f 6e 65 2c 20 62  dOptions=None, b
6690: 53 68 6f 77 52 75 6c 65 49 64 3d 46 61 6c 73 65  ShowRuleId=False
66a0: 2c 20 62 44 65 62 75 67 3d 46 61 6c 73 65 2c 20  , bDebug=False, 
66b0: 62 43 6f 6e 74 65 78 74 3d 46 61 6c 73 65 29 3a  bContext=False):
66c0: 0a 20 20 20 20 20 20 20 20 22 70 61 72 73 65 20  .        "parse 
66d0: 74 6f 6b 65 6e 73 20 66 72 6f 6d 20 74 68 65 20  tokens from the 
66e0: 74 65 78 74 20 61 6e 64 20 65 78 65 63 75 74 65  text and execute
66f0: 20 61 63 74 69 6f 6e 73 20 65 6e 63 6f 75 6e 74   actions encount
6700: 65 72 65 64 22 0a 20 20 20 20 20 20 20 20 73 65  ered".        se
6710: 6c 66 2e 64 45 72 72 6f 72 20 3d 20 7b 7d 0a 20  lf.dError = {}. 
6720: 20 20 20 20 20 20 20 64 50 72 69 6f 72 69 74 79         dPriority
6730: 20 3d 20 7b 7d 20 20 23 20 4b 65 79 20 3d 20 70   = {}  # Key = p
6740: 6f 73 69 74 69 6f 6e 3b 20 76 61 6c 75 65 20 3d  osition; value =
6750: 20 70 72 69 6f 72 69 74 79 0a 20 20 20 20 20 20   priority.      
6760: 20 20 64 4f 70 74 20 3d 20 5f 64 4f 70 74 69 6f    dOpt = _dOptio
6770: 6e 73 20 20 69 66 20 6e 6f 74 20 64 4f 70 74 69  ns  if not dOpti
6780: 6f 6e 73 20 20 65 6c 73 65 20 64 4f 70 74 69 6f  ons  else dOptio
6790: 6e 73 0a 20 20 20 20 20 20 20 20 6c 50 6f 69 6e  ns.        lPoin
67a0: 74 65 72 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20  ter = [].       
67b0: 20 62 54 61 67 41 6e 64 52 65 77 72 69 74 65 20   bTagAndRewrite 
67c0: 3d 20 46 61 6c 73 65 0a 20 20 20 20 20 20 20 20  = False.        
67d0: 66 6f 72 20 64 54 6f 6b 65 6e 20 69 6e 20 73 65  for dToken in se
67e0: 6c 66 2e 6c 54 6f 6b 65 6e 3a 0a 20 20 20 20 20  lf.lToken:.     
67f0: 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67         if bDebug
6800: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
6810: 20 20 70 72 69 6e 74 28 22 54 4f 4b 45 4e 3a 22    print("TOKEN:"
6820: 2c 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65  , dToken["sValue
6830: 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  "]).            
6840: 23 20 63 68 65 63 6b 20 61 72 63 73 20 66 6f 72  # check arcs for
6850: 20 65 61 63 68 20 65 78 69 73 74 69 6e 67 20 70   each existing p
6860: 6f 69 6e 74 65 72 0a 20 20 20 20 20 20 20 20 20  ointer.         
6870: 20 20 20 6c 4e 65 78 74 50 6f 69 6e 74 65 72 20     lNextPointer 
6880: 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 20 20 20  = [].           
6890: 20 66 6f 72 20 64 50 6f 69 6e 74 65 72 20 69 6e   for dPointer in
68a0: 20 6c 50 6f 69 6e 74 65 72 3a 0a 20 20 20 20 20   lPointer:.     
68b0: 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 64             for d
68c0: 4e 6f 64 65 20 69 6e 20 73 65 6c 66 2e 5f 67 65  Node in self._ge
68d0: 74 4e 65 78 74 4d 61 74 63 68 69 6e 67 4e 6f 64  tNextMatchingNod
68e0: 65 73 28 64 54 6f 6b 65 6e 2c 20 64 47 72 61 70  es(dToken, dGrap
68f0: 68 2c 20 64 50 6f 69 6e 74 65 72 5b 22 64 4e 6f  h, dPointer["dNo
6900: 64 65 22 5d 2c 20 62 44 65 62 75 67 29 3a 0a 20  de"], bDebug):. 
6910: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6920: 20 20 20 6c 4e 65 78 74 50 6f 69 6e 74 65 72 2e     lNextPointer.
6930: 61 70 70 65 6e 64 28 7b 22 69 54 6f 6b 65 6e 22  append({"iToken"
6940: 3a 20 64 50 6f 69 6e 74 65 72 5b 22 69 54 6f 6b  : dPointer["iTok
6950: 65 6e 22 5d 2c 20 22 64 4e 6f 64 65 22 3a 20 64  en"], "dNode": d
6960: 4e 6f 64 65 7d 29 0a 20 20 20 20 20 20 20 20 20  Node}).         
6970: 20 20 20 6c 50 6f 69 6e 74 65 72 20 3d 20 6c 4e     lPointer = lN
6980: 65 78 74 50 6f 69 6e 74 65 72 0a 20 20 20 20 20  extPointer.     
6990: 20 20 20 20 20 20 20 23 20 63 68 65 63 6b 20 61         # check a
69a0: 72 63 73 20 6f 66 20 66 69 72 73 74 20 6e 6f 64  rcs of first nod
69b0: 65 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 66  es.            f
69c0: 6f 72 20 64 4e 6f 64 65 20 69 6e 20 73 65 6c 66  or dNode in self
69d0: 2e 5f 67 65 74 4e 65 78 74 4d 61 74 63 68 69 6e  ._getNextMatchin
69e0: 67 4e 6f 64 65 73 28 64 54 6f 6b 65 6e 2c 20 64  gNodes(dToken, d
69f0: 47 72 61 70 68 2c 20 64 47 72 61 70 68 5b 30 5d  Graph, dGraph[0]
6a00: 2c 20 62 44 65 62 75 67 29 3a 0a 20 20 20 20 20  , bDebug):.     
6a10: 20 20 20 20 20 20 20 20 20 20 20 6c 50 6f 69 6e             lPoin
6a20: 74 65 72 2e 61 70 70 65 6e 64 28 7b 22 69 54 6f  ter.append({"iTo
6a30: 6b 65 6e 22 3a 20 64 54 6f 6b 65 6e 5b 22 69 22  ken": dToken["i"
6a40: 5d 2c 20 22 64 4e 6f 64 65 22 3a 20 64 4e 6f 64  ], "dNode": dNod
6a50: 65 7d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  e}).            
6a60: 23 20 63 68 65 63 6b 20 69 66 20 74 68 65 72 65  # check if there
6a70: 20 69 73 20 72 75 6c 65 73 20 74 6f 20 63 68 65   is rules to che
6a80: 63 6b 20 66 6f 72 20 65 61 63 68 20 70 6f 69 6e  ck for each poin
6a90: 74 65 72 0a 20 20 20 20 20 20 20 20 20 20 20 20  ter.            
6aa0: 66 6f 72 20 64 50 6f 69 6e 74 65 72 20 69 6e 20  for dPointer in 
6ab0: 6c 50 6f 69 6e 74 65 72 3a 0a 20 20 20 20 20 20  lPointer:.      
6ac0: 20 20 20 20 20 20 20 20 20 20 23 69 66 20 62 44            #if bD
6ad0: 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20  ebug:.          
6ae0: 20 20 20 20 20 20 23 20 20 20 20 70 72 69 6e 74        #    print
6af0: 28 22 2b 22 2c 20 64 50 6f 69 6e 74 65 72 29 0a  ("+", dPointer).
6b00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6b10: 69 66 20 22 3c 72 75 6c 65 73 3e 22 20 69 6e 20  if "<rules>" in 
6b20: 64 50 6f 69 6e 74 65 72 5b 22 64 4e 6f 64 65 22  dPointer["dNode"
6b30: 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]:.             
6b40: 20 20 20 20 20 20 20 62 43 68 61 6e 67 65 2c 20         bChange, 
6b50: 64 45 72 72 20 3d 20 73 65 6c 66 2e 5f 65 78 65  dErr = self._exe
6b60: 63 75 74 65 41 63 74 69 6f 6e 73 28 64 47 72 61  cuteActions(dGra
6b70: 70 68 2c 20 64 50 6f 69 6e 74 65 72 5b 22 64 4e  ph, dPointer["dN
6b80: 6f 64 65 22 5d 5b 22 3c 72 75 6c 65 73 3e 22 5d  ode"]["<rules>"]
6b90: 2c 20 64 50 6f 69 6e 74 65 72 5b 22 69 54 6f 6b  , dPointer["iTok
6ba0: 65 6e 22 5d 2d 31 2c 20 64 54 6f 6b 65 6e 5b 22  en"]-1, dToken["
6bb0: 69 22 5d 2c 20 64 50 72 69 6f 72 69 74 79 2c 20  i"], dPriority, 
6bc0: 64 4f 70 74 2c 20 73 43 6f 75 6e 74 72 79 2c 20  dOpt, sCountry, 
6bd0: 62 53 68 6f 77 52 75 6c 65 49 64 2c 20 62 44 65  bShowRuleId, bDe
6be0: 62 75 67 2c 20 62 43 6f 6e 74 65 78 74 29 0a 20  bug, bContext). 
6bf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c00: 20 20 20 73 65 6c 66 2e 64 45 72 72 6f 72 2e 75     self.dError.u
6c10: 70 64 61 74 65 28 64 45 72 72 29 0a 20 20 20 20  pdate(dErr).    
6c20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c30: 69 66 20 62 43 68 61 6e 67 65 3a 0a 20 20 20 20  if bChange:.    
6c40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6c50: 20 20 20 20 62 54 61 67 41 6e 64 52 65 77 72 69      bTagAndRewri
6c60: 74 65 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20  te = True.      
6c70: 20 20 69 66 20 62 54 61 67 41 6e 64 52 65 77 72    if bTagAndRewr
6c80: 69 74 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ite:.           
6c90: 20 73 65 6c 66 2e 72 65 77 72 69 74 65 28 62 44   self.rewrite(bD
6ca0: 65 62 75 67 29 0a 20 20 20 20 20 20 20 20 72 65  ebug).        re
6cb0: 74 75 72 6e 20 28 62 54 61 67 41 6e 64 52 65 77  turn (bTagAndRew
6cc0: 72 69 74 65 2c 20 73 65 6c 66 2e 73 53 65 6e 74  rite, self.sSent
6cd0: 65 6e 63 65 29 0a 0a 20 20 20 20 64 65 66 20 5f  ence)..    def _
6ce0: 65 78 65 63 75 74 65 41 63 74 69 6f 6e 73 20 28  executeActions (
6cf0: 73 65 6c 66 2c 20 64 47 72 61 70 68 2c 20 64 4e  self, dGraph, dN
6d00: 6f 64 65 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65  ode, nTokenOffse
6d10: 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 2c 20 64  t, nLastToken, d
6d20: 50 72 69 6f 72 69 74 79 2c 20 64 4f 70 74 69 6f  Priority, dOptio
6d30: 6e 73 2c 20 73 43 6f 75 6e 74 72 79 2c 20 62 53  ns, sCountry, bS
6d40: 68 6f 77 52 75 6c 65 49 64 2c 20 62 44 65 62 75  howRuleId, bDebu
6d50: 67 2c 20 62 43 6f 6e 74 65 78 74 29 3a 0a 20 20  g, bContext):.  
6d60: 20 20 20 20 20 20 22 65 78 65 63 75 74 65 20 61        "execute a
6d70: 63 74 69 6f 6e 73 20 66 6f 75 6e 64 20 69 6e 20  ctions found in 
6d80: 74 68 65 20 44 41 52 47 22 0a 20 20 20 20 20 20  the DARG".      
6d90: 20 20 64 45 72 72 6f 72 20 3d 20 7b 7d 0a 20 20    dError = {}.  
6da0: 20 20 20 20 20 20 62 43 68 61 6e 67 65 20 3d 20        bChange = 
6db0: 46 61 6c 73 65 0a 20 20 20 20 20 20 20 20 66 6f  False.        fo
6dc0: 72 20 73 4c 69 6e 65 49 64 2c 20 6e 65 78 74 4e  r sLineId, nextN
6dd0: 6f 64 65 4b 65 79 20 69 6e 20 64 4e 6f 64 65 2e  odeKey in dNode.
6de0: 69 74 65 6d 73 28 29 3a 0a 20 20 20 20 20 20 20  items():.       
6df0: 20 20 20 20 20 62 43 6f 6e 64 4d 65 6d 6f 20 3d       bCondMemo =
6e00: 20 4e 6f 6e 65 0a 20 20 20 20 20 20 20 20 20 20   None.          
6e10: 20 20 66 6f 72 20 73 52 75 6c 65 49 64 20 69 6e    for sRuleId in
6e20: 20 64 47 72 61 70 68 5b 6e 65 78 74 4e 6f 64 65   dGraph[nextNode
6e30: 4b 65 79 5d 3a 0a 20 20 20 20 20 20 20 20 20 20  Key]:.          
6e40: 20 20 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20        try:.     
6e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
6e60: 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20  f bDebug:.      
6e70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6e80: 20 20 70 72 69 6e 74 28 22 41 43 54 49 4f 4e 3a    print("ACTION:
6e90: 22 2c 20 73 52 75 6c 65 49 64 29 0a 20 20 20 20  ", sRuleId).    
6ea0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6eb0: 20 20 20 20 70 72 69 6e 74 28 64 52 75 6c 65 5b      print(dRule[
6ec0: 73 52 75 6c 65 49 64 5d 29 0a 20 20 20 20 20 20  sRuleId]).      
6ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 4f                sO
6ee0: 70 74 69 6f 6e 2c 20 73 46 75 6e 63 43 6f 6e 64  ption, sFuncCond
6ef0: 2c 20 63 41 63 74 69 6f 6e 54 79 70 65 2c 20 73  , cActionType, s
6f00: 57 68 61 74 2c 20 2a 65 41 63 74 20 3d 20 64 52  What, *eAct = dR
6f10: 75 6c 65 5b 73 52 75 6c 65 49 64 5d 0a 20 20 20  ule[sRuleId].   
6f20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6f30: 20 23 20 53 75 67 67 65 73 74 69 6f 6e 20 20 20   # Suggestion   
6f40: 20 5b 20 6f 70 74 69 6f 6e 2c 20 63 6f 6e 64 69   [ option, condi
6f50: 74 69 6f 6e 2c 20 22 2d 22 2c 20 72 65 70 6c 61  tion, "-", repla
6f60: 63 65 6d 65 6e 74 2f 73 75 67 67 65 73 74 69 6f  cement/suggestio
6f70: 6e 2f 61 63 74 69 6f 6e 2c 20 69 54 6f 6b 65 6e  n/action, iToken
6f80: 53 74 61 72 74 2c 20 69 54 6f 6b 65 6e 45 6e 64  Start, iTokenEnd
6f90: 2c 20 6e 50 72 69 6f 72 69 74 79 2c 20 6d 65 73  , nPriority, mes
6fa0: 73 61 67 65 2c 20 55 52 4c 20 5d 0a 20 20 20 20  sage, URL ].    
6fb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6fc0: 23 20 54 65 78 74 50 72 6f 63 65 73 73 6f 72 20  # TextProcessor 
6fd0: 5b 20 6f 70 74 69 6f 6e 2c 20 63 6f 6e 64 69 74  [ option, condit
6fe0: 69 6f 6e 2c 20 22 7e 22 2c 20 72 65 70 6c 61 63  ion, "~", replac
6ff0: 65 6d 65 6e 74 2f 73 75 67 67 65 73 74 69 6f 6e  ement/suggestion
7000: 2f 61 63 74 69 6f 6e 2c 20 69 54 6f 6b 65 6e 53  /action, iTokenS
7010: 74 61 72 74 2c 20 69 54 6f 6b 65 6e 45 6e 64 20  tart, iTokenEnd 
7020: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ].              
7030: 20 20 20 20 20 20 23 20 44 69 73 61 6d 62 69 67        # Disambig
7040: 75 61 74 6f 72 20 5b 20 6f 70 74 69 6f 6e 2c 20  uator [ option, 
7050: 63 6f 6e 64 69 74 69 6f 6e 2c 20 22 3d 22 2c 20  condition, "=", 
7060: 72 65 70 6c 61 63 65 6d 65 6e 74 2f 73 75 67 67  replacement/sugg
7070: 65 73 74 69 6f 6e 2f 61 63 74 69 6f 6e 20 5d 0a  estion/action ].
7080: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7090: 20 20 20 20 23 20 53 65 6e 74 65 6e 63 65 20 54      # Sentence T
70a0: 61 67 20 20 5b 20 6f 70 74 69 6f 6e 2c 20 63 6f  ag  [ option, co
70b0: 6e 64 69 74 69 6f 6e 2c 20 22 2f 22 2c 20 72 65  ndition, "/", re
70c0: 70 6c 61 63 65 6d 65 6e 74 2f 73 75 67 67 65 73  placement/sugges
70d0: 74 69 6f 6e 2f 61 63 74 69 6f 6e 2c 20 69 54 6f  tion/action, iTo
70e0: 6b 65 6e 53 74 61 72 74 2c 20 69 54 6f 6b 65 6e  kenStart, iToken
70f0: 45 6e 64 20 5d 0a 20 20 20 20 20 20 20 20 20 20  End ].          
7100: 20 20 20 20 20 20 20 20 20 20 23 20 54 65 73 74            # Test
7110: 20 20 20 20 20 20 20 20 20 20 5b 20 6f 70 74 69            [ opti
7120: 6f 6e 2c 20 63 6f 6e 64 69 74 69 6f 6e 2c 20 22  on, condition, "
7130: 3e 22 2c 20 22 22 20 5d 0a 20 20 20 20 20 20 20  >", "" ].       
7140: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
7150: 6e 6f 74 20 73 4f 70 74 69 6f 6e 20 6f 72 20 64  not sOption or d
7160: 4f 70 74 69 6f 6e 73 2e 67 65 74 28 73 4f 70 74  Options.get(sOpt
7170: 69 6f 6e 2c 20 46 61 6c 73 65 29 3a 0a 20 20 20  ion, False):.   
7180: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7190: 20 20 20 20 20 62 43 6f 6e 64 4d 65 6d 6f 20 3d       bCondMemo =
71a0: 20 6e 6f 74 20 73 46 75 6e 63 43 6f 6e 64 20 6f   not sFuncCond o
71b0: 72 20 67 6c 6f 62 61 6c 73 28 29 5b 73 46 75 6e  r globals()[sFun
71c0: 63 43 6f 6e 64 5d 28 73 65 6c 66 2e 6c 54 6f 6b  cCond](self.lTok
71d0: 65 6e 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74  en, nTokenOffset
71e0: 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 2c 20 73 43  , nLastToken, sC
71f0: 6f 75 6e 74 72 79 2c 20 62 43 6f 6e 64 4d 65 6d  ountry, bCondMem
7200: 6f 2c 20 73 65 6c 66 2e 64 54 61 67 73 2c 20 73  o, self.dTags, s
7210: 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65 2c 20 73  elf.sSentence, s
7220: 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65 30 29 0a  elf.sSentence0).
7230: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7240: 20 20 20 20 20 20 20 20 69 66 20 62 43 6f 6e 64          if bCond
7250: 4d 65 6d 6f 3a 0a 20 20 20 20 20 20 20 20 20 20  Memo:.          
7260: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7270: 20 20 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65    if cActionType
7280: 20 3d 3d 20 22 2d 22 3a 0a 20 20 20 20 20 20 20   == "-":.       
7290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
72a0: 20 20 20 20 20 20 20 20 20 23 20 67 72 61 6d 6d           # gramm
72b0: 61 72 20 65 72 72 6f 72 0a 20 20 20 20 20 20 20  ar error.       
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 6e 54 6f 6b 65 6e 45           nTokenE
72e0: 72 72 6f 72 53 74 61 72 74 20 3d 20 6e 54 6f 6b  rrorStart = nTok
72f0: 65 6e 4f 66 66 73 65 74 20 2b 20 65 41 63 74 5b  enOffset + eAct[
7300: 30 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  0].             
7310: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7320: 20 20 20 69 66 20 22 62 49 6d 6d 75 6e 65 22 20     if "bImmune" 
7330: 6e 6f 74 20 69 6e 20 73 65 6c 66 2e 6c 54 6f 6b  not in self.lTok
7340: 65 6e 5b 6e 54 6f 6b 65 6e 45 72 72 6f 72 53 74  en[nTokenErrorSt
7350: 61 72 74 5d 3a 0a 20 20 20 20 20 20 20 20 20 20  art]:.          
7360: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7370: 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b 65 6e            nToken
7380: 45 72 72 6f 72 45 6e 64 20 3d 20 28 6e 54 6f 6b  ErrorEnd = (nTok
7390: 65 6e 4f 66 66 73 65 74 20 2b 20 65 41 63 74 5b  enOffset + eAct[
73a0: 31 5d 29 20 20 69 66 20 65 41 63 74 5b 31 5d 20  1])  if eAct[1] 
73b0: 20 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e   else nLastToken
73c0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
73d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
73e0: 20 20 20 20 20 6e 45 72 72 6f 72 53 74 61 72 74       nErrorStart
73f0: 20 3d 20 73 65 6c 66 2e 6e 4f 66 66 73 65 74 57   = self.nOffsetW
7400: 69 74 68 69 6e 50 61 72 61 67 72 61 70 68 20 2b  ithinParagraph +
7410: 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f   self.lToken[nTo
7420: 6b 65 6e 45 72 72 6f 72 53 74 61 72 74 5d 5b 22  kenErrorStart]["
7430: 6e 53 74 61 72 74 22 5d 0a 20 20 20 20 20 20 20  nStart"].       
7440: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7450: 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 45 72               nEr
7460: 72 6f 72 45 6e 64 20 3d 20 73 65 6c 66 2e 6e 4f  rorEnd = self.nO
7470: 66 66 73 65 74 57 69 74 68 69 6e 50 61 72 61 67  ffsetWithinParag
7480: 72 61 70 68 20 2b 20 73 65 6c 66 2e 6c 54 6f 6b  raph + self.lTok
7490: 65 6e 5b 6e 54 6f 6b 65 6e 45 72 72 6f 72 45 6e  en[nTokenErrorEn
74a0: 64 5d 5b 22 6e 45 6e 64 22 5d 0a 20 20 20 20 20  d]["nEnd"].     
74b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
74c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
74d0: 66 20 6e 45 72 72 6f 72 53 74 61 72 74 20 6e 6f  f nErrorStart no
74e0: 74 20 69 6e 20 64 45 72 72 6f 72 20 6f 72 20 65  t in dError or e
74f0: 41 63 74 5b 32 5d 20 3e 20 64 50 72 69 6f 72 69  Act[2] > dPriori
7500: 74 79 2e 67 65 74 28 6e 45 72 72 6f 72 53 74 61  ty.get(nErrorSta
7510: 72 74 2c 20 2d 31 29 3a 0a 20 20 20 20 20 20 20  rt, -1):.       
7520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7530: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7540: 20 64 45 72 72 6f 72 5b 6e 45 72 72 6f 72 53 74   dError[nErrorSt
7550: 61 72 74 5d 20 3d 20 73 65 6c 66 2e 63 72 65 61  art] = self.crea
7560: 74 65 45 72 72 6f 72 28 73 57 68 61 74 2c 20 6e  teError(sWhat, n
7570: 54 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 6e 54 6f  TokenOffset, nTo
7580: 6b 65 6e 45 72 72 6f 72 53 74 61 72 74 2c 20 6e  kenErrorStart, n
7590: 45 72 72 6f 72 53 74 61 72 74 2c 20 6e 45 72 72  ErrorStart, nErr
75a0: 6f 72 45 6e 64 2c 20 73 4c 69 6e 65 49 64 2c 20  orEnd, sLineId, 
75b0: 73 52 75 6c 65 49 64 2c 20 54 72 75 65 2c 20 65  sRuleId, True, e
75c0: 41 63 74 5b 33 5d 2c 20 65 41 63 74 5b 34 5d 2c  Act[3], eAct[4],
75d0: 20 62 53 68 6f 77 52 75 6c 65 49 64 2c 20 22 6e   bShowRuleId, "n
75e0: 6f 74 79 70 65 22 2c 20 62 43 6f 6e 74 65 78 74  otype", bContext
75f0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
7600: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7610: 20 20 20 20 20 20 20 20 20 20 64 50 72 69 6f 72            dPrior
7620: 69 74 79 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d  ity[nErrorStart]
7630: 20 3d 20 65 41 63 74 5b 32 5d 0a 20 20 20 20 20   = eAct[2].     
7640: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7650: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7660: 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20     if bDebug:.  
7670: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7680: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7690: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28            print(
76a0: 22 45 52 52 4f 52 3a 22 2c 20 73 52 75 6c 65 49  "ERROR:", sRuleI
76b0: 64 2c 20 64 45 72 72 6f 72 5b 6e 45 72 72 6f 72  d, dError[nError
76c0: 53 74 61 72 74 5d 29 0a 20 20 20 20 20 20 20 20  Start]).        
76d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
76e0: 20 20 20 20 65 6c 69 66 20 63 41 63 74 69 6f 6e      elif cAction
76f0: 54 79 70 65 20 3d 3d 20 22 7e 22 3a 0a 20 20 20  Type == "~":.   
7700: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7710: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 74               # t
7720: 65 78 74 20 70 72 6f 63 65 73 73 6f 72 0a 20 20  ext processor.  
7730: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 45                nE
7750: 6e 64 54 6f 6b 65 6e 20 3d 20 28 6e 54 6f 6b 65  ndToken = (nToke
7760: 6e 4f 66 66 73 65 74 20 2b 20 65 41 63 74 5b 31  nOffset + eAct[1
7770: 5d 29 20 20 69 66 20 65 41 63 74 5b 31 5d 20 20  ])  if eAct[1]  
7780: 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 0a  else nLastToken.
7790: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
77a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
77b0: 73 65 6c 66 2e 5f 74 61 67 41 6e 64 50 72 65 70  self._tagAndPrep
77c0: 61 72 65 54 6f 6b 65 6e 46 6f 72 52 65 77 72 69  areTokenForRewri
77d0: 74 69 6e 67 28 73 57 68 61 74 2c 20 6e 54 6f 6b  ting(sWhat, nTok
77e0: 65 6e 4f 66 66 73 65 74 20 2b 20 65 41 63 74 5b  enOffset + eAct[
77f0: 30 5d 2c 20 6e 45 6e 64 54 6f 6b 65 6e 2c 20 62  0], nEndToken, b
7800: 44 65 62 75 67 29 0a 20 20 20 20 20 20 20 20 20  Debug).         
7810: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7820: 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67         if bDebug
7830: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
7840: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7850: 20 20 20 20 20 20 70 72 69 6e 74 28 22 52 57 3a        print("RW:
7860: 22 2c 20 73 52 75 6c 65 49 64 29 0a 20 20 20 20  ", sRuleId).    
7870: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7880: 20 20 20 20 20 20 20 20 20 20 20 20 62 43 68 61              bCha
7890: 6e 67 65 20 3d 20 54 72 75 65 0a 20 20 20 20 20  nge = True.     
78a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
78b0: 20 20 20 20 20 20 20 65 6c 69 66 20 63 41 63 74         elif cAct
78c0: 69 6f 6e 54 79 70 65 20 3d 3d 20 22 3d 22 3a 0a  ionType == "=":.
78d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
78e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
78f0: 23 20 64 69 73 61 6d 62 69 67 75 61 74 69 6f 6e  # disambiguation
7900: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
7910: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7920: 20 67 6c 6f 62 61 6c 73 28 29 5b 73 57 68 61 74   globals()[sWhat
7930: 5d 28 73 65 6c 66 2e 6c 54 6f 6b 65 6e 2c 20 6e  ](self.lToken, n
7940: 54 6f 6b 65 6e 4f 66 66 73 65 74 29 0a 20 20 20  TokenOffset).   
7950: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7960: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
7970: 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20  bDebug:.        
7980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7990: 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e              prin
79a0: 74 28 22 44 41 3a 22 2c 20 73 52 75 6c 65 49 64  t("DA:", sRuleId
79b0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
79c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c                el
79d0: 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20 3d  if cActionType =
79e0: 3d 20 22 3e 22 3a 0a 20 20 20 20 20 20 20 20 20  = ">":.         
79f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7a00: 20 20 20 20 20 20 20 23 20 77 65 20 64 6f 20 6e         # we do n
7a10: 6f 74 68 69 6e 67 2c 20 74 68 69 73 20 74 65 73  othing, this tes
7a20: 74 20 69 73 20 6a 75 73 74 20 61 20 63 6f 6e 64  t is just a cond
7a30: 69 74 69 6f 6e 20 74 6f 20 61 70 70 6c 79 20 61  ition to apply a
7a40: 6c 6c 20 66 6f 6c 6c 6f 77 69 6e 67 20 61 63 74  ll following act
7a50: 69 6f 6e 73 0a 20 20 20 20 20 20 20 20 20 20 20  ions.           
7a60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7a70: 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a       if bDebug:.
7a80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7a90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7aa0: 20 20 20 20 70 72 69 6e 74 28 22 3e 3e 3e 22 2c      print(">>>",
7ab0: 20 73 52 75 6c 65 49 64 29 0a 20 20 20 20 20 20   sRuleId).      
7ac0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7ad0: 20 20 20 20 20 20 20 20 20 20 70 61 73 73 0a 20            pass. 
7ae0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7af0: 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66 20             elif 
7b00: 63 41 63 74 69 6f 6e 54 79 70 65 20 3d 3d 20 22  cActionType == "
7b10: 2f 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  /":.            
7b20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7b30: 20 20 20 20 23 20 74 61 67 73 0a 20 20 20 20 20      # tags.     
7b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7b50: 20 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b 65             nToke
7b60: 6e 54 61 67 20 3d 20 6e 54 6f 6b 65 6e 4f 66 66  nTag = nTokenOff
7b70: 73 65 74 20 2b 20 65 41 63 74 5b 30 5d 0a 20 20  set + eAct[0].  
7b80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7b90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
7ba0: 20 73 57 68 61 74 20 6e 6f 74 20 69 6e 20 73 65   sWhat not in se
7bb0: 6c 66 2e 64 54 61 67 73 3a 0a 20 20 20 20 20 20  lf.dTags:.      
7bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
7be0: 6c 66 2e 64 54 61 67 73 5b 73 57 68 61 74 5d 20  lf.dTags[sWhat] 
7bf0: 3d 20 28 6e 54 6f 6b 65 6e 54 61 67 2c 20 6e 54  = (nTokenTag, nT
7c00: 6f 6b 65 6e 54 61 67 29 0a 20 20 20 20 20 20 20  okenTag).       
7c10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7c20: 20 20 20 20 20 20 20 20 20 65 6c 69 66 20 6e 54           elif nT
7c30: 6f 6b 65 6e 54 61 67 20 3e 20 73 65 6c 66 2e 64  okenTag > self.d
7c40: 54 61 67 73 5b 73 57 68 61 74 5d 5b 31 5d 3a 0a  Tags[sWhat][1]:.
7c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7c60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7c70: 20 20 20 20 73 65 6c 66 2e 64 54 61 67 73 5b 73      self.dTags[s
7c80: 57 68 61 74 5d 20 3d 20 28 73 65 6c 66 2e 64 54  What] = (self.dT
7c90: 61 67 73 5b 73 57 68 61 74 5d 5b 30 5d 2c 20 6e  ags[sWhat][0], n
7ca0: 54 6f 6b 65 6e 54 61 67 29 0a 20 20 20 20 20 20  TokenTag).      
7cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7cc0: 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65            if bDe
7cd0: 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  bug:.           
7ce0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7cf0: 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22           print("
7d00: 2f 22 2c 20 73 52 75 6c 65 49 64 29 0a 20 20 20  /", sRuleId).   
7d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7d20: 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20           else:. 
7d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7d40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
7d50: 72 69 6e 74 28 22 23 20 65 72 72 6f 72 3a 20 75  rint("# error: u
7d60: 6e 6b 6e 6f 77 6e 20 61 63 74 69 6f 6e 20 61 74  nknown action at
7d70: 20 22 20 2b 20 73 4c 69 6e 65 49 64 29 0a 20 20   " + sLineId).  
7d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7d90: 20 20 20 20 20 20 65 6c 69 66 20 63 41 63 74 69        elif cActi
7da0: 6f 6e 54 79 70 65 20 3d 3d 20 22 3e 22 3a 0a 20  onType == ">":. 
7db0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7dc0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44             if bD
7dd0: 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20  ebug:.          
7de0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7df0: 20 20 20 20 20 20 70 72 69 6e 74 28 22 3e 21 22        print(">!"
7e00: 2c 20 73 52 75 6c 65 49 64 29 0a 20 20 20 20 20  , sRuleId).     
7e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7e20: 20 20 20 20 20 20 20 62 72 65 61 6b 0a 20 20 20         break.   
7e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 78 63               exc
7e40: 65 70 74 20 45 78 63 65 70 74 69 6f 6e 20 61 73  ept Exception as
7e50: 20 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20   e:.            
7e60: 20 20 20 20 20 20 20 20 72 61 69 73 65 20 45 78          raise Ex
7e70: 63 65 70 74 69 6f 6e 28 73 74 72 28 65 29 2c 20  ception(str(e), 
7e80: 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65 49 64  sLineId, sRuleId
7e90: 2c 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65  , self.sSentence
7ea0: 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ).        return
7eb0: 20 62 43 68 61 6e 67 65 2c 20 64 45 72 72 6f 72   bChange, dError
7ec0: 0a 0a 20 20 20 20 64 65 66 20 5f 63 72 65 61 74  ..    def _creat
7ed0: 65 57 72 69 74 65 72 45 72 72 6f 72 20 28 73 65  eWriterError (se
7ee0: 6c 66 2c 20 73 53 75 67 67 2c 20 6e 54 6f 6b 65  lf, sSugg, nToke
7ef0: 6e 4f 66 66 73 65 74 2c 20 69 46 69 72 73 74 54  nOffset, iFirstT
7f00: 6f 6b 65 6e 2c 20 6e 53 74 61 72 74 2c 20 6e 45  oken, nStart, nE
7f10: 6e 64 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52 75  nd, sLineId, sRu
7f20: 6c 65 49 64 2c 20 62 55 70 70 65 72 63 61 73 65  leId, bUppercase
7f30: 2c 20 73 4d 73 67 2c 20 73 55 52 4c 2c 20 62 53  , sMsg, sURL, bS
7f40: 68 6f 77 52 75 6c 65 49 64 2c 20 73 4f 70 74 69  howRuleId, sOpti
7f50: 6f 6e 2c 20 62 43 6f 6e 74 65 78 74 29 3a 0a 20  on, bContext):. 
7f60: 20 20 20 20 20 20 20 22 65 72 72 6f 72 20 66 6f         "error fo
7f70: 72 20 57 72 69 74 65 72 20 28 4c 4f 2f 4f 4f 29  r Writer (LO/OO)
7f80: 22 0a 20 20 20 20 20 20 20 20 78 45 72 72 20 3d  ".        xErr =
7f90: 20 53 69 6e 67 6c 65 50 72 6f 6f 66 72 65 61 64   SingleProofread
7fa0: 69 6e 67 45 72 72 6f 72 28 29 0a 20 20 20 20 20  ingError().     
7fb0: 20 20 20 23 78 45 72 72 20 3d 20 75 6e 6f 2e 63     #xErr = uno.c
7fc0: 72 65 61 74 65 55 6e 6f 53 74 72 75 63 74 28 20  reateUnoStruct( 
7fd0: 22 63 6f 6d 2e 73 75 6e 2e 73 74 61 72 2e 6c 69  "com.sun.star.li
7fe0: 6e 67 75 69 73 74 69 63 32 2e 53 69 6e 67 6c 65  nguistic2.Single
7ff0: 50 72 6f 6f 66 72 65 61 64 69 6e 67 45 72 72 6f  ProofreadingErro
8000: 72 22 20 29 0a 20 20 20 20 20 20 20 20 78 45 72  r" ).        xEr
8010: 72 2e 6e 45 72 72 6f 72 53 74 61 72 74 20 3d 20  r.nErrorStart = 
8020: 6e 53 74 61 72 74 0a 20 20 20 20 20 20 20 20 78  nStart.        x
8030: 45 72 72 2e 6e 45 72 72 6f 72 4c 65 6e 67 74 68  Err.nErrorLength
8040: 20 3d 20 6e 45 6e 64 20 2d 20 6e 53 74 61 72 74   = nEnd - nStart
8050: 0a 20 20 20 20 20 20 20 20 78 45 72 72 2e 6e 45  .        xErr.nE
8060: 72 72 6f 72 54 79 70 65 20 3d 20 50 52 4f 4f 46  rrorType = PROOF
8070: 52 45 41 44 49 4e 47 0a 20 20 20 20 20 20 20 20  READING.        
8080: 78 45 72 72 2e 61 52 75 6c 65 49 64 65 6e 74 69  xErr.aRuleIdenti
8090: 66 69 65 72 20 3d 20 73 52 75 6c 65 49 64 0a 20  fier = sRuleId. 
80a0: 20 20 20 20 20 20 20 23 20 73 75 67 67 65 73 74         # suggest
80b0: 69 6f 6e 73 0a 20 20 20 20 20 20 20 20 69 66 20  ions.        if 
80c0: 73 53 75 67 67 5b 30 3a 31 5d 20 3d 3d 20 22 3d  sSugg[0:1] == "=
80d0: 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  ":.            s
80e0: 53 75 67 67 20 3d 20 67 6c 6f 62 61 6c 73 28 29  Sugg = globals()
80f0: 5b 73 53 75 67 67 5b 31 3a 5d 5d 28 73 65 6c 66  [sSugg[1:]](self
8100: 2e 6c 54 6f 6b 65 6e 2c 20 6e 54 6f 6b 65 6e 4f  .lToken, nTokenO
8110: 66 66 73 65 74 29 0a 20 20 20 20 20 20 20 20 20  ffset).         
8120: 20 20 20 69 66 20 73 53 75 67 67 3a 0a 20 20 20     if sSugg:.   
8130: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
8140: 62 55 70 70 65 72 63 61 73 65 20 61 6e 64 20 73  bUppercase and s
8150: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 46 69 72 73  elf.lToken[iFirs
8160: 74 54 6f 6b 65 6e 5d 5b 22 73 56 61 6c 75 65 22  tToken]["sValue"
8170: 5d 5b 30 3a 31 5d 2e 69 73 75 70 70 65 72 28 29  ][0:1].isupper()
8180: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
8190: 20 20 20 20 20 20 78 45 72 72 2e 61 53 75 67 67        xErr.aSugg
81a0: 65 73 74 69 6f 6e 73 20 3d 20 74 75 70 6c 65 28  estions = tuple(
81b0: 6d 61 70 28 73 74 72 2e 63 61 70 69 74 61 6c 69  map(str.capitali
81c0: 7a 65 2c 20 73 53 75 67 67 2e 73 70 6c 69 74 28  ze, sSugg.split(
81d0: 22 7c 22 29 29 29 0a 20 20 20 20 20 20 20 20 20  "|"))).         
81e0: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
81f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8200: 20 78 45 72 72 2e 61 53 75 67 67 65 73 74 69 6f   xErr.aSuggestio
8210: 6e 73 20 3d 20 74 75 70 6c 65 28 73 53 75 67 67  ns = tuple(sSugg
8220: 2e 73 70 6c 69 74 28 22 7c 22 29 29 0a 20 20 20  .split("|")).   
8230: 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20           else:. 
8240: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 78                 x
8250: 45 72 72 2e 61 53 75 67 67 65 73 74 69 6f 6e 73  Err.aSuggestions
8260: 20 3d 20 28 29 0a 20 20 20 20 20 20 20 20 65 6c   = ().        el
8270: 69 66 20 73 53 75 67 67 20 3d 3d 20 22 5f 22 3a  if sSugg == "_":
8280: 0a 20 20 20 20 20 20 20 20 20 20 20 20 78 45 72  .            xEr
8290: 72 2e 61 53 75 67 67 65 73 74 69 6f 6e 73 20 3d  r.aSuggestions =
82a0: 20 28 29 0a 20 20 20 20 20 20 20 20 65 6c 73 65   ().        else
82b0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  :.            if
82c0: 20 62 55 70 70 65 72 63 61 73 65 20 61 6e 64 20   bUppercase and 
82d0: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 46 69 72  self.lToken[iFir
82e0: 73 74 54 6f 6b 65 6e 5d 5b 22 73 56 61 6c 75 65  stToken]["sValue
82f0: 22 5d 5b 30 3a 31 5d 2e 69 73 75 70 70 65 72 28  "][0:1].isupper(
8300: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
8310: 20 20 20 78 45 72 72 2e 61 53 75 67 67 65 73 74     xErr.aSuggest
8320: 69 6f 6e 73 20 3d 20 74 75 70 6c 65 28 6d 61 70  ions = tuple(map
8330: 28 73 74 72 2e 63 61 70 69 74 61 6c 69 7a 65 2c  (str.capitalize,
8340: 20 73 65 6c 66 2e 5f 65 78 70 61 6e 64 28 73 53   self._expand(sS
8350: 75 67 67 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65  ugg, nTokenOffse
8360: 74 29 2e 73 70 6c 69 74 28 22 7c 22 29 29 29 0a  t).split("|"))).
8370: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
8380: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
8390: 20 20 78 45 72 72 2e 61 53 75 67 67 65 73 74 69    xErr.aSuggesti
83a0: 6f 6e 73 20 3d 20 74 75 70 6c 65 28 73 65 6c 66  ons = tuple(self
83b0: 2e 5f 65 78 70 61 6e 64 28 73 53 75 67 67 2c 20  ._expand(sSugg, 
83c0: 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 29 2e 73 70  nTokenOffset).sp
83d0: 6c 69 74 28 22 7c 22 29 29 0a 20 20 20 20 20 20  lit("|")).      
83e0: 20 20 23 20 4d 65 73 73 61 67 65 0a 20 20 20 20    # Message.    
83f0: 20 20 20 20 73 4d 65 73 73 61 67 65 20 3d 20 67      sMessage = g
8400: 6c 6f 62 61 6c 73 28 29 5b 73 4d 73 67 5b 31 3a  lobals()[sMsg[1:
8410: 5d 5d 28 73 65 6c 66 2e 6c 54 6f 6b 65 6e 29 20  ]](self.lToken) 
8420: 20 69 66 20 73 4d 73 67 5b 30 3a 31 5d 20 3d 3d   if sMsg[0:1] ==
8430: 20 22 3d 22 20 20 65 6c 73 65 20 73 65 6c 66 2e   "="  else self.
8440: 5f 65 78 70 61 6e 64 28 73 4d 73 67 2c 20 6e 54  _expand(sMsg, nT
8450: 6f 6b 65 6e 4f 66 66 73 65 74 29 0a 20 20 20 20  okenOffset).    
8460: 20 20 20 20 78 45 72 72 2e 61 53 68 6f 72 74 43      xErr.aShortC
8470: 6f 6d 6d 65 6e 74 20 3d 20 73 4d 65 73 73 61 67  omment = sMessag
8480: 65 20 20 20 23 20 73 4d 65 73 73 61 67 65 2e 73  e   # sMessage.s
8490: 70 6c 69 74 28 22 7c 22 29 5b 30 5d 20 20 20 20  plit("|")[0]    
84a0: 20 23 20 69 6e 20 63 6f 6e 74 65 78 74 20 6d 65   # in context me
84b0: 6e 75 0a 20 20 20 20 20 20 20 20 78 45 72 72 2e  nu.        xErr.
84c0: 61 46 75 6c 6c 43 6f 6d 6d 65 6e 74 20 3d 20 73  aFullComment = s
84d0: 4d 65 73 73 61 67 65 20 20 20 23 20 73 4d 65 73  Message   # sMes
84e0: 73 61 67 65 2e 73 70 6c 69 74 28 22 7c 22 29 5b  sage.split("|")[
84f0: 2d 31 5d 20 20 20 20 23 20 69 6e 20 64 69 61 6c  -1]    # in dial
8500: 6f 67 0a 20 20 20 20 20 20 20 20 69 66 20 62 53  og.        if bS
8510: 68 6f 77 52 75 6c 65 49 64 3a 0a 20 20 20 20 20  howRuleId:.     
8520: 20 20 20 20 20 20 20 78 45 72 72 2e 61 53 68 6f         xErr.aSho
8530: 72 74 43 6f 6d 6d 65 6e 74 20 2b 3d 20 22 20 20  rtComment += "  
8540: 22 20 2b 20 73 4c 69 6e 65 49 64 20 2b 20 22 20  " + sLineId + " 
8550: 23 20 22 20 2b 20 73 52 75 6c 65 49 64 0a 20 20  # " + sRuleId.  
8560: 20 20 20 20 20 20 23 20 55 52 4c 0a 20 20 20 20        # URL.    
8570: 20 20 20 20 69 66 20 73 55 52 4c 3a 0a 20 20 20      if sURL:.   
8580: 20 20 20 20 20 20 20 20 20 78 50 72 6f 70 65 72           xProper
8590: 74 79 20 3d 20 50 72 6f 70 65 72 74 79 56 61 6c  ty = PropertyVal
85a0: 75 65 28 29 0a 20 20 20 20 20 20 20 20 20 20 20  ue().           
85b0: 20 78 50 72 6f 70 65 72 74 79 2e 4e 61 6d 65 20   xProperty.Name 
85c0: 3d 20 22 46 75 6c 6c 43 6f 6d 6d 65 6e 74 55 52  = "FullCommentUR
85d0: 4c 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 78  L".            x
85e0: 50 72 6f 70 65 72 74 79 2e 56 61 6c 75 65 20 3d  Property.Value =
85f0: 20 73 55 52 4c 0a 20 20 20 20 20 20 20 20 20 20   sURL.          
8600: 20 20 78 45 72 72 2e 61 50 72 6f 70 65 72 74 69    xErr.aProperti
8610: 65 73 20 3d 20 28 78 50 72 6f 70 65 72 74 79 2c  es = (xProperty,
8620: 29 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a  ).        else:.
8630: 20 20 20 20 20 20 20 20 20 20 20 20 78 45 72 72              xErr
8640: 2e 61 50 72 6f 70 65 72 74 69 65 73 20 3d 20 28  .aProperties = (
8650: 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ).        return
8660: 20 78 45 72 72 0a 0a 20 20 20 20 64 65 66 20 5f   xErr..    def _
8670: 63 72 65 61 74 65 44 69 63 74 45 72 72 6f 72 20  createDictError 
8680: 28 73 65 6c 66 2c 20 73 53 75 67 67 2c 20 6e 54  (self, sSugg, nT
8690: 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 69 46 69 72  okenOffset, iFir
86a0: 73 74 54 6f 6b 65 6e 2c 20 6e 53 74 61 72 74 2c  stToken, nStart,
86b0: 20 6e 45 6e 64 2c 20 73 4c 69 6e 65 49 64 2c 20   nEnd, sLineId, 
86c0: 73 52 75 6c 65 49 64 2c 20 62 55 70 70 65 72 63  sRuleId, bUpperc
86d0: 61 73 65 2c 20 73 4d 73 67 2c 20 73 55 52 4c 2c  ase, sMsg, sURL,
86e0: 20 62 53 68 6f 77 52 75 6c 65 49 64 2c 20 73 4f   bShowRuleId, sO
86f0: 70 74 69 6f 6e 2c 20 62 43 6f 6e 74 65 78 74 29  ption, bContext)
8700: 3a 0a 20 20 20 20 20 20 20 20 22 65 72 72 6f 72  :.        "error
8710: 20 61 73 20 61 20 64 69 63 74 69 6f 6e 61 72 79   as a dictionary
8720: 22 0a 20 20 20 20 20 20 20 20 64 45 72 72 20 3d  ".        dErr =
8730: 20 7b 7d 0a 20 20 20 20 20 20 20 20 64 45 72 72   {}.        dErr
8740: 5b 22 6e 53 74 61 72 74 22 5d 20 3d 20 6e 53 74  ["nStart"] = nSt
8750: 61 72 74 0a 20 20 20 20 20 20 20 20 64 45 72 72  art.        dErr
8760: 5b 22 6e 45 6e 64 22 5d 20 3d 20 6e 45 6e 64 0a  ["nEnd"] = nEnd.
8770: 20 20 20 20 20 20 20 20 64 45 72 72 5b 22 73 4c          dErr["sL
8780: 69 6e 65 49 64 22 5d 20 3d 20 73 4c 69 6e 65 49  ineId"] = sLineI
8790: 64 0a 20 20 20 20 20 20 20 20 64 45 72 72 5b 22  d.        dErr["
87a0: 73 52 75 6c 65 49 64 22 5d 20 3d 20 73 52 75 6c  sRuleId"] = sRul
87b0: 65 49 64 0a 20 20 20 20 20 20 20 20 64 45 72 72  eId.        dErr
87c0: 5b 22 73 54 79 70 65 22 5d 20 3d 20 73 4f 70 74  ["sType"] = sOpt
87d0: 69 6f 6e 20 20 69 66 20 73 4f 70 74 69 6f 6e 20  ion  if sOption 
87e0: 20 65 6c 73 65 20 22 6e 6f 74 79 70 65 22 0a 20   else "notype". 
87f0: 20 20 20 20 20 20 20 23 20 73 75 67 67 65 73 74         # suggest
8800: 69 6f 6e 73 0a 20 20 20 20 20 20 20 20 69 66 20  ions.        if 
8810: 73 53 75 67 67 5b 30 3a 31 5d 20 3d 3d 20 22 3d  sSugg[0:1] == "=
8820: 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  ":.            s
8830: 53 75 67 67 20 3d 20 67 6c 6f 62 61 6c 73 28 29  Sugg = globals()
8840: 5b 73 53 75 67 67 5b 31 3a 5d 5d 28 73 65 6c 66  [sSugg[1:]](self
8850: 2e 6c 54 6f 6b 65 6e 2c 20 6e 54 6f 6b 65 6e 4f  .lToken, nTokenO
8860: 66 66 73 65 74 29 0a 20 20 20 20 20 20 20 20 20  ffset).         
8870: 20 20 20 69 66 20 73 53 75 67 67 3a 0a 20 20 20     if sSugg:.   
8880: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
8890: 62 55 70 70 65 72 63 61 73 65 20 61 6e 64 20 73  bUppercase and s
88a0: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 46 69 72 73  elf.lToken[iFirs
88b0: 74 54 6f 6b 65 6e 5d 5b 22 73 56 61 6c 75 65 22  tToken]["sValue"
88c0: 5d 5b 30 3a 31 5d 2e 69 73 75 70 70 65 72 28 29  ][0:1].isupper()
88d0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
88e0: 20 20 20 20 20 20 64 45 72 72 5b 22 61 53 75 67        dErr["aSug
88f0: 67 65 73 74 69 6f 6e 73 22 5d 20 3d 20 6c 69 73  gestions"] = lis
8900: 74 28 6d 61 70 28 73 74 72 2e 63 61 70 69 74 61  t(map(str.capita
8910: 6c 69 7a 65 2c 20 73 53 75 67 67 2e 73 70 6c 69  lize, sSugg.spli
8920: 74 28 22 7c 22 29 29 29 0a 20 20 20 20 20 20 20  t("|"))).       
8930: 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20           else:. 
8940: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8950: 20 20 20 64 45 72 72 5b 22 61 53 75 67 67 65 73     dErr["aSugges
8960: 74 69 6f 6e 73 22 5d 20 3d 20 73 53 75 67 67 2e  tions"] = sSugg.
8970: 73 70 6c 69 74 28 22 7c 22 29 0a 20 20 20 20 20  split("|").     
8980: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
8990: 20 20 20 20 20 20 20 20 20 20 20 20 20 64 45 72               dEr
89a0: 72 5b 22 61 53 75 67 67 65 73 74 69 6f 6e 73 22  r["aSuggestions"
89b0: 5d 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 65  ] = [].        e
89c0: 6c 69 66 20 73 53 75 67 67 20 3d 3d 20 22 5f 22  lif sSugg == "_"
89d0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 45  :.            dE
89e0: 72 72 5b 22 61 53 75 67 67 65 73 74 69 6f 6e 73  rr["aSuggestions
89f0: 22 5d 20 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20  "] = [].        
8a00: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
8a10: 20 20 69 66 20 62 55 70 70 65 72 63 61 73 65 20    if bUppercase 
8a20: 61 6e 64 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b  and self.lToken[
8a30: 69 46 69 72 73 74 54 6f 6b 65 6e 5d 5b 22 73 56  iFirstToken]["sV
8a40: 61 6c 75 65 22 5d 5b 30 3a 31 5d 2e 69 73 75 70  alue"][0:1].isup
8a50: 70 65 72 28 29 3a 0a 20 20 20 20 20 20 20 20 20  per():.         
8a60: 20 20 20 20 20 20 20 64 45 72 72 5b 22 61 53 75         dErr["aSu
8a70: 67 67 65 73 74 69 6f 6e 73 22 5d 20 3d 20 6c 69  ggestions"] = li
8a80: 73 74 28 6d 61 70 28 73 74 72 2e 63 61 70 69 74  st(map(str.capit
8a90: 61 6c 69 7a 65 2c 20 73 65 6c 66 2e 5f 65 78 70  alize, self._exp
8aa0: 61 6e 64 28 73 53 75 67 67 2c 20 6e 54 6f 6b 65  and(sSugg, nToke
8ab0: 6e 4f 66 66 73 65 74 29 2e 73 70 6c 69 74 28 22  nOffset).split("
8ac0: 7c 22 29 29 29 0a 20 20 20 20 20 20 20 20 20 20  |"))).          
8ad0: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
8ae0: 20 20 20 20 20 20 20 20 64 45 72 72 5b 22 61 53          dErr["aS
8af0: 75 67 67 65 73 74 69 6f 6e 73 22 5d 20 3d 20 73  uggestions"] = s
8b00: 65 6c 66 2e 5f 65 78 70 61 6e 64 28 73 53 75 67  elf._expand(sSug
8b10: 67 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 29  g, nTokenOffset)
8b20: 2e 73 70 6c 69 74 28 22 7c 22 29 0a 20 20 20 20  .split("|").    
8b30: 20 20 20 20 23 20 4d 65 73 73 61 67 65 0a 20 20      # Message.  
8b40: 20 20 20 20 20 20 64 45 72 72 5b 22 73 4d 65 73        dErr["sMes
8b50: 73 61 67 65 22 5d 20 3d 20 67 6c 6f 62 61 6c 73  sage"] = globals
8b60: 28 29 5b 73 4d 73 67 5b 31 3a 5d 5d 28 73 65 6c  ()[sMsg[1:]](sel
8b70: 66 2e 6c 54 6f 6b 65 6e 29 20 20 69 66 20 73 4d  f.lToken)  if sM
8b80: 73 67 5b 30 3a 31 5d 20 3d 3d 20 22 3d 22 20 20  sg[0:1] == "="  
8b90: 65 6c 73 65 20 73 65 6c 66 2e 5f 65 78 70 61 6e  else self._expan
8ba0: 64 28 73 4d 73 67 2c 20 6e 54 6f 6b 65 6e 4f 66  d(sMsg, nTokenOf
8bb0: 66 73 65 74 29 0a 20 20 20 20 20 20 20 20 69 66  fset).        if
8bc0: 20 62 53 68 6f 77 52 75 6c 65 49 64 3a 0a 20 20   bShowRuleId:.  
8bd0: 20 20 20 20 20 20 20 20 20 20 64 45 72 72 5b 22            dErr["
8be0: 73 4d 65 73 73 61 67 65 22 5d 20 2b 3d 20 22 20  sMessage"] += " 
8bf0: 20 22 20 2b 20 73 4c 69 6e 65 49 64 20 2b 20 22   " + sLineId + "
8c00: 20 23 20 22 20 2b 20 73 52 75 6c 65 49 64 0a 20   # " + sRuleId. 
8c10: 20 20 20 20 20 20 20 23 20 55 52 4c 0a 20 20 20         # URL.   
8c20: 20 20 20 20 20 64 45 72 72 5b 22 55 52 4c 22 5d       dErr["URL"]
8c30: 20 3d 20 73 55 52 4c 20 20 69 66 20 73 55 52 4c   = sURL  if sURL
8c40: 20 20 65 6c 73 65 20 22 22 0a 20 20 20 20 20 20    else "".      
8c50: 20 20 23 20 43 6f 6e 74 65 78 74 0a 20 20 20 20    # Context.    
8c60: 20 20 20 20 69 66 20 62 43 6f 6e 74 65 78 74 3a      if bContext:
8c70: 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 45 72  .            dEr
8c80: 72 5b 27 73 55 6e 64 65 72 6c 69 6e 65 64 27 5d  r['sUnderlined']
8c90: 20 3d 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63   = self.sSentenc
8ca0: 65 30 5b 64 45 72 72 5b 22 6e 53 74 61 72 74 22  e0[dErr["nStart"
8cb0: 5d 3a 64 45 72 72 5b 22 6e 45 6e 64 22 5d 5d 0a  ]:dErr["nEnd"]].
8cc0: 20 20 20 20 20 20 20 20 20 20 20 20 64 45 72 72              dErr
8cd0: 5b 27 73 42 65 66 6f 72 65 27 5d 20 3d 20 73 65  ['sBefore'] = se
8ce0: 6c 66 2e 73 53 65 6e 74 65 6e 63 65 30 5b 6d 61  lf.sSentence0[ma
8cf0: 78 28 30 2c 64 45 72 72 5b 22 6e 53 74 61 72 74  x(0,dErr["nStart
8d00: 22 5d 2d 38 30 29 3a 64 45 72 72 5b 22 6e 53 74  "]-80):dErr["nSt
8d10: 61 72 74 22 5d 5d 0a 20 20 20 20 20 20 20 20 20  art"]].         
8d20: 20 20 20 64 45 72 72 5b 27 73 41 66 74 65 72 27     dErr['sAfter'
8d30: 5d 20 3d 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e  ] = self.sSenten
8d40: 63 65 30 5b 64 45 72 72 5b 22 6e 45 6e 64 22 5d  ce0[dErr["nEnd"]
8d50: 3a 64 45 72 72 5b 22 6e 45 6e 64 22 5d 2b 38 30  :dErr["nEnd"]+80
8d60: 5d 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ].        return
8d70: 20 64 45 72 72 0a 0a 20 20 20 20 64 65 66 20 5f   dErr..    def _
8d80: 65 78 70 61 6e 64 20 28 73 65 6c 66 2c 20 73 4d  expand (self, sM
8d90: 73 67 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74  sg, nTokenOffset
8da0: 29 3a 0a 20 20 20 20 20 20 20 20 23 70 72 69 6e  ):.        #prin
8db0: 74 28 22 2a 22 2c 20 73 4d 73 67 29 0a 20 20 20  t("*", sMsg).   
8dc0: 20 20 20 20 20 66 6f 72 20 6d 20 69 6e 20 72 65       for m in re
8dd0: 2e 66 69 6e 64 69 74 65 72 28 72 22 5c 5c 28 5b  .finditer(r"\\([
8de0: 30 2d 39 5d 2b 29 22 2c 20 73 4d 73 67 29 3a 0a  0-9]+)", sMsg):.
8df0: 20 20 20 20 20 20 20 20 20 20 20 20 73 4d 73 67              sMsg
8e00: 20 3d 20 73 4d 73 67 2e 72 65 70 6c 61 63 65 28   = sMsg.replace(
8e10: 6d 2e 67 72 6f 75 70 28 30 29 2c 20 73 65 6c 66  m.group(0), self
8e20: 2e 6c 54 6f 6b 65 6e 5b 69 6e 74 28 6d 2e 67 72  .lToken[int(m.gr
8e30: 6f 75 70 28 31 29 29 2b 6e 54 6f 6b 65 6e 4f 66  oup(1))+nTokenOf
8e40: 66 73 65 74 5d 5b 22 73 56 61 6c 75 65 22 5d 29  fset]["sValue"])
8e50: 0a 20 20 20 20 20 20 20 20 23 70 72 69 6e 74 28  .        #print(
8e60: 22 3e 22 2c 20 73 4d 73 67 29 0a 20 20 20 20 20  ">", sMsg).     
8e70: 20 20 20 72 65 74 75 72 6e 20 73 4d 73 67 0a 0a     return sMsg..
8e80: 20 20 20 20 64 65 66 20 5f 74 61 67 41 6e 64 50      def _tagAndP
8e90: 72 65 70 61 72 65 54 6f 6b 65 6e 46 6f 72 52 65  repareTokenForRe
8ea0: 77 72 69 74 69 6e 67 20 28 73 65 6c 66 2c 20 73  writing (self, s
8eb0: 57 68 61 74 2c 20 6e 54 6f 6b 65 6e 52 65 77 72  What, nTokenRewr
8ec0: 69 74 65 53 74 61 72 74 2c 20 6e 54 6f 6b 65 6e  iteStart, nToken
8ed0: 52 65 77 72 69 74 65 45 6e 64 2c 20 62 55 70 70  RewriteEnd, bUpp
8ee0: 65 72 63 61 73 65 3d 54 72 75 65 2c 20 62 44 65  ercase=True, bDe
8ef0: 62 75 67 3d 46 61 6c 73 65 29 3a 0a 20 20 20 20  bug=False):.    
8f00: 20 20 20 20 22 74 65 78 74 20 70 72 6f 63 65 73      "text proces
8f10: 73 6f 72 3a 20 72 65 77 72 69 74 65 20 74 6f 6b  sor: rewrite tok
8f20: 65 6e 73 20 62 65 74 77 65 65 6e 20 3c 6e 54 6f  ens between <nTo
8f30: 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72 74 3e  kenRewriteStart>
8f40: 20 61 6e 64 20 3c 6e 54 6f 6b 65 6e 52 65 77 72   and <nTokenRewr
8f50: 69 74 65 45 6e 64 3e 20 70 6f 73 69 74 69 6f 6e  iteEnd> position
8f60: 22 0a 20 20 20 20 20 20 20 20 69 66 20 62 44 65  ".        if bDe
8f70: 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  bug:.           
8f80: 20 70 72 69 6e 74 28 22 52 45 57 52 49 54 49 4e   print("REWRITIN
8f90: 47 3a 22 2c 20 6e 54 6f 6b 65 6e 52 65 77 72 69  G:", nTokenRewri
8fa0: 74 65 53 74 61 72 74 2c 20 6e 54 6f 6b 65 6e 52  teStart, nTokenR
8fb0: 65 77 72 69 74 65 45 6e 64 29 0a 20 20 20 20 20  ewriteEnd).     
8fc0: 20 20 20 69 66 20 73 57 68 61 74 20 3d 3d 20 22     if sWhat == "
8fd0: 2a 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  *":.            
8fe0: 23 20 70 75 72 67 65 20 74 65 78 74 0a 20 20 20  # purge text.   
8ff0: 20 20 20 20 20 20 20 20 20 69 66 20 6e 54 6f 6b           if nTok
9000: 65 6e 52 65 77 72 69 74 65 45 6e 64 20 2d 20 6e  enRewriteEnd - n
9010: 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72  TokenRewriteStar
9020: 74 20 3d 3d 20 30 3a 0a 20 20 20 20 20 20 20 20  t == 0:.        
9030: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f          self.lTo
9040: 6b 65 6e 5b 6e 54 6f 6b 65 6e 52 65 77 72 69 74  ken[nTokenRewrit
9050: 65 53 74 61 72 74 5d 5b 22 62 54 6f 52 65 6d 6f  eStart]["bToRemo
9060: 76 65 22 5d 20 3d 20 54 72 75 65 0a 20 20 20 20  ve"] = True.    
9070: 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20          else:.  
9080: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f                fo
9090: 72 20 69 20 69 6e 20 72 61 6e 67 65 28 6e 54 6f  r i in range(nTo
90a0: 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72 74 2c  kenRewriteStart,
90b0: 20 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 45 6e   nTokenRewriteEn
90c0: 64 2b 31 29 3a 0a 20 20 20 20 20 20 20 20 20 20  d+1):.          
90d0: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c            self.l
90e0: 54 6f 6b 65 6e 5b 69 5d 5b 22 62 54 6f 52 65 6d  Token[i]["bToRem
90f0: 6f 76 65 22 5d 20 3d 20 54 72 75 65 0a 20 20 20  ove"] = True.   
9100: 20 20 20 20 20 65 6c 69 66 20 73 57 68 61 74 20       elif sWhat 
9110: 3d 3d 20 22 3d 22 3a 0a 20 20 20 20 20 20 20 20  == "=":.        
9120: 20 20 20 20 23 20 6d 65 72 67 65 20 74 6f 6b 65      # merge toke
9130: 6e 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  ns.            s
9140: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65  elf.lToken[nToke
9150: 6e 52 65 77 72 69 74 65 53 74 61 72 74 5d 5b 22  nRewriteStart]["
9160: 6e 4d 65 72 67 65 55 6e 74 69 6c 22 5d 20 3d 20  nMergeUntil"] = 
9170: 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 45 6e 64  nTokenRewriteEnd
9180: 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 73 57  .        elif sW
9190: 68 61 74 20 3d 3d 20 22 21 22 3a 0a 20 20 20 20  hat == "!":.    
91a0: 20 20 20 20 20 20 20 20 23 20 69 6d 6d 75 6e 69          # immuni
91b0: 74 79 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  ty.            i
91c0: 66 20 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 45  f nTokenRewriteE
91d0: 6e 64 20 2d 20 6e 54 6f 6b 65 6e 52 65 77 72 69  nd - nTokenRewri
91e0: 74 65 53 74 61 72 74 20 3d 3d 20 30 3a 0a 20 20  teStart == 0:.  
91f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
9200: 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e  lf.lToken[nToken
9210: 52 65 77 72 69 74 65 53 74 61 72 74 5d 5b 22 62  RewriteStart]["b
9220: 49 6d 6d 75 6e 65 22 5d 20 3d 20 54 72 75 65 0a  Immune"] = True.
9230: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65              else
9240: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
9250: 20 20 66 6f 72 20 69 20 69 6e 20 72 61 6e 67 65    for i in range
9260: 28 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74  (nTokenRewriteSt
9270: 61 72 74 2c 20 6e 54 6f 6b 65 6e 52 65 77 72 69  art, nTokenRewri
9280: 74 65 45 6e 64 2b 31 29 3a 0a 20 20 20 20 20 20  teEnd+1):.      
9290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
92a0: 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 62 49  lf.lToken[i]["bI
92b0: 6d 6d 75 6e 65 22 5d 20 3d 20 54 72 75 65 0a 20  mmune"] = True. 
92c0: 20 20 20 20 20 20 20 65 6c 69 66 20 73 57 68 61         elif sWha
92d0: 74 20 3d 3d 20 22 5f 22 3a 0a 20 20 20 20 20 20  t == "_":.      
92e0: 20 20 20 20 20 20 23 20 6e 65 75 74 72 61 6c 69        # neutrali
92f0: 7a 65 64 20 74 6f 6b 65 6e 0a 20 20 20 20 20 20  zed token.      
9300: 20 20 20 20 20 20 69 66 20 6e 54 6f 6b 65 6e 52        if nTokenR
9310: 65 77 72 69 74 65 45 6e 64 20 2d 20 6e 54 6f 6b  ewriteEnd - nTok
9320: 65 6e 52 65 77 72 69 74 65 53 74 61 72 74 20 3d  enRewriteStart =
9330: 3d 20 30 3a 0a 20 20 20 20 20 20 20 20 20 20 20  = 0:.           
9340: 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e       self.lToken
9350: 5b 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74  [nTokenRewriteSt
9360: 61 72 74 5d 5b 22 73 4e 65 77 56 61 6c 75 65 22  art]["sNewValue"
9370: 5d 20 3d 20 22 5f 22 0a 20 20 20 20 20 20 20 20  ] = "_".        
9380: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
9390: 20 20 20 20 20 20 20 20 20 20 66 6f 72 20 69 20            for i 
93a0: 69 6e 20 72 61 6e 67 65 28 6e 54 6f 6b 65 6e 52  in range(nTokenR
93b0: 65 77 72 69 74 65 53 74 61 72 74 2c 20 6e 54 6f  ewriteStart, nTo
93c0: 6b 65 6e 52 65 77 72 69 74 65 45 6e 64 2b 31 29  kenRewriteEnd+1)
93d0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
93e0: 20 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65        self.lToke
93f0: 6e 5b 69 5d 5b 22 73 4e 65 77 56 61 6c 75 65 22  n[i]["sNewValue"
9400: 5d 20 3d 20 22 5f 22 0a 20 20 20 20 20 20 20 20  ] = "_".        
9410: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
9420: 20 20 69 66 20 73 57 68 61 74 2e 73 74 61 72 74    if sWhat.start
9430: 73 77 69 74 68 28 22 3d 22 29 3a 0a 20 20 20 20  swith("="):.    
9440: 20 20 20 20 20 20 20 20 20 20 20 20 73 57 68 61              sWha
9450: 74 20 3d 20 67 6c 6f 62 61 6c 73 28 29 5b 73 57  t = globals()[sW
9460: 68 61 74 5b 31 3a 5d 5d 28 73 65 6c 66 2e 6c 54  hat[1:]](self.lT
9470: 6f 6b 65 6e 29 0a 20 20 20 20 20 20 20 20 20 20  oken).          
9480: 20 20 62 55 70 70 65 72 63 61 73 65 20 3d 20 62    bUppercase = b
9490: 55 70 70 65 72 63 61 73 65 20 61 6e 64 20 73 65  Uppercase and se
94a0: 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e  lf.lToken[nToken
94b0: 52 65 77 72 69 74 65 53 74 61 72 74 5d 5b 22 73  RewriteStart]["s
94c0: 56 61 6c 75 65 22 5d 5b 30 3a 31 5d 2e 69 73 75  Value"][0:1].isu
94d0: 70 70 65 72 28 29 0a 20 20 20 20 20 20 20 20 20  pper().         
94e0: 20 20 20 69 66 20 6e 54 6f 6b 65 6e 52 65 77 72     if nTokenRewr
94f0: 69 74 65 45 6e 64 20 2d 20 6e 54 6f 6b 65 6e 52  iteEnd - nTokenR
9500: 65 77 72 69 74 65 53 74 61 72 74 20 3d 3d 20 30  ewriteStart == 0
9510: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
9520: 20 20 73 57 68 61 74 20 3d 20 73 57 68 61 74 20    sWhat = sWhat 
9530: 2b 20 22 20 22 20 2a 20 28 6c 65 6e 28 73 65 6c  + " " * (len(sel
9540: 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 52  f.lToken[nTokenR
9550: 65 77 72 69 74 65 53 74 61 72 74 5d 5b 22 73 56  ewriteStart]["sV
9560: 61 6c 75 65 22 5d 29 2d 6c 65 6e 28 73 57 68 61  alue"])-len(sWha
9570: 74 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  t)).            
9580: 20 20 20 20 69 66 20 62 55 70 70 65 72 63 61 73      if bUppercas
9590: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
95a0: 20 20 20 20 20 20 20 73 57 68 61 74 20 3d 20 73         sWhat = s
95b0: 57 68 61 74 5b 30 3a 31 5d 2e 75 70 70 65 72 28  What[0:1].upper(
95c0: 29 20 2b 20 73 57 68 61 74 5b 31 3a 5d 0a 20 20  ) + sWhat[1:].  
95d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
95e0: 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e  lf.lToken[nToken
95f0: 52 65 77 72 69 74 65 53 74 61 72 74 5d 5b 22 73  RewriteStart]["s
9600: 4e 65 77 56 61 6c 75 65 22 5d 20 3d 20 73 57 68  NewValue"] = sWh
9610: 61 74 0a 20 20 20 20 20 20 20 20 20 20 20 20 65  at.            e
9620: 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  lse:.           
9630: 20 20 20 20 20 6c 54 6f 6b 65 6e 56 61 6c 75 65       lTokenValue
9640: 20 3d 20 73 57 68 61 74 2e 73 70 6c 69 74 28 22   = sWhat.split("
9650: 7c 22 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  |").            
9660: 20 20 20 20 69 66 20 6c 65 6e 28 6c 54 6f 6b 65      if len(lToke
9670: 6e 56 61 6c 75 65 29 20 21 3d 20 28 6e 54 6f 6b  nValue) != (nTok
9680: 65 6e 52 65 77 72 69 74 65 45 6e 64 20 2d 20 6e  enRewriteEnd - n
9690: 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72  TokenRewriteStar
96a0: 74 20 2b 20 31 29 3a 0a 20 20 20 20 20 20 20 20  t + 1):.        
96b0: 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e              prin
96c0: 74 28 22 45 72 72 6f 72 2e 20 54 65 78 74 20 70  t("Error. Text p
96d0: 72 6f 63 65 73 73 6f 72 3a 20 6e 75 6d 62 65 72  rocessor: number
96e0: 20 6f 66 20 72 65 70 6c 61 63 65 6d 65 6e 74 73   of replacements
96f0: 20 21 3d 20 6e 75 6d 62 65 72 20 6f 66 20 74 6f   != number of to
9700: 6b 65 6e 73 2e 22 29 0a 20 20 20 20 20 20 20 20  kens.").        
9710: 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74 75              retu
9720: 72 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  rn.             
9730: 20 20 20 66 6f 72 20 69 2c 20 73 56 61 6c 75 65     for i, sValue
9740: 20 69 6e 20 7a 69 70 28 72 61 6e 67 65 28 6e 54   in zip(range(nT
9750: 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72 74  okenRewriteStart
9760: 2c 20 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 45  , nTokenRewriteE
9770: 6e 64 2b 31 29 2c 20 6c 54 6f 6b 65 6e 56 61 6c  nd+1), lTokenVal
9780: 75 65 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ue):.           
9790: 20 20 20 20 20 20 20 20 20 69 66 20 62 55 70 70           if bUpp
97a0: 65 72 63 61 73 65 3a 0a 20 20 20 20 20 20 20 20  ercase:.        
97b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
97c0: 73 56 61 6c 75 65 20 3d 20 73 56 61 6c 75 65 5b  sValue = sValue[
97d0: 30 3a 31 5d 2e 75 70 70 65 72 28 29 20 2b 20 73  0:1].upper() + s
97e0: 56 61 6c 75 65 5b 31 3a 5d 0a 20 20 20 20 20 20  Value[1:].      
97f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 65                se
9800: 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 73 4e  lf.lToken[i]["sN
9810: 65 77 56 61 6c 75 65 22 5d 20 3d 20 73 56 61 6c  ewValue"] = sVal
9820: 75 65 0a 0a 20 20 20 20 64 65 66 20 72 65 77 72  ue..    def rewr
9830: 69 74 65 20 28 73 65 6c 66 2c 20 62 44 65 62 75  ite (self, bDebu
9840: 67 3d 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20  g=False):.      
9850: 20 20 22 72 65 77 72 69 74 65 20 74 68 65 20 73    "rewrite the s
9860: 65 6e 74 65 6e 63 65 2c 20 6d 6f 64 69 66 79 20  entence, modify 
9870: 74 6f 6b 65 6e 73 2c 20 70 75 72 67 65 20 74 68  tokens, purge th
9880: 65 20 74 6f 6b 65 6e 20 6c 69 73 74 22 0a 20 20  e token list".  
9890: 20 20 20 20 20 20 6c 4e 65 77 54 6f 6b 65 6e 20        lNewToken 
98a0: 3d 20 5b 5d 0a 20 20 20 20 20 20 20 20 6e 4d 65  = [].        nMe
98b0: 72 67 65 55 6e 74 69 6c 20 3d 20 30 0a 20 20 20  rgeUntil = 0.   
98c0: 20 20 20 20 20 64 54 6f 6b 65 6e 4d 65 72 67 65       dTokenMerge
98d0: 72 20 3d 20 4e 6f 6e 65 0a 20 20 20 20 20 20 20  r = None.       
98e0: 20 66 6f 72 20 64 54 6f 6b 65 6e 20 69 6e 20 73   for dToken in s
98f0: 65 6c 66 2e 6c 54 6f 6b 65 6e 3a 0a 20 20 20 20  elf.lToken:.    
9900: 20 20 20 20 20 20 20 20 62 4b 65 65 70 54 6f 6b          bKeepTok
9910: 65 6e 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20  en = True.      
9920: 20 20 20 20 20 20 69 66 20 22 62 49 6d 6d 75 6e        if "bImmun
9930: 65 22 20 69 6e 20 64 54 6f 6b 65 6e 3a 0a 20 20  e" in dToken:.  
9940: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 45                nE
9950: 72 72 6f 72 53 74 61 72 74 20 3d 20 73 65 6c 66  rrorStart = self
9960: 2e 6e 4f 66 66 73 65 74 57 69 74 68 69 6e 50 61  .nOffsetWithinPa
9970: 72 61 67 72 61 70 68 20 2b 20 64 54 6f 6b 65 6e  ragraph + dToken
9980: 5b 22 6e 53 74 61 72 74 22 5d 0a 20 20 20 20 20  ["nStart"].     
9990: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 45             if nE
99a0: 72 72 6f 72 53 74 61 72 74 20 69 6e 20 73 65 6c  rrorStart in sel
99b0: 66 2e 64 45 72 72 6f 72 3a 0a 20 20 20 20 20 20  f.dError:.      
99c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
99d0: 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20   bDebug:.       
99e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
99f0: 20 70 72 69 6e 74 28 22 69 6d 6d 75 6e 69 74 79   print("immunity
9a00: 20 2d 3e 20 65 72 72 6f 72 20 72 65 6d 6f 76 65   -> error remove
9a10: 64 3a 22 2c 20 73 65 6c 66 2e 64 45 72 72 6f 72  d:", self.dError
9a20: 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d 29 0a 20  [nErrorStart]). 
9a30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9a40: 20 20 20 64 65 6c 20 73 65 6c 66 2e 64 45 72 72     del self.dErr
9a50: 6f 72 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d 0a  or[nErrorStart].
9a60: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
9a70: 4d 65 72 67 65 55 6e 74 69 6c 20 61 6e 64 20 64  MergeUntil and d
9a80: 54 6f 6b 65 6e 5b 22 69 22 5d 20 3c 3d 20 6e 4d  Token["i"] <= nM
9a90: 65 72 67 65 55 6e 74 69 6c 3a 0a 20 20 20 20 20  ergeUntil:.     
9aa0: 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65             dToke
9ab0: 6e 4d 65 72 67 65 72 5b 22 73 56 61 6c 75 65 22  nMerger["sValue"
9ac0: 5d 20 2b 3d 20 22 20 22 20 2a 20 28 64 54 6f 6b  ] += " " * (dTok
9ad0: 65 6e 5b 22 6e 53 74 61 72 74 22 5d 20 2d 20 64  en["nStart"] - d
9ae0: 54 6f 6b 65 6e 4d 65 72 67 65 72 5b 22 6e 45 6e  TokenMerger["nEn
9af0: 64 22 5d 29 20 2b 20 64 54 6f 6b 65 6e 5b 22 73  d"]) + dToken["s
9b00: 56 61 6c 75 65 22 5d 0a 20 20 20 20 20 20 20 20  Value"].        
9b10: 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 4d 65          dTokenMe
9b20: 72 67 65 72 5b 22 6e 45 6e 64 22 5d 20 3d 20 64  rger["nEnd"] = d
9b30: 54 6f 6b 65 6e 5b 22 6e 45 6e 64 22 5d 0a 20 20  Token["nEnd"].  
9b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
9b50: 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20   bDebug:.       
9b60: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69               pri
9b70: 6e 74 28 22 4d 65 72 67 65 64 20 74 6f 6b 65 6e  nt("Merged token
9b80: 3a 22 2c 20 64 54 6f 6b 65 6e 4d 65 72 67 65 72  :", dTokenMerger
9b90: 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20  ["sValue"]).    
9ba0: 20 20 20 20 20 20 20 20 20 20 20 20 62 4b 65 65              bKee
9bb0: 70 54 6f 6b 65 6e 20 3d 20 46 61 6c 73 65 0a 20  pToken = False. 
9bc0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 22 6e             if "n
9bd0: 4d 65 72 67 65 55 6e 74 69 6c 22 20 69 6e 20 64  MergeUntil" in d
9be0: 54 6f 6b 65 6e 3a 0a 20 20 20 20 20 20 20 20 20  Token:.         
9bf0: 20 20 20 20 20 20 20 69 66 20 64 54 6f 6b 65 6e         if dToken
9c00: 5b 22 69 22 5d 20 3e 20 6e 4d 65 72 67 65 55 6e  ["i"] > nMergeUn
9c10: 74 69 6c 3a 20 23 20 74 68 69 73 20 74 6f 6b 65  til: # this toke
9c20: 6e 20 69 73 20 6e 6f 74 20 61 6c 72 65 61 64 79  n is not already
9c30: 20 6d 65 72 67 65 64 20 77 69 74 68 20 61 20 70   merged with a p
9c40: 72 65 76 69 6f 75 73 20 74 6f 6b 65 6e 0a 20 20  revious token.  
9c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9c60: 20 20 64 54 6f 6b 65 6e 4d 65 72 67 65 72 20 3d    dTokenMerger =
9c70: 20 64 54 6f 6b 65 6e 0a 20 20 20 20 20 20 20 20   dToken.        
9c80: 20 20 20 20 20 20 20 20 69 66 20 64 54 6f 6b 65          if dToke
9c90: 6e 5b 22 6e 4d 65 72 67 65 55 6e 74 69 6c 22 5d  n["nMergeUntil"]
9ca0: 20 3e 20 6e 4d 65 72 67 65 55 6e 74 69 6c 3a 0a   > nMergeUntil:.
9cb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9cc0: 20 20 20 20 6e 4d 65 72 67 65 55 6e 74 69 6c 20      nMergeUntil 
9cd0: 3d 20 64 54 6f 6b 65 6e 5b 22 6e 4d 65 72 67 65  = dToken["nMerge
9ce0: 55 6e 74 69 6c 22 5d 0a 20 20 20 20 20 20 20 20  Until"].        
9cf0: 20 20 20 20 20 20 20 20 64 65 6c 20 64 54 6f 6b          del dTok
9d00: 65 6e 5b 22 6e 4d 65 72 67 65 55 6e 74 69 6c 22  en["nMergeUntil"
9d10: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c  ].            el
9d20: 69 66 20 22 62 54 6f 52 65 6d 6f 76 65 22 20 69  if "bToRemove" i
9d30: 6e 20 64 54 6f 6b 65 6e 3a 0a 20 20 20 20 20 20  n dToken:.      
9d40: 20 20 20 20 20 20 20 20 20 20 23 20 72 65 6d 6f            # remo
9d50: 76 65 20 75 73 65 6c 65 73 73 20 74 6f 6b 65 6e  ve useless token
9d60: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9d70: 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65 20   self.sSentence 
9d80: 3d 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65  = self.sSentence
9d90: 5b 3a 64 54 6f 6b 65 6e 5b 22 6e 53 74 61 72 74  [:dToken["nStart
9da0: 22 5d 5d 20 2b 20 22 20 22 20 2a 20 28 64 54 6f  "]] + " " * (dTo
9db0: 6b 65 6e 5b 22 6e 45 6e 64 22 5d 20 2d 20 64 54  ken["nEnd"] - dT
9dc0: 6f 6b 65 6e 5b 22 6e 53 74 61 72 74 22 5d 29 20  oken["nStart"]) 
9dd0: 2b 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65  + self.sSentence
9de0: 5b 64 54 6f 6b 65 6e 5b 22 6e 45 6e 64 22 5d 3a  [dToken["nEnd"]:
9df0: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ].              
9e00: 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20    if bDebug:.   
9e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9e20: 20 70 72 69 6e 74 28 22 72 65 6d 6f 76 65 64 3a   print("removed:
9e30: 22 2c 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  ", dToken["sValu
9e40: 65 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20  e"]).           
9e50: 20 20 20 20 20 62 4b 65 65 70 54 6f 6b 65 6e 20       bKeepToken 
9e60: 3d 20 46 61 6c 73 65 0a 20 20 20 20 20 20 20 20  = False.        
9e70: 20 20 20 20 23 0a 20 20 20 20 20 20 20 20 20 20      #.          
9e80: 20 20 69 66 20 62 4b 65 65 70 54 6f 6b 65 6e 3a    if bKeepToken:
9e90: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9ea0: 20 6c 4e 65 77 54 6f 6b 65 6e 2e 61 70 70 65 6e   lNewToken.appen
9eb0: 64 28 64 54 6f 6b 65 6e 29 0a 20 20 20 20 20 20  d(dToken).      
9ec0: 20 20 20 20 20 20 20 20 20 20 69 66 20 22 73 4e            if "sN
9ed0: 65 77 56 61 6c 75 65 22 20 69 6e 20 64 54 6f 6b  ewValue" in dTok
9ee0: 65 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  en:.            
9ef0: 20 20 20 20 20 20 20 20 23 20 72 65 77 72 69 74          # rewrit
9f00: 65 20 74 6f 6b 65 6e 20 61 6e 64 20 73 65 6e 74  e token and sent
9f10: 65 6e 63 65 0a 20 20 20 20 20 20 20 20 20 20 20  ence.           
9f20: 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62           if bDeb
9f30: 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ug:.            
9f40: 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e              prin
9f50: 74 28 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65  t(dToken["sValue
9f60: 22 5d 2c 20 22 2d 3e 22 2c 20 64 54 6f 6b 65 6e  "], "->", dToken
9f70: 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d 29 0a 20  ["sNewValue"]). 
9f80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9f90: 20 20 20 64 54 6f 6b 65 6e 5b 22 73 52 65 61 6c     dToken["sReal
9fa0: 56 61 6c 75 65 22 5d 20 3d 20 64 54 6f 6b 65 6e  Value"] = dToken
9fb0: 5b 22 73 56 61 6c 75 65 22 5d 0a 20 20 20 20 20  ["sValue"].     
9fc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64                 d
9fd0: 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 20  Token["sValue"] 
9fe0: 3d 20 64 54 6f 6b 65 6e 5b 22 73 4e 65 77 56 61  = dToken["sNewVa
9ff0: 6c 75 65 22 5d 0a 20 20 20 20 20 20 20 20 20 20  lue"].          
a000: 20 20 20 20 20 20 20 20 20 20 6e 44 69 66 66 4c            nDiffL
a010: 65 6e 20 3d 20 6c 65 6e 28 64 54 6f 6b 65 6e 5b  en = len(dToken[
a020: 22 73 52 65 61 6c 56 61 6c 75 65 22 5d 29 20 2d  "sRealValue"]) -
a030: 20 6c 65 6e 28 64 54 6f 6b 65 6e 5b 22 73 4e 65   len(dToken["sNe
a040: 77 56 61 6c 75 65 22 5d 29 0a 20 20 20 20 20 20  wValue"]).      
a050: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 4e                sN
a060: 65 77 52 65 70 6c 20 3d 20 28 64 54 6f 6b 65 6e  ewRepl = (dToken
a070: 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d 20 2b 20  ["sNewValue"] + 
a080: 22 20 22 20 2a 20 6e 44 69 66 66 4c 65 6e 29 20  " " * nDiffLen) 
a090: 20 69 66 20 6e 44 69 66 66 4c 65 6e 20 3e 3d 20   if nDiffLen >= 
a0a0: 30 20 20 65 6c 73 65 20 64 54 6f 6b 65 6e 5b 22  0  else dToken["
a0b0: 73 4e 65 77 56 61 6c 75 65 22 5d 5b 3a 6c 65 6e  sNewValue"][:len
a0c0: 28 64 54 6f 6b 65 6e 5b 22 73 52 65 61 6c 56 61  (dToken["sRealVa
a0d0: 6c 75 65 22 5d 29 5d 0a 20 20 20 20 20 20 20 20  lue"])].        
a0e0: 20 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66              self
a0f0: 2e 73 53 65 6e 74 65 6e 63 65 20 3d 20 73 65 6c  .sSentence = sel
a100: 66 2e 73 53 65 6e 74 65 6e 63 65 5b 3a 64 54 6f  f.sSentence[:dTo
a110: 6b 65 6e 5b 22 6e 53 74 61 72 74 22 5d 5d 20 2b  ken["nStart"]] +
a120: 20 73 4e 65 77 52 65 70 6c 20 2b 20 73 65 6c 66   sNewRepl + self
a130: 2e 73 53 65 6e 74 65 6e 63 65 5b 64 54 6f 6b 65  .sSentence[dToke
a140: 6e 5b 22 6e 45 6e 64 22 5d 3a 5d 0a 20 20 20 20  n["nEnd"]:].    
a150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a160: 64 65 6c 20 64 54 6f 6b 65 6e 5b 22 73 4e 65 77  del dToken["sNew
a170: 56 61 6c 75 65 22 5d 0a 20 20 20 20 20 20 20 20  Value"].        
a180: 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20  if bDebug:.     
a190: 20 20 20 20 20 20 20 70 72 69 6e 74 28 73 65 6c         print(sel
a1a0: 66 2e 73 53 65 6e 74 65 6e 63 65 29 0a 20 20 20  f.sSentence).   
a1b0: 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e       self.lToken
a1c0: 2e 63 6c 65 61 72 28 29 0a 20 20 20 20 20 20 20  .clear().       
a1d0: 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 3d 20 6c   self.lToken = l
a1e0: 4e 65 77 54 6f 6b 65 6e 0a 0a 0a 0a 23 23 23 23  NewToken....####
a1f0: 20 41 6e 61 6c 79 73 65 20 74 6f 6b 65 6e 73 0a   Analyse tokens.
a200: 0a 64 65 66 20 67 5f 6d 6f 72 70 68 20 28 64 54  .def g_morph (dT
a210: 6f 6b 65 6e 2c 20 73 50 61 74 74 65 72 6e 2c 20  oken, sPattern, 
a220: 73 4e 65 67 50 61 74 74 65 72 6e 3d 22 22 29 3a  sNegPattern=""):
a230: 0a 20 20 20 20 22 61 6e 61 6c 79 73 65 20 61 20  .    "analyse a 
a240: 74 6f 6b 65 6e 2c 20 72 65 74 75 72 6e 20 54 72  token, return Tr
a250: 75 65 20 69 66 20 3c 73 4e 65 67 50 61 74 74 65  ue if <sNegPatte
a260: 72 6e 3e 20 6e 6f 74 20 69 6e 20 6d 6f 72 70 68  rn> not in morph
a270: 6f 6c 6f 67 69 65 73 20 61 6e 64 20 3c 73 50 61  ologies and <sPa
a280: 74 74 65 72 6e 3e 20 69 6e 20 6d 6f 72 70 68 6f  ttern> in morpho
a290: 6c 6f 67 69 65 73 22 0a 20 20 20 20 69 66 20 22  logies".    if "
a2a0: 6c 4d 6f 72 70 68 22 20 69 6e 20 64 54 6f 6b 65  lMorph" in dToke
a2b0: 6e 3a 0a 20 20 20 20 20 20 20 20 6c 4d 6f 72 70  n:.        lMorp
a2c0: 68 20 3d 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72  h = dToken["lMor
a2d0: 70 68 22 5d 0a 20 20 20 20 65 6c 73 65 3a 0a 20  ph"].    else:. 
a2e0: 20 20 20 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20         lMorph = 
a2f0: 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67  _oSpellChecker.g
a300: 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e 5b 22  etMorph(dToken["
a310: 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20 20 20  sValue"]).      
a320: 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 3a    if not lMorph:
a330: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
a340: 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 23 20  urn False.    # 
a350: 63 68 65 63 6b 20 6e 65 67 61 74 69 76 65 20 63  check negative c
a360: 6f 6e 64 69 74 69 6f 6e 0a 20 20 20 20 69 66 20  ondition.    if 
a370: 73 4e 65 67 50 61 74 74 65 72 6e 3a 0a 20 20 20  sNegPattern:.   
a380: 20 20 20 20 20 69 66 20 73 4e 65 67 50 61 74 74       if sNegPatt
a390: 65 72 6e 20 3d 3d 20 22 2a 22 3a 0a 20 20 20 20  ern == "*":.    
a3a0: 20 20 20 20 20 20 20 20 23 20 61 6c 6c 20 6d 6f          # all mo
a3b0: 72 70 68 20 6d 75 73 74 20 6d 61 74 63 68 20 73  rph must match s
a3c0: 50 61 74 74 65 72 6e 0a 20 20 20 20 20 20 20 20  Pattern.        
a3d0: 20 20 20 20 7a 50 61 74 74 65 72 6e 20 3d 20 72      zPattern = r
a3e0: 65 2e 63 6f 6d 70 69 6c 65 28 73 50 61 74 74 65  e.compile(sPatte
a3f0: 72 6e 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  rn).            
a400: 72 65 74 75 72 6e 20 61 6c 6c 28 7a 50 61 74 74  return all(zPatt
a410: 65 72 6e 2e 73 65 61 72 63 68 28 73 4d 6f 72 70  ern.search(sMorp
a420: 68 29 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69  h)  for sMorph i
a430: 6e 20 6c 4d 6f 72 70 68 29 0a 20 20 20 20 20 20  n lMorph).      
a440: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
a450: 20 20 20 20 7a 4e 65 67 50 61 74 74 65 72 6e 20      zNegPattern 
a460: 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 4e 65  = re.compile(sNe
a470: 67 50 61 74 74 65 72 6e 29 0a 20 20 20 20 20 20  gPattern).      
a480: 20 20 20 20 20 20 69 66 20 61 6e 79 28 7a 4e 65        if any(zNe
a490: 67 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28  gPattern.search(
a4a0: 73 4d 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f  sMorph)  for sMo
a4b0: 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29 3a 0a  rph in lMorph):.
a4c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a4d0: 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20  return False.   
a4e0: 20 23 20 73 65 61 72 63 68 20 73 50 61 74 74 65   # search sPatte
a4f0: 72 6e 0a 20 20 20 20 7a 50 61 74 74 65 72 6e 20  rn.    zPattern 
a500: 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 50 61  = re.compile(sPa
a510: 74 74 65 72 6e 29 0a 20 20 20 20 72 65 74 75 72  ttern).    retur
a520: 6e 20 61 6e 79 28 7a 50 61 74 74 65 72 6e 2e 73  n any(zPattern.s
a530: 65 61 72 63 68 28 73 4d 6f 72 70 68 29 20 20 66  earch(sMorph)  f
a540: 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f  or sMorph in lMo
a550: 72 70 68 29 0a 0a 0a 64 65 66 20 67 5f 61 6e 61  rph)...def g_ana
a560: 6c 79 73 65 20 28 64 54 6f 6b 65 6e 2c 20 73 50  lyse (dToken, sP
a570: 61 74 74 65 72 6e 2c 20 73 4e 65 67 50 61 74 74  attern, sNegPatt
a580: 65 72 6e 3d 22 22 29 3a 0a 20 20 20 20 22 61 6e  ern=""):.    "an
a590: 61 6c 79 73 65 20 61 20 74 6f 6b 65 6e 2c 20 72  alyse a token, r
a5a0: 65 74 75 72 6e 20 54 72 75 65 20 69 66 20 3c 73  eturn True if <s
a5b0: 4e 65 67 50 61 74 74 65 72 6e 3e 20 6e 6f 74 20  NegPattern> not 
a5c0: 69 6e 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20  in morphologies 
a5d0: 61 6e 64 20 3c 73 50 61 74 74 65 72 6e 3e 20 69  and <sPattern> i
a5e0: 6e 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 28  n morphologies (
a5f0: 64 69 73 61 6d 62 69 67 75 61 74 69 6f 6e 20 6f  disambiguation o
a600: 66 66 29 22 0a 20 20 20 20 6c 4d 6f 72 70 68 20  ff)".    lMorph 
a610: 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72  = _oSpellChecker
a620: 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e  .getMorph(dToken
a630: 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20  ["sValue"]).    
a640: 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 3a 0a 20  if not lMorph:. 
a650: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 46 61         return Fa
a660: 6c 73 65 0a 20 20 20 20 23 20 63 68 65 63 6b 20  lse.    # check 
a670: 6e 65 67 61 74 69 76 65 20 63 6f 6e 64 69 74 69  negative conditi
a680: 6f 6e 0a 20 20 20 20 69 66 20 73 4e 65 67 50 61  on.    if sNegPa
a690: 74 74 65 72 6e 3a 0a 20 20 20 20 20 20 20 20 69  ttern:.        i
a6a0: 66 20 73 4e 65 67 50 61 74 74 65 72 6e 20 3d 3d  f sNegPattern ==
a6b0: 20 22 2a 22 3a 0a 20 20 20 20 20 20 20 20 20 20   "*":.          
a6c0: 20 20 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e    zPattern = re.
a6d0: 63 6f 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e  compile(sPattern
a6e0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  ).            re
a6f0: 74 75 72 6e 20 61 6c 6c 28 7a 50 61 74 74 65 72  turn all(zPatter
a700: 6e 2e 73 65 61 72 63 68 28 73 4d 6f 72 70 68 29  n.search(sMorph)
a710: 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20    for sMorph in 
a720: 6c 4d 6f 72 70 68 29 0a 20 20 20 20 20 20 20 20  lMorph).        
a730: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
a740: 20 20 7a 4e 65 67 50 61 74 74 65 72 6e 20 3d 20    zNegPattern = 
a750: 72 65 2e 63 6f 6d 70 69 6c 65 28 73 4e 65 67 50  re.compile(sNegP
a760: 61 74 74 65 72 6e 29 0a 20 20 20 20 20 20 20 20  attern).        
a770: 20 20 20 20 69 66 20 61 6e 79 28 7a 4e 65 67 50      if any(zNegP
a780: 61 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73 4d  attern.search(sM
a790: 6f 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70  orph)  for sMorp
a7a0: 68 20 69 6e 20 6c 4d 6f 72 70 68 29 3a 0a 20 20  h in lMorph):.  
a7b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
a7c0: 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 23  turn False.    #
a7d0: 20 73 65 61 72 63 68 20 73 50 61 74 74 65 72 6e   search sPattern
a7e0: 0a 20 20 20 20 7a 50 61 74 74 65 72 6e 20 3d 20  .    zPattern = 
a7f0: 72 65 2e 63 6f 6d 70 69 6c 65 28 73 50 61 74 74  re.compile(sPatt
a800: 65 72 6e 29 0a 20 20 20 20 72 65 74 75 72 6e 20  ern).    return 
a810: 61 6e 79 28 7a 50 61 74 74 65 72 6e 2e 73 65 61  any(zPattern.sea
a820: 72 63 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72  rch(sMorph)  for
a830: 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70   sMorph in lMorp
a840: 68 29 0a 0a 0a 64 65 66 20 67 5f 74 61 67 5f 62  h)...def g_tag_b
a850: 65 66 6f 72 65 20 28 64 54 6f 6b 65 6e 2c 20 64  efore (dToken, d
a860: 54 61 67 73 2c 20 73 54 61 67 29 3a 0a 20 20 20  Tags, sTag):.   
a870: 20 69 66 20 73 54 61 67 20 6e 6f 74 20 69 6e 20   if sTag not in 
a880: 64 54 61 67 73 3a 0a 20 20 20 20 20 20 20 20 72  dTags:.        r
a890: 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20  eturn False.    
a8a0: 69 66 20 64 54 6f 6b 65 6e 5b 22 69 22 5d 20 3e  if dToken["i"] >
a8b0: 20 64 54 61 67 73 5b 73 54 61 67 5d 5b 30 5d 3a   dTags[sTag][0]:
a8c0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
a8d0: 54 72 75 65 0a 20 20 20 20 72 65 74 75 72 6e 20  True.    return 
a8e0: 46 61 6c 73 65 0a 0a 0a 64 65 66 20 67 5f 74 61  False...def g_ta
a8f0: 67 5f 61 66 74 65 72 20 28 64 54 6f 6b 65 6e 2c  g_after (dToken,
a900: 20 64 54 61 67 73 2c 20 73 54 61 67 29 3a 0a 20   dTags, sTag):. 
a910: 20 20 20 69 66 20 73 54 61 67 20 6e 6f 74 20 69     if sTag not i
a920: 6e 20 64 54 61 67 73 3a 0a 20 20 20 20 20 20 20  n dTags:.       
a930: 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20   return False.  
a940: 20 20 69 66 20 64 54 6f 6b 65 6e 5b 22 69 22 5d    if dToken["i"]
a950: 20 3c 20 64 54 61 67 73 5b 73 54 61 67 5d 5b 31   < dTags[sTag][1
a960: 5d 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  ]:.        retur
a970: 6e 20 54 72 75 65 0a 20 20 20 20 72 65 74 75 72  n True.    retur
a980: 6e 20 46 61 6c 73 65 0a 0a 0a 23 23 23 23 20 44  n False...#### D
a990: 69 73 61 6d 62 69 67 75 61 74 6f 72 0a 0a 64 65  isambiguator..de
a9a0: 66 20 67 5f 73 65 6c 65 63 74 20 28 64 54 6f 6b  f g_select (dTok
a9b0: 65 6e 2c 20 73 50 61 74 74 65 72 6e 2c 20 6c 44  en, sPattern, lD
a9c0: 65 66 61 75 6c 74 3d 4e 6f 6e 65 29 3a 0a 20 20  efault=None):.  
a9d0: 20 20 22 73 65 6c 65 63 74 20 6d 6f 72 70 68 6f    "select morpho
a9e0: 6c 6f 67 69 65 73 20 66 6f 72 20 3c 64 54 6f 6b  logies for <dTok
a9f0: 65 6e 3e 20 61 63 63 6f 72 64 69 6e 67 20 74 6f  en> according to
aa00: 20 3c 73 50 61 74 74 65 72 6e 3e 2c 20 61 6c 77   <sPattern>, alw
aa10: 61 79 73 20 72 65 74 75 72 6e 20 54 72 75 65 22  ays return True"
aa20: 0a 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20 64 54  .    lMorph = dT
aa30: 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 20  oken["lMorph"]  
aa40: 69 66 20 22 6c 4d 6f 72 70 68 22 20 69 6e 20 64  if "lMorph" in d
aa50: 54 6f 6b 65 6e 20 20 65 6c 73 65 20 5f 6f 53 70  Token  else _oSp
aa60: 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f  ellChecker.getMo
aa70: 72 70 68 28 64 54 6f 6b 65 6e 5b 22 73 56 61 6c  rph(dToken["sVal
aa80: 75 65 22 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74  ue"]).    if not
aa90: 20 6c 4d 6f 72 70 68 20 6f 72 20 6c 65 6e 28 6c   lMorph or len(l
aaa0: 4d 6f 72 70 68 29 20 3d 3d 20 31 3a 0a 20 20 20  Morph) == 1:.   
aab0: 20 20 20 20 20 69 66 20 6c 44 65 66 61 75 6c 74       if lDefault
aac0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 54  :.            dT
aad0: 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d  oken["lMorph"] =
aae0: 20 6c 44 65 66 61 75 6c 74 0a 20 20 20 20 20 20   lDefault.      
aaf0: 20 20 20 20 20 20 23 70 72 69 6e 74 28 22 44 41        #print("DA
ab00: 3a 22 2c 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c  :", dToken["sVal
ab10: 75 65 22 5d 2c 20 64 54 6f 6b 65 6e 5b 22 6c 4d  ue"], dToken["lM
ab20: 6f 72 70 68 22 5d 29 0a 20 20 20 20 20 20 20 20  orph"]).        
ab30: 72 65 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20  return True.    
ab40: 6c 53 65 6c 65 63 74 20 3d 20 5b 20 73 4d 6f 72  lSelect = [ sMor
ab50: 70 68 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69  ph  for sMorph i
ab60: 6e 20 6c 4d 6f 72 70 68 20 20 69 66 20 72 65 2e  n lMorph  if re.
ab70: 73 65 61 72 63 68 28 73 50 61 74 74 65 72 6e 2c  search(sPattern,
ab80: 20 73 4d 6f 72 70 68 29 20 5d 0a 20 20 20 20 69   sMorph) ].    i
ab90: 66 20 6c 53 65 6c 65 63 74 3a 0a 20 20 20 20 20  f lSelect:.     
aba0: 20 20 20 69 66 20 6c 65 6e 28 6c 53 65 6c 65 63     if len(lSelec
abb0: 74 29 20 21 3d 20 6c 65 6e 28 6c 4d 6f 72 70 68  t) != len(lMorph
abc0: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  ):.            d
abd0: 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20  Token["lMorph"] 
abe0: 3d 20 6c 53 65 6c 65 63 74 0a 20 20 20 20 65 6c  = lSelect.    el
abf0: 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a 20 20 20  if lDefault:.   
ac00: 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f       dToken["lMo
ac10: 72 70 68 22 5d 20 3d 20 6c 44 65 66 61 75 6c 74  rph"] = lDefault
ac20: 0a 20 20 20 20 23 70 72 69 6e 74 28 22 44 41 3a  .    #print("DA:
ac30: 22 2c 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  ", dToken["sValu
ac40: 65 22 5d 2c 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f  e"], dToken["lMo
ac50: 72 70 68 22 5d 29 0a 20 20 20 20 72 65 74 75 72  rph"]).    retur
ac60: 6e 20 54 72 75 65 0a 0a 0a 64 65 66 20 67 5f 65  n True...def g_e
ac70: 78 63 6c 75 64 65 20 28 64 54 6f 6b 65 6e 2c 20  xclude (dToken, 
ac80: 73 50 61 74 74 65 72 6e 2c 20 6c 44 65 66 61 75  sPattern, lDefau
ac90: 6c 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 73  lt=None):.    "s
aca0: 65 6c 65 63 74 20 6d 6f 72 70 68 6f 6c 6f 67 69  elect morphologi
acb0: 65 73 20 66 6f 72 20 3c 64 54 6f 6b 65 6e 3e 20  es for <dToken> 
acc0: 61 63 63 6f 72 64 69 6e 67 20 74 6f 20 3c 73 50  according to <sP
acd0: 61 74 74 65 72 6e 3e 2c 20 61 6c 77 61 79 73 20  attern>, always 
ace0: 72 65 74 75 72 6e 20 54 72 75 65 22 0a 20 20 20  return True".   
acf0: 20 6c 4d 6f 72 70 68 20 3d 20 64 54 6f 6b 65 6e   lMorph = dToken
ad00: 5b 22 6c 4d 6f 72 70 68 22 5d 20 20 69 66 20 22  ["lMorph"]  if "
ad10: 6c 4d 6f 72 70 68 22 20 69 6e 20 64 54 6f 6b 65  lMorph" in dToke
ad20: 6e 20 20 65 6c 73 65 20 5f 6f 53 70 65 6c 6c 43  n  else _oSpellC
ad30: 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28  hecker.getMorph(
ad40: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
ad50: 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f  ).    if not lMo
ad60: 72 70 68 20 6f 72 20 6c 65 6e 28 6c 4d 6f 72 70  rph or len(lMorp
ad70: 68 29 20 3d 3d 20 31 3a 0a 20 20 20 20 20 20 20  h) == 1:.       
ad80: 20 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a 20 20   if lDefault:.  
ad90: 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e            dToken
ada0: 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 44 65  ["lMorph"] = lDe
adb0: 66 61 75 6c 74 0a 20 20 20 20 20 20 20 20 20 20  fault.          
adc0: 20 20 23 70 72 69 6e 74 28 22 44 41 3a 22 2c 20    #print("DA:", 
add0: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
ade0: 2c 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68  , dToken["lMorph
adf0: 22 5d 29 0a 20 20 20 20 20 20 20 20 72 65 74 75  "]).        retu
ae00: 72 6e 20 54 72 75 65 0a 20 20 20 20 6c 53 65 6c  rn True.    lSel
ae10: 65 63 74 20 3d 20 5b 20 73 4d 6f 72 70 68 20 20  ect = [ sMorph  
ae20: 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d  for sMorph in lM
ae30: 6f 72 70 68 20 20 69 66 20 6e 6f 74 20 72 65 2e  orph  if not re.
ae40: 73 65 61 72 63 68 28 73 50 61 74 74 65 72 6e 2c  search(sPattern,
ae50: 20 73 4d 6f 72 70 68 29 20 5d 0a 20 20 20 20 69   sMorph) ].    i
ae60: 66 20 6c 53 65 6c 65 63 74 3a 0a 20 20 20 20 20  f lSelect:.     
ae70: 20 20 20 69 66 20 6c 65 6e 28 6c 53 65 6c 65 63     if len(lSelec
ae80: 74 29 20 21 3d 20 6c 65 6e 28 6c 4d 6f 72 70 68  t) != len(lMorph
ae90: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  ):.            d
aea0: 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20  Token["lMorph"] 
aeb0: 3d 20 6c 53 65 6c 65 63 74 0a 20 20 20 20 65 6c  = lSelect.    el
aec0: 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a 20 20 20  if lDefault:.   
aed0: 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f       dToken["lMo
aee0: 72 70 68 22 5d 20 3d 20 6c 44 65 66 61 75 6c 74  rph"] = lDefault
aef0: 0a 20 20 20 20 23 70 72 69 6e 74 28 22 44 41 3a  .    #print("DA:
af00: 22 2c 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  ", dToken["sValu
af10: 65 22 5d 2c 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f  e"], dToken["lMo
af20: 72 70 68 22 5d 29 0a 20 20 20 20 72 65 74 75 72  rph"]).    retur
af30: 6e 20 54 72 75 65 0a 0a 0a 64 65 66 20 67 5f 64  n True...def g_d
af40: 65 66 69 6e 65 20 28 64 54 6f 6b 65 6e 2c 20 6c  efine (dToken, l
af50: 4d 6f 72 70 68 29 3a 0a 20 20 20 20 22 73 65 74  Morph):.    "set
af60: 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 6f 66   morphologies of
af70: 20 3c 64 54 6f 6b 65 6e 3e 2c 20 61 6c 77 61 79   <dToken>, alway
af80: 73 20 72 65 74 75 72 6e 20 54 72 75 65 22 0a 20  s return True". 
af90: 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70     dToken["lMorp
afa0: 68 22 5d 20 3d 20 6c 4d 6f 72 70 68 0a 20 20 20  h"] = lMorph.   
afb0: 20 23 70 72 69 6e 74 28 22 44 41 3a 22 2c 20 64   #print("DA:", d
afc0: 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2c  Token["sValue"],
afd0: 20 6c 4d 6f 72 70 68 29 0a 20 20 20 20 72 65 74   lMorph).    ret
afe0: 75 72 6e 20 54 72 75 65 0a 0a 0a 0a 23 23 23 23  urn True....####
aff0: 20 47 52 41 4d 4d 41 52 20 43 48 45 43 4b 45 52   GRAMMAR CHECKER
b000: 20 50 4c 55 47 49 4e 53 0a 0a 24 7b 70 6c 75 67   PLUGINS..${plug
b010: 69 6e 73 7d 0a 0a 0a 23 23 23 23 20 43 41 4c 4c  ins}...#### CALL
b020: 41 42 4c 45 53 20 46 4f 52 20 52 45 47 45 58 20  ABLES FOR REGEX 
b030: 52 55 4c 45 53 20 28 67 65 6e 65 72 61 74 65 64  RULES (generated
b040: 20 63 6f 64 65 29 0a 0a 24 7b 63 61 6c 6c 61 62   code)..${callab
b050: 6c 65 73 7d 0a 0a 0a 23 23 23 23 20 43 41 4c 4c  les}...#### CALL
b060: 41 42 4c 45 53 20 46 4f 52 20 47 52 41 50 48 20  ABLES FOR GRAPH 
b070: 52 55 4c 45 53 20 28 67 65 6e 65 72 61 74 65 64  RULES (generated
b080: 20 63 6f 64 65 29 0a 0a 24 7b 67 72 61 70 68 5f   code)..${graph_
b090: 63 61 6c 6c 61 62 6c 65 73 7d 0a                 callables}.