Grammalecte  Hex Artifact Content

Artifact 6ed05b155179195f248085f8987f6fcde59a0f7d90be27ef52899203144894af:


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 0a  Rules = set()...
0570: 0a 23 23 23 23 20 49 6e 69 74 69 61 6c 69 7a 61  .#### Initializa
0580: 74 69 6f 6e 0a 0a 64 65 66 20 6c 6f 61 64 20 28  tion..def load (
0590: 73 43 6f 6e 74 65 78 74 3d 22 50 79 74 68 6f 6e  sContext="Python
05a0: 22 29 3a 0a 20 20 20 20 22 69 6e 69 74 69 61 6c  "):.    "initial
05b0: 69 7a 61 74 69 6f 6e 20 6f 66 20 74 68 65 20 67  ization of the g
05c0: 72 61 6d 6d 61 72 20 63 68 65 63 6b 65 72 22 0a  rammar checker".
05d0: 20 20 20 20 67 6c 6f 62 61 6c 20 5f 6f 53 70 65      global _oSpe
05e0: 6c 6c 43 68 65 63 6b 65 72 0a 20 20 20 20 67 6c  llChecker.    gl
05f0: 6f 62 61 6c 20 5f 73 41 70 70 43 6f 6e 74 65 78  obal _sAppContex
0600: 74 0a 20 20 20 20 67 6c 6f 62 61 6c 20 5f 64 4f  t.    global _dO
0610: 70 74 69 6f 6e 73 0a 20 20 20 20 67 6c 6f 62 61  ptions.    globa
0620: 6c 20 5f 6f 54 6f 6b 65 6e 69 7a 65 72 0a 20 20  l _oTokenizer.  
0630: 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 5f    try:.        _
0640: 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 20 3d 20  oSpellChecker = 
0650: 53 70 65 6c 6c 43 68 65 63 6b 65 72 28 22 24 7b  SpellChecker("${
0660: 6c 61 6e 67 7d 22 2c 20 22 24 7b 64 69 63 5f 6d  lang}", "${dic_m
0670: 61 69 6e 5f 66 69 6c 65 6e 61 6d 65 5f 70 79 7d  ain_filename_py}
0680: 22 2c 20 22 24 7b 64 69 63 5f 65 78 74 65 6e 64  ", "${dic_extend
0690: 65 64 5f 66 69 6c 65 6e 61 6d 65 5f 70 79 7d 22  ed_filename_py}"
06a0: 2c 20 22 24 7b 64 69 63 5f 63 6f 6d 6d 75 6e 69  , "${dic_communi
06b0: 74 79 5f 66 69 6c 65 6e 61 6d 65 5f 70 79 7d 22  ty_filename_py}"
06c0: 2c 20 22 24 7b 64 69 63 5f 70 65 72 73 6f 6e 61  , "${dic_persona
06d0: 6c 5f 66 69 6c 65 6e 61 6d 65 5f 70 79 7d 22 29  l_filename_py}")
06e0: 0a 20 20 20 20 20 20 20 20 5f 73 41 70 70 43 6f  .        _sAppCo
06f0: 6e 74 65 78 74 20 3d 20 73 43 6f 6e 74 65 78 74  ntext = sContext
0700: 0a 20 20 20 20 20 20 20 20 5f 64 4f 70 74 69 6f  .        _dOptio
0710: 6e 73 20 3d 20 64 69 63 74 28 67 63 5f 6f 70 74  ns = dict(gc_opt
0720: 69 6f 6e 73 2e 67 65 74 4f 70 74 69 6f 6e 73 28  ions.getOptions(
0730: 73 43 6f 6e 74 65 78 74 29 29 20 20 20 23 20 64  sContext))   # d
0740: 75 70 6c 69 63 61 74 69 6f 6e 20 6e 65 63 65 73  uplication neces
0750: 73 61 72 79 2c 20 74 6f 20 62 65 20 61 62 6c 65  sary, to be able
0760: 20 74 6f 20 72 65 73 65 74 20 74 6f 20 64 65 66   to reset to def
0770: 61 75 6c 74 0a 20 20 20 20 20 20 20 20 5f 6f 54  ault.        _oT
0780: 6f 6b 65 6e 69 7a 65 72 20 3d 20 5f 6f 53 70 65  okenizer = _oSpe
0790: 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 54 6f 6b  llChecker.getTok
07a0: 65 6e 69 7a 65 72 28 29 0a 20 20 20 20 20 20 20  enizer().       
07b0: 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e   _oSpellChecker.
07c0: 61 63 74 69 76 61 74 65 53 74 6f 72 61 67 65 28  activateStorage(
07d0: 29 0a 20 20 20 20 65 78 63 65 70 74 3a 0a 20 20  ).    except:.  
07e0: 20 20 20 20 20 20 74 72 61 63 65 62 61 63 6b 2e        traceback.
07f0: 70 72 69 6e 74 5f 65 78 63 28 29 0a 0a 0a 64 65  print_exc()...de
0800: 66 20 5f 67 65 74 52 75 6c 65 73 20 28 62 50 61  f _getRules (bPa
0810: 72 61 67 72 61 70 68 29 3a 0a 20 20 20 20 74 72  ragraph):.    tr
0820: 79 3a 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f  y:.        if no
0830: 74 20 62 50 61 72 61 67 72 61 70 68 3a 0a 20 20  t bParagraph:.  
0840: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
0850: 20 5f 72 75 6c 65 73 2e 6c 53 65 6e 74 65 6e 63   _rules.lSentenc
0860: 65 52 75 6c 65 73 0a 20 20 20 20 20 20 20 20 72  eRules.        r
0870: 65 74 75 72 6e 20 5f 72 75 6c 65 73 2e 6c 50 61  eturn _rules.lPa
0880: 72 61 67 72 61 70 68 52 75 6c 65 73 0a 20 20 20  ragraphRules.   
0890: 20 65 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20   except:.       
08a0: 20 5f 6c 6f 61 64 52 75 6c 65 73 28 29 0a 20 20   _loadRules().  
08b0: 20 20 69 66 20 6e 6f 74 20 62 50 61 72 61 67 72    if not bParagr
08c0: 61 70 68 3a 0a 20 20 20 20 20 20 20 20 72 65 74  aph:.        ret
08d0: 75 72 6e 20 5f 72 75 6c 65 73 2e 6c 53 65 6e 74  urn _rules.lSent
08e0: 65 6e 63 65 52 75 6c 65 73 0a 20 20 20 20 72 65  enceRules.    re
08f0: 74 75 72 6e 20 5f 72 75 6c 65 73 2e 6c 50 61 72  turn _rules.lPar
0900: 61 67 72 61 70 68 52 75 6c 65 73 0a 0a 0a 64 65  agraphRules...de
0910: 66 20 5f 6c 6f 61 64 52 75 6c 65 73 20 28 29 3a  f _loadRules ():
0920: 0a 20 20 20 20 66 72 6f 6d 20 2e 20 69 6d 70 6f  .    from . impo
0930: 72 74 20 67 63 5f 72 75 6c 65 73 0a 20 20 20 20  rt gc_rules.    
0940: 67 6c 6f 62 61 6c 20 5f 72 75 6c 65 73 0a 20 20  global _rules.  
0950: 20 20 5f 72 75 6c 65 73 20 3d 20 67 63 5f 72 75    _rules = gc_ru
0960: 6c 65 73 0a 20 20 20 20 23 20 63 6f 6d 70 69 6c  les.    # compil
0970: 65 20 72 75 6c 65 73 20 72 65 67 65 78 0a 20 20  e rules regex.  
0980: 20 20 66 6f 72 20 73 4f 70 74 69 6f 6e 2c 20 6c    for sOption, l
0990: 52 75 6c 65 47 72 6f 75 70 20 69 6e 20 63 68 61  RuleGroup in cha
09a0: 69 6e 28 5f 72 75 6c 65 73 2e 6c 50 61 72 61 67  in(_rules.lParag
09b0: 72 61 70 68 52 75 6c 65 73 2c 20 5f 72 75 6c 65  raphRules, _rule
09c0: 73 2e 6c 53 65 6e 74 65 6e 63 65 52 75 6c 65 73  s.lSentenceRules
09d0: 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20 73 4f  ):.        if sO
09e0: 70 74 69 6f 6e 20 21 3d 20 22 40 40 40 40 22 3a  ption != "@@@@":
09f0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72  .            for
0a00: 20 61 52 75 6c 65 20 69 6e 20 6c 52 75 6c 65 47   aRule in lRuleG
0a10: 72 6f 75 70 3a 0a 20 20 20 20 20 20 20 20 20 20  roup:.          
0a20: 20 20 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20        try:.     
0a30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 61                 a
0a40: 52 75 6c 65 5b 30 5d 20 3d 20 72 65 2e 63 6f 6d  Rule[0] = re.com
0a50: 70 69 6c 65 28 61 52 75 6c 65 5b 30 5d 29 0a 20  pile(aRule[0]). 
0a60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
0a70: 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20 20  xcept:.         
0a80: 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f 28             echo(
0a90: 22 42 61 64 20 72 65 67 75 6c 61 72 20 65 78 70  "Bad regular exp
0aa0: 72 65 73 73 69 6f 6e 20 69 6e 20 23 20 22 20 2b  ression in # " +
0ab0: 20 73 74 72 28 61 52 75 6c 65 5b 32 5d 29 29 0a   str(aRule[2])).
0ac0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ad0: 20 20 20 20 61 52 75 6c 65 5b 30 5d 20 3d 20 22      aRule[0] = "
0ae0: 28 3f 69 29 3c 47 72 61 6d 6d 61 6c 65 63 74 65  (?i)<Grammalecte
0af0: 3e 22 0a 0a 0a 23 23 23 23 20 50 61 72 73 69 6e  >"...#### Parsin
0b00: 67 0a 0a 5f 7a 45 6e 64 4f 66 53 65 6e 74 65 6e  g.._zEndOfSenten
0b10: 63 65 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28  ce = re.compile(
0b20: 72 27 28 5b 2e 3f 21 3a 3b e2 80 a6 5d 5b 20 2e  r'([.?!:;...][ .
0b30: 3f 21 e2 80 a6 20 c2 bb e2 80 9d 22 29 5d 2a 7c  ?!... .....")]*|
0b40: 2e 24 29 27 29 0a 5f 7a 42 65 67 69 6e 4f 66 50  .$)')._zBeginOfP
0b50: 61 72 61 67 72 61 70 68 20 3d 20 72 65 2e 63 6f  aragraph = re.co
0b60: 6d 70 69 6c 65 28 72 22 5e 5c 57 2a 22 29 0a 5f  mpile(r"^\W*")._
0b70: 7a 45 6e 64 4f 66 50 61 72 61 67 72 61 70 68 20  zEndOfParagraph 
0b80: 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 72 22 5c  = re.compile(r"\
0b90: 57 2a 24 22 29 0a 0a 64 65 66 20 5f 67 65 74 53  W*$")..def _getS
0ba0: 65 6e 74 65 6e 63 65 42 6f 75 6e 64 61 72 69 65  entenceBoundarie
0bb0: 73 20 28 73 54 65 78 74 29 3a 0a 20 20 20 20 69  s (sText):.    i
0bc0: 53 74 61 72 74 20 3d 20 5f 7a 42 65 67 69 6e 4f  Start = _zBeginO
0bd0: 66 50 61 72 61 67 72 61 70 68 2e 6d 61 74 63 68  fParagraph.match
0be0: 28 73 54 65 78 74 29 2e 65 6e 64 28 29 0a 20 20  (sText).end().  
0bf0: 20 20 66 6f 72 20 6d 20 69 6e 20 5f 7a 45 6e 64    for m in _zEnd
0c00: 4f 66 53 65 6e 74 65 6e 63 65 2e 66 69 6e 64 69  OfSentence.findi
0c10: 74 65 72 28 73 54 65 78 74 29 3a 0a 20 20 20 20  ter(sText):.    
0c20: 20 20 20 20 79 69 65 6c 64 20 28 69 53 74 61 72      yield (iStar
0c30: 74 2c 20 6d 2e 65 6e 64 28 29 29 0a 20 20 20 20  t, m.end()).    
0c40: 20 20 20 20 69 53 74 61 72 74 20 3d 20 6d 2e 65      iStart = m.e
0c50: 6e 64 28 29 0a 0a 0a 64 65 66 20 70 61 72 73 65  nd()...def parse
0c60: 20 28 73 54 65 78 74 2c 20 73 43 6f 75 6e 74 72   (sText, sCountr
0c70: 79 3d 22 24 7b 63 6f 75 6e 74 72 79 5f 64 65 66  y="${country_def
0c80: 61 75 6c 74 7d 22 2c 20 62 44 65 62 75 67 3d 46  ault}", bDebug=F
0c90: 61 6c 73 65 2c 20 64 4f 70 74 69 6f 6e 73 3d 4e  alse, dOptions=N
0ca0: 6f 6e 65 2c 20 62 43 6f 6e 74 65 78 74 3d 46 61  one, bContext=Fa
0cb0: 6c 73 65 29 3a 0a 20 20 20 20 22 61 6e 61 6c 79  lse):.    "analy
0cc0: 73 65 73 20 74 68 65 20 70 61 72 61 67 72 61 70  ses the paragrap
0cd0: 68 20 73 54 65 78 74 20 61 6e 64 20 72 65 74 75  h sText and retu
0ce0: 72 6e 73 20 6c 69 73 74 20 6f 66 20 65 72 72 6f  rns list of erro
0cf0: 72 73 22 0a 20 20 20 20 23 73 54 65 78 74 20 3d  rs".    #sText =
0d00: 20 75 6e 69 63 6f 64 65 64 61 74 61 2e 6e 6f 72   unicodedata.nor
0d10: 6d 61 6c 69 7a 65 28 22 4e 46 43 22 2c 20 73 54  malize("NFC", sT
0d20: 65 78 74 29 0a 20 20 20 20 64 45 72 72 6f 72 73  ext).    dErrors
0d30: 20 3d 20 7b 7d 0a 20 20 20 20 73 52 65 61 6c 54   = {}.    sRealT
0d40: 65 78 74 20 3d 20 73 54 65 78 74 0a 20 20 20 20  ext = sText.    
0d50: 64 50 72 69 6f 72 69 74 79 20 3d 20 7b 7d 20 20  dPriority = {}  
0d60: 23 20 4b 65 79 20 3d 20 70 6f 73 69 74 69 6f 6e  # Key = position
0d70: 3b 20 76 61 6c 75 65 20 3d 20 70 72 69 6f 72 69  ; value = priori
0d80: 74 79 0a 20 20 20 20 64 4f 70 74 20 3d 20 5f 64  ty.    dOpt = _d
0d90: 4f 70 74 69 6f 6e 73 20 20 69 66 20 6e 6f 74 20  Options  if not 
0da0: 64 4f 70 74 69 6f 6e 73 20 20 65 6c 73 65 20 64  dOptions  else d
0db0: 4f 70 74 69 6f 6e 73 0a 20 20 20 20 62 53 68 6f  Options.    bSho
0dc0: 77 52 75 6c 65 49 64 20 3d 20 6f 70 74 69 6f 6e  wRuleId = option
0dd0: 28 27 69 64 72 75 6c 65 27 29 0a 0a 20 20 20 20  ('idrule')..    
0de0: 23 20 70 61 72 73 65 20 70 61 72 61 67 72 61 70  # parse paragrap
0df0: 68 0a 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20  h.    try:.     
0e00: 20 20 20 73 4e 65 77 2c 20 64 45 72 72 6f 72 73     sNew, dErrors
0e10: 20 3d 20 5f 70 72 6f 6f 66 72 65 61 64 28 4e 6f   = _proofread(No
0e20: 6e 65 2c 20 73 54 65 78 74 2c 20 73 52 65 61 6c  ne, sText, sReal
0e30: 54 65 78 74 2c 20 30 2c 20 54 72 75 65 2c 20 64  Text, 0, True, d
0e40: 45 72 72 6f 72 73 2c 20 64 50 72 69 6f 72 69 74  Errors, dPriorit
0e50: 79 2c 20 73 43 6f 75 6e 74 72 79 2c 20 64 4f 70  y, sCountry, dOp
0e60: 74 2c 20 62 53 68 6f 77 52 75 6c 65 49 64 2c 20  t, bShowRuleId, 
0e70: 62 44 65 62 75 67 2c 20 62 43 6f 6e 74 65 78 74  bDebug, bContext
0e80: 29 0a 20 20 20 20 20 20 20 20 69 66 20 73 4e 65  ).        if sNe
0e90: 77 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  w:.            s
0ea0: 54 65 78 74 20 3d 20 73 4e 65 77 0a 20 20 20 20  Text = sNew.    
0eb0: 65 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20  except:.        
0ec0: 72 61 69 73 65 0a 0a 20 20 20 20 23 20 63 6c 65  raise..    # cle
0ed0: 61 6e 75 70 0a 20 20 20 20 69 66 20 22 c2 a0 22  anup.    if ".."
0ee0: 20 69 6e 20 73 54 65 78 74 3a 0a 20 20 20 20 20   in sText:.     
0ef0: 20 20 20 73 54 65 78 74 20 3d 20 73 54 65 78 74     sText = sText
0f00: 2e 72 65 70 6c 61 63 65 28 22 c2 a0 22 2c 20 27  .replace("..", '
0f10: 20 27 29 20 23 20 6e 62 73 70 0a 20 20 20 20 69   ') # nbsp.    i
0f20: 66 20 22 e2 80 af 22 20 69 6e 20 73 54 65 78 74  f "..." in sText
0f30: 3a 0a 20 20 20 20 20 20 20 20 73 54 65 78 74 20  :.        sText 
0f40: 3d 20 73 54 65 78 74 2e 72 65 70 6c 61 63 65 28  = sText.replace(
0f50: 22 e2 80 af 22 2c 20 27 20 27 29 20 23 20 6e 6e  "...", ' ') # nn
0f60: 62 73 70 0a 20 20 20 20 69 66 20 22 27 22 20 69  bsp.    if "'" i
0f70: 6e 20 73 54 65 78 74 3a 0a 20 20 20 20 20 20 20  n sText:.       
0f80: 20 73 54 65 78 74 20 3d 20 73 54 65 78 74 2e 72   sText = sText.r
0f90: 65 70 6c 61 63 65 28 22 27 22 2c 20 22 e2 80 99  eplace("'", "...
0fa0: 22 29 0a 20 20 20 20 69 66 20 22 e2 80 91 22 20  ").    if "..." 
0fb0: 69 6e 20 73 54 65 78 74 3a 0a 20 20 20 20 20 20  in sText:.      
0fc0: 20 20 73 54 65 78 74 20 3d 20 73 54 65 78 74 2e    sText = sText.
0fd0: 72 65 70 6c 61 63 65 28 22 e2 80 91 22 2c 20 22  replace("...", "
0fe0: 2d 22 29 20 23 20 6e 6f 62 72 65 61 6b 64 61 73  -") # nobreakdas
0ff0: 68 0a 0a 20 20 20 20 23 20 70 61 72 73 65 20 73  h..    # parse s
1000: 65 6e 74 65 6e 63 65 73 0a 20 20 20 20 66 6f 72  entences.    for
1010: 20 69 53 74 61 72 74 2c 20 69 45 6e 64 20 69 6e   iStart, iEnd in
1020: 20 5f 67 65 74 53 65 6e 74 65 6e 63 65 42 6f 75   _getSentenceBou
1030: 6e 64 61 72 69 65 73 28 73 54 65 78 74 29 3a 0a  ndaries(sText):.
1040: 20 20 20 20 20 20 20 20 69 66 20 34 20 3c 20 28          if 4 < (
1050: 69 45 6e 64 20 2d 20 69 53 74 61 72 74 29 20 3c  iEnd - iStart) <
1060: 20 32 30 30 30 3a 0a 20 20 20 20 20 20 20 20 20   2000:.         
1070: 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20     try:.        
1080: 20 20 20 20 20 20 20 20 6f 53 65 6e 74 65 6e 63          oSentenc
1090: 65 20 3d 20 54 65 78 74 50 61 72 73 65 72 28 73  e = TextParser(s
10a0: 54 65 78 74 5b 69 53 74 61 72 74 3a 69 45 6e 64  Text[iStart:iEnd
10b0: 5d 2c 20 73 52 65 61 6c 54 65 78 74 5b 69 53 74  ], sRealText[iSt
10c0: 61 72 74 3a 69 45 6e 64 5d 2c 20 69 53 74 61 72  art:iEnd], iStar
10d0: 74 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  t).             
10e0: 20 20 20 5f 2c 20 64 45 72 72 6f 72 73 20 3d 20     _, dErrors = 
10f0: 5f 70 72 6f 6f 66 72 65 61 64 28 6f 53 65 6e 74  _proofread(oSent
1100: 65 6e 63 65 2c 20 73 54 65 78 74 5b 69 53 74 61  ence, sText[iSta
1110: 72 74 3a 69 45 6e 64 5d 2c 20 73 52 65 61 6c 54  rt:iEnd], sRealT
1120: 65 78 74 5b 69 53 74 61 72 74 3a 69 45 6e 64 5d  ext[iStart:iEnd]
1130: 2c 20 69 53 74 61 72 74 2c 20 46 61 6c 73 65 2c  , iStart, False,
1140: 20 64 45 72 72 6f 72 73 2c 20 64 50 72 69 6f 72   dErrors, dPrior
1150: 69 74 79 2c 20 73 43 6f 75 6e 74 72 79 2c 20 64  ity, sCountry, d
1160: 4f 70 74 2c 20 62 53 68 6f 77 52 75 6c 65 49 64  Opt, bShowRuleId
1170: 2c 20 62 44 65 62 75 67 2c 20 62 43 6f 6e 74 65  , bDebug, bConte
1180: 78 74 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  xt).            
1190: 65 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20  except:.        
11a0: 20 20 20 20 20 20 20 20 72 61 69 73 65 0a 20 20          raise.  
11b0: 20 20 72 65 74 75 72 6e 20 64 45 72 72 6f 72 73    return dErrors
11c0: 2e 76 61 6c 75 65 73 28 29 20 23 20 74 68 69 73  .values() # this
11d0: 20 69 73 20 61 20 76 69 65 77 20 28 69 74 65 72   is a view (iter
11e0: 61 62 6c 65 29 0a 0a 0a 64 65 66 20 5f 70 72 6f  able)...def _pro
11f0: 6f 66 72 65 61 64 20 28 6f 53 65 6e 74 65 6e 63  ofread (oSentenc
1200: 65 2c 20 73 2c 20 73 78 2c 20 6e 4f 66 66 73 65  e, s, sx, nOffse
1210: 74 2c 20 62 50 61 72 61 67 72 61 70 68 2c 20 64  t, bParagraph, d
1220: 45 72 72 6f 72 73 2c 20 64 50 72 69 6f 72 69 74  Errors, dPriorit
1230: 79 2c 20 73 43 6f 75 6e 74 72 79 2c 20 64 4f 70  y, sCountry, dOp
1240: 74 69 6f 6e 73 2c 20 62 53 68 6f 77 52 75 6c 65  tions, bShowRule
1250: 49 64 2c 20 62 44 65 62 75 67 2c 20 62 43 6f 6e  Id, bDebug, bCon
1260: 74 65 78 74 29 3a 0a 20 20 20 20 62 50 61 72 61  text):.    bPara
1270: 67 72 61 70 68 43 68 61 6e 67 65 20 3d 20 46 61  graphChange = Fa
1280: 6c 73 65 0a 20 20 20 20 62 53 65 6e 74 65 6e 63  lse.    bSentenc
1290: 65 43 68 61 6e 67 65 20 3d 20 46 61 6c 73 65 0a  eChange = False.
12a0: 20 20 20 20 64 54 6f 6b 65 6e 50 6f 73 20 3d 20      dTokenPos = 
12b0: 6f 53 65 6e 74 65 6e 63 65 2e 64 54 6f 6b 65 6e  oSentence.dToken
12c0: 50 6f 73 20 69 66 20 6f 53 65 6e 74 65 6e 63 65  Pos if oSentence
12d0: 20 65 6c 73 65 20 7b 7d 0a 20 20 20 20 66 6f 72   else {}.    for
12e0: 20 73 4f 70 74 69 6f 6e 2c 20 6c 52 75 6c 65 47   sOption, lRuleG
12f0: 72 6f 75 70 20 69 6e 20 5f 67 65 74 52 75 6c 65  roup in _getRule
1300: 73 28 62 50 61 72 61 67 72 61 70 68 29 3a 0a 20  s(bParagraph):. 
1310: 20 20 20 20 20 20 20 69 66 20 73 4f 70 74 69 6f         if sOptio
1320: 6e 20 3d 3d 20 22 40 40 40 40 22 3a 0a 20 20 20  n == "@@@@":.   
1330: 20 20 20 20 20 20 20 20 20 23 20 67 72 61 70 68           # graph
1340: 20 72 75 6c 65 73 0a 20 20 20 20 20 20 20 20 20   rules.         
1350: 20 20 20 6f 53 65 6e 74 65 6e 63 65 2e 64 45 72     oSentence.dEr
1360: 72 6f 72 20 3d 20 64 45 72 72 6f 72 73 0a 20 20  ror = dErrors.  
1370: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74            if not
1380: 20 62 50 61 72 61 67 72 61 70 68 20 61 6e 64 20   bParagraph and 
1390: 62 53 65 6e 74 65 6e 63 65 43 68 61 6e 67 65 3a  bSentenceChange:
13a0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
13b0: 20 6f 53 65 6e 74 65 6e 63 65 2e 75 70 64 61 74   oSentence.updat
13c0: 65 28 73 2c 20 62 44 65 62 75 67 29 0a 20 20 20  e(s, bDebug).   
13d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 62 53 65               bSe
13e0: 6e 74 65 6e 63 65 43 68 61 6e 67 65 20 3d 20 46  ntenceChange = F
13f0: 61 6c 73 65 0a 20 20 20 20 20 20 20 20 20 20 20  alse.           
1400: 20 66 6f 72 20 73 47 72 61 70 68 4e 61 6d 65 2c   for sGraphName,
1410: 20 73 4c 69 6e 65 49 64 20 69 6e 20 6c 52 75 6c   sLineId in lRul
1420: 65 47 72 6f 75 70 3a 0a 20 20 20 20 20 20 20 20  eGroup:.        
1430: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
1440: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  g:.             
1450: 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 5c 6e         print("\n
1460: 3e 3e 3e 3e 20 47 52 41 50 48 3a 22 2c 20 73 47  >>>> GRAPH:", sG
1470: 72 61 70 68 4e 61 6d 65 2c 20 73 4c 69 6e 65 49  raphName, sLineI
1480: 64 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  d).             
1490: 20 20 20 62 50 61 72 61 67 72 61 70 68 43 68 61     bParagraphCha
14a0: 6e 67 65 2c 20 73 20 3d 20 6f 53 65 6e 74 65 6e  nge, s = oSenten
14b0: 63 65 2e 70 61 72 73 65 28 64 41 6c 6c 47 72 61  ce.parse(dAllGra
14c0: 70 68 5b 73 47 72 61 70 68 4e 61 6d 65 5d 2c 20  ph[sGraphName], 
14d0: 64 50 72 69 6f 72 69 74 79 2c 20 73 43 6f 75 6e  dPriority, sCoun
14e0: 74 72 79 2c 20 64 4f 70 74 69 6f 6e 73 2c 20 62  try, dOptions, b
14f0: 53 68 6f 77 52 75 6c 65 49 64 2c 20 62 44 65 62  ShowRuleId, bDeb
1500: 75 67 2c 20 62 43 6f 6e 74 65 78 74 29 0a 20 20  ug, bContext).  
1510: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64 45                dE
1520: 72 72 6f 72 73 2e 75 70 64 61 74 65 28 6f 53 65  rrors.update(oSe
1530: 6e 74 65 6e 63 65 2e 64 45 72 72 6f 72 29 0a 20  ntence.dError). 
1540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64                 d
1550: 54 6f 6b 65 6e 50 6f 73 20 3d 20 6f 53 65 6e 74  TokenPos = oSent
1560: 65 6e 63 65 2e 64 54 6f 6b 65 6e 50 6f 73 0a 20  ence.dTokenPos. 
1570: 20 20 20 20 20 20 20 65 6c 69 66 20 6e 6f 74 20         elif not 
1580: 73 4f 70 74 69 6f 6e 20 6f 72 20 64 4f 70 74 69  sOption or dOpti
1590: 6f 6e 73 2e 67 65 74 28 73 4f 70 74 69 6f 6e 2c  ons.get(sOption,
15a0: 20 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20   False):.       
15b0: 20 20 20 20 20 23 20 72 65 67 65 78 20 72 75 6c       # regex rul
15c0: 65 73 0a 20 20 20 20 20 20 20 20 20 20 20 20 66  es.            f
15d0: 6f 72 20 7a 52 65 67 65 78 2c 20 62 55 70 70 65  or zRegex, bUppe
15e0: 72 63 61 73 65 2c 20 73 4c 69 6e 65 49 64 2c 20  rcase, sLineId, 
15f0: 73 52 75 6c 65 49 64 2c 20 6e 50 72 69 6f 72 69  sRuleId, nPriori
1600: 74 79 2c 20 6c 41 63 74 69 6f 6e 73 20 69 6e 20  ty, lActions in 
1610: 6c 52 75 6c 65 47 72 6f 75 70 3a 0a 20 20 20 20  lRuleGroup:.    
1620: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73              if s
1630: 52 75 6c 65 49 64 20 6e 6f 74 20 69 6e 20 5f 61  RuleId not in _a
1640: 49 67 6e 6f 72 65 64 52 75 6c 65 73 3a 0a 20 20  IgnoredRules:.  
1650: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1660: 20 20 66 6f 72 20 6d 20 69 6e 20 7a 52 65 67 65    for m in zRege
1670: 78 2e 66 69 6e 64 69 74 65 72 28 73 29 3a 0a 20  x.finditer(s):. 
1680: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1690: 20 20 20 20 20 20 20 62 43 6f 6e 64 4d 65 6d 6f         bCondMemo
16a0: 20 3d 20 4e 6f 6e 65 0a 20 20 20 20 20 20 20 20   = None.        
16b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
16c0: 66 6f 72 20 73 46 75 6e 63 43 6f 6e 64 2c 20 63  for sFuncCond, c
16d0: 41 63 74 69 6f 6e 54 79 70 65 2c 20 73 57 68 61  ActionType, sWha
16e0: 74 2c 20 2a 65 41 63 74 20 69 6e 20 6c 41 63 74  t, *eAct in lAct
16f0: 69 6f 6e 73 3a 0a 20 20 20 20 20 20 20 20 20 20  ions:.          
1700: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1710: 20 20 23 20 61 63 74 69 6f 6e 20 69 6e 20 6c 41    # action in lA
1720: 63 74 69 6f 6e 73 3a 20 5b 20 63 6f 6e 64 69 74  ctions: [ condit
1730: 69 6f 6e 2c 20 61 63 74 69 6f 6e 20 74 79 70 65  ion, action type
1740: 2c 20 72 65 70 6c 61 63 65 6d 65 6e 74 2f 73 75  , replacement/su
1750: 67 67 65 73 74 69 6f 6e 2f 61 63 74 69 6f 6e 5b  ggestion/action[
1760: 2c 20 69 47 72 6f 75 70 5b 2c 20 6d 65 73 73 61  , iGroup[, messa
1770: 67 65 2c 20 55 52 4c 5d 5d 20 5d 0a 20 20 20 20  ge, URL]] ].    
1780: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1790: 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20 20 20          try:.   
17a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
17b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 62 43 6f               bCo
17c0: 6e 64 4d 65 6d 6f 20 3d 20 6e 6f 74 20 73 46 75  ndMemo = not sFu
17d0: 6e 63 43 6f 6e 64 20 6f 72 20 67 6c 6f 62 61 6c  ncCond or global
17e0: 73 28 29 5b 73 46 75 6e 63 43 6f 6e 64 5d 28 73  s()[sFuncCond](s
17f0: 2c 20 73 78 2c 20 6d 2c 20 64 54 6f 6b 65 6e 50  , sx, m, dTokenP
1800: 6f 73 2c 20 73 43 6f 75 6e 74 72 79 2c 20 62 43  os, sCountry, bC
1810: 6f 6e 64 4d 65 6d 6f 29 0a 20 20 20 20 20 20 20  ondMemo).       
1820: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1830: 20 20 20 20 20 20 20 20 20 69 66 20 62 43 6f 6e           if bCon
1840: 64 4d 65 6d 6f 3a 0a 20 20 20 20 20 20 20 20 20  dMemo:.         
1850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1860: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44             if bD
1870: 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20  ebug:.          
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 20 20 20 20 20 20 20 70 72                pr
18a0: 69 6e 74 28 22 52 55 4c 45 3a 22 2c 20 73 4c 69  int("RULE:", sLi
18b0: 6e 65 49 64 29 0a 20 20 20 20 20 20 20 20 20 20  neId).          
18c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
18d0: 20 20 20 20 20 20 20 20 20 20 69 66 20 63 41 63            if cAc
18e0: 74 69 6f 6e 54 79 70 65 20 3d 3d 20 22 2d 22 3a  tionType == "-":
18f0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1900: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1910: 20 20 20 20 20 20 20 20 20 23 20 67 72 61 6d 6d           # gramm
1920: 61 72 20 65 72 72 6f 72 0a 20 20 20 20 20 20 20  ar error.       
1930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1940: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1950: 20 6e 45 72 72 6f 72 53 74 61 72 74 20 3d 20 6e   nErrorStart = n
1960: 4f 66 66 73 65 74 20 2b 20 6d 2e 73 74 61 72 74  Offset + m.start
1970: 28 65 41 63 74 5b 30 5d 29 0a 20 20 20 20 20 20  (eAct[0]).      
1980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1990: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
19a0: 20 20 69 66 20 6e 45 72 72 6f 72 53 74 61 72 74    if nErrorStart
19b0: 20 6e 6f 74 20 69 6e 20 64 45 72 72 6f 72 73 20   not in dErrors 
19c0: 6f 72 20 6e 50 72 69 6f 72 69 74 79 20 3e 20 64  or nPriority > d
19d0: 50 72 69 6f 72 69 74 79 2e 67 65 74 28 6e 45 72  Priority.get(nEr
19e0: 72 6f 72 53 74 61 72 74 2c 20 2d 31 29 3a 0a 20  rorStart, -1):. 
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 20 20 20 20 20 20 20 20                  
1a10: 20 20 20 20 20 20 20 20 20 20 20 64 45 72 72 6f             dErro
1a20: 72 73 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d 20  rs[nErrorStart] 
1a30: 3d 20 5f 63 72 65 61 74 65 45 72 72 6f 72 28 73  = _createError(s
1a40: 2c 20 73 78 2c 20 73 57 68 61 74 2c 20 6e 4f 66  , sx, sWhat, nOf
1a50: 66 73 65 74 2c 20 6d 2c 20 65 41 63 74 5b 30 5d  fset, m, eAct[0]
1a60: 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65  , sLineId, sRule
1a70: 49 64 2c 20 62 55 70 70 65 72 63 61 73 65 2c 20  Id, bUppercase, 
1a80: 65 41 63 74 5b 31 5d 2c 20 65 41 63 74 5b 32 5d  eAct[1], eAct[2]
1a90: 2c 20 62 53 68 6f 77 52 75 6c 65 49 64 2c 20 73  , bShowRuleId, s
1aa0: 4f 70 74 69 6f 6e 2c 20 62 43 6f 6e 74 65 78 74  Option, bContext
1ab0: 29 0a 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 20 20                  
1ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64 50                dP
1ae0: 72 69 6f 72 69 74 79 5b 6e 45 72 72 6f 72 53 74  riority[nErrorSt
1af0: 61 72 74 5d 20 3d 20 6e 50 72 69 6f 72 69 74 79  art] = nPriority
1b00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1b10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b20: 20 20 20 20 20 65 6c 69 66 20 63 41 63 74 69 6f       elif cActio
1b30: 6e 54 79 70 65 20 3d 3d 20 22 7e 22 3a 0a 20 20  nType == "~":.  
1b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b60: 20 20 20 20 20 20 23 20 74 65 78 74 20 70 72 6f        # text pro
1b70: 63 65 73 73 6f 72 0a 20 20 20 20 20 20 20 20 20  cessor.         
1b80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
1ba0: 20 3d 20 5f 72 65 77 72 69 74 65 28 73 2c 20 73   = _rewrite(s, s
1bb0: 57 68 61 74 2c 20 65 41 63 74 5b 30 5d 2c 20 6d  What, eAct[0], m
1bc0: 2c 20 62 55 70 70 65 72 63 61 73 65 29 0a 20 20  , bUppercase).  
1bd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1bf0: 20 20 20 20 20 20 62 50 61 72 61 67 72 61 70 68        bParagraph
1c00: 43 68 61 6e 67 65 20 3d 20 54 72 75 65 0a 20 20  Change = True.  
1c10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c30: 20 20 20 20 20 20 62 53 65 6e 74 65 6e 63 65 43        bSentenceC
1c40: 68 61 6e 67 65 20 3d 20 54 72 75 65 0a 20 20 20  hange = True.   
1c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c70: 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a       if bDebug:.
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 20 20 20 20                  
1ca0: 20 20 20 20 20 20 20 20 20 20 20 20 65 63 68 6f              echo
1cb0: 28 22 7e 20 22 20 2b 20 73 20 2b 20 22 20 20 2d  ("~ " + s + "  -
1cc0: 2d 20 22 20 2b 20 6d 2e 67 72 6f 75 70 28 65 41  - " + m.group(eA
1cd0: 63 74 5b 30 5d 29 20 2b 20 22 20 20 23 20 22 20  ct[0]) + "  # " 
1ce0: 2b 20 73 4c 69 6e 65 49 64 29 0a 20 20 20 20 20  + sLineId).     
1cf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
1d10: 6c 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20  lif cActionType 
1d20: 3d 3d 20 22 3d 22 3a 0a 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: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d50: 23 20 64 69 73 61 6d 62 69 67 75 61 74 69 6f 6e  # disambiguation
1d60: 0a 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 20 20 20 20 20 20 20                  
1d80: 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20           if not 
1d90: 62 50 61 72 61 67 72 61 70 68 3a 0a 20 20 20 20  bParagraph:.    
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 20 20 20 20 20 20 20 20                  
1dc0: 20 20 20 20 20 20 20 20 67 6c 6f 62 61 6c 73 28          globals(
1dd0: 29 5b 73 57 68 61 74 5d 28 73 2c 20 6d 2c 20 64  )[sWhat](s, m, d
1de0: 54 6f 6b 65 6e 50 6f 73 29 0a 20 20 20 20 20 20  TokenPos).      
1df0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e10: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
1e20: 0a 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 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e50: 20 65 63 68 6f 28 22 3d 20 22 20 2b 20 6d 2e 67   echo("= " + m.g
1e60: 72 6f 75 70 28 30 29 20 2b 20 22 20 20 23 20 22  roup(0) + "  # "
1e70: 20 2b 20 73 4c 69 6e 65 49 64 29 0a 20 20 20 20   + sLineId).    
1e80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ea0: 65 6c 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65  elif cActionType
1eb0: 20 3d 3d 20 22 3e 22 3a 0a 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 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ee0: 20 23 20 77 65 20 64 6f 20 6e 6f 74 68 69 6e 67   # we do nothing
1ef0: 2c 20 74 68 69 73 20 74 65 73 74 20 69 73 20 6a  , this test is j
1f00: 75 73 74 20 61 20 63 6f 6e 64 69 74 69 6f 6e 20  ust a condition 
1f10: 74 6f 20 61 70 70 6c 79 20 61 6c 6c 20 66 6f 6c  to apply all fol
1f20: 6c 6f 77 69 6e 67 20 61 63 74 69 6f 6e 73 0a 20  lowing actions. 
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 20 20 20 20 20 20 20 20 20                  
1f50: 20 20 20 20 20 20 20 70 61 73 73 0a 20 20 20 20         pass.    
1f60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f80: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
1f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 63                ec
1fb0: 68 6f 28 22 23 20 65 72 72 6f 72 3a 20 75 6e 6b  ho("# error: unk
1fc0: 6e 6f 77 6e 20 61 63 74 69 6f 6e 20 61 74 20 22  nown action at "
1fd0: 20 2b 20 73 4c 69 6e 65 49 64 29 0a 20 20 20 20   + sLineId).    
1fe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ff0: 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69 66              elif
2000: 20 63 41 63 74 69 6f 6e 54 79 70 65 20 3d 3d 20   cActionType == 
2010: 22 3e 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ">":.           
2020: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2030: 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 0a 20           break. 
2040: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2050: 20 20 20 20 20 20 20 20 20 20 20 65 78 63 65 70             excep
2060: 74 20 45 78 63 65 70 74 69 6f 6e 20 61 73 20 65  t Exception as e
2070: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
2080: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2090: 20 20 72 61 69 73 65 20 45 78 63 65 70 74 69 6f    raise Exceptio
20a0: 6e 28 73 74 72 28 65 29 2c 20 22 23 20 22 20 2b  n(str(e), "# " +
20b0: 20 73 4c 69 6e 65 49 64 20 2b 20 22 20 23 20 22   sLineId + " # "
20c0: 20 2b 20 73 52 75 6c 65 49 64 29 0a 20 20 20 20   + sRuleId).    
20d0: 69 66 20 62 50 61 72 61 67 72 61 70 68 43 68 61  if bParagraphCha
20e0: 6e 67 65 3a 0a 20 20 20 20 20 20 20 20 72 65 74  nge:.        ret
20f0: 75 72 6e 20 28 73 2c 20 64 45 72 72 6f 72 73 29  urn (s, dErrors)
2100: 0a 20 20 20 20 72 65 74 75 72 6e 20 28 46 61 6c  .    return (Fal
2110: 73 65 2c 20 64 45 72 72 6f 72 73 29 0a 0a 0a 64  se, dErrors)...d
2120: 65 66 20 5f 63 72 65 61 74 65 45 72 72 6f 72 20  ef _createError 
2130: 28 73 2c 20 73 78 2c 20 73 52 65 70 6c 2c 20 6e  (s, sx, sRepl, n
2140: 4f 66 66 73 65 74 2c 20 6d 2c 20 69 47 72 6f 75  Offset, m, iGrou
2150: 70 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c  p, sLineId, sRul
2160: 65 49 64 2c 20 62 55 70 70 65 72 63 61 73 65 2c  eId, bUppercase,
2170: 20 73 4d 73 67 2c 20 73 55 52 4c 2c 20 62 53 68   sMsg, sURL, bSh
2180: 6f 77 52 75 6c 65 49 64 2c 20 73 4f 70 74 69 6f  owRuleId, sOptio
2190: 6e 2c 20 62 43 6f 6e 74 65 78 74 29 3a 0a 20 20  n, bContext):.  
21a0: 20 20 6e 53 74 61 72 74 20 3d 20 6e 4f 66 66 73    nStart = nOffs
21b0: 65 74 20 2b 20 6d 2e 73 74 61 72 74 28 69 47 72  et + m.start(iGr
21c0: 6f 75 70 29 0a 20 20 20 20 6e 45 6e 64 20 3d 20  oup).    nEnd = 
21d0: 6e 4f 66 66 73 65 74 20 2b 20 6d 2e 65 6e 64 28  nOffset + m.end(
21e0: 69 47 72 6f 75 70 29 0a 20 20 20 20 23 20 73 75  iGroup).    # su
21f0: 67 67 65 73 74 69 6f 6e 73 0a 20 20 20 20 69 66  ggestions.    if
2200: 20 73 52 65 70 6c 5b 30 3a 31 5d 20 3d 3d 20 22   sRepl[0:1] == "
2210: 3d 22 3a 0a 20 20 20 20 20 20 20 20 73 53 75 67  =":.        sSug
2220: 67 20 3d 20 67 6c 6f 62 61 6c 73 28 29 5b 73 52  g = globals()[sR
2230: 65 70 6c 5b 31 3a 5d 5d 28 73 2c 20 6d 29 0a 20  epl[1:]](s, m). 
2240: 20 20 20 20 20 20 20 6c 53 75 67 67 20 3d 20 73         lSugg = s
2250: 53 75 67 67 2e 73 70 6c 69 74 28 22 7c 22 29 20  Sugg.split("|") 
2260: 20 69 66 20 73 53 75 67 67 20 20 65 6c 73 65 20   if sSugg  else 
2270: 5b 5d 0a 20 20 20 20 65 6c 69 66 20 73 52 65 70  [].    elif sRep
2280: 6c 20 3d 3d 20 22 5f 22 3a 0a 20 20 20 20 20 20  l == "_":.      
2290: 20 20 6c 53 75 67 67 20 3d 20 5b 5d 0a 20 20 20    lSugg = [].   
22a0: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 6c   else:.        l
22b0: 53 75 67 67 20 3d 20 6d 2e 65 78 70 61 6e 64 28  Sugg = m.expand(
22c0: 73 52 65 70 6c 29 2e 73 70 6c 69 74 28 22 7c 22  sRepl).split("|"
22d0: 29 0a 20 20 20 20 69 66 20 62 55 70 70 65 72 63  ).    if bUpperc
22e0: 61 73 65 20 61 6e 64 20 6c 53 75 67 67 20 61 6e  ase and lSugg an
22f0: 64 20 6d 2e 67 72 6f 75 70 28 69 47 72 6f 75 70  d m.group(iGroup
2300: 29 5b 30 3a 31 5d 2e 69 73 75 70 70 65 72 28 29  )[0:1].isupper()
2310: 3a 0a 20 20 20 20 20 20 20 20 6c 53 75 67 67 20  :.        lSugg 
2320: 3d 20 6c 69 73 74 28 6d 61 70 28 73 74 72 2e 63  = list(map(str.c
2330: 61 70 69 74 61 6c 69 7a 65 2c 20 6c 53 75 67 67  apitalize, lSugg
2340: 29 29 0a 20 20 20 20 23 20 4d 65 73 73 61 67 65  )).    # Message
2350: 0a 20 20 20 20 73 4d 65 73 73 61 67 65 20 3d 20  .    sMessage = 
2360: 67 6c 6f 62 61 6c 73 28 29 5b 73 4d 73 67 5b 31  globals()[sMsg[1
2370: 3a 5d 5d 28 73 2c 20 6d 29 20 20 69 66 20 73 4d  :]](s, m)  if sM
2380: 73 67 5b 30 3a 31 5d 20 3d 3d 20 22 3d 22 20 20  sg[0:1] == "="  
2390: 65 6c 73 65 20 20 6d 2e 65 78 70 61 6e 64 28 73  else  m.expand(s
23a0: 4d 73 67 29 0a 20 20 20 20 69 66 20 62 53 68 6f  Msg).    if bSho
23b0: 77 52 75 6c 65 49 64 3a 0a 20 20 20 20 20 20 20  wRuleId:.       
23c0: 20 73 4d 65 73 73 61 67 65 20 2b 3d 20 22 20 20   sMessage += "  
23d0: 23 20 22 20 2b 20 73 4c 69 6e 65 49 64 20 2b 20  # " + sLineId + 
23e0: 22 20 23 20 22 20 2b 20 73 52 75 6c 65 49 64 0a  " # " + sRuleId.
23f0: 20 20 20 20 23 0a 20 20 20 20 69 66 20 5f 62 57      #.    if _bW
2400: 72 69 74 65 72 45 72 72 6f 72 3a 0a 20 20 20 20  riterError:.    
2410: 20 20 20 20 78 45 72 72 20 3d 20 53 69 6e 67 6c      xErr = Singl
2420: 65 50 72 6f 6f 66 72 65 61 64 69 6e 67 45 72 72  eProofreadingErr
2430: 6f 72 28 29 20 20 20 20 23 20 75 6e 6f 2e 63 72  or()    # uno.cr
2440: 65 61 74 65 55 6e 6f 53 74 72 75 63 74 28 20 22  eateUnoStruct( "
2450: 63 6f 6d 2e 73 75 6e 2e 73 74 61 72 2e 6c 69 6e  com.sun.star.lin
2460: 67 75 69 73 74 69 63 32 2e 53 69 6e 67 6c 65 50  guistic2.SingleP
2470: 72 6f 6f 66 72 65 61 64 69 6e 67 45 72 72 6f 72  roofreadingError
2480: 22 20 29 0a 20 20 20 20 20 20 20 20 78 45 72 72  " ).        xErr
2490: 2e 6e 45 72 72 6f 72 53 74 61 72 74 20 3d 20 6e  .nErrorStart = n
24a0: 53 74 61 72 74 0a 20 20 20 20 20 20 20 20 78 45  Start.        xE
24b0: 72 72 2e 6e 45 72 72 6f 72 4c 65 6e 67 74 68 20  rr.nErrorLength 
24c0: 3d 20 6e 45 6e 64 20 2d 20 6e 53 74 61 72 74 0a  = nEnd - nStart.
24d0: 20 20 20 20 20 20 20 20 78 45 72 72 2e 6e 45 72          xErr.nEr
24e0: 72 6f 72 54 79 70 65 20 3d 20 50 52 4f 4f 46 52  rorType = PROOFR
24f0: 45 41 44 49 4e 47 0a 20 20 20 20 20 20 20 20 78  EADING.        x
2500: 45 72 72 2e 61 52 75 6c 65 49 64 65 6e 74 69 66  Err.aRuleIdentif
2510: 69 65 72 20 3d 20 73 52 75 6c 65 49 64 0a 20 20  ier = sRuleId.  
2520: 20 20 20 20 20 20 78 45 72 72 2e 61 53 68 6f 72        xErr.aShor
2530: 74 43 6f 6d 6d 65 6e 74 20 3d 20 73 4d 65 73 73  tComment = sMess
2540: 61 67 65 20 20 20 23 20 73 4d 65 73 73 61 67 65  age   # sMessage
2550: 2e 73 70 6c 69 74 28 22 7c 22 29 5b 30 5d 20 20  .split("|")[0]  
2560: 20 20 20 23 20 69 6e 20 63 6f 6e 74 65 78 74 20     # in context 
2570: 6d 65 6e 75 0a 20 20 20 20 20 20 20 20 78 45 72  menu.        xEr
2580: 72 2e 61 46 75 6c 6c 43 6f 6d 6d 65 6e 74 20 3d  r.aFullComment =
2590: 20 73 4d 65 73 73 61 67 65 20 20 20 23 20 73 4d   sMessage   # sM
25a0: 65 73 73 61 67 65 2e 73 70 6c 69 74 28 22 7c 22  essage.split("|"
25b0: 29 5b 2d 31 5d 20 20 20 20 23 20 69 6e 20 64 69  )[-1]    # in di
25c0: 61 6c 6f 67 0a 20 20 20 20 20 20 20 20 69 66 20  alog.        if 
25d0: 62 53 68 6f 77 52 75 6c 65 49 64 3a 0a 20 20 20  bShowRuleId:.   
25e0: 20 20 20 20 20 20 20 20 20 78 45 72 72 2e 61 53           xErr.aS
25f0: 68 6f 72 74 43 6f 6d 6d 65 6e 74 20 2b 3d 20 22  hortComment += "
2600: 20 20 22 20 2b 20 73 4c 69 6e 65 49 64 20 2b 20    " + sLineId + 
2610: 22 20 23 20 22 20 2b 20 73 52 75 6c 65 49 64 0a  " # " + sRuleId.
2620: 20 20 20 20 20 20 20 20 78 45 72 72 2e 61 53 75          xErr.aSu
2630: 67 67 65 73 74 69 6f 6e 73 20 3d 20 74 75 70 6c  ggestions = tupl
2640: 65 28 6c 53 75 67 67 29 0a 20 20 20 20 20 20 20  e(lSugg).       
2650: 20 69 66 20 73 55 52 4c 3a 0a 20 20 20 20 20 20   if sURL:.      
2660: 20 20 20 20 20 20 78 50 72 6f 70 65 72 74 79 20        xProperty 
2670: 3d 20 50 72 6f 70 65 72 74 79 56 61 6c 75 65 28  = PropertyValue(
2680: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 78 50  ).            xP
2690: 72 6f 70 65 72 74 79 2e 4e 61 6d 65 20 3d 20 22  roperty.Name = "
26a0: 46 75 6c 6c 43 6f 6d 6d 65 6e 74 55 52 4c 22 0a  FullCommentURL".
26b0: 20 20 20 20 20 20 20 20 20 20 20 20 78 50 72 6f              xPro
26c0: 70 65 72 74 79 2e 56 61 6c 75 65 20 3d 20 73 55  perty.Value = sU
26d0: 52 4c 0a 20 20 20 20 20 20 20 20 20 20 20 20 78  RL.            x
26e0: 45 72 72 2e 61 50 72 6f 70 65 72 74 69 65 73 20  Err.aProperties 
26f0: 3d 20 28 78 50 72 6f 70 65 72 74 79 2c 29 0a 20  = (xProperty,). 
2700: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
2710: 20 20 20 20 20 20 20 20 20 78 45 72 72 2e 61 50           xErr.aP
2720: 72 6f 70 65 72 74 69 65 73 20 3d 20 28 29 0a 20  roperties = (). 
2730: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 78 45         return xE
2740: 72 72 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20 20  rr.    else:.   
2750: 20 20 20 20 20 64 45 72 72 20 3d 20 7b 7d 0a 20       dErr = {}. 
2760: 20 20 20 20 20 20 20 64 45 72 72 5b 22 6e 53 74         dErr["nSt
2770: 61 72 74 22 5d 20 3d 20 6e 53 74 61 72 74 0a 20  art"] = nStart. 
2780: 20 20 20 20 20 20 20 64 45 72 72 5b 22 6e 45 6e         dErr["nEn
2790: 64 22 5d 20 3d 20 6e 45 6e 64 0a 20 20 20 20 20  d"] = nEnd.     
27a0: 20 20 20 64 45 72 72 5b 22 73 4c 69 6e 65 49 64     dErr["sLineId
27b0: 22 5d 20 3d 20 73 4c 69 6e 65 49 64 0a 20 20 20  "] = sLineId.   
27c0: 20 20 20 20 20 64 45 72 72 5b 22 73 52 75 6c 65       dErr["sRule
27d0: 49 64 22 5d 20 3d 20 73 52 75 6c 65 49 64 0a 20  Id"] = sRuleId. 
27e0: 20 20 20 20 20 20 20 64 45 72 72 5b 22 73 54 79         dErr["sTy
27f0: 70 65 22 5d 20 3d 20 73 4f 70 74 69 6f 6e 20 20  pe"] = sOption  
2800: 69 66 20 73 4f 70 74 69 6f 6e 20 20 65 6c 73 65  if sOption  else
2810: 20 22 6e 6f 74 79 70 65 22 0a 20 20 20 20 20 20   "notype".      
2820: 20 20 64 45 72 72 5b 22 73 4d 65 73 73 61 67 65    dErr["sMessage
2830: 22 5d 20 3d 20 73 4d 65 73 73 61 67 65 0a 20 20  "] = sMessage.  
2840: 20 20 20 20 20 20 64 45 72 72 5b 22 61 53 75 67        dErr["aSug
2850: 67 65 73 74 69 6f 6e 73 22 5d 20 3d 20 6c 53 75  gestions"] = lSu
2860: 67 67 0a 20 20 20 20 20 20 20 20 64 45 72 72 5b  gg.        dErr[
2870: 22 55 52 4c 22 5d 20 3d 20 73 55 52 4c 20 20 69  "URL"] = sURL  i
2880: 66 20 73 55 52 4c 20 20 65 6c 73 65 20 22 22 0a  f sURL  else "".
2890: 20 20 20 20 20 20 20 20 69 66 20 62 43 6f 6e 74          if bCont
28a0: 65 78 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ext:.           
28b0: 20 64 45 72 72 5b 27 73 55 6e 64 65 72 6c 69 6e   dErr['sUnderlin
28c0: 65 64 27 5d 20 3d 20 73 65 6c 66 2e 73 53 65 6e  ed'] = self.sSen
28d0: 74 65 6e 63 65 30 5b 6e 53 74 61 72 74 3a 6e 45  tence0[nStart:nE
28e0: 6e 64 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  nd].            
28f0: 64 45 72 72 5b 27 73 42 65 66 6f 72 65 27 5d 20  dErr['sBefore'] 
2900: 3d 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65  = self.sSentence
2910: 30 5b 6d 61 78 28 30 2c 6e 53 74 61 72 74 2d 38  0[max(0,nStart-8
2920: 30 29 3a 6e 53 74 61 72 74 5d 0a 20 20 20 20 20  0):nStart].     
2930: 20 20 20 20 20 20 20 64 45 72 72 5b 27 73 41 66         dErr['sAf
2940: 74 65 72 27 5d 20 3d 20 73 65 6c 66 2e 73 53 65  ter'] = self.sSe
2950: 6e 74 65 6e 63 65 30 5b 6e 45 6e 64 3a 6e 45 6e  ntence0[nEnd:nEn
2960: 64 2b 38 30 5d 0a 20 20 20 20 20 20 20 20 72 65  d+80].        re
2970: 74 75 72 6e 20 64 45 72 72 0a 0a 0a 64 65 66 20  turn dErr...def 
2980: 5f 72 65 77 72 69 74 65 20 28 73 53 65 6e 74 65  _rewrite (sSente
2990: 6e 63 65 2c 20 73 52 65 70 6c 2c 20 69 47 72 6f  nce, sRepl, iGro
29a0: 75 70 2c 20 6d 2c 20 62 55 70 70 65 72 63 61 73  up, m, bUppercas
29b0: 65 29 3a 0a 20 20 20 20 22 74 65 78 74 20 70 72  e):.    "text pr
29c0: 6f 63 65 73 73 6f 72 3a 20 77 72 69 74 65 20 3c  ocessor: write <
29d0: 73 52 65 70 6c 3e 20 69 6e 20 3c 73 53 65 6e 74  sRepl> in <sSent
29e0: 65 6e 63 65 3e 20 61 74 20 3c 69 47 72 6f 75 70  ence> at <iGroup
29f0: 3e 20 70 6f 73 69 74 69 6f 6e 22 0a 20 20 20 20  > position".    
2a00: 6e 4c 65 6e 20 3d 20 6d 2e 65 6e 64 28 69 47 72  nLen = m.end(iGr
2a10: 6f 75 70 29 20 2d 20 6d 2e 73 74 61 72 74 28 69  oup) - m.start(i
2a20: 47 72 6f 75 70 29 0a 20 20 20 20 69 66 20 73 52  Group).    if sR
2a30: 65 70 6c 20 3d 3d 20 22 2a 22 3a 0a 20 20 20 20  epl == "*":.    
2a40: 20 20 20 20 73 4e 65 77 20 3d 20 22 20 22 20 2a      sNew = " " *
2a50: 20 6e 4c 65 6e 0a 20 20 20 20 65 6c 69 66 20 73   nLen.    elif s
2a60: 52 65 70 6c 20 3d 3d 20 22 5f 22 3a 0a 20 20 20  Repl == "_":.   
2a70: 20 20 20 20 20 73 4e 65 77 20 3d 20 73 52 65 70       sNew = sRep
2a80: 6c 20 2b 20 22 20 22 20 2a 20 28 6e 4c 65 6e 2d  l + " " * (nLen-
2a90: 31 29 0a 20 20 20 20 65 6c 69 66 20 73 52 65 70  1).    elif sRep
2aa0: 6c 5b 30 3a 31 5d 20 3d 3d 20 22 3d 22 3a 0a 20  l[0:1] == "=":. 
2ab0: 20 20 20 20 20 20 20 73 4e 65 77 20 3d 20 67 6c         sNew = gl
2ac0: 6f 62 61 6c 73 28 29 5b 73 52 65 70 6c 5b 31 3a  obals()[sRepl[1:
2ad0: 5d 5d 28 73 53 65 6e 74 65 6e 63 65 2c 20 6d 29  ]](sSentence, m)
2ae0: 0a 20 20 20 20 20 20 20 20 73 4e 65 77 20 3d 20  .        sNew = 
2af0: 73 4e 65 77 20 2b 20 22 20 22 20 2a 20 28 6e 4c  sNew + " " * (nL
2b00: 65 6e 2d 6c 65 6e 28 73 4e 65 77 29 29 0a 20 20  en-len(sNew)).  
2b10: 20 20 20 20 20 20 69 66 20 62 55 70 70 65 72 63        if bUpperc
2b20: 61 73 65 20 61 6e 64 20 6d 2e 67 72 6f 75 70 28  ase and m.group(
2b30: 69 47 72 6f 75 70 29 5b 30 3a 31 5d 2e 69 73 75  iGroup)[0:1].isu
2b40: 70 70 65 72 28 29 3a 0a 20 20 20 20 20 20 20 20  pper():.        
2b50: 20 20 20 20 73 4e 65 77 20 3d 20 73 4e 65 77 2e      sNew = sNew.
2b60: 63 61 70 69 74 61 6c 69 7a 65 28 29 0a 20 20 20  capitalize().   
2b70: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 73   else:.        s
2b80: 4e 65 77 20 3d 20 6d 2e 65 78 70 61 6e 64 28 73  New = m.expand(s
2b90: 52 65 70 6c 29 0a 20 20 20 20 20 20 20 20 73 4e  Repl).        sN
2ba0: 65 77 20 3d 20 73 4e 65 77 20 2b 20 22 20 22 20  ew = sNew + " " 
2bb0: 2a 20 28 6e 4c 65 6e 2d 6c 65 6e 28 73 4e 65 77  * (nLen-len(sNew
2bc0: 29 29 0a 20 20 20 20 72 65 74 75 72 6e 20 73 53  )).    return sS
2bd0: 65 6e 74 65 6e 63 65 5b 30 3a 6d 2e 73 74 61 72  entence[0:m.star
2be0: 74 28 69 47 72 6f 75 70 29 5d 20 2b 20 73 4e 65  t(iGroup)] + sNe
2bf0: 77 20 2b 20 73 53 65 6e 74 65 6e 63 65 5b 6d 2e  w + sSentence[m.
2c00: 65 6e 64 28 69 47 72 6f 75 70 29 3a 5d 0a 0a 0a  end(iGroup):]...
2c10: 64 65 66 20 69 67 6e 6f 72 65 52 75 6c 65 20 28  def ignoreRule (
2c20: 73 52 75 6c 65 49 64 29 3a 0a 20 20 20 20 22 64  sRuleId):.    "d
2c30: 69 73 61 62 6c 65 20 72 75 6c 65 20 3c 73 52 75  isable rule <sRu
2c40: 6c 65 49 64 3e 22 0a 20 20 20 20 5f 61 49 67 6e  leId>".    _aIgn
2c50: 6f 72 65 64 52 75 6c 65 73 2e 61 64 64 28 73 52  oredRules.add(sR
2c60: 75 6c 65 49 64 29 0a 0a 0a 64 65 66 20 72 65 73  uleId)...def res
2c70: 65 74 49 67 6e 6f 72 65 52 75 6c 65 73 20 28 29  etIgnoreRules ()
2c80: 3a 0a 20 20 20 20 22 63 6c 65 61 72 20 61 6c 6c  :.    "clear all
2c90: 20 69 67 6e 6f 72 65 64 20 72 75 6c 65 73 22 0a   ignored rules".
2ca0: 20 20 20 20 5f 61 49 67 6e 6f 72 65 64 52 75 6c      _aIgnoredRul
2cb0: 65 73 2e 63 6c 65 61 72 28 29 0a 0a 0a 64 65 66  es.clear()...def
2cc0: 20 72 65 61 63 74 69 76 61 74 65 52 75 6c 65 20   reactivateRule 
2cd0: 28 73 52 75 6c 65 49 64 29 3a 0a 20 20 20 20 22  (sRuleId):.    "
2ce0: 28 72 65 29 61 63 74 69 76 61 74 65 20 72 75 6c  (re)activate rul
2cf0: 65 20 3c 73 52 75 6c 65 49 64 3e 22 0a 20 20 20  e <sRuleId>".   
2d00: 20 5f 61 49 67 6e 6f 72 65 64 52 75 6c 65 73 2e   _aIgnoredRules.
2d10: 64 69 73 63 61 72 64 28 73 52 75 6c 65 49 64 29  discard(sRuleId)
2d20: 0a 0a 0a 64 65 66 20 6c 69 73 74 52 75 6c 65 73  ...def listRules
2d30: 20 28 73 46 69 6c 74 65 72 3d 4e 6f 6e 65 29 3a   (sFilter=None):
2d40: 0a 20 20 20 20 22 67 65 6e 65 72 61 74 6f 72 3a  .    "generator:
2d50: 20 72 65 74 75 72 6e 73 20 74 79 70 6c 65 20 28   returns typle (
2d60: 73 4f 70 74 69 6f 6e 2c 20 73 4c 69 6e 65 49 64  sOption, sLineId
2d70: 2c 20 73 52 75 6c 65 49 64 29 22 0a 20 20 20 20  , sRuleId)".    
2d80: 69 66 20 73 46 69 6c 74 65 72 3a 0a 20 20 20 20  if sFilter:.    
2d90: 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20      try:.       
2da0: 20 20 20 20 20 7a 46 69 6c 74 65 72 20 3d 20 72       zFilter = r
2db0: 65 2e 63 6f 6d 70 69 6c 65 28 73 46 69 6c 74 65  e.compile(sFilte
2dc0: 72 29 0a 20 20 20 20 20 20 20 20 65 78 63 65 70  r).        excep
2dd0: 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 65  t:.            e
2de0: 63 68 6f 28 22 23 20 45 72 72 6f 72 2e 20 4c 69  cho("# Error. Li
2df0: 73 74 20 72 75 6c 65 73 3a 20 77 72 6f 6e 67 20  st rules: wrong 
2e00: 72 65 67 65 78 2e 22 29 0a 20 20 20 20 20 20 20  regex.").       
2e10: 20 20 20 20 20 73 46 69 6c 74 65 72 20 3d 20 4e       sFilter = N
2e20: 6f 6e 65 0a 20 20 20 20 66 6f 72 20 73 4f 70 74  one.    for sOpt
2e30: 69 6f 6e 2c 20 6c 52 75 6c 65 47 72 6f 75 70 20  ion, lRuleGroup 
2e40: 69 6e 20 63 68 61 69 6e 28 5f 67 65 74 52 75 6c  in chain(_getRul
2e50: 65 73 28 54 72 75 65 29 2c 20 5f 67 65 74 52 75  es(True), _getRu
2e60: 6c 65 73 28 46 61 6c 73 65 29 29 3a 0a 20 20 20  les(False)):.   
2e70: 20 20 20 20 20 69 66 20 73 4f 70 74 69 6f 6e 20       if sOption 
2e80: 21 3d 20 22 40 40 40 40 22 3a 0a 20 20 20 20 20  != "@@@@":.     
2e90: 20 20 20 20 20 20 20 66 6f 72 20 5f 2c 20 5f 2c         for _, _,
2ea0: 20 73 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65 49   sLineId, sRuleI
2eb0: 64 2c 20 5f 2c 20 5f 20 69 6e 20 6c 52 75 6c 65  d, _, _ in lRule
2ec0: 47 72 6f 75 70 3a 0a 20 20 20 20 20 20 20 20 20  Group:.         
2ed0: 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20 73 46         if not sF
2ee0: 69 6c 74 65 72 20 6f 72 20 7a 46 69 6c 74 65 72  ilter or zFilter
2ef0: 2e 73 65 61 72 63 68 28 73 52 75 6c 65 49 64 29  .search(sRuleId)
2f00: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
2f10: 20 20 20 20 20 20 79 69 65 6c 64 20 28 73 4f 70        yield (sOp
2f20: 74 69 6f 6e 2c 20 73 4c 69 6e 65 49 64 2c 20 73  tion, sLineId, s
2f30: 52 75 6c 65 49 64 29 0a 0a 0a 64 65 66 20 64 69  RuleId)...def di
2f40: 73 70 6c 61 79 52 75 6c 65 73 20 28 73 46 69 6c  splayRules (sFil
2f50: 74 65 72 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 22  ter=None):.    "
2f60: 64 69 73 70 6c 61 79 20 74 68 65 20 6e 61 6d 65  display the name
2f70: 20 6f 66 20 72 75 6c 65 73 2c 20 77 69 74 68 20   of rules, with 
2f80: 74 68 65 20 66 69 6c 74 65 72 20 3c 73 46 69 6c  the filter <sFil
2f90: 74 65 72 3e 22 0a 20 20 20 20 65 63 68 6f 28 22  ter>".    echo("
2fa0: 4c 69 73 74 20 6f 66 20 72 75 6c 65 73 2e 20 46  List of rules. F
2fb0: 69 6c 74 65 72 3a 20 3c 3c 20 22 20 2b 20 73 74  ilter: << " + st
2fc0: 72 28 73 46 69 6c 74 65 72 29 20 2b 20 22 20 3e  r(sFilter) + " >
2fd0: 3e 22 29 0a 20 20 20 20 66 6f 72 20 73 4f 70 74  >").    for sOpt
2fe0: 69 6f 6e 2c 20 73 4c 69 6e 65 49 64 2c 20 73 52  ion, sLineId, sR
2ff0: 75 6c 65 49 64 20 69 6e 20 6c 69 73 74 52 75 6c  uleId in listRul
3000: 65 73 28 73 46 69 6c 74 65 72 29 3a 0a 20 20 20  es(sFilter):.   
3010: 20 20 20 20 20 65 63 68 6f 28 22 7b 3a 3c 31 30       echo("{:<10
3020: 7d 20 7b 3a 3c 31 30 7d 20 7b 7d 22 2e 66 6f 72  } {:<10} {}".for
3030: 6d 61 74 28 73 4f 70 74 69 6f 6e 2c 20 73 4c 69  mat(sOption, sLi
3040: 6e 65 49 64 2c 20 73 52 75 6c 65 49 64 29 29 0a  neId, sRuleId)).
3050: 0a 0a 64 65 66 20 73 65 74 4f 70 74 69 6f 6e 20  ..def setOption 
3060: 28 73 4f 70 74 2c 20 62 56 61 6c 29 3a 0a 20 20  (sOpt, bVal):.  
3070: 20 20 22 73 65 74 20 6f 70 74 69 6f 6e 20 3c 73    "set option <s
3080: 4f 70 74 3e 20 77 69 74 68 20 3c 62 56 61 6c 3e  Opt> with <bVal>
3090: 20 69 66 20 69 74 20 65 78 69 73 74 73 22 0a 20   if it exists". 
30a0: 20 20 20 69 66 20 73 4f 70 74 20 69 6e 20 5f 64     if sOpt in _d
30b0: 4f 70 74 69 6f 6e 73 3a 0a 20 20 20 20 20 20 20  Options:.       
30c0: 20 5f 64 4f 70 74 69 6f 6e 73 5b 73 4f 70 74 5d   _dOptions[sOpt]
30d0: 20 3d 20 62 56 61 6c 0a 0a 0a 64 65 66 20 73 65   = bVal...def se
30e0: 74 4f 70 74 69 6f 6e 73 20 28 64 4f 70 74 29 3a  tOptions (dOpt):
30f0: 0a 20 20 20 20 22 75 70 64 61 74 65 20 74 68 65  .    "update the
3100: 20 64 69 63 74 69 6f 6e 61 72 79 20 6f 66 20 6f   dictionary of o
3110: 70 74 69 6f 6e 73 20 77 69 74 68 20 3c 64 4f 70  ptions with <dOp
3120: 74 3e 22 0a 20 20 20 20 66 6f 72 20 73 4b 65 79  t>".    for sKey
3130: 2c 20 62 56 61 6c 20 69 6e 20 64 4f 70 74 2e 69  , bVal in dOpt.i
3140: 74 65 6d 73 28 29 3a 0a 20 20 20 20 20 20 20 20  tems():.        
3150: 69 66 20 73 4b 65 79 20 69 6e 20 5f 64 4f 70 74  if sKey in _dOpt
3160: 69 6f 6e 73 3a 0a 20 20 20 20 20 20 20 20 20 20  ions:.          
3170: 20 20 5f 64 4f 70 74 69 6f 6e 73 5b 73 4b 65 79    _dOptions[sKey
3180: 5d 20 3d 20 62 56 61 6c 0a 0a 0a 64 65 66 20 67  ] = bVal...def g
3190: 65 74 4f 70 74 69 6f 6e 73 20 28 29 3a 0a 20 20  etOptions ():.  
31a0: 20 20 22 72 65 74 75 72 6e 20 74 68 65 20 64 69    "return the di
31b0: 63 74 69 6f 6e 61 72 79 20 6f 66 20 63 75 72 72  ctionary of curr
31c0: 65 6e 74 20 6f 70 74 69 6f 6e 73 22 0a 20 20 20  ent options".   
31d0: 20 72 65 74 75 72 6e 20 5f 64 4f 70 74 69 6f 6e   return _dOption
31e0: 73 0a 0a 0a 64 65 66 20 67 65 74 44 65 66 61 75  s...def getDefau
31f0: 6c 74 4f 70 74 69 6f 6e 73 20 28 29 3a 0a 20 20  ltOptions ():.  
3200: 20 20 22 72 65 74 75 72 6e 20 74 68 65 20 64 69    "return the di
3210: 63 74 69 6f 6e 61 72 79 20 6f 66 20 64 65 66 61  ctionary of defa
3220: 75 6c 74 20 6f 70 74 69 6f 6e 73 22 0a 20 20 20  ult options".   
3230: 20 72 65 74 75 72 6e 20 64 69 63 74 28 67 63 5f   return dict(gc_
3240: 6f 70 74 69 6f 6e 73 2e 67 65 74 4f 70 74 69 6f  options.getOptio
3250: 6e 73 28 5f 73 41 70 70 43 6f 6e 74 65 78 74 29  ns(_sAppContext)
3260: 29 0a 0a 0a 64 65 66 20 67 65 74 4f 70 74 69 6f  )...def getOptio
3270: 6e 73 4c 61 62 65 6c 73 20 28 73 4c 61 6e 67 29  nsLabels (sLang)
3280: 3a 0a 20 20 20 20 22 72 65 74 75 72 6e 20 6f 70  :.    "return op
3290: 74 69 6f 6e 73 20 6c 61 62 65 6c 73 22 0a 20 20  tions labels".  
32a0: 20 20 72 65 74 75 72 6e 20 67 63 5f 6f 70 74 69    return gc_opti
32b0: 6f 6e 73 2e 67 65 74 55 49 28 73 4c 61 6e 67 29  ons.getUI(sLang)
32c0: 0a 0a 0a 64 65 66 20 64 69 73 70 6c 61 79 4f 70  ...def displayOp
32d0: 74 69 6f 6e 73 20 28 73 4c 61 6e 67 29 3a 0a 20  tions (sLang):. 
32e0: 20 20 20 22 64 69 73 70 6c 61 79 20 74 68 65 20     "display the 
32f0: 6c 69 73 74 20 6f 66 20 67 72 61 6d 6d 61 72 20  list of grammar 
3300: 63 68 65 63 6b 69 6e 67 20 6f 70 74 69 6f 6e 73  checking options
3310: 22 0a 20 20 20 20 65 63 68 6f 28 22 4c 69 73 74  ".    echo("List
3320: 20 6f 66 20 6f 70 74 69 6f 6e 73 22 29 0a 20 20   of options").  
3330: 20 20 65 63 68 6f 28 22 5c 6e 22 2e 6a 6f 69 6e    echo("\n".join
3340: 28 20 5b 20 6b 2b 22 3a 5c 74 22 2b 73 74 72 28  ( [ k+":\t"+str(
3350: 76 29 2b 22 5c 74 22 2b 67 63 5f 6f 70 74 69 6f  v)+"\t"+gc_optio
3360: 6e 73 2e 67 65 74 55 49 28 73 4c 61 6e 67 29 2e  ns.getUI(sLang).
3370: 67 65 74 28 6b 2c 20 28 22 3f 22 2c 20 22 22 29  get(k, ("?", "")
3380: 29 5b 30 5d 20 20 66 6f 72 20 6b 2c 20 76 20 20  )[0]  for k, v  
3390: 69 6e 20 73 6f 72 74 65 64 28 5f 64 4f 70 74 69  in sorted(_dOpti
33a0: 6f 6e 73 2e 69 74 65 6d 73 28 29 29 20 5d 20 29  ons.items()) ] )
33b0: 29 0a 20 20 20 20 65 63 68 6f 28 22 22 29 0a 0a  ).    echo("")..
33c0: 0a 64 65 66 20 72 65 73 65 74 4f 70 74 69 6f 6e  .def resetOption
33d0: 73 20 28 29 3a 0a 20 20 20 20 22 73 65 74 20 6f  s ():.    "set o
33e0: 70 74 69 6f 6e 73 20 74 6f 20 64 65 66 61 75 6c  ptions to defaul
33f0: 74 20 76 61 6c 75 65 73 22 0a 20 20 20 20 67 6c  t values".    gl
3400: 6f 62 61 6c 20 5f 64 4f 70 74 69 6f 6e 73 0a 20  obal _dOptions. 
3410: 20 20 20 5f 64 4f 70 74 69 6f 6e 73 20 3d 20 64     _dOptions = d
3420: 69 63 74 28 67 63 5f 6f 70 74 69 6f 6e 73 2e 67  ict(gc_options.g
3430: 65 74 4f 70 74 69 6f 6e 73 28 5f 73 41 70 70 43  etOptions(_sAppC
3440: 6f 6e 74 65 78 74 29 29 0a 0a 0a 64 65 66 20 67  ontext))...def g
3450: 65 74 53 70 65 6c 6c 43 68 65 63 6b 65 72 20 28  etSpellChecker (
3460: 29 3a 0a 20 20 20 20 22 72 65 74 75 72 6e 20 74  ):.    "return t
3470: 68 65 20 73 70 65 6c 6c 63 68 65 63 6b 65 72 20  he spellchecker 
3480: 6f 62 6a 65 63 74 22 0a 20 20 20 20 72 65 74 75  object".    retu
3490: 72 6e 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65  rn _oSpellChecke
34a0: 72 0a 0a 0a 64 65 66 20 5f 67 65 74 50 61 74 68  r...def _getPath
34b0: 20 28 29 3a 0a 20 20 20 20 72 65 74 75 72 6e 20   ():.    return 
34c0: 6f 73 2e 70 61 74 68 2e 6a 6f 69 6e 28 6f 73 2e  os.path.join(os.
34d0: 70 61 74 68 2e 64 69 72 6e 61 6d 65 28 73 79 73  path.dirname(sys
34e0: 2e 6d 6f 64 75 6c 65 73 5b 5f 5f 6e 61 6d 65 5f  .modules[__name_
34f0: 5f 5d 2e 5f 5f 66 69 6c 65 5f 5f 29 2c 20 5f 5f  _].__file__), __
3500: 6e 61 6d 65 5f 5f 20 2b 20 22 2e 70 79 22 29 0a  name__ + ".py").
3510: 0a 0a 0a 23 23 23 23 20 63 6f 6d 6d 6f 6e 20 66  ...#### common f
3520: 75 6e 63 74 69 6f 6e 73 0a 0a 64 65 66 20 6f 70  unctions..def op
3530: 74 69 6f 6e 20 28 73 4f 70 74 29 3a 0a 20 20 20  tion (sOpt):.   
3540: 20 22 72 65 74 75 72 6e 20 54 72 75 65 20 69 66   "return True if
3550: 20 6f 70 74 69 6f 6e 20 3c 73 4f 70 74 3e 20 69   option <sOpt> i
3560: 73 20 61 63 74 69 76 65 22 0a 20 20 20 20 72 65  s active".    re
3570: 74 75 72 6e 20 5f 64 4f 70 74 69 6f 6e 73 2e 67  turn _dOptions.g
3580: 65 74 28 73 4f 70 74 2c 20 46 61 6c 73 65 29 0a  et(sOpt, False).
3590: 0a 0a 64 65 66 20 64 69 73 70 6c 61 79 49 6e 66  ..def displayInf
35a0: 6f 20 28 64 54 6f 6b 65 6e 50 6f 73 2c 20 74 57  o (dTokenPos, tW
35b0: 6f 72 64 29 3a 0a 20 20 20 20 22 66 6f 72 20 64  ord):.    "for d
35c0: 65 62 75 67 67 69 6e 67 3a 20 72 65 74 72 69 65  ebugging: retrie
35d0: 76 65 20 69 6e 66 6f 20 6f 66 20 77 6f 72 64 22  ve info of word"
35e0: 0a 20 20 20 20 69 66 20 6e 6f 74 20 74 57 6f 72  .    if not tWor
35f0: 64 3a 0a 20 20 20 20 20 20 20 20 65 63 68 6f 28  d:.        echo(
3600: 22 3e 20 6e 6f 74 68 69 6e 67 20 74 6f 20 66 69  "> nothing to fi
3610: 6e 64 22 29 0a 20 20 20 20 20 20 20 20 72 65 74  nd").        ret
3620: 75 72 6e 20 54 72 75 65 0a 20 20 20 20 6c 4d 6f  urn True.    lMo
3630: 72 70 68 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65  rph = _oSpellChe
3640: 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 74 57  cker.getMorph(tW
3650: 6f 72 64 5b 31 5d 29 0a 20 20 20 20 69 66 20 6e  ord[1]).    if n
3660: 6f 74 20 6c 4d 6f 72 70 68 3a 0a 20 20 20 20 20  ot lMorph:.     
3670: 20 20 20 65 63 68 6f 28 22 3e 20 6e 6f 74 20 69     echo("> not i
3680: 6e 20 64 69 63 74 69 6f 6e 61 72 79 22 29 0a 20  n dictionary"). 
3690: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54 72         return Tr
36a0: 75 65 0a 20 20 20 20 70 72 69 6e 74 28 22 54 4f  ue.    print("TO
36b0: 4b 45 4e 53 3a 22 2c 20 64 54 6f 6b 65 6e 50 6f  KENS:", dTokenPo
36c0: 73 29 0a 20 20 20 20 69 66 20 74 57 6f 72 64 5b  s).    if tWord[
36d0: 30 5d 20 69 6e 20 64 54 6f 6b 65 6e 50 6f 73 20  0] in dTokenPos 
36e0: 61 6e 64 20 22 6c 4d 6f 72 70 68 22 20 69 6e 20  and "lMorph" in 
36f0: 64 54 6f 6b 65 6e 50 6f 73 5b 74 57 6f 72 64 5b  dTokenPos[tWord[
3700: 30 5d 5d 3a 0a 20 20 20 20 20 20 20 20 65 63 68  0]]:.        ech
3710: 6f 28 22 44 41 3a 20 22 20 2b 20 73 74 72 28 64  o("DA: " + str(d
3720: 54 6f 6b 65 6e 50 6f 73 5b 74 57 6f 72 64 5b 30  TokenPos[tWord[0
3730: 5d 5d 5b 22 6c 4d 6f 72 70 68 22 5d 29 29 0a 20  ]]["lMorph"])). 
3740: 20 20 20 65 63 68 6f 28 22 46 53 41 3a 20 22 20     echo("FSA: " 
3750: 2b 20 73 74 72 28 6c 4d 6f 72 70 68 29 29 0a 20  + str(lMorph)). 
3760: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 0a     return True..
3770: 0a 64 65 66 20 6d 6f 72 70 68 20 28 64 54 6f 6b  .def morph (dTok
3780: 65 6e 50 6f 73 2c 20 74 57 6f 72 64 2c 20 73 50  enPos, tWord, sP
3790: 61 74 74 65 72 6e 2c 20 62 53 74 72 69 63 74 3d  attern, bStrict=
37a0: 54 72 75 65 2c 20 62 4e 6f 57 6f 72 64 3d 46 61  True, bNoWord=Fa
37b0: 6c 73 65 29 3a 0a 20 20 20 20 22 61 6e 61 6c 79  lse):.    "analy
37c0: 73 65 20 61 20 74 75 70 6c 65 20 28 70 6f 73 69  se a tuple (posi
37d0: 74 69 6f 6e 2c 20 77 6f 72 64 29 2c 20 72 65 74  tion, word), ret
37e0: 75 72 6e 20 54 72 75 65 20 69 66 20 73 50 61 74  urn True if sPat
37f0: 74 65 72 6e 20 69 6e 20 6d 6f 72 70 68 6f 6c 6f  tern in morpholo
3800: 67 69 65 73 20 28 64 69 73 61 6d 62 69 67 75 61  gies (disambigua
3810: 74 69 6f 6e 20 6f 6e 29 22 0a 20 20 20 20 69 66  tion on)".    if
3820: 20 6e 6f 74 20 74 57 6f 72 64 3a 0a 20 20 20 20   not tWord:.    
3830: 20 20 20 20 72 65 74 75 72 6e 20 62 4e 6f 57 6f      return bNoWo
3840: 72 64 0a 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20  rd.    lMorph = 
3850: 64 54 6f 6b 65 6e 50 6f 73 5b 74 57 6f 72 64 5b  dTokenPos[tWord[
3860: 30 5d 5d 5b 22 6c 4d 6f 72 70 68 22 5d 20 20 69  0]]["lMorph"]  i
3870: 66 20 74 57 6f 72 64 5b 30 5d 20 69 6e 20 64 54  f tWord[0] in dT
3880: 6f 6b 65 6e 50 6f 73 20 61 6e 64 20 22 6c 4d 6f  okenPos and "lMo
3890: 72 70 68 22 20 69 6e 20 64 54 6f 6b 65 6e 50 6f  rph" in dTokenPo
38a0: 73 5b 74 57 6f 72 64 5b 30 5d 5d 20 20 65 6c 73  s[tWord[0]]  els
38b0: 65 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72  e _oSpellChecker
38c0: 2e 67 65 74 4d 6f 72 70 68 28 74 57 6f 72 64 5b  .getMorph(tWord[
38d0: 31 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c  1]).    if not l
38e0: 4d 6f 72 70 68 3a 0a 20 20 20 20 20 20 20 20 72  Morph:.        r
38f0: 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20  eturn False.    
3900: 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f  zPattern = re.co
3910: 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29 0a  mpile(sPattern).
3920: 20 20 20 20 69 66 20 62 53 74 72 69 63 74 3a 0a      if bStrict:.
3930: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 62          return b
3940: 6f 6f 6c 28 6c 4d 6f 72 70 68 29 20 61 6e 64 20  ool(lMorph) and 
3950: 61 6c 6c 28 7a 50 61 74 74 65 72 6e 2e 73 65 61  all(zPattern.sea
3960: 72 63 68 28 73 29 20 20 66 6f 72 20 73 20 69 6e  rch(s)  for s in
3970: 20 6c 4d 6f 72 70 68 29 0a 20 20 20 20 72 65 74   lMorph).    ret
3980: 75 72 6e 20 61 6e 79 28 7a 50 61 74 74 65 72 6e  urn any(zPattern
3990: 2e 73 65 61 72 63 68 28 73 29 20 20 66 6f 72 20  .search(s)  for 
39a0: 73 20 69 6e 20 6c 4d 6f 72 70 68 29 0a 0a 0a 64  s in lMorph)...d
39b0: 65 66 20 6d 6f 72 70 68 65 78 20 28 64 54 6f 6b  ef morphex (dTok
39c0: 65 6e 50 6f 73 2c 20 74 57 6f 72 64 2c 20 73 50  enPos, tWord, sP
39d0: 61 74 74 65 72 6e 2c 20 73 4e 65 67 50 61 74 74  attern, sNegPatt
39e0: 65 72 6e 2c 20 62 4e 6f 57 6f 72 64 3d 46 61 6c  ern, bNoWord=Fal
39f0: 73 65 29 3a 0a 20 20 20 20 22 61 6e 61 6c 79 73  se):.    "analys
3a00: 65 20 61 20 74 75 70 6c 65 20 28 70 6f 73 69 74  e a tuple (posit
3a10: 69 6f 6e 2c 20 77 6f 72 64 29 2c 20 72 65 74 75  ion, word), retu
3a20: 72 6e 73 20 54 72 75 65 20 69 66 20 6e 6f 74 20  rns True if not 
3a30: 73 4e 65 67 50 61 74 74 65 72 6e 20 69 6e 20 77  sNegPattern in w
3a40: 6f 72 64 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73  ord morphologies
3a50: 20 61 6e 64 20 73 50 61 74 74 65 72 6e 20 69 6e   and sPattern in
3a60: 20 77 6f 72 64 20 6d 6f 72 70 68 6f 6c 6f 67 69   word morphologi
3a70: 65 73 20 28 64 69 73 61 6d 62 69 67 75 61 74 69  es (disambiguati
3a80: 6f 6e 20 6f 6e 29 22 0a 20 20 20 20 69 66 20 6e  on on)".    if n
3a90: 6f 74 20 74 57 6f 72 64 3a 0a 20 20 20 20 20 20  ot tWord:.      
3aa0: 20 20 72 65 74 75 72 6e 20 62 4e 6f 57 6f 72 64    return bNoWord
3ab0: 0a 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20 64 54  .    lMorph = dT
3ac0: 6f 6b 65 6e 50 6f 73 5b 74 57 6f 72 64 5b 30 5d  okenPos[tWord[0]
3ad0: 5d 5b 22 6c 4d 6f 72 70 68 22 5d 20 20 69 66 20  ]["lMorph"]  if 
3ae0: 74 57 6f 72 64 5b 30 5d 20 69 6e 20 64 54 6f 6b  tWord[0] in dTok
3af0: 65 6e 50 6f 73 20 61 6e 64 20 22 6c 4d 6f 72 70  enPos and "lMorp
3b00: 68 22 20 69 6e 20 64 54 6f 6b 65 6e 50 6f 73 5b  h" in dTokenPos[
3b10: 74 57 6f 72 64 5b 30 5d 5d 20 20 65 6c 73 65 20  tWord[0]]  else 
3b20: 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67  _oSpellChecker.g
3b30: 65 74 4d 6f 72 70 68 28 74 57 6f 72 64 5b 31 5d  etMorph(tWord[1]
3b40: 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f  ).    if not lMo
3b50: 72 70 68 3a 0a 20 20 20 20 20 20 20 20 72 65 74  rph:.        ret
3b60: 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 23 20  urn False.    # 
3b70: 63 68 65 63 6b 20 6e 65 67 61 74 69 76 65 20 63  check negative c
3b80: 6f 6e 64 69 74 69 6f 6e 0a 20 20 20 20 7a 4e 65  ondition.    zNe
3b90: 67 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f  gPattern = re.co
3ba0: 6d 70 69 6c 65 28 73 4e 65 67 50 61 74 74 65 72  mpile(sNegPatter
3bb0: 6e 29 0a 20 20 20 20 69 66 20 61 6e 79 28 7a 4e  n).    if any(zN
3bc0: 65 67 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68  egPattern.search
3bd0: 28 73 29 20 20 66 6f 72 20 73 20 69 6e 20 6c 4d  (s)  for s in lM
3be0: 6f 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20 72  orph):.        r
3bf0: 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20  eturn False.    
3c00: 23 20 73 65 61 72 63 68 20 73 50 61 74 74 65 72  # search sPatter
3c10: 6e 0a 20 20 20 20 7a 50 61 74 74 65 72 6e 20 3d  n.    zPattern =
3c20: 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 50 61 74   re.compile(sPat
3c30: 74 65 72 6e 29 0a 20 20 20 20 72 65 74 75 72 6e  tern).    return
3c40: 20 61 6e 79 28 7a 50 61 74 74 65 72 6e 2e 73 65   any(zPattern.se
3c50: 61 72 63 68 28 73 29 20 20 66 6f 72 20 73 20 69  arch(s)  for s i
3c60: 6e 20 6c 4d 6f 72 70 68 29 0a 0a 0a 64 65 66 20  n lMorph)...def 
3c70: 61 6e 61 6c 79 73 65 20 28 73 57 6f 72 64 2c 20  analyse (sWord, 
3c80: 73 50 61 74 74 65 72 6e 2c 20 62 53 74 72 69 63  sPattern, bStric
3c90: 74 3d 54 72 75 65 29 3a 0a 20 20 20 20 22 61 6e  t=True):.    "an
3ca0: 61 6c 79 73 65 20 61 20 77 6f 72 64 2c 20 72 65  alyse a word, re
3cb0: 74 75 72 6e 20 54 72 75 65 20 69 66 20 73 50 61  turn True if sPa
3cc0: 74 74 65 72 6e 20 69 6e 20 6d 6f 72 70 68 6f 6c  ttern in morphol
3cd0: 6f 67 69 65 73 20 28 64 69 73 61 6d 62 69 67 75  ogies (disambigu
3ce0: 61 74 69 6f 6e 20 6f 66 66 29 22 0a 20 20 20 20  ation off)".    
3cf0: 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53 70 65 6c 6c  lMorph = _oSpell
3d00: 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68  Checker.getMorph
3d10: 28 73 57 6f 72 64 29 0a 20 20 20 20 69 66 20 6e  (sWord).    if n
3d20: 6f 74 20 6c 4d 6f 72 70 68 3a 0a 20 20 20 20 20  ot lMorph:.     
3d30: 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a     return False.
3d40: 20 20 20 20 7a 50 61 74 74 65 72 6e 20 3d 20 72      zPattern = r
3d50: 65 2e 63 6f 6d 70 69 6c 65 28 73 50 61 74 74 65  e.compile(sPatte
3d60: 72 6e 29 0a 20 20 20 20 69 66 20 62 53 74 72 69  rn).    if bStri
3d70: 63 74 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75  ct:.        retu
3d80: 72 6e 20 62 6f 6f 6c 28 6c 4d 6f 72 70 68 29 20  rn bool(lMorph) 
3d90: 61 6e 64 20 61 6c 6c 28 7a 50 61 74 74 65 72 6e  and all(zPattern
3da0: 2e 73 65 61 72 63 68 28 73 29 20 20 66 6f 72 20  .search(s)  for 
3db0: 73 20 69 6e 20 6c 4d 6f 72 70 68 29 0a 20 20 20  s in lMorph).   
3dc0: 20 72 65 74 75 72 6e 20 61 6e 79 28 7a 50 61 74   return any(zPat
3dd0: 74 65 72 6e 2e 73 65 61 72 63 68 28 73 29 20 20  tern.search(s)  
3de0: 66 6f 72 20 73 20 69 6e 20 6c 4d 6f 72 70 68 29  for s in lMorph)
3df0: 0a 0a 0a 64 65 66 20 61 6e 61 6c 79 73 65 78 20  ...def analysex 
3e00: 28 73 57 6f 72 64 2c 20 73 50 61 74 74 65 72 6e  (sWord, sPattern
3e10: 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 29 3a 0a  , sNegPattern):.
3e20: 20 20 20 20 22 61 6e 61 6c 79 73 65 20 61 20 77      "analyse a w
3e30: 6f 72 64 2c 20 72 65 74 75 72 6e 73 20 54 72 75  ord, returns Tru
3e40: 65 20 69 66 20 6e 6f 74 20 73 4e 65 67 50 61 74  e if not sNegPat
3e50: 74 65 72 6e 20 69 6e 20 77 6f 72 64 20 6d 6f 72  tern in word mor
3e60: 70 68 6f 6c 6f 67 69 65 73 20 61 6e 64 20 73 50  phologies and sP
3e70: 61 74 74 65 72 6e 20 69 6e 20 77 6f 72 64 20 6d  attern in word m
3e80: 6f 72 70 68 6f 6c 6f 67 69 65 73 20 28 64 69 73  orphologies (dis
3e90: 61 6d 62 69 67 75 61 74 69 6f 6e 20 6f 66 66 29  ambiguation off)
3ea0: 22 0a 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20 5f  ".    lMorph = _
3eb0: 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65  oSpellChecker.ge
3ec0: 74 4d 6f 72 70 68 28 73 57 6f 72 64 29 0a 20 20  tMorph(sWord).  
3ed0: 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 3a    if not lMorph:
3ee0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
3ef0: 46 61 6c 73 65 0a 20 20 20 20 23 20 63 68 65 63  False.    # chec
3f00: 6b 20 6e 65 67 61 74 69 76 65 20 63 6f 6e 64 69  k negative condi
3f10: 74 69 6f 6e 0a 20 20 20 20 7a 4e 65 67 50 61 74  tion.    zNegPat
3f20: 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c  tern = re.compil
3f30: 65 28 73 4e 65 67 50 61 74 74 65 72 6e 29 0a 20  e(sNegPattern). 
3f40: 20 20 20 69 66 20 61 6e 79 28 7a 4e 65 67 50 61     if any(zNegPa
3f50: 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73 29 20  ttern.search(s) 
3f60: 20 66 6f 72 20 73 20 69 6e 20 6c 4d 6f 72 70 68   for s in lMorph
3f70: 29 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  ):.        retur
3f80: 6e 20 46 61 6c 73 65 0a 20 20 20 20 23 20 73 65  n False.    # se
3f90: 61 72 63 68 20 73 50 61 74 74 65 72 6e 0a 20 20  arch sPattern.  
3fa0: 20 20 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e    zPattern = re.
3fb0: 63 6f 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e  compile(sPattern
3fc0: 29 0a 20 20 20 20 72 65 74 75 72 6e 20 61 6e 79  ).    return any
3fd0: 28 7a 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68  (zPattern.search
3fe0: 28 73 29 20 20 66 6f 72 20 73 20 69 6e 20 6c 4d  (s)  for s in lM
3ff0: 6f 72 70 68 29 0a 0a 0a 0a 23 23 20 66 75 6e 63  orph)....## func
4000: 74 69 6f 6e 73 20 74 6f 20 67 65 74 20 74 65 78  tions to get tex
4010: 74 20 6f 75 74 73 69 64 65 20 70 61 74 74 65 72  t outside patter
4020: 6e 20 73 63 6f 70 65 0a 0a 23 20 77 61 72 6e 69  n scope..# warni
4030: 6e 67 3a 20 63 68 65 63 6b 20 63 6f 6d 70 69 6c  ng: check compil
4040: 65 5f 72 75 6c 65 73 2e 70 79 20 74 6f 20 75 6e  e_rules.py to un
4050: 64 65 72 73 74 61 6e 64 20 68 6f 77 20 69 74 20  derstand how it 
4060: 77 6f 72 6b 73 0a 0a 5f 7a 4e 65 78 74 57 6f 72  works.._zNextWor
4070: 64 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65 28 72  d = re.compile(r
4080: 22 20 2b 28 5c 77 5b 5c 77 2d 5d 2a 29 22 29 0a  " +(\w[\w-]*)").
4090: 5f 7a 50 72 65 76 57 6f 72 64 20 3d 20 72 65 2e  _zPrevWord = re.
40a0: 63 6f 6d 70 69 6c 65 28 72 22 28 5c 77 5b 5c 77  compile(r"(\w[\w
40b0: 2d 5d 2a 29 20 2b 24 22 29 0a 0a 64 65 66 20 6e  -]*) +$")..def n
40c0: 65 78 74 77 6f 72 64 20 28 73 2c 20 69 53 74 61  extword (s, iSta
40d0: 72 74 2c 20 6e 29 3a 0a 20 20 20 20 22 67 65 74  rt, n):.    "get
40e0: 20 74 68 65 20 6e 74 68 20 77 6f 72 64 20 6f 66   the nth word of
40f0: 20 74 68 65 20 69 6e 70 75 74 20 73 74 72 69 6e   the input strin
4100: 67 20 6f 72 20 65 6d 70 74 79 20 73 74 72 69 6e  g or empty strin
4110: 67 22 0a 20 20 20 20 6d 20 3d 20 72 65 2e 6d 61  g".    m = re.ma
4120: 74 63 68 28 22 28 3f 3a 20 2b 5b 5c 5c 77 25 2d  tch("(?: +[\\w%-
4130: 5d 2b 29 7b 22 20 2b 20 73 74 72 28 6e 2d 31 29  ]+){" + str(n-1)
4140: 20 2b 20 22 7d 20 2b 28 5b 5c 5c 77 25 2d 5d 2b   + "} +([\\w%-]+
4150: 29 22 2c 20 73 5b 69 53 74 61 72 74 3a 5d 29 0a  )", s[iStart:]).
4160: 20 20 20 20 69 66 20 6e 6f 74 20 6d 3a 0a 20 20      if not m:.  
4170: 20 20 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e        return Non
4180: 65 0a 20 20 20 20 72 65 74 75 72 6e 20 28 69 53  e.    return (iS
4190: 74 61 72 74 2b 6d 2e 73 74 61 72 74 28 31 29 2c  tart+m.start(1),
41a0: 20 6d 2e 67 72 6f 75 70 28 31 29 29 0a 0a 0a 64   m.group(1))...d
41b0: 65 66 20 70 72 65 76 77 6f 72 64 20 28 73 2c 20  ef prevword (s, 
41c0: 69 45 6e 64 2c 20 6e 29 3a 0a 20 20 20 20 22 67  iEnd, n):.    "g
41d0: 65 74 20 74 68 65 20 28 2d 29 6e 74 68 20 77 6f  et the (-)nth wo
41e0: 72 64 20 6f 66 20 74 68 65 20 69 6e 70 75 74 20  rd of the input 
41f0: 73 74 72 69 6e 67 20 6f 72 20 65 6d 70 74 79 20  string or empty 
4200: 73 74 72 69 6e 67 22 0a 20 20 20 20 6d 20 3d 20  string".    m = 
4210: 72 65 2e 73 65 61 72 63 68 28 22 28 5b 5c 5c 77  re.search("([\\w
4220: 25 2d 5d 2b 29 20 2b 28 3f 3a 5b 5c 5c 77 25 2d  %-]+) +(?:[\\w%-
4230: 5d 2b 20 2b 29 7b 22 20 2b 20 73 74 72 28 6e 2d  ]+ +){" + str(n-
4240: 31 29 20 2b 20 22 7d 24 22 2c 20 73 5b 3a 69 45  1) + "}$", s[:iE
4250: 6e 64 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20  nd]).    if not 
4260: 6d 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  m:.        retur
4270: 6e 20 4e 6f 6e 65 0a 20 20 20 20 72 65 74 75 72  n None.    retur
4280: 6e 20 28 6d 2e 73 74 61 72 74 28 31 29 2c 20 6d  n (m.start(1), m
4290: 2e 67 72 6f 75 70 28 31 29 29 0a 0a 0a 64 65 66  .group(1))...def
42a0: 20 6e 65 78 74 77 6f 72 64 31 20 28 73 2c 20 69   nextword1 (s, i
42b0: 53 74 61 72 74 29 3a 0a 20 20 20 20 22 67 65 74  Start):.    "get
42c0: 20 6e 65 78 74 20 77 6f 72 64 20 28 6f 70 74 69   next word (opti
42d0: 6d 69 7a 61 74 69 6f 6e 29 22 0a 20 20 20 20 6d  mization)".    m
42e0: 20 3d 20 5f 7a 4e 65 78 74 57 6f 72 64 2e 6d 61   = _zNextWord.ma
42f0: 74 63 68 28 73 5b 69 53 74 61 72 74 3a 5d 29 0a  tch(s[iStart:]).
4300: 20 20 20 20 69 66 20 6e 6f 74 20 6d 3a 0a 20 20      if not m:.  
4310: 20 20 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e        return Non
4320: 65 0a 20 20 20 20 72 65 74 75 72 6e 20 28 69 53  e.    return (iS
4330: 74 61 72 74 2b 6d 2e 73 74 61 72 74 28 31 29 2c  tart+m.start(1),
4340: 20 6d 2e 67 72 6f 75 70 28 31 29 29 0a 0a 0a 64   m.group(1))...d
4350: 65 66 20 70 72 65 76 77 6f 72 64 31 20 28 73 2c  ef prevword1 (s,
4360: 20 69 45 6e 64 29 3a 0a 20 20 20 20 22 67 65 74   iEnd):.    "get
4370: 20 70 72 65 76 69 6f 75 73 20 77 6f 72 64 20 28   previous word (
4380: 6f 70 74 69 6d 69 7a 61 74 69 6f 6e 29 22 0a 20  optimization)". 
4390: 20 20 20 6d 20 3d 20 5f 7a 50 72 65 76 57 6f 72     m = _zPrevWor
43a0: 64 2e 73 65 61 72 63 68 28 73 5b 3a 69 45 6e 64  d.search(s[:iEnd
43b0: 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6d 3a  ]).    if not m:
43c0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
43d0: 4e 6f 6e 65 0a 20 20 20 20 72 65 74 75 72 6e 20  None.    return 
43e0: 28 6d 2e 73 74 61 72 74 28 31 29 2c 20 6d 2e 67  (m.start(1), m.g
43f0: 72 6f 75 70 28 31 29 29 0a 0a 0a 64 65 66 20 6c  roup(1))...def l
4400: 6f 6f 6b 20 28 73 2c 20 73 50 61 74 74 65 72 6e  ook (s, sPattern
4410: 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 3d 4e 6f  , sNegPattern=No
4420: 6e 65 29 3a 0a 20 20 20 20 22 73 65 65 6b 20 73  ne):.    "seek s
4430: 50 61 74 74 65 72 6e 20 69 6e 20 73 20 28 62 65  Pattern in s (be
4440: 66 6f 72 65 2f 61 66 74 65 72 2f 66 75 6c 6c 74  fore/after/fullt
4450: 65 78 74 29 2c 20 69 66 20 73 4e 65 67 50 61 74  ext), if sNegPat
4460: 74 65 72 6e 20 6e 6f 74 20 69 6e 20 73 22 0a 20  tern not in s". 
4470: 20 20 20 69 66 20 73 4e 65 67 50 61 74 74 65 72     if sNegPatter
4480: 6e 20 61 6e 64 20 72 65 2e 73 65 61 72 63 68 28  n and re.search(
4490: 73 4e 65 67 50 61 74 74 65 72 6e 2c 20 73 29 3a  sNegPattern, s):
44a0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
44b0: 46 61 6c 73 65 0a 20 20 20 20 69 66 20 72 65 2e  False.    if re.
44c0: 73 65 61 72 63 68 28 73 50 61 74 74 65 72 6e 2c  search(sPattern,
44d0: 20 73 29 3a 0a 20 20 20 20 20 20 20 20 72 65 74   s):.        ret
44e0: 75 72 6e 20 54 72 75 65 0a 20 20 20 20 72 65 74  urn True.    ret
44f0: 75 72 6e 20 46 61 6c 73 65 0a 0a 0a 64 65 66 20  urn False...def 
4500: 6c 6f 6f 6b 5f 63 68 6b 31 20 28 64 54 6f 6b 65  look_chk1 (dToke
4510: 6e 50 6f 73 2c 20 73 2c 20 6e 4f 66 66 73 65 74  nPos, s, nOffset
4520: 2c 20 73 50 61 74 74 65 72 6e 2c 20 73 50 61 74  , sPattern, sPat
4530: 74 65 72 6e 47 72 6f 75 70 31 2c 20 73 4e 65 67  ternGroup1, sNeg
4540: 50 61 74 74 65 72 6e 47 72 6f 75 70 31 3d 4e 6f  PatternGroup1=No
4550: 6e 65 29 3a 0a 20 20 20 20 22 72 65 74 75 72 6e  ne):.    "return
4560: 73 20 54 72 75 65 20 69 66 20 73 20 68 61 73 20  s True if s has 
4570: 70 61 74 74 65 72 6e 20 73 50 61 74 74 65 72 6e  pattern sPattern
4580: 20 61 6e 64 20 6d 2e 67 72 6f 75 70 28 31 29 20   and m.group(1) 
4590: 68 61 73 20 70 61 74 74 65 72 6e 20 73 50 61 74  has pattern sPat
45a0: 74 65 72 6e 47 72 6f 75 70 31 22 0a 20 20 20 20  ternGroup1".    
45b0: 6d 20 3d 20 72 65 2e 73 65 61 72 63 68 28 73 50  m = re.search(sP
45c0: 61 74 74 65 72 6e 2c 20 73 29 0a 20 20 20 20 69  attern, s).    i
45d0: 66 20 6e 6f 74 20 6d 3a 0a 20 20 20 20 20 20 20  f not m:.       
45e0: 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20   return False.  
45f0: 20 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 73    try:.        s
4600: 57 6f 72 64 20 3d 20 6d 2e 67 72 6f 75 70 28 31  Word = m.group(1
4610: 29 0a 20 20 20 20 20 20 20 20 6e 50 6f 73 20 3d  ).        nPos =
4620: 20 6d 2e 73 74 61 72 74 28 31 29 20 2b 20 6e 4f   m.start(1) + nO
4630: 66 66 73 65 74 0a 20 20 20 20 65 78 63 65 70 74  ffset.    except
4640: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
4650: 20 46 61 6c 73 65 0a 20 20 20 20 69 66 20 73 4e   False.    if sN
4660: 65 67 50 61 74 74 65 72 6e 47 72 6f 75 70 31 3a  egPatternGroup1:
4670: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
4680: 6d 6f 72 70 68 65 78 28 64 54 6f 6b 65 6e 50 6f  morphex(dTokenPo
4690: 73 2c 20 28 6e 50 6f 73 2c 20 73 57 6f 72 64 29  s, (nPos, sWord)
46a0: 2c 20 73 50 61 74 74 65 72 6e 47 72 6f 75 70 31  , sPatternGroup1
46b0: 2c 20 73 4e 65 67 50 61 74 74 65 72 6e 47 72 6f  , sNegPatternGro
46c0: 75 70 31 29 0a 20 20 20 20 72 65 74 75 72 6e 20  up1).    return 
46d0: 6d 6f 72 70 68 28 64 54 6f 6b 65 6e 50 6f 73 2c  morph(dTokenPos,
46e0: 20 28 6e 50 6f 73 2c 20 73 57 6f 72 64 29 2c 20   (nPos, sWord), 
46f0: 73 50 61 74 74 65 72 6e 47 72 6f 75 70 31 2c 20  sPatternGroup1, 
4700: 46 61 6c 73 65 29 0a 0a 0a 23 23 23 23 20 44 69  False)...#### Di
4710: 73 61 6d 62 69 67 75 61 74 6f 72 0a 0a 64 65 66  sambiguator..def
4720: 20 73 65 6c 65 63 74 20 28 64 54 6f 6b 65 6e 50   select (dTokenP
4730: 6f 73 2c 20 6e 50 6f 73 2c 20 73 57 6f 72 64 2c  os, nPos, sWord,
4740: 20 73 50 61 74 74 65 72 6e 2c 20 6c 44 65 66 61   sPattern, lDefa
4750: 75 6c 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 22  ult=None):.    "
4760: 44 69 73 61 6d 62 69 67 75 61 74 69 6f 6e 3a 20  Disambiguation: 
4770: 73 65 6c 65 63 74 20 6d 6f 72 70 68 6f 6c 6f 67  select morpholog
4780: 69 65 73 20 6f 66 20 3c 73 57 6f 72 64 3e 20 6d  ies of <sWord> m
4790: 61 74 63 68 69 6e 67 20 3c 73 50 61 74 74 65 72  atching <sPatter
47a0: 6e 3e 22 0a 20 20 20 20 69 66 20 6e 6f 74 20 73  n>".    if not s
47b0: 57 6f 72 64 3a 0a 20 20 20 20 20 20 20 20 72 65  Word:.        re
47c0: 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 69 66  turn True.    if
47d0: 20 6e 50 6f 73 20 6e 6f 74 20 69 6e 20 64 54 6f   nPos not in dTo
47e0: 6b 65 6e 50 6f 73 3a 0a 20 20 20 20 20 20 20 20  kenPos:.        
47f0: 70 72 69 6e 74 28 22 45 72 72 6f 72 2e 20 54 68  print("Error. Th
4800: 65 72 65 20 73 68 6f 75 6c 64 20 62 65 20 61 20  ere should be a 
4810: 74 6f 6b 65 6e 20 61 74 20 74 68 69 73 20 70 6f  token at this po
4820: 73 69 74 69 6f 6e 3a 20 22 2c 20 6e 50 6f 73 29  sition: ", nPos)
4830: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
4840: 54 72 75 65 0a 20 20 20 20 6c 4d 6f 72 70 68 20  True.    lMorph 
4850: 3d 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72  = _oSpellChecker
4860: 2e 67 65 74 4d 6f 72 70 68 28 73 57 6f 72 64 29  .getMorph(sWord)
4870: 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72  .    if not lMor
4880: 70 68 20 6f 72 20 6c 65 6e 28 6c 4d 6f 72 70 68  ph or len(lMorph
4890: 29 20 3d 3d 20 31 3a 0a 20 20 20 20 20 20 20 20  ) == 1:.        
48a0: 72 65 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20  return True.    
48b0: 6c 53 65 6c 65 63 74 20 3d 20 5b 20 73 4d 6f 72  lSelect = [ sMor
48c0: 70 68 20 20 66 6f 72 20 73 4d 6f 72 70 68 20 69  ph  for sMorph i
48d0: 6e 20 6c 4d 6f 72 70 68 20 20 69 66 20 72 65 2e  n lMorph  if re.
48e0: 73 65 61 72 63 68 28 73 50 61 74 74 65 72 6e 2c  search(sPattern,
48f0: 20 73 4d 6f 72 70 68 29 20 5d 0a 20 20 20 20 69   sMorph) ].    i
4900: 66 20 6c 53 65 6c 65 63 74 3a 0a 20 20 20 20 20  f lSelect:.     
4910: 20 20 20 69 66 20 6c 65 6e 28 6c 53 65 6c 65 63     if len(lSelec
4920: 74 29 20 21 3d 20 6c 65 6e 28 6c 4d 6f 72 70 68  t) != len(lMorph
4930: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  ):.            d
4940: 54 6f 6b 65 6e 50 6f 73 5b 6e 50 6f 73 5d 5b 22  TokenPos[nPos]["
4950: 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 53 65 6c 65  lMorph"] = lSele
4960: 63 74 0a 20 20 20 20 65 6c 69 66 20 6c 44 65 66  ct.    elif lDef
4970: 61 75 6c 74 3a 0a 20 20 20 20 20 20 20 20 64 54  ault:.        dT
4980: 6f 6b 65 6e 50 6f 73 5b 6e 50 6f 73 5d 5b 22 6c  okenPos[nPos]["l
4990: 4d 6f 72 70 68 22 5d 20 3d 20 6c 44 65 66 61 75  Morph"] = lDefau
49a0: 6c 74 0a 20 20 20 20 72 65 74 75 72 6e 20 54 72  lt.    return Tr
49b0: 75 65 0a 0a 0a 64 65 66 20 65 78 63 6c 75 64 65  ue...def exclude
49c0: 20 28 64 54 6f 6b 65 6e 50 6f 73 2c 20 6e 50 6f   (dTokenPos, nPo
49d0: 73 2c 20 73 57 6f 72 64 2c 20 73 50 61 74 74 65  s, sWord, sPatte
49e0: 72 6e 2c 20 6c 44 65 66 61 75 6c 74 3d 4e 6f 6e  rn, lDefault=Non
49f0: 65 29 3a 0a 20 20 20 20 22 44 69 73 61 6d 62 69  e):.    "Disambi
4a00: 67 75 61 74 69 6f 6e 3a 20 65 78 63 6c 75 64 65  guation: exclude
4a10: 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 6f 66   morphologies of
4a20: 20 3c 73 57 6f 72 64 3e 20 6d 61 74 63 68 69 6e   <sWord> matchin
4a30: 67 20 3c 73 50 61 74 74 65 72 6e 3e 22 0a 20 20  g <sPattern>".  
4a40: 20 20 69 66 20 6e 6f 74 20 73 57 6f 72 64 3a 0a    if not sWord:.
4a50: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54          return T
4a60: 72 75 65 0a 20 20 20 20 69 66 20 6e 50 6f 73 20  rue.    if nPos 
4a70: 6e 6f 74 20 69 6e 20 64 54 6f 6b 65 6e 50 6f 73  not in dTokenPos
4a80: 3a 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28  :.        print(
4a90: 22 45 72 72 6f 72 2e 20 54 68 65 72 65 20 73 68  "Error. There sh
4aa0: 6f 75 6c 64 20 62 65 20 61 20 74 6f 6b 65 6e 20  ould be a token 
4ab0: 61 74 20 74 68 69 73 20 70 6f 73 69 74 69 6f 6e  at this position
4ac0: 3a 20 22 2c 20 6e 50 6f 73 29 0a 20 20 20 20 20  : ", nPos).     
4ad0: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
4ae0: 20 20 20 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53 70     lMorph = _oSp
4af0: 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f  ellChecker.getMo
4b00: 72 70 68 28 73 57 6f 72 64 29 0a 20 20 20 20 69  rph(sWord).    i
4b10: 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 20 6f 72 20  f not lMorph or 
4b20: 6c 65 6e 28 6c 4d 6f 72 70 68 29 20 3d 3d 20 31  len(lMorph) == 1
4b30: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
4b40: 20 54 72 75 65 0a 20 20 20 20 6c 53 65 6c 65 63   True.    lSelec
4b50: 74 20 3d 20 5b 20 73 4d 6f 72 70 68 20 20 66 6f  t = [ sMorph  fo
4b60: 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72  r sMorph in lMor
4b70: 70 68 20 20 69 66 20 6e 6f 74 20 72 65 2e 73 65  ph  if not re.se
4b80: 61 72 63 68 28 73 50 61 74 74 65 72 6e 2c 20 73  arch(sPattern, s
4b90: 4d 6f 72 70 68 29 20 5d 0a 20 20 20 20 69 66 20  Morph) ].    if 
4ba0: 6c 53 65 6c 65 63 74 3a 0a 20 20 20 20 20 20 20  lSelect:.       
4bb0: 20 69 66 20 6c 65 6e 28 6c 53 65 6c 65 63 74 29   if len(lSelect)
4bc0: 20 21 3d 20 6c 65 6e 28 6c 4d 6f 72 70 68 29 3a   != len(lMorph):
4bd0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f  .            dTo
4be0: 6b 65 6e 50 6f 73 5b 6e 50 6f 73 5d 5b 22 6c 4d  kenPos[nPos]["lM
4bf0: 6f 72 70 68 22 5d 20 3d 20 6c 53 65 6c 65 63 74  orph"] = lSelect
4c00: 0a 20 20 20 20 65 6c 69 66 20 6c 44 65 66 61 75  .    elif lDefau
4c10: 6c 74 3a 0a 20 20 20 20 20 20 20 20 64 54 6f 6b  lt:.        dTok
4c20: 65 6e 50 6f 73 5b 6e 50 6f 73 5d 5b 22 6c 4d 6f  enPos[nPos]["lMo
4c30: 72 70 68 22 5d 20 3d 20 6c 44 65 66 61 75 6c 74  rph"] = lDefault
4c40: 0a 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65  .    return True
4c50: 0a 0a 0a 64 65 66 20 64 65 66 69 6e 65 20 28 64  ...def define (d
4c60: 54 6f 6b 65 6e 50 6f 73 2c 20 6e 50 6f 73 2c 20  TokenPos, nPos, 
4c70: 6c 4d 6f 72 70 68 29 3a 0a 20 20 20 20 22 44 69  lMorph):.    "Di
4c80: 73 61 6d 62 69 67 75 61 74 69 6f 6e 3a 20 73 65  sambiguation: se
4c90: 74 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 6f  t morphologies o
4ca0: 66 20 74 6f 6b 65 6e 20 61 74 20 3c 6e 50 6f 73  f token at <nPos
4cb0: 3e 20 77 69 74 68 20 3c 6c 4d 6f 72 70 68 3e 22  > with <lMorph>"
4cc0: 0a 20 20 20 20 69 66 20 6e 50 6f 73 20 6e 6f 74  .    if nPos not
4cd0: 20 69 6e 20 64 54 6f 6b 65 6e 50 6f 73 3a 0a 20   in dTokenPos:. 
4ce0: 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 45 72         print("Er
4cf0: 72 6f 72 2e 20 54 68 65 72 65 20 73 68 6f 75 6c  ror. There shoul
4d00: 64 20 62 65 20 61 20 74 6f 6b 65 6e 20 61 74 20  d be a token at 
4d10: 74 68 69 73 20 70 6f 73 69 74 69 6f 6e 3a 20 22  this position: "
4d20: 2c 20 6e 50 6f 73 29 0a 20 20 20 20 20 20 20 20  , nPos).        
4d30: 72 65 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20  return True.    
4d40: 64 54 6f 6b 65 6e 50 6f 73 5b 6e 50 6f 73 5d 5b  dTokenPos[nPos][
4d50: 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 4d 6f 72  "lMorph"] = lMor
4d60: 70 68 0a 20 20 20 20 72 65 74 75 72 6e 20 54 72  ph.    return Tr
4d70: 75 65 0a 0a 0a 0a 0a 23 23 23 23 20 54 45 58 54  ue.....#### TEXT
4d80: 20 50 41 52 53 45 52 0a 0a 63 6c 61 73 73 20 54   PARSER..class T
4d90: 65 78 74 50 61 72 73 65 72 3a 0a 20 20 20 20 22  extParser:.    "
4da0: 54 65 78 74 20 70 61 72 73 65 72 22 0a 0a 20 20  Text parser"..  
4db0: 20 20 64 65 66 20 5f 5f 69 6e 69 74 5f 5f 20 28    def __init__ (
4dc0: 73 65 6c 66 2c 20 73 53 65 6e 74 65 6e 63 65 2c  self, sSentence,
4dd0: 20 73 53 65 6e 74 65 6e 63 65 30 2c 20 6e 4f 66   sSentence0, nOf
4de0: 66 73 65 74 29 3a 0a 20 20 20 20 20 20 20 20 73  fset):.        s
4df0: 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65 20 3d 20  elf.sSentence = 
4e00: 73 53 65 6e 74 65 6e 63 65 0a 20 20 20 20 20 20  sSentence.      
4e10: 20 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65    self.sSentence
4e20: 30 20 3d 20 73 53 65 6e 74 65 6e 63 65 30 0a 20  0 = sSentence0. 
4e30: 20 20 20 20 20 20 20 73 65 6c 66 2e 6e 4f 66 66         self.nOff
4e40: 73 65 74 57 69 74 68 69 6e 50 61 72 61 67 72 61  setWithinParagra
4e50: 70 68 20 3d 20 6e 4f 66 66 73 65 74 0a 20 20 20  ph = nOffset.   
4e60: 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e       self.lToken
4e70: 20 3d 20 6c 69 73 74 28 5f 6f 54 6f 6b 65 6e 69   = list(_oTokeni
4e80: 7a 65 72 2e 67 65 6e 54 6f 6b 65 6e 73 28 73 53  zer.genTokens(sS
4e90: 65 6e 74 65 6e 63 65 2c 20 54 72 75 65 29 29 0a  entence, True)).
4ea0: 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64 54 6f          self.dTo
4eb0: 6b 65 6e 50 6f 73 20 3d 20 7b 20 64 54 6f 6b 65  kenPos = { dToke
4ec0: 6e 5b 22 6e 53 74 61 72 74 22 5d 3a 20 64 54 6f  n["nStart"]: dTo
4ed0: 6b 65 6e 20 20 66 6f 72 20 64 54 6f 6b 65 6e 20  ken  for dToken 
4ee0: 69 6e 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 20  in self.lToken  
4ef0: 69 66 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70 65  if dToken["sType
4f00: 22 5d 20 21 3d 20 22 49 4e 46 4f 22 20 7d 0a 20  "] != "INFO" }. 
4f10: 20 20 20 20 20 20 20 73 65 6c 66 2e 64 54 61 67         self.dTag
4f20: 73 20 3d 20 7b 7d 0a 20 20 20 20 20 20 20 20 73  s = {}.        s
4f30: 65 6c 66 2e 64 45 72 72 6f 72 20 3d 20 7b 7d 0a  elf.dError = {}.
4f40: 0a 20 20 20 20 64 65 66 20 5f 5f 73 74 72 5f 5f  .    def __str__
4f50: 20 28 73 65 6c 66 29 3a 0a 20 20 20 20 20 20 20   (self):.       
4f60: 20 73 20 3d 20 22 3d 3d 3d 3d 3d 20 54 45 58 54   s = "===== TEXT
4f70: 20 3d 3d 3d 3d 3d 5c 6e 22 0a 20 20 20 20 20 20   =====\n".      
4f80: 20 20 73 20 2b 3d 20 22 73 65 6e 74 65 6e 63 65    s += "sentence
4f90: 3a 20 22 20 2b 20 73 65 6c 66 2e 73 53 65 6e 74  : " + self.sSent
4fa0: 65 6e 63 65 30 20 2b 20 22 5c 6e 22 0a 20 20 20  ence0 + "\n".   
4fb0: 20 20 20 20 20 73 20 2b 3d 20 22 6e 6f 77 3a 20       s += "now: 
4fc0: 20 20 20 20 20 22 20 2b 20 73 65 6c 66 2e 73 53       " + self.sS
4fd0: 65 6e 74 65 6e 63 65 20 20 2b 20 22 5c 6e 22 0a  entence  + "\n".
4fe0: 20 20 20 20 20 20 20 20 66 6f 72 20 64 54 6f 6b          for dTok
4ff0: 65 6e 20 69 6e 20 73 65 6c 66 2e 6c 54 6f 6b 65  en in self.lToke
5000: 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  n:.            s
5010: 20 2b 3d 20 66 27 23 7b 64 54 6f 6b 65 6e 5b 22   += f'#{dToken["
5020: 69 22 5d 7d 5c 74 7b 64 54 6f 6b 65 6e 5b 22 6e  i"]}\t{dToken["n
5030: 53 74 61 72 74 22 5d 7d 3a 7b 64 54 6f 6b 65 6e  Start"]}:{dToken
5040: 5b 22 6e 45 6e 64 22 5d 7d 5c 74 7b 64 54 6f 6b  ["nEnd"]}\t{dTok
5050: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 7d 5c 74 7b  en["sValue"]}\t{
5060: 64 54 6f 6b 65 6e 5b 22 73 54 79 70 65 22 5d 7d  dToken["sType"]}
5070: 27 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  '.            if
5080: 20 22 6c 4d 6f 72 70 68 22 20 69 6e 20 64 54 6f   "lMorph" in dTo
5090: 6b 65 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ken:.           
50a0: 20 20 20 20 20 73 20 2b 3d 20 22 5c 74 22 20 2b       s += "\t" +
50b0: 20 73 74 72 28 64 54 6f 6b 65 6e 5b 22 6c 4d 6f   str(dToken["lMo
50c0: 72 70 68 22 5d 29 0a 20 20 20 20 20 20 20 20 20  rph"]).         
50d0: 20 20 20 69 66 20 22 74 61 67 73 22 20 69 6e 20     if "tags" in 
50e0: 64 54 6f 6b 65 6e 3a 0a 20 20 20 20 20 20 20 20  dToken:.        
50f0: 20 20 20 20 20 20 20 20 73 20 2b 3d 20 22 5c 74          s += "\t
5100: 22 20 2b 20 73 74 72 28 64 54 6f 6b 65 6e 5b 22  " + str(dToken["
5110: 74 61 67 73 22 5d 29 0a 20 20 20 20 20 20 20 20  tags"]).        
5120: 20 20 20 20 73 20 2b 3d 20 22 5c 6e 22 0a 20 20      s += "\n".  
5130: 20 20 20 20 20 20 23 66 6f 72 20 6e 50 6f 73 2c        #for nPos,
5140: 20 64 54 6f 6b 65 6e 20 69 6e 20 73 65 6c 66 2e   dToken in self.
5150: 64 54 6f 6b 65 6e 50 6f 73 2e 69 74 65 6d 73 28  dTokenPos.items(
5160: 29 3a 0a 20 20 20 20 20 20 20 20 23 20 20 20 20  ):.        #    
5170: 73 20 2b 3d 20 66 22 7b 6e 50 6f 73 7d 5c 74 7b  s += f"{nPos}\t{
5180: 64 54 6f 6b 65 6e 7d 5c 6e 22 0a 20 20 20 20 20  dToken}\n".     
5190: 20 20 20 72 65 74 75 72 6e 20 73 0a 0a 20 20 20     return s..   
51a0: 20 64 65 66 20 75 70 64 61 74 65 20 28 73 65 6c   def update (sel
51b0: 66 2c 20 73 53 65 6e 74 65 6e 63 65 2c 20 62 44  f, sSentence, bD
51c0: 65 62 75 67 3d 46 61 6c 73 65 29 3a 0a 20 20 20  ebug=False):.   
51d0: 20 20 20 20 20 22 75 70 64 61 74 65 20 3c 73 53       "update <sS
51e0: 65 6e 74 65 6e 63 65 3e 20 61 6e 64 20 72 65 74  entence> and ret
51f0: 6f 6b 65 6e 69 7a 65 22 0a 20 20 20 20 20 20 20  okenize".       
5200: 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65 20   self.sSentence 
5210: 3d 20 73 53 65 6e 74 65 6e 63 65 0a 20 20 20 20  = sSentence.    
5220: 20 20 20 20 6c 4e 65 77 54 6f 6b 65 6e 20 3d 20      lNewToken = 
5230: 6c 69 73 74 28 5f 6f 54 6f 6b 65 6e 69 7a 65 72  list(_oTokenizer
5240: 2e 67 65 6e 54 6f 6b 65 6e 73 28 73 53 65 6e 74  .genTokens(sSent
5250: 65 6e 63 65 2c 20 54 72 75 65 29 29 0a 20 20 20  ence, True)).   
5260: 20 20 20 20 20 66 6f 72 20 64 54 6f 6b 65 6e 20       for dToken 
5270: 69 6e 20 6c 4e 65 77 54 6f 6b 65 6e 3a 0a 20 20  in lNewToken:.  
5280: 20 20 20 20 20 20 20 20 20 20 69 66 20 22 6c 4d            if "lM
5290: 6f 72 70 68 22 20 69 6e 20 73 65 6c 66 2e 64 54  orph" in self.dT
52a0: 6f 6b 65 6e 50 6f 73 2e 67 65 74 28 64 54 6f 6b  okenPos.get(dTok
52b0: 65 6e 5b 22 6e 53 74 61 72 74 22 5d 2c 20 7b 7d  en["nStart"], {}
52c0: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
52d0: 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70     dToken["lMorp
52e0: 68 22 5d 20 3d 20 73 65 6c 66 2e 64 54 6f 6b 65  h"] = self.dToke
52f0: 6e 50 6f 73 5b 64 54 6f 6b 65 6e 5b 22 6e 53 74  nPos[dToken["nSt
5300: 61 72 74 22 5d 5d 5b 22 6c 4d 6f 72 70 68 22 5d  art"]]["lMorph"]
5310: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c 54  .        self.lT
5320: 6f 6b 65 6e 20 3d 20 6c 4e 65 77 54 6f 6b 65 6e  oken = lNewToken
5330: 0a 20 20 20 20 20 20 20 20 73 65 6c 66 2e 64 54  .        self.dT
5340: 6f 6b 65 6e 50 6f 73 20 3d 20 7b 20 64 54 6f 6b  okenPos = { dTok
5350: 65 6e 5b 22 6e 53 74 61 72 74 22 5d 3a 20 64 54  en["nStart"]: dT
5360: 6f 6b 65 6e 20 20 66 6f 72 20 64 54 6f 6b 65 6e  oken  for dToken
5370: 20 69 6e 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20   in self.lToken 
5380: 20 69 66 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70   if dToken["sTyp
5390: 65 22 5d 20 21 3d 20 22 49 4e 46 4f 22 20 7d 0a  e"] != "INFO" }.
53a0: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
53b0: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 70  g:.            p
53c0: 72 69 6e 74 28 22 55 50 44 41 54 45 3a 22 29 0a  rint("UPDATE:").
53d0: 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e              prin
53e0: 74 28 73 65 6c 66 29 0a 0a 20 20 20 20 64 65 66  t(self)..    def
53f0: 20 5f 67 65 74 4e 65 78 74 50 6f 69 6e 74 65 72   _getNextPointer
5400: 73 20 28 73 65 6c 66 2c 20 64 54 6f 6b 65 6e 2c  s (self, dToken,
5410: 20 64 47 72 61 70 68 2c 20 64 50 6f 69 6e 74 65   dGraph, dPointe
5420: 72 2c 20 62 44 65 62 75 67 3d 46 61 6c 73 65 29  r, bDebug=False)
5430: 3a 0a 20 20 20 20 20 20 20 20 22 67 65 6e 65 72  :.        "gener
5440: 61 74 6f 72 3a 20 72 65 74 75 72 6e 20 6e 6f 64  ator: return nod
5450: 65 73 20 77 68 65 72 65 20 3c 64 54 6f 6b 65 6e  es where <dToken
5460: 3e 20 e2 80 9c 76 61 6c 75 65 73 e2 80 9d 20 6d  > ...values... m
5470: 61 74 63 68 20 3c 64 4e 6f 64 65 3e 20 61 72 63  atch <dNode> arc
5480: 73 22 0a 20 20 20 20 20 20 20 20 64 4e 6f 64 65  s".        dNode
5490: 20 3d 20 64 50 6f 69 6e 74 65 72 5b 22 64 4e 6f   = dPointer["dNo
54a0: 64 65 22 5d 0a 20 20 20 20 20 20 20 20 69 4e 6f  de"].        iNo
54b0: 64 65 31 20 3d 20 64 50 6f 69 6e 74 65 72 5b 22  de1 = dPointer["
54c0: 69 4e 6f 64 65 31 22 5d 0a 20 20 20 20 20 20 20  iNode1"].       
54d0: 20 62 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 46   bTokenFound = F
54e0: 61 6c 73 65 0a 20 20 20 20 20 20 20 20 23 20 74  alse.        # t
54f0: 6f 6b 65 6e 20 76 61 6c 75 65 0a 20 20 20 20 20  oken value.     
5500: 20 20 20 69 66 20 64 54 6f 6b 65 6e 5b 22 73 56     if dToken["sV
5510: 61 6c 75 65 22 5d 20 69 6e 20 64 4e 6f 64 65 3a  alue"] in dNode:
5520: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
5530: 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20  bDebug:.        
5540: 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 20          print(" 
5550: 20 4d 41 54 43 48 3a 22 2c 20 64 54 6f 6b 65 6e   MATCH:", dToken
5560: 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20  ["sValue"]).    
5570: 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 7b 20          yield { 
5580: 22 69 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31  "iNode1": iNode1
5590: 2c 20 22 64 4e 6f 64 65 22 3a 20 64 47 72 61 70  , "dNode": dGrap
55a0: 68 5b 64 4e 6f 64 65 5b 64 54 6f 6b 65 6e 5b 22  h[dNode[dToken["
55b0: 73 56 61 6c 75 65 22 5d 5d 5d 20 7d 0a 20 20 20  sValue"]]] }.   
55c0: 20 20 20 20 20 20 20 20 20 62 54 6f 6b 65 6e 46           bTokenF
55d0: 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20 20 20 20  ound = True.    
55e0: 20 20 20 20 69 66 20 64 54 6f 6b 65 6e 5b 22 73      if dToken["s
55f0: 56 61 6c 75 65 22 5d 5b 30 3a 32 5d 2e 69 73 74  Value"][0:2].ist
5600: 69 74 6c 65 28 29 3a 20 23 20 77 65 20 74 65 73  itle(): # we tes
5610: 74 20 6f 6e 6c 79 20 32 20 66 69 72 73 74 20 63  t only 2 first c
5620: 68 61 72 73 2c 20 74 6f 20 6d 61 6b 65 20 76 61  hars, to make va
5630: 6c 69 64 20 77 6f 72 64 73 20 73 75 63 68 20 61  lid words such a
5640: 73 20 22 4c 61 69 73 73 65 7a 2d 6c 65 73 22 2c  s "Laissez-les",
5650: 20 22 50 61 73 73 65 2d 70 61 72 74 6f 75 74 22   "Passe-partout"
5660: 2e 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 56  ..            sV
5670: 61 6c 75 65 20 3d 20 64 54 6f 6b 65 6e 5b 22 73  alue = dToken["s
5680: 56 61 6c 75 65 22 5d 2e 6c 6f 77 65 72 28 29 0a  Value"].lower().
5690: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73              if s
56a0: 56 61 6c 75 65 20 69 6e 20 64 4e 6f 64 65 3a 0a  Value in dNode:.
56b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
56c0: 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20  if bDebug:.     
56d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
56e0: 72 69 6e 74 28 22 20 20 4d 41 54 43 48 3a 22 2c  rint("  MATCH:",
56f0: 20 73 56 61 6c 75 65 29 0a 20 20 20 20 20 20 20   sValue).       
5700: 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 7b           yield {
5710: 20 22 69 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65   "iNode1": iNode
5720: 31 2c 20 22 64 4e 6f 64 65 22 3a 20 64 47 72 61  1, "dNode": dGra
5730: 70 68 5b 64 4e 6f 64 65 5b 73 56 61 6c 75 65 5d  ph[dNode[sValue]
5740: 5d 20 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20  ] }.            
5750: 20 20 20 20 62 54 6f 6b 65 6e 46 6f 75 6e 64 20      bTokenFound 
5760: 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20 20 65  = True.        e
5770: 6c 69 66 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c  lif dToken["sVal
5780: 75 65 22 5d 2e 69 73 75 70 70 65 72 28 29 3a 0a  ue"].isupper():.
5790: 20 20 20 20 20 20 20 20 20 20 20 20 73 56 61 6c              sVal
57a0: 75 65 20 3d 20 64 54 6f 6b 65 6e 5b 22 73 56 61  ue = dToken["sVa
57b0: 6c 75 65 22 5d 2e 6c 6f 77 65 72 28 29 0a 20 20  lue"].lower().  
57c0: 20 20 20 20 20 20 20 20 20 20 69 66 20 73 56 61            if sVa
57d0: 6c 75 65 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20  lue in dNode:.  
57e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
57f0: 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20   bDebug:.       
5800: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69               pri
5810: 6e 74 28 22 20 20 4d 41 54 43 48 3a 22 2c 20 73  nt("  MATCH:", s
5820: 56 61 6c 75 65 29 0a 20 20 20 20 20 20 20 20 20  Value).         
5830: 20 20 20 20 20 20 20 79 69 65 6c 64 20 7b 20 22         yield { "
5840: 69 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c  iNode1": iNode1,
5850: 20 22 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68   "dNode": dGraph
5860: 5b 64 4e 6f 64 65 5b 73 56 61 6c 75 65 5d 5d 20  [dNode[sValue]] 
5870: 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  }.              
5880: 20 20 62 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20    bTokenFound = 
5890: 54 72 75 65 0a 20 20 20 20 20 20 20 20 20 20 20  True.           
58a0: 20 73 56 61 6c 75 65 20 3d 20 64 54 6f 6b 65 6e   sValue = dToken
58b0: 5b 22 73 56 61 6c 75 65 22 5d 2e 63 61 70 69 74  ["sValue"].capit
58c0: 61 6c 69 7a 65 28 29 0a 20 20 20 20 20 20 20 20  alize().        
58d0: 20 20 20 20 69 66 20 73 56 61 6c 75 65 20 69 6e      if sValue in
58e0: 20 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20   dNode:.        
58f0: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
5900: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  g:.             
5910: 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 20 20         print("  
5920: 4d 41 54 43 48 3a 22 2c 20 73 56 61 6c 75 65 29  MATCH:", sValue)
5930: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5940: 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31   yield { "iNode1
5950: 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64  ": iNode1, "dNod
5960: 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64 65  e": dGraph[dNode
5970: 5b 73 56 61 6c 75 65 5d 5d 20 7d 0a 20 20 20 20  [sValue]] }.    
5980: 20 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b              bTok
5990: 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20  enFound = True. 
59a0: 20 20 20 20 20 20 20 23 20 72 65 67 65 78 20 76         # regex v
59b0: 61 6c 75 65 20 61 72 63 73 0a 20 20 20 20 20 20  alue arcs.      
59c0: 20 20 69 66 20 64 54 6f 6b 65 6e 5b 22 73 54 79    if dToken["sTy
59d0: 70 65 22 5d 20 6e 6f 74 20 69 6e 20 66 72 6f 7a  pe"] not in froz
59e0: 65 6e 73 65 74 28 5b 22 49 4e 46 4f 22 2c 20 22  enset(["INFO", "
59f0: 50 55 4e 43 22 2c 20 22 53 49 47 4e 22 5d 29 3a  PUNC", "SIGN"]):
5a00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
5a10: 22 3c 72 65 5f 76 61 6c 75 65 3e 22 20 69 6e 20  "<re_value>" in 
5a20: 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20 20  dNode:.         
5a30: 20 20 20 20 20 20 20 66 6f 72 20 73 52 65 67 65         for sRege
5a40: 78 20 69 6e 20 64 4e 6f 64 65 5b 22 3c 72 65 5f  x in dNode["<re_
5a50: 76 61 6c 75 65 3e 22 5d 3a 0a 20 20 20 20 20 20  value>"]:.      
5a60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
5a70: 20 22 c2 ac 22 20 6e 6f 74 20 69 6e 20 73 52 65   ".." not in sRe
5a80: 67 65 78 3a 0a 20 20 20 20 20 20 20 20 20 20 20  gex:.           
5a90: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 6e               # n
5aa0: 6f 20 61 6e 74 69 2d 70 61 74 74 65 72 6e 0a 20  o anti-pattern. 
5ab0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ac0: 20 20 20 20 20 20 20 69 66 20 72 65 2e 73 65 61         if re.sea
5ad0: 72 63 68 28 73 52 65 67 65 78 2c 20 64 54 6f 6b  rch(sRegex, dTok
5ae0: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 3a 0a 20  en["sValue"]):. 
5af0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5b00: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44             if bD
5b10: 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20  ebug:.          
5b20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5b30: 20 20 20 20 20 20 70 72 69 6e 74 28 22 20 20 4d        print("  M
5b40: 41 54 43 48 3a 20 7e 22 20 2b 20 73 52 65 67 65  ATCH: ~" + sRege
5b50: 78 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  x).             
5b60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 79                 y
5b70: 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31 22 3a  ield { "iNode1":
5b80: 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64 65 22   iNode1, "dNode"
5b90: 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b 22  : dGraph[dNode["
5ba0: 3c 72 65 5f 76 61 6c 75 65 3e 22 5d 5b 73 52 65  <re_value>"][sRe
5bb0: 67 65 78 5d 5d 20 7d 0a 20 20 20 20 20 20 20 20  gex]] }.        
5bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5bd0: 20 20 20 20 62 54 6f 6b 65 6e 46 6f 75 6e 64 20      bTokenFound 
5be0: 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20 20 20  = True.         
5bf0: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
5c00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5c10: 20 20 20 20 20 20 20 20 20 23 20 74 68 65 72 65           # there
5c20: 20 69 73 20 61 6e 20 61 6e 74 69 2d 70 61 74 74   is an anti-patt
5c30: 65 72 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20  ern.            
5c40: 20 20 20 20 20 20 20 20 20 20 20 20 73 50 61 74              sPat
5c50: 74 65 72 6e 2c 20 73 4e 65 67 50 61 74 74 65 72  tern, sNegPatter
5c60: 6e 20 3d 20 73 52 65 67 65 78 2e 73 70 6c 69 74  n = sRegex.split
5c70: 28 22 c2 ac 22 2c 20 31 29 0a 20 20 20 20 20 20  ("..", 1).      
5c80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5c90: 20 20 69 66 20 73 4e 65 67 50 61 74 74 65 72 6e    if sNegPattern
5ca0: 20 61 6e 64 20 72 65 2e 73 65 61 72 63 68 28 73   and re.search(s
5cb0: 4e 65 67 50 61 74 74 65 72 6e 2c 20 64 54 6f 6b  NegPattern, dTok
5cc0: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 3a 0a 20  en["sValue"]):. 
5cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ce0: 20 20 20 20 20 20 20 20 20 20 20 63 6f 6e 74 69             conti
5cf0: 6e 75 65 0a 20 20 20 20 20 20 20 20 20 20 20 20  nue.            
5d00: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
5d10: 6f 74 20 73 50 61 74 74 65 72 6e 20 6f 72 20 72  ot sPattern or r
5d20: 65 2e 73 65 61 72 63 68 28 73 50 61 74 74 65 72  e.search(sPatter
5d30: 6e 2c 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  n, dToken["sValu
5d40: 65 22 5d 29 3a 0a 20 20 20 20 20 20 20 20 20 20  e"]):.          
5d50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5d60: 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20    if bDebug:.   
5d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69               pri
5d90: 6e 74 28 22 20 20 4d 41 54 43 48 3a 20 7e 22 20  nt("  MATCH: ~" 
5da0: 2b 20 73 52 65 67 65 78 29 0a 20 20 20 20 20 20  + sRegex).      
5db0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5dc0: 20 20 20 20 20 20 79 69 65 6c 64 20 7b 20 22 69        yield { "i
5dd0: 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20  Node1": iNode1, 
5de0: 22 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b  "dNode": dGraph[
5df0: 64 4e 6f 64 65 5b 22 3c 72 65 5f 76 61 6c 75 65  dNode["<re_value
5e00: 3e 22 5d 5b 73 52 65 67 65 78 5d 5d 20 7d 0a 20  >"][sRegex]] }. 
5e10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e20: 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b 65             bToke
5e30: 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20 20  nFound = True.  
5e40: 20 20 20 20 20 20 23 20 61 6e 61 6c 79 73 61 62        # analysab
5e50: 6c 65 20 74 6f 6b 65 6e 73 0a 20 20 20 20 20 20  le tokens.      
5e60: 20 20 69 66 20 64 54 6f 6b 65 6e 5b 22 73 54 79    if dToken["sTy
5e70: 70 65 22 5d 5b 30 3a 34 5d 20 3d 3d 20 22 57 4f  pe"][0:4] == "WO
5e80: 52 44 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20  RD":.           
5e90: 20 23 20 74 6f 6b 65 6e 20 6c 65 6d 6d 61 73 0a   # token lemmas.
5ea0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 22              if "
5eb0: 3c 6c 65 6d 6d 61 73 3e 22 20 69 6e 20 64 4e 6f  <lemmas>" in dNo
5ec0: 64 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  de:.            
5ed0: 20 20 20 20 66 6f 72 20 73 4c 65 6d 6d 61 20 69      for sLemma i
5ee0: 6e 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72  n _oSpellChecker
5ef0: 2e 67 65 74 4c 65 6d 6d 61 28 64 54 6f 6b 65 6e  .getLemma(dToken
5f00: 5b 22 73 56 61 6c 75 65 22 5d 29 3a 0a 20 20 20  ["sValue"]):.   
5f10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5f20: 20 69 66 20 73 4c 65 6d 6d 61 20 69 6e 20 64 4e   if sLemma in dN
5f30: 6f 64 65 5b 22 3c 6c 65 6d 6d 61 73 3e 22 5d 3a  ode["<lemmas>"]:
5f40: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5f50: 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62           if bDeb
5f60: 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ug:.            
5f70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5f80: 70 72 69 6e 74 28 22 20 20 4d 41 54 43 48 3a 20  print("  MATCH: 
5f90: 3e 22 20 2b 20 73 4c 65 6d 6d 61 29 0a 20 20 20  >" + sLemma).   
5fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5fb0: 20 20 20 20 20 79 69 65 6c 64 20 7b 20 22 69 4e       yield { "iN
5fc0: 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22  ode1": iNode1, "
5fd0: 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b 64  dNode": dGraph[d
5fe0: 4e 6f 64 65 5b 22 3c 6c 65 6d 6d 61 73 3e 22 5d  Node["<lemmas>"]
5ff0: 5b 73 4c 65 6d 6d 61 5d 5d 20 7d 0a 20 20 20 20  [sLemma]] }.    
6000: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6010: 20 20 20 20 62 54 6f 6b 65 6e 46 6f 75 6e 64 20      bTokenFound 
6020: 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20 20 20  = True.         
6030: 20 20 20 23 20 72 65 67 65 78 20 6d 6f 72 70 68     # regex morph
6040: 20 61 72 63 73 0a 20 20 20 20 20 20 20 20 20 20   arcs.          
6050: 20 20 69 66 20 22 3c 72 65 5f 6d 6f 72 70 68 3e    if "<re_morph>
6060: 22 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20 20  " in dNode:.    
6070: 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20              for 
6080: 73 52 65 67 65 78 20 69 6e 20 64 4e 6f 64 65 5b  sRegex in dNode[
6090: 22 3c 72 65 5f 6d 6f 72 70 68 3e 22 5d 3a 0a 20  "<re_morph>"]:. 
60a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
60b0: 20 20 20 69 66 20 22 c2 ac 22 20 6e 6f 74 20 69     if ".." not i
60c0: 6e 20 73 52 65 67 65 78 3a 0a 20 20 20 20 20 20  n sRegex:.      
60d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
60e0: 20 20 23 20 6e 6f 20 61 6e 74 69 2d 70 61 74 74    # no anti-patt
60f0: 65 72 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20  ern.            
6100: 20 20 20 20 20 20 20 20 20 20 20 20 6c 4d 6f 72              lMor
6110: 70 68 20 3d 20 64 54 6f 6b 65 6e 2e 67 65 74 28  ph = dToken.get(
6120: 22 6c 4d 6f 72 70 68 22 2c 20 5f 6f 53 70 65 6c  "lMorph", _oSpel
6130: 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70  lChecker.getMorp
6140: 68 28 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65  h(dToken["sValue
6150: 22 5d 29 29 0a 20 20 20 20 20 20 20 20 20 20 20  "])).           
6160: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
6170: 61 6e 79 28 72 65 2e 73 65 61 72 63 68 28 73 52  any(re.search(sR
6180: 65 67 65 78 2c 20 73 4d 6f 72 70 68 29 20 20 66  egex, sMorph)  f
6190: 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f  or sMorph in lMo
61a0: 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20 20  rph):.          
61b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
61c0: 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20    if bDebug:.   
61d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
61e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69               pri
61f0: 6e 74 28 22 20 20 4d 41 54 43 48 3a 20 40 22 20  nt("  MATCH: @" 
6200: 2b 20 73 52 65 67 65 78 29 0a 20 20 20 20 20 20  + sRegex).      
6210: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6220: 20 20 20 20 20 20 79 69 65 6c 64 20 7b 20 22 69        yield { "i
6230: 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20  Node1": iNode1, 
6240: 22 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68 5b  "dNode": dGraph[
6250: 64 4e 6f 64 65 5b 22 3c 72 65 5f 6d 6f 72 70 68  dNode["<re_morph
6260: 3e 22 5d 5b 73 52 65 67 65 78 5d 5d 20 7d 0a 20  >"][sRegex]] }. 
6270: 20 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 62 54 6f 6b 65             bToke
6290: 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20 20  nFound = True.  
62a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
62b0: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
62c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
62d0: 23 20 74 68 65 72 65 20 69 73 20 61 6e 20 61 6e  # there is an an
62e0: 74 69 2d 70 61 74 74 65 72 6e 0a 20 20 20 20 20  ti-pattern.     
62f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6300: 20 20 20 73 50 61 74 74 65 72 6e 2c 20 73 4e 65     sPattern, sNe
6310: 67 50 61 74 74 65 72 6e 20 3d 20 73 52 65 67 65  gPattern = sRege
6320: 78 2e 73 70 6c 69 74 28 22 c2 ac 22 2c 20 31 29  x.split("..", 1)
6330: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6340: 20 20 20 20 20 20 20 20 20 69 66 20 73 4e 65 67           if sNeg
6350: 50 61 74 74 65 72 6e 20 3d 3d 20 22 2a 22 3a 0a  Pattern == "*":.
6360: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6370: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 61 6c              # al
6380: 6c 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 6d  l morphologies m
6390: 75 73 74 20 6d 61 74 63 68 20 77 69 74 68 20 3c  ust match with <
63a0: 73 50 61 74 74 65 72 6e 3e 0a 20 20 20 20 20 20  sPattern>.      
63b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
63c0: 20 20 20 20 20 20 69 66 20 73 50 61 74 74 65 72        if sPatter
63d0: 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  n:.             
63e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
63f0: 20 20 20 6c 4d 6f 72 70 68 20 3d 20 64 54 6f 6b     lMorph = dTok
6400: 65 6e 2e 67 65 74 28 22 6c 4d 6f 72 70 68 22 2c  en.get("lMorph",
6410: 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e   _oSpellChecker.
6420: 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e 5b  getMorph(dToken[
6430: 22 73 56 61 6c 75 65 22 5d 29 29 0a 20 20 20 20  "sValue"])).    
6440: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6450: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6c              if l
6460: 4d 6f 72 70 68 20 61 6e 64 20 61 6c 6c 28 72 65  Morph and all(re
6470: 2e 73 65 61 72 63 68 28 73 50 61 74 74 65 72 6e  .search(sPattern
6480: 2c 20 73 4d 6f 72 70 68 29 20 20 66 6f 72 20 73  , sMorph)  for s
6490: 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29  Morph in lMorph)
64a0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
64b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
64c0: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
64d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
64e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
64f0: 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22           print("
6500: 20 20 4d 41 54 43 48 3a 20 40 22 20 2b 20 73 52    MATCH: @" + sR
6510: 65 67 65 78 29 0a 20 20 20 20 20 20 20 20 20 20  egex).          
6520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6530: 20 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20            yield 
6540: 7b 20 22 69 4e 6f 64 65 31 22 3a 20 69 4e 6f 64  { "iNode1": iNod
6550: 65 31 2c 20 22 64 4e 6f 64 65 22 3a 20 64 47 72  e1, "dNode": dGr
6560: 61 70 68 5b 64 4e 6f 64 65 5b 22 3c 72 65 5f 6d  aph[dNode["<re_m
6570: 6f 72 70 68 3e 22 5d 5b 73 52 65 67 65 78 5d 5d  orph>"][sRegex]]
6580: 20 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   }.             
6590: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
65a0: 20 20 20 20 20 20 20 62 54 6f 6b 65 6e 46 6f 75         bTokenFou
65b0: 6e 64 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20  nd = True.      
65c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
65d0: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
65e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
65f0: 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20 64 54 6f      lMorph = dTo
6600: 6b 65 6e 2e 67 65 74 28 22 6c 4d 6f 72 70 68 22  ken.get("lMorph"
6610: 2c 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72  , _oSpellChecker
6620: 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e  .getMorph(dToken
6630: 5b 22 73 56 61 6c 75 65 22 5d 29 29 0a 20 20 20  ["sValue"])).   
6640: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6650: 20 20 20 20 20 20 20 20 20 69 66 20 73 4e 65 67           if sNeg
6660: 50 61 74 74 65 72 6e 20 61 6e 64 20 61 6e 79 28  Pattern and any(
6670: 72 65 2e 73 65 61 72 63 68 28 73 4e 65 67 50 61  re.search(sNegPa
6680: 74 74 65 72 6e 2c 20 73 4d 6f 72 70 68 29 20 20  ttern, sMorph)  
6690: 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d  for sMorph in lM
66a0: 6f 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20  orph):.         
66b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
66c0: 20 20 20 20 20 20 20 63 6f 6e 74 69 6e 75 65 0a         continue.
66d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
66e0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
66f0: 6f 74 20 73 50 61 74 74 65 72 6e 20 6f 72 20 61  ot sPattern or a
6700: 6e 79 28 72 65 2e 73 65 61 72 63 68 28 73 50 61  ny(re.search(sPa
6710: 74 74 65 72 6e 2c 20 73 4d 6f 72 70 68 29 20 20  ttern, sMorph)  
6720: 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d  for sMorph in lM
6730: 6f 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20  orph):.         
6740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6750: 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67         if bDebug
6760: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
6770: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6780: 20 20 20 20 20 20 70 72 69 6e 74 28 22 20 20 4d        print("  M
6790: 41 54 43 48 3a 20 40 22 20 2b 20 73 52 65 67 65  ATCH: @" + sRege
67a0: 78 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  x).             
67b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
67c0: 20 20 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64     yield { "iNod
67d0: 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e  e1": iNode1, "dN
67e0: 6f 64 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f  ode": dGraph[dNo
67f0: 64 65 5b 22 3c 72 65 5f 6d 6f 72 70 68 3e 22 5d  de["<re_morph>"]
6800: 5b 73 52 65 67 65 78 5d 5d 20 7d 0a 20 20 20 20  [sRegex]] }.    
6810: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6820: 20 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b              bTok
6830: 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20  enFound = True. 
6840: 20 20 20 20 20 20 20 23 20 74 6f 6b 65 6e 20 74         # token t
6850: 61 67 73 0a 20 20 20 20 20 20 20 20 69 66 20 22  ags.        if "
6860: 74 61 67 73 22 20 69 6e 20 64 54 6f 6b 65 6e 20  tags" in dToken 
6870: 61 6e 64 20 22 3c 74 61 67 73 3e 22 20 69 6e 20  and "<tags>" in 
6880: 64 4e 6f 64 65 3a 0a 20 20 20 20 20 20 20 20 20  dNode:.         
6890: 20 20 20 66 6f 72 20 73 54 61 67 20 69 6e 20 64     for sTag in d
68a0: 54 6f 6b 65 6e 5b 22 74 61 67 73 22 5d 3a 0a 20  Token["tags"]:. 
68b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
68c0: 66 20 73 54 61 67 20 69 6e 20 64 4e 6f 64 65 5b  f sTag in dNode[
68d0: 22 3c 74 61 67 73 3e 22 5d 3a 0a 20 20 20 20 20  "<tags>"]:.     
68e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
68f0: 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20  f bDebug:.      
6900: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6910: 20 20 70 72 69 6e 74 28 22 20 20 4d 41 54 43 48    print("  MATCH
6920: 3a 20 2f 22 20 2b 20 73 54 61 67 29 0a 20 20 20  : /" + sTag).   
6930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6940: 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31   yield { "iNode1
6950: 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64  ": iNode1, "dNod
6960: 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f 64 65  e": dGraph[dNode
6970: 5b 22 3c 74 61 67 73 3e 22 5d 5b 73 54 61 67 5d  ["<tags>"][sTag]
6980: 5d 20 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20  ] }.            
6990: 20 20 20 20 20 20 20 20 62 54 6f 6b 65 6e 46 6f          bTokenFo
69a0: 75 6e 64 20 3d 20 54 72 75 65 0a 20 20 20 20 20  und = True.     
69b0: 20 20 20 23 20 6d 65 74 61 20 61 72 63 20 28 66     # meta arc (f
69c0: 6f 72 20 74 6f 6b 65 6e 20 74 79 70 65 29 0a 20  or token type). 
69d0: 20 20 20 20 20 20 20 69 66 20 22 3c 6d 65 74 61         if "<meta
69e0: 3e 22 20 69 6e 20 64 4e 6f 64 65 3a 0a 20 20 20  >" in dNode:.   
69f0: 20 20 20 20 20 20 20 20 20 66 6f 72 20 73 4d 65           for sMe
6a00: 74 61 20 69 6e 20 64 4e 6f 64 65 5b 22 3c 6d 65  ta in dNode["<me
6a10: 74 61 3e 22 5d 3a 0a 20 20 20 20 20 20 20 20 20  ta>"]:.         
6a20: 20 20 20 20 20 20 20 23 20 6e 6f 20 72 65 67 65         # no rege
6a30: 78 20 68 65 72 65 2c 20 77 65 20 6a 75 73 74 20  x here, we just 
6a40: 73 65 61 72 63 68 20 69 66 20 3c 64 4e 6f 64 65  search if <dNode
6a50: 5b 22 73 54 79 70 65 22 5d 3e 20 65 78 69 73 74  ["sType"]> exist
6a60: 73 20 77 69 74 68 69 6e 20 3c 73 4d 65 74 61 3e  s within <sMeta>
6a70: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6a80: 20 69 66 20 73 4d 65 74 61 20 3d 3d 20 22 2a 22   if sMeta == "*"
6a90: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
6aa0: 20 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a        if bDebug:
6ab0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
6ac0: 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22           print("
6ad0: 20 20 4d 41 54 43 48 3a 20 2a 22 20 2b 20 73 4d    MATCH: *" + sM
6ae0: 65 74 61 29 0a 20 20 20 20 20 20 20 20 20 20 20  eta).           
6af0: 20 20 20 20 20 20 20 20 20 79 69 65 6c 64 20 7b           yield {
6b00: 20 22 69 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65   "iNode1": iNode
6b10: 31 2c 20 22 64 4e 6f 64 65 22 3a 20 64 47 72 61  1, "dNode": dGra
6b20: 70 68 5b 64 4e 6f 64 65 5b 22 3c 6d 65 74 61 3e  ph[dNode["<meta>
6b30: 22 5d 5b 22 2a 22 5d 5d 20 7d 0a 20 20 20 20 20  "]["*"]] }.     
6b40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62                 b
6b50: 54 6f 6b 65 6e 46 6f 75 6e 64 20 3d 20 54 72 75  TokenFound = Tru
6b60: 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e.              
6b70: 20 20 65 6c 69 66 20 22 c2 ac 22 20 69 6e 20 73    elif ".." in s
6b80: 4d 65 74 61 3a 0a 20 20 20 20 20 20 20 20 20 20  Meta:.          
6b90: 20 20 20 20 20 20 20 20 20 20 69 66 20 64 54 6f            if dTo
6ba0: 6b 65 6e 5b 22 73 54 79 70 65 22 5d 20 6e 6f 74  ken["sType"] not
6bb0: 20 69 6e 20 73 4d 65 74 61 3a 0a 20 20 20 20 20   in sMeta:.     
6bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6bd0: 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20     if bDebug:.  
6be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6bf0: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28            print(
6c00: 22 20 20 4d 41 54 43 48 3a 20 2a 22 20 2b 20 73  "  MATCH: *" + s
6c10: 4d 65 74 61 29 0a 20 20 20 20 20 20 20 20 20 20  Meta).          
6c20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 79 69                yi
6c30: 65 6c 64 20 7b 20 22 69 4e 6f 64 65 31 22 3a 20  eld { "iNode1": 
6c40: 69 4e 6f 64 65 31 2c 20 22 64 4e 6f 64 65 22 3a  iNode1, "dNode":
6c50: 20 64 47 72 61 70 68 5b 64 4e 6f 64 65 5b 22 3c   dGraph[dNode["<
6c60: 6d 65 74 61 3e 22 5d 5b 73 4d 65 74 61 5d 5d 20  meta>"][sMeta]] 
6c70: 7d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  }.              
6c80: 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b 65 6e            bToken
6c90: 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20 20 20  Found = True.   
6ca0: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69               eli
6cb0: 66 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70 65 22  f dToken["sType"
6cc0: 5d 20 3d 3d 20 73 4d 65 74 61 3a 0a 20 20 20 20  ] == sMeta:.    
6cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6ce0: 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20  if bDebug:.     
6cf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6d00: 20 20 20 70 72 69 6e 74 28 22 20 20 4d 41 54 43     print("  MATC
6d10: 48 3a 20 2a 22 20 2b 20 73 4d 65 74 61 29 0a 20  H: *" + sMeta). 
6d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6d30: 20 20 20 79 69 65 6c 64 20 7b 20 22 69 4e 6f 64     yield { "iNod
6d40: 65 31 22 3a 20 69 4e 6f 64 65 31 2c 20 22 64 4e  e1": iNode1, "dN
6d50: 6f 64 65 22 3a 20 64 47 72 61 70 68 5b 64 4e 6f  ode": dGraph[dNo
6d60: 64 65 5b 22 3c 6d 65 74 61 3e 22 5d 5b 73 4d 65  de["<meta>"][sMe
6d70: 74 61 5d 5d 20 7d 0a 20 20 20 20 20 20 20 20 20  ta]] }.         
6d80: 20 20 20 20 20 20 20 20 20 20 20 62 54 6f 6b 65             bToke
6d90: 6e 46 6f 75 6e 64 20 3d 20 54 72 75 65 0a 20 20  nFound = True.  
6da0: 20 20 20 20 20 20 69 66 20 22 62 4b 65 65 70 22        if "bKeep"
6db0: 20 69 6e 20 64 50 6f 69 6e 74 65 72 20 61 6e 64   in dPointer and
6dc0: 20 6e 6f 74 20 62 54 6f 6b 65 6e 46 6f 75 6e 64   not bTokenFound
6dd0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 79 69  :.            yi
6de0: 65 6c 64 20 64 50 6f 69 6e 74 65 72 0a 20 20 20  eld dPointer.   
6df0: 20 20 20 20 20 23 20 4a 55 4d 50 0a 20 20 20 20       # JUMP.    
6e00: 20 20 20 20 23 20 57 61 72 6e 69 6e 67 21 20 52      # Warning! R
6e10: 65 63 75 72 73 73 69 6f 6e 21 0a 20 20 20 20 20  ecurssion!.     
6e20: 20 20 20 69 66 20 22 3c 3e 22 20 69 6e 20 64 4e     if "<>" in dN
6e30: 6f 64 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ode:.           
6e40: 20 64 50 6f 69 6e 74 65 72 32 20 3d 20 7b 20 22   dPointer2 = { "
6e50: 69 4e 6f 64 65 31 22 3a 20 69 4e 6f 64 65 31 2c  iNode1": iNode1,
6e60: 20 22 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68   "dNode": dGraph
6e70: 5b 64 4e 6f 64 65 5b 22 3c 3e 22 5d 5d 2c 20 22  [dNode["<>"]], "
6e80: 62 4b 65 65 70 22 3a 20 54 72 75 65 20 7d 0a 20  bKeep": True }. 
6e90: 20 20 20 20 20 20 20 20 20 20 20 79 69 65 6c 64             yield
6ea0: 20 66 72 6f 6d 20 73 65 6c 66 2e 5f 67 65 74 4e   from self._getN
6eb0: 65 78 74 50 6f 69 6e 74 65 72 73 28 64 54 6f 6b  extPointers(dTok
6ec0: 65 6e 2c 20 64 47 72 61 70 68 2c 20 64 50 6f 69  en, dGraph, dPoi
6ed0: 6e 74 65 72 32 2c 20 62 44 65 62 75 67 29 0a 0a  nter2, bDebug)..
6ee0: 0a 20 20 20 20 64 65 66 20 70 61 72 73 65 20 28  .    def parse (
6ef0: 73 65 6c 66 2c 20 64 47 72 61 70 68 2c 20 64 50  self, dGraph, dP
6f00: 72 69 6f 72 69 74 79 2c 20 73 43 6f 75 6e 74 72  riority, sCountr
6f10: 79 3d 22 24 7b 63 6f 75 6e 74 72 79 5f 64 65 66  y="${country_def
6f20: 61 75 6c 74 7d 22 2c 20 64 4f 70 74 69 6f 6e 73  ault}", dOptions
6f30: 3d 4e 6f 6e 65 2c 20 62 53 68 6f 77 52 75 6c 65  =None, bShowRule
6f40: 49 64 3d 46 61 6c 73 65 2c 20 62 44 65 62 75 67  Id=False, bDebug
6f50: 3d 46 61 6c 73 65 2c 20 62 43 6f 6e 74 65 78 74  =False, bContext
6f60: 3d 46 61 6c 73 65 29 3a 0a 20 20 20 20 20 20 20  =False):.       
6f70: 20 22 70 61 72 73 65 20 74 6f 6b 65 6e 73 20 66   "parse tokens f
6f80: 72 6f 6d 20 74 68 65 20 74 65 78 74 20 61 6e 64  rom the text and
6f90: 20 65 78 65 63 75 74 65 20 61 63 74 69 6f 6e 73   execute actions
6fa0: 20 65 6e 63 6f 75 6e 74 65 72 65 64 22 0a 20 20   encountered".  
6fb0: 20 20 20 20 20 20 64 4f 70 74 20 3d 20 5f 64 4f        dOpt = _dO
6fc0: 70 74 69 6f 6e 73 20 20 69 66 20 6e 6f 74 20 64  ptions  if not d
6fd0: 4f 70 74 69 6f 6e 73 20 20 65 6c 73 65 20 64 4f  Options  else dO
6fe0: 70 74 69 6f 6e 73 0a 20 20 20 20 20 20 20 20 6c  ptions.        l
6ff0: 50 6f 69 6e 74 65 72 20 3d 20 5b 5d 0a 20 20 20  Pointer = [].   
7000: 20 20 20 20 20 62 54 61 67 41 6e 64 52 65 77 72       bTagAndRewr
7010: 69 74 65 20 3d 20 46 61 6c 73 65 0a 20 20 20 20  ite = False.    
7020: 20 20 20 20 66 6f 72 20 69 54 6f 6b 65 6e 2c 20      for iToken, 
7030: 64 54 6f 6b 65 6e 20 69 6e 20 65 6e 75 6d 65 72  dToken in enumer
7040: 61 74 65 28 73 65 6c 66 2e 6c 54 6f 6b 65 6e 29  ate(self.lToken)
7050: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  :.            if
7060: 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20   bDebug:.       
7070: 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22           print("
7080: 54 4f 4b 45 4e 3a 22 2c 20 64 54 6f 6b 65 6e 5b  TOKEN:", dToken[
7090: 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20 20  "sValue"]).     
70a0: 20 20 20 20 20 20 20 23 20 63 68 65 63 6b 20 61         # check a
70b0: 72 63 73 20 66 6f 72 20 65 61 63 68 20 65 78 69  rcs for each exi
70c0: 73 74 69 6e 67 20 70 6f 69 6e 74 65 72 0a 20 20  sting pointer.  
70d0: 20 20 20 20 20 20 20 20 20 20 6c 4e 65 78 74 50            lNextP
70e0: 6f 69 6e 74 65 72 20 3d 20 5b 5d 0a 20 20 20 20  ointer = [].    
70f0: 20 20 20 20 20 20 20 20 66 6f 72 20 64 50 6f 69          for dPoi
7100: 6e 74 65 72 20 69 6e 20 6c 50 6f 69 6e 74 65 72  nter in lPointer
7110: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
7120: 20 20 6c 4e 65 78 74 50 6f 69 6e 74 65 72 2e 65    lNextPointer.e
7130: 78 74 65 6e 64 28 73 65 6c 66 2e 5f 67 65 74 4e  xtend(self._getN
7140: 65 78 74 50 6f 69 6e 74 65 72 73 28 64 54 6f 6b  extPointers(dTok
7150: 65 6e 2c 20 64 47 72 61 70 68 2c 20 64 50 6f 69  en, dGraph, dPoi
7160: 6e 74 65 72 2c 20 62 44 65 62 75 67 29 29 0a 20  nter, bDebug)). 
7170: 20 20 20 20 20 20 20 20 20 20 20 6c 50 6f 69 6e             lPoin
7180: 74 65 72 20 3d 20 6c 4e 65 78 74 50 6f 69 6e 74  ter = lNextPoint
7190: 65 72 0a 20 20 20 20 20 20 20 20 20 20 20 20 23  er.            #
71a0: 20 63 68 65 63 6b 20 61 72 63 73 20 6f 66 20 66   check arcs of f
71b0: 69 72 73 74 20 6e 6f 64 65 73 0a 20 20 20 20 20  irst nodes.     
71c0: 20 20 20 20 20 20 20 6c 50 6f 69 6e 74 65 72 2e         lPointer.
71d0: 65 78 74 65 6e 64 28 73 65 6c 66 2e 5f 67 65 74  extend(self._get
71e0: 4e 65 78 74 50 6f 69 6e 74 65 72 73 28 64 54 6f  NextPointers(dTo
71f0: 6b 65 6e 2c 20 64 47 72 61 70 68 2c 20 7b 20 22  ken, dGraph, { "
7200: 69 4e 6f 64 65 31 22 3a 20 69 54 6f 6b 65 6e 2c  iNode1": iToken,
7210: 20 22 64 4e 6f 64 65 22 3a 20 64 47 72 61 70 68   "dNode": dGraph
7220: 5b 30 5d 20 7d 2c 20 62 44 65 62 75 67 29 29 0a  [0] }, bDebug)).
7230: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 63 68              # ch
7240: 65 63 6b 20 69 66 20 74 68 65 72 65 20 69 73 20  eck if there is 
7250: 72 75 6c 65 73 20 74 6f 20 63 68 65 63 6b 20 66  rules to check f
7260: 6f 72 20 65 61 63 68 20 70 6f 69 6e 74 65 72 0a  or each pointer.
7270: 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72 20              for 
7280: 64 50 6f 69 6e 74 65 72 20 69 6e 20 6c 50 6f 69  dPointer in lPoi
7290: 6e 74 65 72 3a 0a 20 20 20 20 20 20 20 20 20 20  nter:.          
72a0: 20 20 20 20 20 20 23 69 66 20 62 44 65 62 75 67        #if bDebug
72b0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
72c0: 20 20 23 20 20 20 20 70 72 69 6e 74 28 22 2b 22    #    print("+"
72d0: 2c 20 64 50 6f 69 6e 74 65 72 29 0a 20 20 20 20  , dPointer).    
72e0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 22              if "
72f0: 3c 72 75 6c 65 73 3e 22 20 69 6e 20 64 50 6f 69  <rules>" in dPoi
7300: 6e 74 65 72 5b 22 64 4e 6f 64 65 22 5d 3a 0a 20  nter["dNode"]:. 
7310: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7320: 20 20 20 62 43 68 61 6e 67 65 20 3d 20 73 65 6c     bChange = sel
7330: 66 2e 5f 65 78 65 63 75 74 65 41 63 74 69 6f 6e  f._executeAction
7340: 73 28 64 47 72 61 70 68 2c 20 64 50 6f 69 6e 74  s(dGraph, dPoint
7350: 65 72 5b 22 64 4e 6f 64 65 22 5d 5b 22 3c 72 75  er["dNode"]["<ru
7360: 6c 65 73 3e 22 5d 2c 20 64 50 6f 69 6e 74 65 72  les>"], dPointer
7370: 5b 22 69 4e 6f 64 65 31 22 5d 2d 31 2c 20 69 54  ["iNode1"]-1, iT
7380: 6f 6b 65 6e 2c 20 64 50 72 69 6f 72 69 74 79 2c  oken, dPriority,
7390: 20 64 4f 70 74 2c 20 73 43 6f 75 6e 74 72 79 2c   dOpt, sCountry,
73a0: 20 62 53 68 6f 77 52 75 6c 65 49 64 2c 20 62 44   bShowRuleId, bD
73b0: 65 62 75 67 2c 20 62 43 6f 6e 74 65 78 74 29 0a  ebug, bContext).
73c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
73d0: 20 20 20 20 69 66 20 62 43 68 61 6e 67 65 3a 0a      if bChange:.
73e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
73f0: 20 20 20 20 20 20 20 20 62 54 61 67 41 6e 64 52          bTagAndR
7400: 65 77 72 69 74 65 20 3d 20 54 72 75 65 0a 20 20  ewrite = True.  
7410: 20 20 20 20 20 20 69 66 20 62 54 61 67 41 6e 64        if bTagAnd
7420: 52 65 77 72 69 74 65 3a 0a 20 20 20 20 20 20 20  Rewrite:.       
7430: 20 20 20 20 20 73 65 6c 66 2e 72 65 77 72 69 74       self.rewrit
7440: 65 28 62 44 65 62 75 67 29 0a 20 20 20 20 20 20  e(bDebug).      
7450: 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20    if bDebug:.   
7460: 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 73           print(s
7470: 65 6c 66 29 0a 20 20 20 20 20 20 20 20 72 65 74  elf).        ret
7480: 75 72 6e 20 28 62 54 61 67 41 6e 64 52 65 77 72  urn (bTagAndRewr
7490: 69 74 65 2c 20 73 65 6c 66 2e 73 53 65 6e 74 65  ite, self.sSente
74a0: 6e 63 65 29 0a 0a 20 20 20 20 64 65 66 20 5f 65  nce)..    def _e
74b0: 78 65 63 75 74 65 41 63 74 69 6f 6e 73 20 28 73  xecuteActions (s
74c0: 65 6c 66 2c 20 64 47 72 61 70 68 2c 20 64 4e 6f  elf, dGraph, dNo
74d0: 64 65 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74  de, nTokenOffset
74e0: 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 2c 20 64 50  , nLastToken, dP
74f0: 72 69 6f 72 69 74 79 2c 20 64 4f 70 74 69 6f 6e  riority, dOption
7500: 73 2c 20 73 43 6f 75 6e 74 72 79 2c 20 62 53 68  s, sCountry, bSh
7510: 6f 77 52 75 6c 65 49 64 2c 20 62 44 65 62 75 67  owRuleId, bDebug
7520: 2c 20 62 43 6f 6e 74 65 78 74 29 3a 0a 20 20 20  , bContext):.   
7530: 20 20 20 20 20 22 65 78 65 63 75 74 65 20 61 63       "execute ac
7540: 74 69 6f 6e 73 20 66 6f 75 6e 64 20 69 6e 20 74  tions found in t
7550: 68 65 20 44 41 52 47 22 0a 20 20 20 20 20 20 20  he DARG".       
7560: 20 62 43 68 61 6e 67 65 20 3d 20 46 61 6c 73 65   bChange = False
7570: 0a 20 20 20 20 20 20 20 20 66 6f 72 20 73 4c 69  .        for sLi
7580: 6e 65 49 64 2c 20 6e 65 78 74 4e 6f 64 65 4b 65  neId, nextNodeKe
7590: 79 20 69 6e 20 64 4e 6f 64 65 2e 69 74 65 6d 73  y in dNode.items
75a0: 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ():.            
75b0: 62 43 6f 6e 64 4d 65 6d 6f 20 3d 20 4e 6f 6e 65  bCondMemo = None
75c0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72  .            for
75d0: 20 73 52 75 6c 65 49 64 20 69 6e 20 64 47 72 61   sRuleId in dGra
75e0: 70 68 5b 6e 65 78 74 4e 6f 64 65 4b 65 79 5d 3a  ph[nextNodeKey]:
75f0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
7600: 20 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20   try:.          
7610: 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65            if bDe
7620: 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  bug:.           
7630: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69               pri
7640: 6e 74 28 22 20 20 20 3e 54 52 59 3a 22 2c 20 73  nt("   >TRY:", s
7650: 52 75 6c 65 49 64 29 0a 20 20 20 20 20 20 20 20  RuleId).        
7660: 20 20 20 20 20 20 20 20 20 20 20 20 73 4f 70 74              sOpt
7670: 69 6f 6e 2c 20 73 46 75 6e 63 43 6f 6e 64 2c 20  ion, sFuncCond, 
7680: 63 41 63 74 69 6f 6e 54 79 70 65 2c 20 73 57 68  cActionType, sWh
7690: 61 74 2c 20 2a 65 41 63 74 20 3d 20 64 52 75 6c  at, *eAct = dRul
76a0: 65 5b 73 52 75 6c 65 49 64 5d 0a 20 20 20 20 20  e[sRuleId].     
76b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23                 #
76c0: 20 53 75 67 67 65 73 74 69 6f 6e 20 20 20 20 5b   Suggestion    [
76d0: 20 6f 70 74 69 6f 6e 2c 20 63 6f 6e 64 69 74 69   option, conditi
76e0: 6f 6e 2c 20 22 2d 22 2c 20 72 65 70 6c 61 63 65  on, "-", replace
76f0: 6d 65 6e 74 2f 73 75 67 67 65 73 74 69 6f 6e 2f  ment/suggestion/
7700: 61 63 74 69 6f 6e 2c 20 69 54 6f 6b 65 6e 53 74  action, iTokenSt
7710: 61 72 74 2c 20 69 54 6f 6b 65 6e 45 6e 64 2c 20  art, iTokenEnd, 
7720: 63 53 74 61 72 74 4c 69 6d 69 74 2c 20 63 45 6e  cStartLimit, cEn
7730: 64 4c 69 6d 69 74 2c 20 62 43 61 73 65 53 76 74  dLimit, bCaseSvt
7740: 79 2c 20 6e 50 72 69 6f 72 69 74 79 2c 20 73 4d  y, nPriority, sM
7750: 65 73 73 61 67 65 2c 20 73 55 52 4c 20 5d 0a 20  essage, sURL ]. 
7760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7770: 20 20 20 23 20 54 65 78 74 50 72 6f 63 65 73 73     # TextProcess
7780: 6f 72 20 5b 20 6f 70 74 69 6f 6e 2c 20 63 6f 6e  or [ option, con
7790: 64 69 74 69 6f 6e 2c 20 22 7e 22 2c 20 72 65 70  dition, "~", rep
77a0: 6c 61 63 65 6d 65 6e 74 2f 73 75 67 67 65 73 74  lacement/suggest
77b0: 69 6f 6e 2f 61 63 74 69 6f 6e 2c 20 69 54 6f 6b  ion/action, iTok
77c0: 65 6e 53 74 61 72 74 2c 20 69 54 6f 6b 65 6e 45  enStart, iTokenE
77d0: 6e 64 2c 20 62 43 61 73 65 53 76 74 79 20 5d 0a  nd, bCaseSvty ].
77e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
77f0: 20 20 20 20 23 20 44 69 73 61 6d 62 69 67 75 61      # Disambigua
7800: 74 6f 72 20 5b 20 6f 70 74 69 6f 6e 2c 20 63 6f  tor [ option, co
7810: 6e 64 69 74 69 6f 6e 2c 20 22 3d 22 2c 20 72 65  ndition, "=", re
7820: 70 6c 61 63 65 6d 65 6e 74 2f 73 75 67 67 65 73  placement/sugges
7830: 74 69 6f 6e 2f 61 63 74 69 6f 6e 20 5d 0a 20 20  tion/action ].  
7840: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7850: 20 20 23 20 54 61 67 20 20 20 20 20 20 20 20 20    # Tag         
7860: 20 20 5b 20 6f 70 74 69 6f 6e 2c 20 63 6f 6e 64    [ option, cond
7870: 69 74 69 6f 6e 2c 20 22 2f 22 2c 20 72 65 70 6c  ition, "/", repl
7880: 61 63 65 6d 65 6e 74 2f 73 75 67 67 65 73 74 69  acement/suggesti
7890: 6f 6e 2f 61 63 74 69 6f 6e 2c 20 69 54 6f 6b 65  on/action, iToke
78a0: 6e 53 74 61 72 74 2c 20 69 54 6f 6b 65 6e 45 6e  nStart, iTokenEn
78b0: 64 20 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  d ].            
78c0: 20 20 20 20 20 20 20 20 23 20 49 6d 6d 75 6e 69          # Immuni
78d0: 74 79 20 20 20 20 20 20 5b 20 6f 70 74 69 6f 6e  ty      [ option
78e0: 2c 20 63 6f 6e 64 69 74 69 6f 6e 2c 20 22 25 22  , condition, "%"
78f0: 2c 20 22 22 2c 20 20 20 20 20 20 20 20 20 20 20  , "",           
7900: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7910: 20 69 54 6f 6b 65 6e 53 74 61 72 74 2c 20 69 54   iTokenStart, iT
7920: 6f 6b 65 6e 45 6e 64 20 5d 0a 20 20 20 20 20 20  okenEnd ].      
7930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
7940: 54 65 73 74 20 20 20 20 20 20 20 20 20 20 5b 20  Test          [ 
7950: 6f 70 74 69 6f 6e 2c 20 63 6f 6e 64 69 74 69 6f  option, conditio
7960: 6e 2c 20 22 3e 22 2c 20 22 22 20 5d 0a 20 20 20  n, ">", "" ].   
7970: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7980: 20 69 66 20 6e 6f 74 20 73 4f 70 74 69 6f 6e 20   if not sOption 
7990: 6f 72 20 64 4f 70 74 69 6f 6e 73 2e 67 65 74 28  or dOptions.get(
79a0: 73 4f 70 74 69 6f 6e 2c 20 46 61 6c 73 65 29 3a  sOption, False):
79b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
79c0: 20 20 20 20 20 20 20 20 20 62 43 6f 6e 64 4d 65           bCondMe
79d0: 6d 6f 20 3d 20 6e 6f 74 20 73 46 75 6e 63 43 6f  mo = not sFuncCo
79e0: 6e 64 20 6f 72 20 67 6c 6f 62 61 6c 73 28 29 5b  nd or globals()[
79f0: 73 46 75 6e 63 43 6f 6e 64 5d 28 73 65 6c 66 2e  sFuncCond](self.
7a00: 6c 54 6f 6b 65 6e 2c 20 6e 54 6f 6b 65 6e 4f 66  lToken, nTokenOf
7a10: 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e  fset, nLastToken
7a20: 2c 20 73 43 6f 75 6e 74 72 79 2c 20 62 43 6f 6e  , sCountry, bCon
7a30: 64 4d 65 6d 6f 2c 20 73 65 6c 66 2e 64 54 61 67  dMemo, self.dTag
7a40: 73 2c 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63  s, self.sSentenc
7a50: 65 2c 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63  e, self.sSentenc
7a60: 65 30 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  e0).            
7a70: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 62              if b
7a80: 43 6f 6e 64 4d 65 6d 6f 3a 0a 20 20 20 20 20 20  CondMemo:.      
7a90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7aa0: 20 20 20 20 20 20 69 66 20 63 41 63 74 69 6f 6e        if cAction
7ab0: 54 79 70 65 20 3d 3d 20 22 2d 22 3a 0a 20 20 20  Type == "-":.   
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 20 20 20 23 20 67               # g
7ae0: 72 61 6d 6d 61 72 20 65 72 72 6f 72 0a 20 20 20  rammar error.   
7af0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7b00: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 54 6f               iTo
7b10: 6b 65 6e 53 74 61 72 74 2c 20 69 54 6f 6b 65 6e  kenStart, iToken
7b20: 45 6e 64 2c 20 63 53 74 61 72 74 4c 69 6d 69 74  End, cStartLimit
7b30: 2c 20 63 45 6e 64 4c 69 6d 69 74 2c 20 62 43 61  , cEndLimit, bCa
7b40: 73 65 53 76 74 79 2c 20 6e 50 72 69 6f 72 69 74  seSvty, nPriorit
7b50: 79 2c 20 73 4d 65 73 73 61 67 65 2c 20 73 55 52  y, sMessage, sUR
7b60: 4c 20 3d 20 65 41 63 74 0a 20 20 20 20 20 20 20  L = eAct.       
7b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7b80: 20 20 20 20 20 20 20 20 20 6e 54 6f 6b 65 6e 45           nTokenE
7b90: 72 72 6f 72 53 74 61 72 74 20 3d 20 6e 54 6f 6b  rrorStart = nTok
7ba0: 65 6e 4f 66 66 73 65 74 20 2b 20 69 54 6f 6b 65  enOffset + iToke
7bb0: 6e 53 74 61 72 74 20 20 69 66 20 69 54 6f 6b 65  nStart  if iToke
7bc0: 6e 53 74 61 72 74 20 3e 20 30 20 20 65 6c 73 65  nStart > 0  else
7bd0: 20 6e 4c 61 73 74 54 6f 6b 65 6e 20 2b 20 69 54   nLastToken + iT
7be0: 6f 6b 65 6e 53 74 61 72 74 0a 20 20 20 20 20 20  okenStart.      
7bf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7c00: 20 20 20 20 20 20 20 20 20 20 69 66 20 22 62 49            if "bI
7c10: 6d 6d 75 6e 65 22 20 6e 6f 74 20 69 6e 20 73 65  mmune" not in se
7c20: 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e  lf.lToken[nToken
7c30: 45 72 72 6f 72 53 74 61 72 74 5d 3a 0a 20 20 20  ErrorStart]:.   
7c40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7c60: 20 6e 54 6f 6b 65 6e 45 72 72 6f 72 45 6e 64 20   nTokenErrorEnd 
7c70: 3d 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 20 2b  = nTokenOffset +
7c80: 20 69 54 6f 6b 65 6e 45 6e 64 20 20 69 66 20 69   iTokenEnd  if i
7c90: 54 6f 6b 65 6e 45 6e 64 20 3e 20 30 20 20 65 6c  TokenEnd > 0  el
7ca0: 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20 2b 20  se nLastToken + 
7cb0: 69 54 6f 6b 65 6e 45 6e 64 0a 20 20 20 20 20 20  iTokenEnd.      
7cc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 45                nE
7ce0: 72 72 6f 72 53 74 61 72 74 20 3d 20 73 65 6c 66  rrorStart = self
7cf0: 2e 6e 4f 66 66 73 65 74 57 69 74 68 69 6e 50 61  .nOffsetWithinPa
7d00: 72 61 67 72 61 70 68 20 2b 20 28 73 65 6c 66 2e  ragraph + (self.
7d10: 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 45 72 72  lToken[nTokenErr
7d20: 6f 72 53 74 61 72 74 5d 5b 22 6e 53 74 61 72 74  orStart]["nStart
7d30: 22 5d 20 69 66 20 63 53 74 61 72 74 4c 69 6d 69  "] if cStartLimi
7d40: 74 20 3d 3d 20 22 3c 22 20 20 65 6c 73 65 20 73  t == "<"  else s
7d50: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65  elf.lToken[nToke
7d60: 6e 45 72 72 6f 72 53 74 61 72 74 5d 5b 22 6e 45  nErrorStart]["nE
7d70: 6e 64 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20  nd"]).          
7d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7d90: 20 20 20 20 20 20 20 20 20 20 6e 45 72 72 6f 72            nError
7da0: 45 6e 64 20 3d 20 73 65 6c 66 2e 6e 4f 66 66 73  End = self.nOffs
7db0: 65 74 57 69 74 68 69 6e 50 61 72 61 67 72 61 70  etWithinParagrap
7dc0: 68 20 2b 20 28 73 65 6c 66 2e 6c 54 6f 6b 65 6e  h + (self.lToken
7dd0: 5b 6e 54 6f 6b 65 6e 45 72 72 6f 72 45 6e 64 5d  [nTokenErrorEnd]
7de0: 5b 22 6e 45 6e 64 22 5d 20 69 66 20 63 45 6e 64  ["nEnd"] if cEnd
7df0: 4c 69 6d 69 74 20 3d 3d 20 22 3e 22 20 20 65 6c  Limit == ">"  el
7e00: 73 65 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e  se self.lToken[n
7e10: 54 6f 6b 65 6e 45 72 72 6f 72 45 6e 64 5d 5b 22  TokenErrorEnd]["
7e20: 6e 53 74 61 72 74 22 5d 29 0a 20 20 20 20 20 20  nStart"]).      
7e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7e40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66                if
7e50: 20 6e 45 72 72 6f 72 53 74 61 72 74 20 6e 6f 74   nErrorStart not
7e60: 20 69 6e 20 73 65 6c 66 2e 64 45 72 72 6f 72 20   in self.dError 
7e70: 6f 72 20 6e 50 72 69 6f 72 69 74 79 20 3e 20 64  or nPriority > d
7e80: 50 72 69 6f 72 69 74 79 2e 67 65 74 28 6e 45 72  Priority.get(nEr
7e90: 72 6f 72 53 74 61 72 74 2c 20 2d 31 29 3a 0a 20  rorStart, -1):. 
7ea0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7ec0: 20 20 20 20 20 20 20 73 65 6c 66 2e 64 45 72 72         self.dErr
7ed0: 6f 72 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d 20  or[nErrorStart] 
7ee0: 3d 20 73 65 6c 66 2e 5f 63 72 65 61 74 65 45 72  = self._createEr
7ef0: 72 6f 72 28 73 57 68 61 74 2c 20 6e 54 6f 6b 65  ror(sWhat, nToke
7f00: 6e 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f  nOffset, nLastTo
7f10: 6b 65 6e 2c 20 6e 54 6f 6b 65 6e 45 72 72 6f 72  ken, nTokenError
7f20: 53 74 61 72 74 2c 20 6e 45 72 72 6f 72 53 74 61  Start, nErrorSta
7f30: 72 74 2c 20 6e 45 72 72 6f 72 45 6e 64 2c 20 73  rt, nErrorEnd, s
7f40: 4c 69 6e 65 49 64 2c 20 73 52 75 6c 65 49 64 2c  LineId, sRuleId,
7f50: 20 62 43 61 73 65 53 76 74 79 2c 20 73 4d 65 73   bCaseSvty, sMes
7f60: 73 61 67 65 2c 20 73 55 52 4c 2c 20 62 53 68 6f  sage, sURL, bSho
7f70: 77 52 75 6c 65 49 64 2c 20 22 6e 6f 74 79 70 65  wRuleId, "notype
7f80: 22 2c 20 62 43 6f 6e 74 65 78 74 29 0a 20 20 20  ", bContext).   
7f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7fb0: 20 20 20 20 20 64 50 72 69 6f 72 69 74 79 5b 6e       dPriority[n
7fc0: 45 72 72 6f 72 53 74 61 72 74 5d 20 3d 20 6e 50  ErrorStart] = nP
7fd0: 72 69 6f 72 69 74 79 0a 20 20 20 20 20 20 20 20  riority.        
7fe0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7ff0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8000: 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20  if bDebug:.     
8010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8020: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8030: 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 20 20         print("  
8040: 20 20 4e 45 57 5f 45 52 52 4f 52 3a 20 20 22 2c    NEW_ERROR:  ",
8050: 20 73 52 75 6c 65 49 64 2c 20 73 4c 69 6e 65 49   sRuleId, sLineI
8060: 64 2c 20 22 3a 20 22 2c 20 73 65 6c 66 2e 64 45  d, ": ", self.dE
8070: 72 72 6f 72 5b 6e 45 72 72 6f 72 53 74 61 72 74  rror[nErrorStart
8080: 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ]).             
8090: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65                 e
80a0: 6c 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20  lif cActionType 
80b0: 3d 3d 20 22 7e 22 3a 0a 20 20 20 20 20 20 20 20  == "~":.        
80c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
80d0: 20 20 20 20 20 20 20 20 23 20 74 65 78 74 20 70          # text p
80e0: 72 6f 63 65 73 73 6f 72 0a 20 20 20 20 20 20 20  rocessor.       
80f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8100: 20 20 20 20 20 20 20 20 20 6e 54 6f 6b 65 6e 53           nTokenS
8110: 74 61 72 74 20 3d 20 6e 54 6f 6b 65 6e 4f 66 66  tart = nTokenOff
8120: 73 65 74 20 2b 20 65 41 63 74 5b 30 5d 20 20 69  set + eAct[0]  i
8130: 66 20 65 41 63 74 5b 30 5d 20 3e 20 30 20 20 65  f eAct[0] > 0  e
8140: 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20 2b  lse nLastToken +
8150: 20 65 41 63 74 5b 30 5d 0a 20 20 20 20 20 20 20   eAct[0].       
8160: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8170: 20 20 20 20 20 20 20 20 20 6e 54 6f 6b 65 6e 45           nTokenE
8180: 6e 64 20 3d 20 6e 54 6f 6b 65 6e 4f 66 66 73 65  nd = nTokenOffse
8190: 74 20 2b 20 65 41 63 74 5b 31 5d 20 20 69 66 20  t + eAct[1]  if 
81a0: 65 41 63 74 5b 31 5d 20 3e 20 30 20 20 65 6c 73  eAct[1] > 0  els
81b0: 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20 2b 20 65  e nLastToken + e
81c0: 41 63 74 5b 31 5d 0a 20 20 20 20 20 20 20 20 20  Act[1].         
81d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
81e0: 20 20 20 20 20 20 20 73 65 6c 66 2e 5f 74 61 67         self._tag
81f0: 41 6e 64 50 72 65 70 61 72 65 54 6f 6b 65 6e 46  AndPrepareTokenF
8200: 6f 72 52 65 77 72 69 74 69 6e 67 28 73 57 68 61  orRewriting(sWha
8210: 74 2c 20 6e 54 6f 6b 65 6e 53 74 61 72 74 2c 20  t, nTokenStart, 
8220: 6e 54 6f 6b 65 6e 45 6e 64 2c 20 6e 54 6f 6b 65  nTokenEnd, nToke
8230: 6e 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f  nOffset, nLastTo
8240: 6b 65 6e 2c 20 65 41 63 74 5b 32 5d 2c 20 62 44  ken, eAct[2], bD
8250: 65 62 75 67 29 0a 20 20 20 20 20 20 20 20 20 20  ebug).          
8260: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8270: 20 20 20 20 20 20 62 43 68 61 6e 67 65 20 3d 20        bChange = 
8280: 54 72 75 65 0a 20 20 20 20 20 20 20 20 20 20 20  True.           
8290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
82a0: 20 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a       if bDebug:.
82b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
82c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
82d0: 20 20 20 20 70 72 69 6e 74 28 22 20 20 20 20 54      print("    T
82e0: 45 58 54 5f 50 52 4f 43 45 53 53 4f 52 3a 20 20  EXT_PROCESSOR:  
82f0: 22 2c 20 73 52 75 6c 65 49 64 2c 20 73 4c 69 6e  ", sRuleId, sLin
8300: 65 49 64 29 0a 20 20 20 20 20 20 20 20 20 20 20  eId).           
8310: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8320: 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22           print("
8330: 20 20 20 20 20 20 22 2c 20 73 65 6c 66 2e 6c 54        ", self.lT
8340: 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 53 74 61 72 74  oken[nTokenStart
8350: 5d 5b 22 73 56 61 6c 75 65 22 5d 2c 20 22 3a 22  ]["sValue"], ":"
8360: 2c 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54  , self.lToken[nT
8370: 6f 6b 65 6e 45 6e 64 5d 5b 22 73 56 61 6c 75 65  okenEnd]["sValue
8380: 22 5d 2c 20 22 20 3e 22 2c 20 73 57 68 61 74 29  "], " >", sWhat)
8390: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
83a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 69               eli
83b0: 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20 3d 3d  f cActionType ==
83c0: 20 22 3d 22 3a 0a 20 20 20 20 20 20 20 20 20 20   "=":.          
83d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
83e0: 20 20 20 20 20 20 23 20 64 69 73 61 6d 62 69 67        # disambig
83f0: 75 61 74 69 6f 6e 0a 20 20 20 20 20 20 20 20 20  uation.         
8400: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8410: 20 20 20 20 20 20 20 67 6c 6f 62 61 6c 73 28 29         globals()
8420: 5b 73 57 68 61 74 5d 28 73 65 6c 66 2e 6c 54 6f  [sWhat](self.lTo
8430: 6b 65 6e 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65  ken, nTokenOffse
8440: 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 29 0a 20  t, nLastToken). 
8450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8460: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
8470: 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20  f bDebug:.      
8480: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8490: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72                pr
84a0: 69 6e 74 28 22 20 20 20 20 44 49 53 41 4d 42 49  int("    DISAMBI
84b0: 47 55 41 54 4f 52 3a 20 20 22 2c 20 73 52 75 6c  GUATOR:  ", sRul
84c0: 65 49 64 2c 20 73 4c 69 6e 65 49 64 2c 20 22 28  eId, sLineId, "(
84d0: 22 2b 73 57 68 61 74 2b 22 29 22 2c 20 73 65 6c  "+sWhat+")", sel
84e0: 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 4f  f.lToken[nTokenO
84f0: 66 66 73 65 74 2b 31 5d 5b 22 73 56 61 6c 75 65  ffset+1]["sValue
8500: 22 5d 2c 20 22 3a 22 2c 20 73 65 6c 66 2e 6c 54  "], ":", self.lT
8510: 6f 6b 65 6e 5b 6e 4c 61 73 74 54 6f 6b 65 6e 5d  oken[nLastToken]
8520: 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20  ["sValue"]).    
8530: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8540: 20 20 20 20 20 20 20 20 65 6c 69 66 20 63 41 63          elif cAc
8550: 74 69 6f 6e 54 79 70 65 20 3d 3d 20 22 3e 22 3a  tionType == ">":
8560: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8570: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8580: 20 23 20 77 65 20 64 6f 20 6e 6f 74 68 69 6e 67   # we do nothing
8590: 2c 20 74 68 69 73 20 74 65 73 74 20 69 73 20 6a  , this test is j
85a0: 75 73 74 20 61 20 63 6f 6e 64 69 74 69 6f 6e 20  ust a condition 
85b0: 74 6f 20 61 70 70 6c 79 20 61 6c 6c 20 66 6f 6c  to apply all fol
85c0: 6c 6f 77 69 6e 67 20 61 63 74 69 6f 6e 73 0a 20  lowing actions. 
85d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
85e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
85f0: 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20  f bDebug:.      
8600: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8610: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72                pr
8620: 69 6e 74 28 22 20 20 20 20 43 4f 4e 44 5f 4f 4b  int("    COND_OK
8630: 3a 20 20 22 2c 20 73 52 75 6c 65 49 64 2c 20 73  :  ", sRuleId, s
8640: 4c 69 6e 65 49 64 29 0a 20 20 20 20 20 20 20 20  LineId).        
8650: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8660: 20 20 20 20 20 20 20 20 70 61 73 73 0a 20 20 20          pass.   
8670: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8680: 20 20 20 20 20 20 20 20 20 65 6c 69 66 20 63 41           elif cA
8690: 63 74 69 6f 6e 54 79 70 65 20 3d 3d 20 22 2f 22  ctionType == "/"
86a0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
86b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
86c0: 20 20 23 20 54 61 67 0a 20 20 20 20 20 20 20 20    # Tag.        
86d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
86e0: 20 20 20 20 20 20 20 20 6e 54 6f 6b 65 6e 53 74          nTokenSt
86f0: 61 72 74 20 3d 20 6e 54 6f 6b 65 6e 4f 66 66 73  art = nTokenOffs
8700: 65 74 20 2b 20 65 41 63 74 5b 30 5d 20 20 69 66  et + eAct[0]  if
8710: 20 65 41 63 74 5b 30 5d 20 3e 20 30 20 20 65 6c   eAct[0] > 0  el
8720: 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20 2b 20  se nLastToken + 
8730: 65 41 63 74 5b 30 5d 0a 20 20 20 20 20 20 20 20  eAct[0].        
8740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8750: 20 20 20 20 20 20 20 20 6e 54 6f 6b 65 6e 45 6e          nTokenEn
8760: 64 20 3d 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74  d = nTokenOffset
8770: 20 2b 20 65 41 63 74 5b 31 5d 20 20 69 66 20 65   + eAct[1]  if e
8780: 41 63 74 5b 31 5d 20 3e 20 30 20 20 65 6c 73 65  Act[1] > 0  else
8790: 20 6e 4c 61 73 74 54 6f 6b 65 6e 20 2b 20 65 41   nLastToken + eA
87a0: 63 74 5b 31 5d 0a 20 20 20 20 20 20 20 20 20 20  ct[1].          
87b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
87c0: 20 20 20 20 20 20 66 6f 72 20 69 20 69 6e 20 72        for i in r
87d0: 61 6e 67 65 28 6e 54 6f 6b 65 6e 53 74 61 72 74  ange(nTokenStart
87e0: 2c 20 6e 54 6f 6b 65 6e 45 6e 64 2b 31 29 3a 0a  , nTokenEnd+1):.
87f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8800: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8810: 20 20 20 20 69 66 20 22 74 61 67 73 22 20 69 6e      if "tags" in
8820: 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 3a   self.lToken[i]:
8830: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
8840: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8850: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c 54           self.lT
8860: 6f 6b 65 6e 5b 69 5d 5b 22 74 61 67 73 22 5d 2e  oken[i]["tags"].
8870: 75 70 64 61 74 65 28 73 57 68 61 74 2e 73 70 6c  update(sWhat.spl
8880: 69 74 28 22 7c 22 29 29 0a 20 20 20 20 20 20 20  it("|")).       
8890: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
88a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c 73               els
88b0: 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  e:.             
88c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
88d0: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
88e0: 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 74 61 67 73 22  lToken[i]["tags"
88f0: 5d 20 3d 20 73 65 74 28 73 57 68 61 74 2e 73 70  ] = set(sWhat.sp
8900: 6c 69 74 28 22 7c 22 29 29 0a 20 20 20 20 20 20  lit("|")).      
8910: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8920: 20 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65            if bDe
8930: 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20  bug:.           
8940: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8950: 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22           print("
8960: 20 20 20 20 54 41 47 3a 20 20 22 2c 20 73 52 75      TAG:  ", sRu
8970: 6c 65 49 64 2c 20 73 4c 69 6e 65 49 64 29 0a 20  leId, sLineId). 
8980: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8990: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
89a0: 20 20 20 70 72 69 6e 74 28 22 20 20 20 20 20 20     print("      
89b0: 22 2c 20 73 57 68 61 74 2c 20 22 20 3e 22 2c 20  ", sWhat, " >", 
89c0: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b  self.lToken[nTok
89d0: 65 6e 53 74 61 72 74 5d 5b 22 73 56 61 6c 75 65  enStart]["sValue
89e0: 22 5d 2c 20 22 3a 22 2c 20 73 65 6c 66 2e 6c 54  "], ":", self.lT
89f0: 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 45 6e 64 5d 5b  oken[nTokenEnd][
8a00: 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20 20  "sValue"]).     
8a10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8a20: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73 57             if sW
8a30: 68 61 74 20 6e 6f 74 20 69 6e 20 73 65 6c 66 2e  hat not in self.
8a40: 64 54 61 67 73 3a 0a 20 20 20 20 20 20 20 20 20  dTags:.         
8a50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8a60: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
8a70: 64 54 61 67 73 5b 73 57 68 61 74 5d 20 3d 20 5b  dTags[sWhat] = [
8a80: 6e 54 6f 6b 65 6e 53 74 61 72 74 2c 20 6e 54 6f  nTokenStart, nTo
8a90: 6b 65 6e 53 74 61 72 74 5d 0a 20 20 20 20 20 20  kenStart].      
8aa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8ab0: 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a            else:.
8ac0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8ae0: 20 20 20 20 73 65 6c 66 2e 64 54 61 67 73 5b 73      self.dTags[s
8af0: 57 68 61 74 5d 5b 30 5d 20 3d 20 6d 69 6e 28 6e  What][0] = min(n
8b00: 54 6f 6b 65 6e 53 74 61 72 74 2c 20 73 65 6c 66  TokenStart, self
8b10: 2e 64 54 61 67 73 5b 73 57 68 61 74 5d 5b 30 5d  .dTags[sWhat][0]
8b20: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
8b30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8b40: 20 20 20 20 20 20 73 65 6c 66 2e 64 54 61 67 73        self.dTags
8b50: 5b 73 57 68 61 74 5d 5b 31 5d 20 3d 20 6d 61 78  [sWhat][1] = max
8b60: 28 6e 54 6f 6b 65 6e 45 6e 64 2c 20 73 65 6c 66  (nTokenEnd, self
8b70: 2e 64 54 61 67 73 5b 73 57 68 61 74 5d 5b 31 5d  .dTags[sWhat][1]
8b80: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
8b90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 6c                el
8ba0: 69 66 20 63 41 63 74 69 6f 6e 54 79 70 65 20 3d  if cActionType =
8bb0: 3d 20 22 25 22 3a 0a 20 20 20 20 20 20 20 20 20  = "%":.         
8bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8bd0: 20 20 20 20 20 20 20 23 20 69 6d 6d 75 6e 69 74         # immunit
8be0: 79 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  y.              
8bf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8c00: 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20 20 20    if bDebug:.   
8c10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8c20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8c30: 20 70 72 69 6e 74 28 22 20 20 20 20 49 4d 4d 55   print("    IMMU
8c40: 4e 49 54 59 3a 5c 6e 20 20 22 2c 20 64 52 75 6c  NITY:\n  ", dRul
8c50: 65 5b 73 52 75 6c 65 49 64 5d 29 0a 20 20 20 20  e[sRuleId]).    
8c60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8c70: 20 20 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b              nTok
8c80: 65 6e 53 74 61 72 74 20 3d 20 6e 54 6f 6b 65 6e  enStart = nToken
8c90: 4f 66 66 73 65 74 20 2b 20 65 41 63 74 5b 30 5d  Offset + eAct[0]
8ca0: 20 20 69 66 20 65 41 63 74 5b 30 5d 20 3e 20 30    if eAct[0] > 0
8cb0: 20 20 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65    else nLastToke
8cc0: 6e 20 2b 20 65 41 63 74 5b 30 5d 0a 20 20 20 20  n + eAct[0].    
8cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8ce0: 20 20 20 20 20 20 20 20 20 20 20 20 6e 54 6f 6b              nTok
8cf0: 65 6e 45 6e 64 20 3d 20 6e 54 6f 6b 65 6e 4f 66  enEnd = nTokenOf
8d00: 66 73 65 74 20 2b 20 65 41 63 74 5b 31 5d 20 20  fset + eAct[1]  
8d10: 69 66 20 65 41 63 74 5b 31 5d 20 3e 20 30 20 20  if eAct[1] > 0  
8d20: 65 6c 73 65 20 6e 4c 61 73 74 54 6f 6b 65 6e 20  else nLastToken 
8d30: 2b 20 65 41 63 74 5b 31 5d 0a 20 20 20 20 20 20  + eAct[1].      
8d40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8d50: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 54 6f            if nTo
8d60: 6b 65 6e 45 6e 64 20 2d 20 6e 54 6f 6b 65 6e 53  kenEnd - nTokenS
8d70: 74 61 72 74 20 3d 3d 20 30 3a 0a 20 20 20 20 20  tart == 0:.     
8d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8d90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
8da0: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65  elf.lToken[nToke
8db0: 6e 53 74 61 72 74 5d 5b 22 62 49 6d 6d 75 6e 65  nStart]["bImmune
8dc0: 22 5d 20 3d 20 54 72 75 65 0a 20 20 20 20 20 20  "] = True.      
8dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8de0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6e 45                nE
8df0: 72 72 6f 72 53 74 61 72 74 20 3d 20 73 65 6c 66  rrorStart = self
8e00: 2e 6e 4f 66 66 73 65 74 57 69 74 68 69 6e 50 61  .nOffsetWithinPa
8e10: 72 61 67 72 61 70 68 20 2b 20 73 65 6c 66 2e 6c  ragraph + self.l
8e20: 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 53 74 61 72  Token[nTokenStar
8e30: 74 5d 5b 22 6e 53 74 61 72 74 22 5d 0a 20 20 20  t]["nStart"].   
8e40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8e60: 20 69 66 20 6e 45 72 72 6f 72 53 74 61 72 74 20   if nErrorStart 
8e70: 69 6e 20 73 65 6c 66 2e 64 45 72 72 6f 72 3a 0a  in self.dError:.
8e80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8ea0: 20 20 20 20 20 20 20 20 64 65 6c 20 73 65 6c 66          del self
8eb0: 2e 64 45 72 72 6f 72 5b 6e 45 72 72 6f 72 53 74  .dError[nErrorSt
8ec0: 61 72 74 5d 0a 20 20 20 20 20 20 20 20 20 20 20  art].           
8ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8ee0: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
8ef0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8f00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66                 f
8f10: 6f 72 20 69 20 69 6e 20 72 61 6e 67 65 28 6e 54  or i in range(nT
8f20: 6f 6b 65 6e 53 74 61 72 74 2c 20 6e 54 6f 6b 65  okenStart, nToke
8f30: 6e 45 6e 64 2b 31 29 3a 0a 20 20 20 20 20 20 20  nEnd+1):.       
8f40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8f50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8f60: 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 5d 5b   self.lToken[i][
8f70: 22 62 49 6d 6d 75 6e 65 22 5d 20 3d 20 54 72 75  "bImmune"] = Tru
8f80: 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  e.              
8f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8fa0: 20 20 20 20 20 20 20 20 20 20 6e 45 72 72 6f 72            nError
8fb0: 53 74 61 72 74 20 3d 20 73 65 6c 66 2e 6e 4f 66  Start = self.nOf
8fc0: 66 73 65 74 57 69 74 68 69 6e 50 61 72 61 67 72  fsetWithinParagr
8fd0: 61 70 68 20 2b 20 73 65 6c 66 2e 6c 54 6f 6b 65  aph + self.lToke
8fe0: 6e 5b 69 5d 5b 22 6e 53 74 61 72 74 22 5d 0a 20  n[i]["nStart"]. 
8ff0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9000: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9010: 20 20 20 20 20 20 20 69 66 20 6e 45 72 72 6f 72         if nError
9020: 53 74 61 72 74 20 69 6e 20 73 65 6c 66 2e 64 45  Start in self.dE
9030: 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20 20 20  rror:.          
9040: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9050: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9060: 20 20 64 65 6c 20 73 65 6c 66 2e 64 45 72 72 6f    del self.dErro
9070: 72 5b 6e 45 72 72 6f 72 53 74 61 72 74 5d 0a 20  r[nErrorStart]. 
9080: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9090: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
90a0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
90b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
90c0: 20 70 72 69 6e 74 28 22 23 20 65 72 72 6f 72 3a   print("# error:
90d0: 20 75 6e 6b 6e 6f 77 6e 20 61 63 74 69 6f 6e 20   unknown action 
90e0: 61 74 20 22 20 2b 20 73 4c 69 6e 65 49 64 29 0a  at " + sLineId).
90f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9100: 20 20 20 20 20 20 20 20 65 6c 69 66 20 63 41 63          elif cAc
9110: 74 69 6f 6e 54 79 70 65 20 3d 3d 20 22 3e 22 3a  tionType == ">":
9120: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9130: 20 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20               if 
9140: 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20  bDebug:.        
9150: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9160: 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 20          print(" 
9170: 20 20 20 43 4f 4e 44 5f 42 52 45 41 4b 3a 20 20     COND_BREAK:  
9180: 22 2c 20 73 52 75 6c 65 49 64 2c 20 73 4c 69 6e  ", sRuleId, sLin
9190: 65 49 64 29 0a 20 20 20 20 20 20 20 20 20 20 20  eId).           
91a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
91b0: 20 62 72 65 61 6b 0a 20 20 20 20 20 20 20 20 20   break.         
91c0: 20 20 20 20 20 20 20 65 78 63 65 70 74 20 45 78         except Ex
91d0: 63 65 70 74 69 6f 6e 20 61 73 20 65 3a 0a 20 20  ception as e:.  
91e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
91f0: 20 20 72 61 69 73 65 20 45 78 63 65 70 74 69 6f    raise Exceptio
9200: 6e 28 73 74 72 28 65 29 2c 20 73 4c 69 6e 65 49  n(str(e), sLineI
9210: 64 2c 20 73 52 75 6c 65 49 64 2c 20 73 65 6c 66  d, sRuleId, self
9220: 2e 73 53 65 6e 74 65 6e 63 65 29 0a 20 20 20 20  .sSentence).    
9230: 20 20 20 20 72 65 74 75 72 6e 20 62 43 68 61 6e      return bChan
9240: 67 65 0a 0a 20 20 20 20 64 65 66 20 5f 63 72 65  ge..    def _cre
9250: 61 74 65 45 72 72 6f 72 20 28 73 65 6c 66 2c 20  ateError (self, 
9260: 73 53 75 67 67 2c 20 6e 54 6f 6b 65 6e 4f 66 66  sSugg, nTokenOff
9270: 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e 2c  set, nLastToken,
9280: 20 69 46 69 72 73 74 54 6f 6b 65 6e 2c 20 6e 53   iFirstToken, nS
9290: 74 61 72 74 2c 20 6e 45 6e 64 2c 20 73 4c 69 6e  tart, nEnd, sLin
92a0: 65 49 64 2c 20 73 52 75 6c 65 49 64 2c 20 62 43  eId, sRuleId, bC
92b0: 61 73 65 53 76 74 79 2c 20 73 4d 73 67 2c 20 73  aseSvty, sMsg, s
92c0: 55 52 4c 2c 20 62 53 68 6f 77 52 75 6c 65 49 64  URL, bShowRuleId
92d0: 2c 20 73 4f 70 74 69 6f 6e 2c 20 62 43 6f 6e 74  , sOption, bCont
92e0: 65 78 74 29 3a 0a 20 20 20 20 20 20 20 20 23 20  ext):.        # 
92f0: 73 75 67 67 65 73 74 69 6f 6e 73 0a 20 20 20 20  suggestions.    
9300: 20 20 20 20 69 66 20 73 53 75 67 67 5b 30 3a 31      if sSugg[0:1
9310: 5d 20 3d 3d 20 22 3d 22 3a 0a 20 20 20 20 20 20  ] == "=":.      
9320: 20 20 20 20 20 20 73 53 75 67 67 20 3d 20 67 6c        sSugg = gl
9330: 6f 62 61 6c 73 28 29 5b 73 53 75 67 67 5b 31 3a  obals()[sSugg[1:
9340: 5d 5d 28 73 65 6c 66 2e 6c 54 6f 6b 65 6e 2c 20  ]](self.lToken, 
9350: 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 6e 4c  nTokenOffset, nL
9360: 61 73 74 54 6f 6b 65 6e 29 0a 20 20 20 20 20 20  astToken).      
9370: 20 20 20 20 20 20 6c 53 75 67 67 20 3d 20 73 53        lSugg = sS
9380: 75 67 67 2e 73 70 6c 69 74 28 22 7c 22 29 20 20  ugg.split("|")  
9390: 69 66 20 73 53 75 67 67 20 20 65 6c 73 65 20 5b  if sSugg  else [
93a0: 5d 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 73  ].        elif s
93b0: 53 75 67 67 20 3d 3d 20 22 5f 22 3a 0a 20 20 20  Sugg == "_":.   
93c0: 20 20 20 20 20 20 20 20 20 6c 53 75 67 67 20 3d           lSugg =
93d0: 20 5b 5d 0a 20 20 20 20 20 20 20 20 65 6c 73 65   [].        else
93e0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6c 53  :.            lS
93f0: 75 67 67 20 3d 20 73 65 6c 66 2e 5f 65 78 70 61  ugg = self._expa
9400: 6e 64 28 73 53 75 67 67 2c 20 6e 54 6f 6b 65 6e  nd(sSugg, nToken
9410: 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b  Offset, nLastTok
9420: 65 6e 29 2e 73 70 6c 69 74 28 22 7c 22 29 0a 20  en).split("|"). 
9430: 20 20 20 20 20 20 20 69 66 20 62 43 61 73 65 53         if bCaseS
9440: 76 74 79 20 61 6e 64 20 6c 53 75 67 67 20 61 6e  vty and lSugg an
9450: 64 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 69 46  d self.lToken[iF
9460: 69 72 73 74 54 6f 6b 65 6e 5d 5b 22 73 56 61 6c  irstToken]["sVal
9470: 75 65 22 5d 5b 30 3a 31 5d 2e 69 73 75 70 70 65  ue"][0:1].isuppe
9480: 72 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  r():.           
9490: 20 6c 53 75 67 67 20 3d 20 6c 69 73 74 28 6d 61   lSugg = list(ma
94a0: 70 28 6c 61 6d 62 64 61 20 73 3a 20 73 5b 30 3a  p(lambda s: s[0:
94b0: 31 5d 2e 75 70 70 65 72 28 29 2b 73 5b 31 3a 5d  1].upper()+s[1:]
94c0: 2c 20 6c 53 75 67 67 29 29 0a 20 20 20 20 20 20  , lSugg)).      
94d0: 20 20 23 20 4d 65 73 73 61 67 65 0a 20 20 20 20    # Message.    
94e0: 20 20 20 20 73 4d 65 73 73 61 67 65 20 3d 20 67      sMessage = g
94f0: 6c 6f 62 61 6c 73 28 29 5b 73 4d 73 67 5b 31 3a  lobals()[sMsg[1:
9500: 5d 5d 28 73 65 6c 66 2e 6c 54 6f 6b 65 6e 2c 20  ]](self.lToken, 
9510: 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2c 20 6e 4c  nTokenOffset, nL
9520: 61 73 74 54 6f 6b 65 6e 29 20 20 69 66 20 73 4d  astToken)  if sM
9530: 73 67 5b 30 3a 31 5d 20 3d 3d 20 22 3d 22 20 20  sg[0:1] == "="  
9540: 65 6c 73 65 20 73 65 6c 66 2e 5f 65 78 70 61 6e  else self._expan
9550: 64 28 73 4d 73 67 2c 20 6e 54 6f 6b 65 6e 4f 66  d(sMsg, nTokenOf
9560: 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e  fset, nLastToken
9570: 29 0a 20 20 20 20 20 20 20 20 69 66 20 62 53 68  ).        if bSh
9580: 6f 77 52 75 6c 65 49 64 3a 0a 20 20 20 20 20 20  owRuleId:.      
9590: 20 20 20 20 20 20 73 4d 65 73 73 61 67 65 20 2b        sMessage +
95a0: 3d 20 22 20 20 22 20 2b 20 73 4c 69 6e 65 49 64  = "  " + sLineId
95b0: 20 2b 20 22 20 23 20 22 20 2b 20 73 52 75 6c 65   + " # " + sRule
95c0: 49 64 0a 20 20 20 20 20 20 20 20 23 0a 20 20 20  Id.        #.   
95d0: 20 20 20 20 20 69 66 20 5f 62 57 72 69 74 65 72       if _bWriter
95e0: 45 72 72 6f 72 3a 0a 20 20 20 20 20 20 20 20 20  Error:.         
95f0: 20 20 20 78 45 72 72 20 3d 20 53 69 6e 67 6c 65     xErr = Single
9600: 50 72 6f 6f 66 72 65 61 64 69 6e 67 45 72 72 6f  ProofreadingErro
9610: 72 28 29 20 20 20 20 23 20 75 6e 6f 2e 63 72 65  r()    # uno.cre
9620: 61 74 65 55 6e 6f 53 74 72 75 63 74 28 20 22 63  ateUnoStruct( "c
9630: 6f 6d 2e 73 75 6e 2e 73 74 61 72 2e 6c 69 6e 67  om.sun.star.ling
9640: 75 69 73 74 69 63 32 2e 53 69 6e 67 6c 65 50 72  uistic2.SinglePr
9650: 6f 6f 66 72 65 61 64 69 6e 67 45 72 72 6f 72 22  oofreadingError"
9660: 20 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 78   ).            x
9670: 45 72 72 2e 6e 45 72 72 6f 72 53 74 61 72 74 20  Err.nErrorStart 
9680: 3d 20 6e 53 74 61 72 74 0a 20 20 20 20 20 20 20  = nStart.       
9690: 20 20 20 20 20 78 45 72 72 2e 6e 45 72 72 6f 72       xErr.nError
96a0: 4c 65 6e 67 74 68 20 3d 20 6e 45 6e 64 20 2d 20  Length = nEnd - 
96b0: 6e 53 74 61 72 74 0a 20 20 20 20 20 20 20 20 20  nStart.         
96c0: 20 20 20 78 45 72 72 2e 6e 45 72 72 6f 72 54 79     xErr.nErrorTy
96d0: 70 65 20 3d 20 50 52 4f 4f 46 52 45 41 44 49 4e  pe = PROOFREADIN
96e0: 47 0a 20 20 20 20 20 20 20 20 20 20 20 20 78 45  G.            xE
96f0: 72 72 2e 61 52 75 6c 65 49 64 65 6e 74 69 66 69  rr.aRuleIdentifi
9700: 65 72 20 3d 20 73 52 75 6c 65 49 64 0a 20 20 20  er = sRuleId.   
9710: 20 20 20 20 20 20 20 20 20 78 45 72 72 2e 61 53           xErr.aS
9720: 68 6f 72 74 43 6f 6d 6d 65 6e 74 20 3d 20 73 4d  hortComment = sM
9730: 65 73 73 61 67 65 20 20 20 23 20 73 4d 65 73 73  essage   # sMess
9740: 61 67 65 2e 73 70 6c 69 74 28 22 7c 22 29 5b 30  age.split("|")[0
9750: 5d 20 20 20 20 20 23 20 69 6e 20 63 6f 6e 74 65  ]     # in conte
9760: 78 74 20 6d 65 6e 75 0a 20 20 20 20 20 20 20 20  xt menu.        
9770: 20 20 20 20 78 45 72 72 2e 61 46 75 6c 6c 43 6f      xErr.aFullCo
9780: 6d 6d 65 6e 74 20 3d 20 73 4d 65 73 73 61 67 65  mment = sMessage
9790: 20 20 20 23 20 73 4d 65 73 73 61 67 65 2e 73 70     # sMessage.sp
97a0: 6c 69 74 28 22 7c 22 29 5b 2d 31 5d 20 20 20 20  lit("|")[-1]    
97b0: 23 20 69 6e 20 64 69 61 6c 6f 67 0a 20 20 20 20  # in dialog.    
97c0: 20 20 20 20 20 20 20 20 69 66 20 62 53 68 6f 77          if bShow
97d0: 52 75 6c 65 49 64 3a 0a 20 20 20 20 20 20 20 20  RuleId:.        
97e0: 20 20 20 20 20 20 20 20 78 45 72 72 2e 61 53 68          xErr.aSh
97f0: 6f 72 74 43 6f 6d 6d 65 6e 74 20 2b 3d 20 22 20  ortComment += " 
9800: 20 22 20 2b 20 73 4c 69 6e 65 49 64 20 2b 20 22   " + sLineId + "
9810: 20 23 20 22 20 2b 20 73 52 75 6c 65 49 64 0a 20   # " + sRuleId. 
9820: 20 20 20 20 20 20 20 20 20 20 20 78 45 72 72 2e             xErr.
9830: 61 53 75 67 67 65 73 74 69 6f 6e 73 20 3d 20 74  aSuggestions = t
9840: 75 70 6c 65 28 6c 53 75 67 67 29 0a 20 20 20 20  uple(lSugg).    
9850: 20 20 20 20 20 20 20 20 69 66 20 73 55 52 4c 3a          if sURL:
9860: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9870: 20 78 50 72 6f 70 65 72 74 79 20 3d 20 50 72 6f   xProperty = Pro
9880: 70 65 72 74 79 56 61 6c 75 65 28 29 0a 20 20 20  pertyValue().   
9890: 20 20 20 20 20 20 20 20 20 20 20 20 20 78 50 72               xPr
98a0: 6f 70 65 72 74 79 2e 4e 61 6d 65 20 3d 20 22 46  operty.Name = "F
98b0: 75 6c 6c 43 6f 6d 6d 65 6e 74 55 52 4c 22 0a 20  ullCommentURL". 
98c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 78                 x
98d0: 50 72 6f 70 65 72 74 79 2e 56 61 6c 75 65 20 3d  Property.Value =
98e0: 20 73 55 52 4c 0a 20 20 20 20 20 20 20 20 20 20   sURL.          
98f0: 20 20 20 20 20 20 78 45 72 72 2e 61 50 72 6f 70        xErr.aProp
9900: 65 72 74 69 65 73 20 3d 20 28 78 50 72 6f 70 65  erties = (xPrope
9910: 72 74 79 2c 29 0a 20 20 20 20 20 20 20 20 20 20  rty,).          
9920: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
9930: 20 20 20 20 20 20 20 20 78 45 72 72 2e 61 50 72          xErr.aPr
9940: 6f 70 65 72 74 69 65 73 20 3d 20 28 29 0a 20 20  operties = ().  
9950: 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72 6e            return
9960: 20 78 45 72 72 0a 20 20 20 20 20 20 20 20 65 6c   xErr.        el
9970: 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
9980: 64 45 72 72 20 3d 20 7b 7d 0a 20 20 20 20 20 20  dErr = {}.      
9990: 20 20 20 20 20 20 64 45 72 72 5b 22 6e 53 74 61        dErr["nSta
99a0: 72 74 22 5d 20 3d 20 6e 53 74 61 72 74 0a 20 20  rt"] = nStart.  
99b0: 20 20 20 20 20 20 20 20 20 20 64 45 72 72 5b 22            dErr["
99c0: 6e 45 6e 64 22 5d 20 3d 20 6e 45 6e 64 0a 20 20  nEnd"] = nEnd.  
99d0: 20 20 20 20 20 20 20 20 20 20 64 45 72 72 5b 22            dErr["
99e0: 73 4c 69 6e 65 49 64 22 5d 20 3d 20 73 4c 69 6e  sLineId"] = sLin
99f0: 65 49 64 0a 20 20 20 20 20 20 20 20 20 20 20 20  eId.            
9a00: 64 45 72 72 5b 22 73 52 75 6c 65 49 64 22 5d 20  dErr["sRuleId"] 
9a10: 3d 20 73 52 75 6c 65 49 64 0a 20 20 20 20 20 20  = sRuleId.      
9a20: 20 20 20 20 20 20 64 45 72 72 5b 22 73 54 79 70        dErr["sTyp
9a30: 65 22 5d 20 3d 20 73 4f 70 74 69 6f 6e 20 20 69  e"] = sOption  i
9a40: 66 20 73 4f 70 74 69 6f 6e 20 20 65 6c 73 65 20  f sOption  else 
9a50: 22 6e 6f 74 79 70 65 22 0a 20 20 20 20 20 20 20  "notype".       
9a60: 20 20 20 20 20 64 45 72 72 5b 22 73 4d 65 73 73       dErr["sMess
9a70: 61 67 65 22 5d 20 3d 20 73 4d 65 73 73 61 67 65  age"] = sMessage
9a80: 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 45 72  .            dEr
9a90: 72 5b 22 61 53 75 67 67 65 73 74 69 6f 6e 73 22  r["aSuggestions"
9aa0: 5d 20 3d 20 6c 53 75 67 67 0a 20 20 20 20 20 20  ] = lSugg.      
9ab0: 20 20 20 20 20 20 64 45 72 72 5b 22 55 52 4c 22        dErr["URL"
9ac0: 5d 20 3d 20 73 55 52 4c 20 20 69 66 20 73 55 52  ] = sURL  if sUR
9ad0: 4c 20 20 65 6c 73 65 20 22 22 0a 20 20 20 20 20  L  else "".     
9ae0: 20 20 20 20 20 20 20 69 66 20 62 43 6f 6e 74 65         if bConte
9af0: 78 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  xt:.            
9b00: 20 20 20 20 64 45 72 72 5b 27 73 55 6e 64 65 72      dErr['sUnder
9b10: 6c 69 6e 65 64 27 5d 20 3d 20 73 65 6c 66 2e 73  lined'] = self.s
9b20: 53 65 6e 74 65 6e 63 65 30 5b 6e 53 74 61 72 74  Sentence0[nStart
9b30: 3a 6e 45 6e 64 5d 0a 20 20 20 20 20 20 20 20 20  :nEnd].         
9b40: 20 20 20 20 20 20 20 64 45 72 72 5b 27 73 42 65         dErr['sBe
9b50: 66 6f 72 65 27 5d 20 3d 20 73 65 6c 66 2e 73 53  fore'] = self.sS
9b60: 65 6e 74 65 6e 63 65 30 5b 6d 61 78 28 30 2c 6e  entence0[max(0,n
9b70: 53 74 61 72 74 2d 38 30 29 3a 6e 53 74 61 72 74  Start-80):nStart
9b80: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ].              
9b90: 20 20 64 45 72 72 5b 27 73 41 66 74 65 72 27 5d    dErr['sAfter']
9ba0: 20 3d 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63   = self.sSentenc
9bb0: 65 30 5b 6e 45 6e 64 3a 6e 45 6e 64 2b 38 30 5d  e0[nEnd:nEnd+80]
9bc0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
9bd0: 75 72 6e 20 64 45 72 72 0a 0a 20 20 20 20 64 65  urn dErr..    de
9be0: 66 20 5f 65 78 70 61 6e 64 20 28 73 65 6c 66 2c  f _expand (self,
9bf0: 20 73 54 65 78 74 2c 20 6e 54 6f 6b 65 6e 4f 66   sText, nTokenOf
9c00: 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e  fset, nLastToken
9c10: 29 3a 0a 20 20 20 20 20 20 20 20 23 70 72 69 6e  ):.        #prin
9c20: 74 28 22 2a 22 2c 20 73 54 65 78 74 29 0a 20 20  t("*", sText).  
9c30: 20 20 20 20 20 20 66 6f 72 20 6d 20 69 6e 20 72        for m in r
9c40: 65 2e 66 69 6e 64 69 74 65 72 28 72 22 5c 5c 28  e.finditer(r"\\(
9c50: 2d 3f 5b 30 2d 39 5d 2b 29 22 2c 20 73 54 65 78  -?[0-9]+)", sTex
9c60: 74 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  t):.            
9c70: 69 66 20 6d 2e 67 72 6f 75 70 28 31 29 5b 30 3a  if m.group(1)[0:
9c80: 31 5d 20 3d 3d 20 22 2d 22 3a 0a 20 20 20 20 20  1] == "-":.     
9c90: 20 20 20 20 20 20 20 20 20 20 20 73 54 65 78 74             sText
9ca0: 20 3d 20 73 54 65 78 74 2e 72 65 70 6c 61 63 65   = sText.replace
9cb0: 28 6d 2e 67 72 6f 75 70 28 30 29 2c 20 73 65 6c  (m.group(0), sel
9cc0: 66 2e 6c 54 6f 6b 65 6e 5b 6e 4c 61 73 74 54 6f  f.lToken[nLastTo
9cd0: 6b 65 6e 2b 69 6e 74 28 6d 2e 67 72 6f 75 70 28  ken+int(m.group(
9ce0: 31 29 29 2b 31 5d 5b 22 73 56 61 6c 75 65 22 5d  1))+1]["sValue"]
9cf0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 65 6c  ).            el
9d00: 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
9d10: 20 20 20 20 73 54 65 78 74 20 3d 20 73 54 65 78      sText = sTex
9d20: 74 2e 72 65 70 6c 61 63 65 28 6d 2e 67 72 6f 75  t.replace(m.grou
9d30: 70 28 30 29 2c 20 73 65 6c 66 2e 6c 54 6f 6b 65  p(0), self.lToke
9d40: 6e 5b 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2b 69  n[nTokenOffset+i
9d50: 6e 74 28 6d 2e 67 72 6f 75 70 28 31 29 29 5d 5b  nt(m.group(1))][
9d60: 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20 20  "sValue"]).     
9d70: 20 20 20 23 70 72 69 6e 74 28 22 3e 22 2c 20 73     #print(">", s
9d80: 54 65 78 74 29 0a 20 20 20 20 20 20 20 20 72 65  Text).        re
9d90: 74 75 72 6e 20 73 54 65 78 74 0a 0a 20 20 20 20  turn sText..    
9da0: 64 65 66 20 5f 74 61 67 41 6e 64 50 72 65 70 61  def _tagAndPrepa
9db0: 72 65 54 6f 6b 65 6e 46 6f 72 52 65 77 72 69 74  reTokenForRewrit
9dc0: 69 6e 67 20 28 73 65 6c 66 2c 20 73 57 68 61 74  ing (self, sWhat
9dd0: 2c 20 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53  , nTokenRewriteS
9de0: 74 61 72 74 2c 20 6e 54 6f 6b 65 6e 52 65 77 72  tart, nTokenRewr
9df0: 69 74 65 45 6e 64 2c 20 6e 54 6f 6b 65 6e 4f 66  iteEnd, nTokenOf
9e00: 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f 6b 65 6e  fset, nLastToken
9e10: 2c 20 62 43 61 73 65 53 76 74 79 2c 20 62 44 65  , bCaseSvty, bDe
9e20: 62 75 67 29 3a 0a 20 20 20 20 20 20 20 20 22 74  bug):.        "t
9e30: 65 78 74 20 70 72 6f 63 65 73 73 6f 72 3a 20 72  ext processor: r
9e40: 65 77 72 69 74 65 20 74 6f 6b 65 6e 73 20 62 65  ewrite tokens be
9e50: 74 77 65 65 6e 20 3c 6e 54 6f 6b 65 6e 52 65 77  tween <nTokenRew
9e60: 72 69 74 65 53 74 61 72 74 3e 20 61 6e 64 20 3c  riteStart> and <
9e70: 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 45 6e 64  nTokenRewriteEnd
9e80: 3e 20 70 6f 73 69 74 69 6f 6e 22 0a 20 20 20 20  > position".    
9e90: 20 20 20 20 69 66 20 62 44 65 62 75 67 3a 0a 20      if bDebug:. 
9ea0: 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74             print
9eb0: 28 22 20 20 20 53 54 41 52 54 3a 22 2c 20 6e 54  ("   START:", nT
9ec0: 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72 74  okenRewriteStart
9ed0: 2c 20 22 45 4e 44 3a 22 2c 20 6e 54 6f 6b 65 6e  , "END:", nToken
9ee0: 52 65 77 72 69 74 65 45 6e 64 29 0a 20 20 20 20  RewriteEnd).    
9ef0: 20 20 20 20 69 66 20 73 57 68 61 74 20 3d 3d 20      if sWhat == 
9f00: 22 2a 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20  "*":.           
9f10: 20 23 20 70 75 72 67 65 20 74 65 78 74 0a 20 20   # purge text.  
9f20: 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 54 6f            if nTo
9f30: 6b 65 6e 52 65 77 72 69 74 65 45 6e 64 20 2d 20  kenRewriteEnd - 
9f40: 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61  nTokenRewriteSta
9f50: 72 74 20 3d 3d 20 30 3a 0a 20 20 20 20 20 20 20  rt == 0:.       
9f60: 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c 54           self.lT
9f70: 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 52 65 77 72 69  oken[nTokenRewri
9f80: 74 65 53 74 61 72 74 5d 5b 22 62 54 6f 52 65 6d  teStart]["bToRem
9f90: 6f 76 65 22 5d 20 3d 20 54 72 75 65 0a 20 20 20  ove"] = True.   
9fa0: 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20           else:. 
9fb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66                 f
9fc0: 6f 72 20 69 20 69 6e 20 72 61 6e 67 65 28 6e 54  or i in range(nT
9fd0: 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72 74  okenRewriteStart
9fe0: 2c 20 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 45  , nTokenRewriteE
9ff0: 6e 64 2b 31 29 3a 0a 20 20 20 20 20 20 20 20 20  nd+1):.         
a000: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
a010: 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 62 54 6f 52 65  lToken[i]["bToRe
a020: 6d 6f 76 65 22 5d 20 3d 20 54 72 75 65 0a 20 20  move"] = True.  
a030: 20 20 20 20 20 20 65 6c 69 66 20 73 57 68 61 74        elif sWhat
a040: 20 3d 3d 20 22 e2 90 a3 22 3a 0a 20 20 20 20 20   == "...":.     
a050: 20 20 20 20 20 20 20 23 20 6d 65 72 67 65 20 74         # merge t
a060: 6f 6b 65 6e 73 0a 20 20 20 20 20 20 20 20 20 20  okens.          
a070: 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54    self.lToken[nT
a080: 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72 74  okenRewriteStart
a090: 5d 5b 22 6e 4d 65 72 67 65 55 6e 74 69 6c 22 5d  ]["nMergeUntil"]
a0a0: 20 3d 20 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65   = nTokenRewrite
a0b0: 45 6e 64 0a 20 20 20 20 20 20 20 20 65 6c 69 66  End.        elif
a0c0: 20 73 57 68 61 74 20 3d 3d 20 22 5f 22 3a 0a 20   sWhat == "_":. 
a0d0: 20 20 20 20 20 20 20 20 20 20 20 23 20 6e 65 75             # neu
a0e0: 74 72 61 6c 69 7a 65 64 20 74 6f 6b 65 6e 0a 20  tralized token. 
a0f0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e 54             if nT
a100: 6f 6b 65 6e 52 65 77 72 69 74 65 45 6e 64 20 2d  okenRewriteEnd -
a110: 20 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74   nTokenRewriteSt
a120: 61 72 74 20 3d 3d 20 30 3a 0a 20 20 20 20 20 20  art == 0:.      
a130: 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e 6c            self.l
a140: 54 6f 6b 65 6e 5b 6e 54 6f 6b 65 6e 52 65 77 72  Token[nTokenRewr
a150: 69 74 65 53 74 61 72 74 5d 5b 22 73 4e 65 77 56  iteStart]["sNewV
a160: 61 6c 75 65 22 5d 20 3d 20 22 5f 22 0a 20 20 20  alue"] = "_".   
a170: 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20           else:. 
a180: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66                 f
a190: 6f 72 20 69 20 69 6e 20 72 61 6e 67 65 28 6e 54  or i in range(nT
a1a0: 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72 74  okenRewriteStart
a1b0: 2c 20 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 45  , nTokenRewriteE
a1c0: 6e 64 2b 31 29 3a 0a 20 20 20 20 20 20 20 20 20  nd+1):.         
a1d0: 20 20 20 20 20 20 20 20 20 20 20 73 65 6c 66 2e             self.
a1e0: 6c 54 6f 6b 65 6e 5b 69 5d 5b 22 73 4e 65 77 56  lToken[i]["sNewV
a1f0: 61 6c 75 65 22 5d 20 3d 20 22 5f 22 0a 20 20 20  alue"] = "_".   
a200: 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20       else:.     
a210: 20 20 20 20 20 20 20 69 66 20 73 57 68 61 74 2e         if sWhat.
a220: 73 74 61 72 74 73 77 69 74 68 28 22 3d 22 29 3a  startswith("="):
a230: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
a240: 20 73 57 68 61 74 20 3d 20 67 6c 6f 62 61 6c 73   sWhat = globals
a250: 28 29 5b 73 57 68 61 74 5b 31 3a 5d 5d 28 73 65  ()[sWhat[1:]](se
a260: 6c 66 2e 6c 54 6f 6b 65 6e 2c 20 6e 54 6f 6b 65  lf.lToken, nToke
a270: 6e 4f 66 66 73 65 74 2c 20 6e 4c 61 73 74 54 6f  nOffset, nLastTo
a280: 6b 65 6e 29 0a 20 20 20 20 20 20 20 20 20 20 20  ken).           
a290: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
a2a0: 20 20 20 20 20 20 20 73 57 68 61 74 20 3d 20 73         sWhat = s
a2b0: 65 6c 66 2e 5f 65 78 70 61 6e 64 28 73 57 68 61  elf._expand(sWha
a2c0: 74 2c 20 6e 54 6f 6b 65 6e 4f 66 66 73 65 74 2c  t, nTokenOffset,
a2d0: 20 6e 4c 61 73 74 54 6f 6b 65 6e 29 0a 20 20 20   nLastToken).   
a2e0: 20 20 20 20 20 20 20 20 20 62 55 70 70 65 72 63           bUpperc
a2f0: 61 73 65 20 3d 20 62 43 61 73 65 53 76 74 79 20  ase = bCaseSvty 
a300: 61 6e 64 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b  and self.lToken[
a310: 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61  nTokenRewriteSta
a320: 72 74 5d 5b 22 73 56 61 6c 75 65 22 5d 5b 30 3a  rt]["sValue"][0:
a330: 31 5d 2e 69 73 75 70 70 65 72 28 29 0a 20 20 20  1].isupper().   
a340: 20 20 20 20 20 20 20 20 20 69 66 20 6e 54 6f 6b           if nTok
a350: 65 6e 52 65 77 72 69 74 65 45 6e 64 20 2d 20 6e  enRewriteEnd - n
a360: 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74 61 72  TokenRewriteStar
a370: 74 20 3d 3d 20 30 3a 0a 20 20 20 20 20 20 20 20  t == 0:.        
a380: 20 20 20 20 20 20 20 20 23 20 6f 6e 65 20 74 6f          # one to
a390: 6b 65 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20  ken.            
a3a0: 20 20 20 20 73 57 68 61 74 20 3d 20 73 57 68 61      sWhat = sWha
a3b0: 74 20 2b 20 22 20 22 20 2a 20 28 6c 65 6e 28 73  t + " " * (len(s
a3c0: 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b 65  elf.lToken[nToke
a3d0: 6e 52 65 77 72 69 74 65 53 74 61 72 74 5d 5b 22  nRewriteStart]["
a3e0: 73 56 61 6c 75 65 22 5d 29 2d 6c 65 6e 28 73 57  sValue"])-len(sW
a3f0: 68 61 74 29 29 0a 20 20 20 20 20 20 20 20 20 20  hat)).          
a400: 20 20 20 20 20 20 69 66 20 62 55 70 70 65 72 63        if bUpperc
a410: 61 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ase:.           
a420: 20 20 20 20 20 20 20 20 20 73 57 68 61 74 20 3d           sWhat =
a430: 20 73 57 68 61 74 5b 30 3a 31 5d 2e 75 70 70 65   sWhat[0:1].uppe
a440: 72 28 29 20 2b 20 73 57 68 61 74 5b 31 3a 5d 0a  r() + sWhat[1:].
a450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a460: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b 6e 54 6f 6b  self.lToken[nTok
a470: 65 6e 52 65 77 72 69 74 65 53 74 61 72 74 5d 5b  enRewriteStart][
a480: 22 73 4e 65 77 56 61 6c 75 65 22 5d 20 3d 20 73  "sNewValue"] = s
a490: 57 68 61 74 0a 20 20 20 20 20 20 20 20 20 20 20  What.           
a4a0: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
a4b0: 20 20 20 20 20 20 20 23 20 73 65 76 65 72 61 6c         # several
a4c0: 20 74 6f 6b 65 6e 73 0a 20 20 20 20 20 20 20 20   tokens.        
a4d0: 20 20 20 20 20 20 20 20 6c 54 6f 6b 65 6e 56 61          lTokenVa
a4e0: 6c 75 65 20 3d 20 73 57 68 61 74 2e 73 70 6c 69  lue = sWhat.spli
a4f0: 74 28 22 7c 22 29 0a 20 20 20 20 20 20 20 20 20  t("|").         
a500: 20 20 20 20 20 20 20 69 66 20 6c 65 6e 28 6c 54         if len(lT
a510: 6f 6b 65 6e 56 61 6c 75 65 29 20 21 3d 20 28 6e  okenValue) != (n
a520: 54 6f 6b 65 6e 52 65 77 72 69 74 65 45 6e 64 20  TokenRewriteEnd 
a530: 2d 20 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53  - nTokenRewriteS
a540: 74 61 72 74 20 2b 20 31 29 3a 0a 20 20 20 20 20  tart + 1):.     
a550: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
a560: 72 69 6e 74 28 22 45 72 72 6f 72 2e 20 54 65 78  rint("Error. Tex
a570: 74 20 70 72 6f 63 65 73 73 6f 72 3a 20 6e 75 6d  t processor: num
a580: 62 65 72 20 6f 66 20 72 65 70 6c 61 63 65 6d 65  ber of replaceme
a590: 6e 74 73 20 21 3d 20 6e 75 6d 62 65 72 20 6f 66  nts != number of
a5a0: 20 74 6f 6b 65 6e 73 2e 22 29 0a 20 20 20 20 20   tokens.").     
a5b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72                 r
a5c0: 65 74 75 72 6e 0a 20 20 20 20 20 20 20 20 20 20  eturn.          
a5d0: 20 20 20 20 20 20 66 6f 72 20 69 2c 20 73 56 61        for i, sVa
a5e0: 6c 75 65 20 69 6e 20 7a 69 70 28 72 61 6e 67 65  lue in zip(range
a5f0: 28 6e 54 6f 6b 65 6e 52 65 77 72 69 74 65 53 74  (nTokenRewriteSt
a600: 61 72 74 2c 20 6e 54 6f 6b 65 6e 52 65 77 72 69  art, nTokenRewri
a610: 74 65 45 6e 64 2b 31 29 2c 20 6c 54 6f 6b 65 6e  teEnd+1), lToken
a620: 56 61 6c 75 65 29 3a 0a 20 20 20 20 20 20 20 20  Value):.        
a630: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 6e              if n
a640: 6f 74 20 73 56 61 6c 75 65 20 6f 72 20 73 56 61  ot sValue or sVa
a650: 6c 75 65 20 3d 3d 20 22 2a 22 3a 0a 20 20 20 20  lue == "*":.    
a660: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a670: 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 5b      self.lToken[
a680: 69 5d 5b 22 62 54 6f 52 65 6d 6f 76 65 22 5d 20  i]["bToRemove"] 
a690: 3d 20 54 72 75 65 0a 20 20 20 20 20 20 20 20 20  = True.         
a6a0: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
a6b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
a6c0: 20 20 20 20 20 20 20 20 20 69 66 20 62 55 70 70           if bUpp
a6d0: 65 72 63 61 73 65 3a 0a 20 20 20 20 20 20 20 20  ercase:.        
a6e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a6f0: 20 20 20 20 73 56 61 6c 75 65 20 3d 20 73 56 61      sValue = sVa
a700: 6c 75 65 5b 30 3a 31 5d 2e 75 70 70 65 72 28 29  lue[0:1].upper()
a710: 20 2b 20 73 56 61 6c 75 65 5b 31 3a 5d 0a 20 20   + sValue[1:].  
a720: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a730: 20 20 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65        self.lToke
a740: 6e 5b 69 5d 5b 22 73 4e 65 77 56 61 6c 75 65 22  n[i]["sNewValue"
a750: 5d 20 3d 20 73 56 61 6c 75 65 0a 0a 20 20 20 20  ] = sValue..    
a760: 64 65 66 20 72 65 77 72 69 74 65 20 28 73 65 6c  def rewrite (sel
a770: 66 2c 20 62 44 65 62 75 67 3d 46 61 6c 73 65 29  f, bDebug=False)
a780: 3a 0a 20 20 20 20 20 20 20 20 22 72 65 77 72 69  :.        "rewri
a790: 74 65 20 74 68 65 20 73 65 6e 74 65 6e 63 65 2c  te the sentence,
a7a0: 20 6d 6f 64 69 66 79 20 74 6f 6b 65 6e 73 2c 20   modify tokens, 
a7b0: 70 75 72 67 65 20 74 68 65 20 74 6f 6b 65 6e 20  purge the token 
a7c0: 6c 69 73 74 22 0a 20 20 20 20 20 20 20 20 69 66  list".        if
a7d0: 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20 20   bDebug:.       
a7e0: 20 20 20 20 20 70 72 69 6e 74 28 22 52 45 57 52       print("REWR
a7f0: 49 54 45 22 29 0a 20 20 20 20 20 20 20 20 6c 4e  ITE").        lN
a800: 65 77 54 6f 6b 65 6e 20 3d 20 5b 5d 0a 20 20 20  ewToken = [].   
a810: 20 20 20 20 20 6e 4d 65 72 67 65 55 6e 74 69 6c       nMergeUntil
a820: 20 3d 20 30 0a 20 20 20 20 20 20 20 20 64 54 6f   = 0.        dTo
a830: 6b 65 6e 4d 65 72 67 65 72 20 3d 20 4e 6f 6e 65  kenMerger = None
a840: 0a 20 20 20 20 20 20 20 20 66 6f 72 20 69 54 6f  .        for iTo
a850: 6b 65 6e 2c 20 64 54 6f 6b 65 6e 20 69 6e 20 65  ken, dToken in e
a860: 6e 75 6d 65 72 61 74 65 28 73 65 6c 66 2e 6c 54  numerate(self.lT
a870: 6f 6b 65 6e 29 3a 0a 20 20 20 20 20 20 20 20 20  oken):.         
a880: 20 20 20 62 4b 65 65 70 54 6f 6b 65 6e 20 3d 20     bKeepToken = 
a890: 54 72 75 65 0a 20 20 20 20 20 20 20 20 20 20 20  True.           
a8a0: 20 69 66 20 64 54 6f 6b 65 6e 5b 22 73 54 79 70   if dToken["sTyp
a8b0: 65 22 5d 20 21 3d 20 22 49 4e 46 4f 22 3a 0a 20  e"] != "INFO":. 
a8c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
a8d0: 66 20 6e 4d 65 72 67 65 55 6e 74 69 6c 20 61 6e  f nMergeUntil an
a8e0: 64 20 69 54 6f 6b 65 6e 20 3c 3d 20 6e 4d 65 72  d iToken <= nMer
a8f0: 67 65 55 6e 74 69 6c 3a 0a 20 20 20 20 20 20 20  geUntil:.       
a900: 20 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f               dTo
a910: 6b 65 6e 4d 65 72 67 65 72 5b 22 73 56 61 6c 75  kenMerger["sValu
a920: 65 22 5d 20 2b 3d 20 22 20 22 20 2a 20 28 64 54  e"] += " " * (dT
a930: 6f 6b 65 6e 5b 22 6e 53 74 61 72 74 22 5d 20 2d  oken["nStart"] -
a940: 20 64 54 6f 6b 65 6e 4d 65 72 67 65 72 5b 22 6e   dTokenMerger["n
a950: 45 6e 64 22 5d 29 20 2b 20 64 54 6f 6b 65 6e 5b  End"]) + dToken[
a960: 22 73 56 61 6c 75 65 22 5d 0a 20 20 20 20 20 20  "sValue"].      
a970: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64 54                dT
a980: 6f 6b 65 6e 4d 65 72 67 65 72 5b 22 6e 45 6e 64  okenMerger["nEnd
a990: 22 5d 20 3d 20 64 54 6f 6b 65 6e 5b 22 6e 45 6e  "] = dToken["nEn
a9a0: 64 22 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20  d"].            
a9b0: 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62 75          if bDebu
a9c0: 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  g:.             
a9d0: 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74             print
a9e0: 28 22 20 20 4d 45 52 47 45 44 20 54 4f 4b 45 4e  ("  MERGED TOKEN
a9f0: 3a 22 2c 20 64 54 6f 6b 65 6e 4d 65 72 67 65 72  :", dTokenMerger
aa00: 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20 20 20  ["sValue"]).    
aa10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
aa20: 62 4b 65 65 70 54 6f 6b 65 6e 20 3d 20 46 61 6c  bKeepToken = Fal
aa30: 73 65 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  se.             
aa40: 20 20 20 69 66 20 22 6e 4d 65 72 67 65 55 6e 74     if "nMergeUnt
aa50: 69 6c 22 20 69 6e 20 64 54 6f 6b 65 6e 3a 0a 20  il" in dToken:. 
aa60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
aa70: 20 20 20 69 66 20 69 54 6f 6b 65 6e 20 3e 20 6e     if iToken > n
aa80: 4d 65 72 67 65 55 6e 74 69 6c 3a 20 23 20 74 68  MergeUntil: # th
aa90: 69 73 20 74 6f 6b 65 6e 20 69 73 20 6e 6f 74 20  is token is not 
aaa0: 61 6c 72 65 61 64 79 20 6d 65 72 67 65 64 20 77  already merged w
aab0: 69 74 68 20 61 20 70 72 65 76 69 6f 75 73 20 74  ith a previous t
aac0: 6f 6b 65 6e 0a 20 20 20 20 20 20 20 20 20 20 20  oken.           
aad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f               dTo
aae0: 6b 65 6e 4d 65 72 67 65 72 20 3d 20 64 54 6f 6b  kenMerger = dTok
aaf0: 65 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  en.             
ab00: 20 20 20 20 20 20 20 69 66 20 64 54 6f 6b 65 6e         if dToken
ab10: 5b 22 6e 4d 65 72 67 65 55 6e 74 69 6c 22 5d 20  ["nMergeUntil"] 
ab20: 3e 20 6e 4d 65 72 67 65 55 6e 74 69 6c 3a 0a 20  > nMergeUntil:. 
ab30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
ab40: 20 20 20 20 20 20 20 6e 4d 65 72 67 65 55 6e 74         nMergeUnt
ab50: 69 6c 20 3d 20 64 54 6f 6b 65 6e 5b 22 6e 4d 65  il = dToken["nMe
ab60: 72 67 65 55 6e 74 69 6c 22 5d 0a 20 20 20 20 20  rgeUntil"].     
ab70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 64                 d
ab80: 65 6c 20 64 54 6f 6b 65 6e 5b 22 6e 4d 65 72 67  el dToken["nMerg
ab90: 65 55 6e 74 69 6c 22 5d 0a 20 20 20 20 20 20 20  eUntil"].       
aba0: 20 20 20 20 20 20 20 20 20 65 6c 69 66 20 22 62           elif "b
abb0: 54 6f 52 65 6d 6f 76 65 22 20 69 6e 20 64 54 6f  ToRemove" in dTo
abc0: 6b 65 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20  ken:.           
abd0: 20 20 20 20 20 20 20 20 20 69 66 20 62 44 65 62           if bDeb
abe0: 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ug:.            
abf0: 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e              prin
ac00: 74 28 22 20 20 52 45 4d 4f 56 45 44 3a 22 2c 20  t("  REMOVED:", 
ac10: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
ac20: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ).              
ac30: 20 20 20 20 20 20 73 65 6c 66 2e 73 53 65 6e 74        self.sSent
ac40: 65 6e 63 65 20 3d 20 73 65 6c 66 2e 73 53 65 6e  ence = self.sSen
ac50: 74 65 6e 63 65 5b 3a 64 54 6f 6b 65 6e 5b 22 6e  tence[:dToken["n
ac60: 53 74 61 72 74 22 5d 5d 20 2b 20 22 20 22 20 2a  Start"]] + " " *
ac70: 20 28 64 54 6f 6b 65 6e 5b 22 6e 45 6e 64 22 5d   (dToken["nEnd"]
ac80: 20 2d 20 64 54 6f 6b 65 6e 5b 22 6e 53 74 61 72   - dToken["nStar
ac90: 74 22 5d 29 20 2b 20 73 65 6c 66 2e 73 53 65 6e  t"]) + self.sSen
aca0: 74 65 6e 63 65 5b 64 54 6f 6b 65 6e 5b 22 6e 45  tence[dToken["nE
acb0: 6e 64 22 5d 3a 5d 0a 20 20 20 20 20 20 20 20 20  nd"]:].         
acc0: 20 20 20 20 20 20 20 20 20 20 20 62 4b 65 65 70             bKeep
acd0: 54 6f 6b 65 6e 20 3d 20 46 61 6c 73 65 0a 20 20  Token = False.  
ace0: 20 20 20 20 20 20 20 20 20 20 23 0a 20 20 20 20            #.    
acf0: 20 20 20 20 20 20 20 20 69 66 20 62 4b 65 65 70          if bKeep
ad00: 54 6f 6b 65 6e 3a 0a 20 20 20 20 20 20 20 20 20  Token:.         
ad10: 20 20 20 20 20 20 20 6c 4e 65 77 54 6f 6b 65 6e         lNewToken
ad20: 2e 61 70 70 65 6e 64 28 64 54 6f 6b 65 6e 29 0a  .append(dToken).
ad30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
ad40: 69 66 20 22 73 4e 65 77 56 61 6c 75 65 22 20 69  if "sNewValue" i
ad50: 6e 20 64 54 6f 6b 65 6e 3a 0a 20 20 20 20 20 20  n dToken:.      
ad60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20                # 
ad70: 72 65 77 72 69 74 65 20 74 6f 6b 65 6e 20 61 6e  rewrite token an
ad80: 64 20 73 65 6e 74 65 6e 63 65 0a 20 20 20 20 20  d sentence.     
ad90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 69                 i
ada0: 66 20 62 44 65 62 75 67 3a 0a 20 20 20 20 20 20  f bDebug:.      
adb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
adc0: 20 20 70 72 69 6e 74 28 64 54 6f 6b 65 6e 5b 22    print(dToken["
add0: 73 56 61 6c 75 65 22 5d 2c 20 22 2d 3e 22 2c 20  sValue"], "->", 
ade0: 64 54 6f 6b 65 6e 5b 22 73 4e 65 77 56 61 6c 75  dToken["sNewValu
adf0: 65 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20  e"]).           
ae00: 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e 5b           dToken[
ae10: 22 73 52 65 61 6c 56 61 6c 75 65 22 5d 20 3d 20  "sRealValue"] = 
ae20: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
ae30: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
ae40: 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22 73 56 61       dToken["sVa
ae50: 6c 75 65 22 5d 20 3d 20 64 54 6f 6b 65 6e 5b 22  lue"] = dToken["
ae60: 73 4e 65 77 56 61 6c 75 65 22 5d 0a 20 20 20 20  sNewValue"].    
ae70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
ae80: 6e 44 69 66 66 4c 65 6e 20 3d 20 6c 65 6e 28 64  nDiffLen = len(d
ae90: 54 6f 6b 65 6e 5b 22 73 52 65 61 6c 56 61 6c 75  Token["sRealValu
aea0: 65 22 5d 29 20 2d 20 6c 65 6e 28 64 54 6f 6b 65  e"]) - len(dToke
aeb0: 6e 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d 29 0a  n["sNewValue"]).
aec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
aed0: 20 20 20 20 73 4e 65 77 52 65 70 6c 20 3d 20 28      sNewRepl = (
aee0: 64 54 6f 6b 65 6e 5b 22 73 4e 65 77 56 61 6c 75  dToken["sNewValu
aef0: 65 22 5d 20 2b 20 22 20 22 20 2a 20 6e 44 69 66  e"] + " " * nDif
af00: 66 4c 65 6e 29 20 20 69 66 20 6e 44 69 66 66 4c  fLen)  if nDiffL
af10: 65 6e 20 3e 3d 20 30 20 20 65 6c 73 65 20 64 54  en >= 0  else dT
af20: 6f 6b 65 6e 5b 22 73 4e 65 77 56 61 6c 75 65 22  oken["sNewValue"
af30: 5d 5b 3a 6c 65 6e 28 64 54 6f 6b 65 6e 5b 22 73  ][:len(dToken["s
af40: 52 65 61 6c 56 61 6c 75 65 22 5d 29 5d 0a 20 20  RealValue"])].  
af50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
af60: 20 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65    self.sSentence
af70: 20 3d 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63   = self.sSentenc
af80: 65 5b 3a 64 54 6f 6b 65 6e 5b 22 6e 53 74 61 72  e[:dToken["nStar
af90: 74 22 5d 5d 20 2b 20 73 4e 65 77 52 65 70 6c 20  t"]] + sNewRepl 
afa0: 2b 20 73 65 6c 66 2e 73 53 65 6e 74 65 6e 63 65  + self.sSentence
afb0: 5b 64 54 6f 6b 65 6e 5b 22 6e 45 6e 64 22 5d 3a  [dToken["nEnd"]:
afc0: 5d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ].              
afd0: 20 20 20 20 20 20 64 65 6c 20 64 54 6f 6b 65 6e        del dToken
afe0: 5b 22 73 4e 65 77 56 61 6c 75 65 22 5d 0a 20 20  ["sNewValue"].  
aff0: 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a            else:.
b000: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b010: 74 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20  try:.           
b020: 20 20 20 20 20 20 20 20 20 64 65 6c 20 73 65 6c           del sel
b030: 66 2e 64 54 6f 6b 65 6e 50 6f 73 5b 64 54 6f 6b  f.dTokenPos[dTok
b040: 65 6e 5b 22 6e 53 74 61 72 74 22 5d 5d 0a 20 20  en["nStart"]].  
b050: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 65 78                ex
b060: 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20 20 20  cept:.          
b070: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28            print(
b080: 73 65 6c 66 29 0a 20 20 20 20 20 20 20 20 20 20  self).          
b090: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28            print(
b0a0: 64 54 6f 6b 65 6e 29 0a 20 20 20 20 20 20 20 20  dToken).        
b0b0: 20 20 20 20 20 20 20 20 20 20 20 20 65 78 69 74              exit
b0c0: 28 29 0a 20 20 20 20 20 20 20 20 69 66 20 62 44  ().        if bD
b0d0: 65 62 75 67 3a 0a 20 20 20 20 20 20 20 20 20 20  ebug:.          
b0e0: 20 20 70 72 69 6e 74 28 22 20 20 54 45 58 54 20    print("  TEXT 
b0f0: 52 45 57 52 49 54 45 44 3a 22 2c 20 73 65 6c 66  REWRITED:", self
b100: 2e 73 53 65 6e 74 65 6e 63 65 29 0a 20 20 20 20  .sSentence).    
b110: 20 20 20 20 73 65 6c 66 2e 6c 54 6f 6b 65 6e 2e      self.lToken.
b120: 63 6c 65 61 72 28 29 0a 20 20 20 20 20 20 20 20  clear().        
b130: 73 65 6c 66 2e 6c 54 6f 6b 65 6e 20 3d 20 6c 4e  self.lToken = lN
b140: 65 77 54 6f 6b 65 6e 0a 0a 0a 0a 23 23 23 23 20  ewToken....#### 
b150: 41 6e 61 6c 79 73 65 20 74 6f 6b 65 6e 73 0a 0a  Analyse tokens..
b160: 64 65 66 20 67 5f 76 61 6c 75 65 20 28 64 54 6f  def g_value (dTo
b170: 6b 65 6e 2c 20 73 56 61 6c 75 65 73 2c 20 6e 4c  ken, sValues, nL
b180: 65 66 74 3d 4e 6f 6e 65 2c 20 6e 52 69 67 68 74  eft=None, nRight
b190: 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 74 65 73  =None):.    "tes
b1a0: 74 20 69 66 20 3c 64 54 6f 6b 65 6e 5b 27 73 56  t if <dToken['sV
b1b0: 61 6c 75 65 27 5d 3e 20 69 73 20 69 6e 20 73 56  alue']> is in sV
b1c0: 61 6c 75 65 73 20 28 65 61 63 68 20 76 61 6c 75  alues (each valu
b1d0: 65 20 73 68 6f 75 6c 64 20 62 65 20 73 65 70 61  e should be sepa
b1e0: 72 61 74 65 64 20 77 69 74 68 20 7c 29 22 0a 20  rated with |)". 
b1f0: 20 20 20 73 56 61 6c 75 65 20 3d 20 22 7c 22 2b     sValue = "|"+
b200: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
b210: 2b 22 7c 22 20 20 69 66 20 6e 4c 65 66 74 20 69  +"|"  if nLeft i
b220: 73 20 4e 6f 6e 65 20 20 65 6c 73 65 20 22 7c 22  s None  else "|"
b230: 2b 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22  +dToken["sValue"
b240: 5d 5b 73 6c 69 63 65 28 6e 4c 65 66 74 2c 20 6e  ][slice(nLeft, n
b250: 52 69 67 68 74 29 5d 2b 22 7c 22 0a 20 20 20 20  Right)]+"|".    
b260: 69 66 20 73 56 61 6c 75 65 20 69 6e 20 73 56 61  if sValue in sVa
b270: 6c 75 65 73 3a 0a 20 20 20 20 20 20 20 20 72 65  lues:.        re
b280: 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 69 66  turn True.    if
b290: 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22   dToken["sValue"
b2a0: 5d 5b 30 3a 32 5d 2e 69 73 74 69 74 6c 65 28 29  ][0:2].istitle()
b2b0: 3a 20 23 20 77 65 20 74 65 73 74 20 6f 6e 6c 79  : # we test only
b2c0: 20 32 20 66 69 72 73 74 20 63 68 61 72 73 2c 20   2 first chars, 
b2d0: 74 6f 20 6d 61 6b 65 20 76 61 6c 69 64 20 77 6f  to make valid wo
b2e0: 72 64 73 20 73 75 63 68 20 61 73 20 22 4c 61 69  rds such as "Lai
b2f0: 73 73 65 7a 2d 6c 65 73 22 2c 20 22 50 61 73 73  ssez-les", "Pass
b300: 65 2d 70 61 72 74 6f 75 74 22 2e 0a 20 20 20 20  e-partout"..    
b310: 20 20 20 20 69 66 20 73 56 61 6c 75 65 2e 6c 6f      if sValue.lo
b320: 77 65 72 28 29 20 69 6e 20 73 56 61 6c 75 65 73  wer() in sValues
b330: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  :.            re
b340: 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 65 6c  turn True.    el
b350: 69 66 20 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  if dToken["sValu
b360: 65 22 5d 2e 69 73 75 70 70 65 72 28 29 3a 0a 20  e"].isupper():. 
b370: 20 20 20 20 20 20 20 23 69 66 20 73 56 61 6c 75         #if sValu
b380: 65 2e 6c 6f 77 65 72 28 29 20 69 6e 20 73 56 61  e.lower() in sVa
b390: 6c 75 65 73 3a 0a 20 20 20 20 20 20 20 20 23 20  lues:.        # 
b3a0: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
b3b0: 20 20 20 20 20 20 20 73 56 61 6c 75 65 20 3d 20         sValue = 
b3c0: 22 7c 22 2b 73 56 61 6c 75 65 5b 31 3a 5d 2e 63  "|"+sValue[1:].c
b3d0: 61 70 69 74 61 6c 69 7a 65 28 29 0a 20 20 20 20  apitalize().    
b3e0: 20 20 20 20 69 66 20 73 56 61 6c 75 65 2e 63 61      if sValue.ca
b3f0: 70 69 74 61 6c 69 7a 65 28 29 20 69 6e 20 73 56  pitalize() in sV
b400: 61 6c 75 65 73 3a 0a 20 20 20 20 20 20 20 20 20  alues:.         
b410: 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a 20     return True. 
b420: 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a     return False.
b430: 0a 0a 64 65 66 20 67 5f 6d 6f 72 70 68 20 28 64  ..def g_morph (d
b440: 54 6f 6b 65 6e 2c 20 73 50 61 74 74 65 72 6e 2c  Token, sPattern,
b450: 20 73 4e 65 67 50 61 74 74 65 72 6e 3d 22 22 2c   sNegPattern="",
b460: 20 6e 4c 65 66 74 3d 4e 6f 6e 65 2c 20 6e 52 69   nLeft=None, nRi
b470: 67 68 74 3d 4e 6f 6e 65 2c 20 62 4d 65 6d 6f 72  ght=None, bMemor
b480: 69 7a 65 4d 6f 72 70 68 3d 54 72 75 65 29 3a 0a  izeMorph=True):.
b490: 20 20 20 20 22 61 6e 61 6c 79 73 65 20 61 20 74      "analyse a t
b4a0: 6f 6b 65 6e 2c 20 72 65 74 75 72 6e 20 54 72 75  oken, return Tru
b4b0: 65 20 69 66 20 3c 73 4e 65 67 50 61 74 74 65 72  e if <sNegPatter
b4c0: 6e 3e 20 6e 6f 74 20 69 6e 20 6d 6f 72 70 68 6f  n> not in morpho
b4d0: 6c 6f 67 69 65 73 20 61 6e 64 20 3c 73 50 61 74  logies and <sPat
b4e0: 74 65 72 6e 3e 20 69 6e 20 6d 6f 72 70 68 6f 6c  tern> in morphol
b4f0: 6f 67 69 65 73 22 0a 20 20 20 20 69 66 20 22 6c  ogies".    if "l
b500: 4d 6f 72 70 68 22 20 69 6e 20 64 54 6f 6b 65 6e  Morph" in dToken
b510: 3a 0a 20 20 20 20 20 20 20 20 6c 4d 6f 72 70 68  :.        lMorph
b520: 20 3d 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70   = dToken["lMorp
b530: 68 22 5d 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20  h"].    else:.  
b540: 20 20 20 20 20 20 69 66 20 6e 4c 65 66 74 20 69        if nLeft i
b550: 73 20 6e 6f 74 20 4e 6f 6e 65 3a 0a 20 20 20 20  s not None:.    
b560: 20 20 20 20 20 20 20 20 6c 4d 6f 72 70 68 20 3d          lMorph =
b570: 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e   _oSpellChecker.
b580: 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e 5b  getMorph(dToken[
b590: 22 73 56 61 6c 75 65 22 5d 5b 73 6c 69 63 65 28  "sValue"][slice(
b5a0: 6e 4c 65 66 74 2c 20 6e 52 69 67 68 74 29 5d 29  nLeft, nRight)])
b5b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
b5c0: 62 4d 65 6d 6f 72 69 7a 65 4d 6f 72 70 68 3a 0a  bMemorizeMorph:.
b5d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
b5e0: 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d  dToken["lMorph"]
b5f0: 20 3d 20 6c 4d 6f 72 70 68 0a 20 20 20 20 20 20   = lMorph.      
b600: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
b610: 20 20 20 20 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53      lMorph = _oS
b620: 70 65 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d  pellChecker.getM
b630: 6f 72 70 68 28 64 54 6f 6b 65 6e 5b 22 73 56 61  orph(dToken["sVa
b640: 6c 75 65 22 5d 29 0a 20 20 20 20 69 66 20 6e 6f  lue"]).    if no
b650: 74 20 6c 4d 6f 72 70 68 3a 0a 20 20 20 20 20 20  t lMorph:.      
b660: 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20    return False. 
b670: 20 20 20 23 20 63 68 65 63 6b 20 6e 65 67 61 74     # check negat
b680: 69 76 65 20 63 6f 6e 64 69 74 69 6f 6e 0a 20 20  ive condition.  
b690: 20 20 69 66 20 73 4e 65 67 50 61 74 74 65 72 6e    if sNegPattern
b6a0: 3a 0a 20 20 20 20 20 20 20 20 69 66 20 73 4e 65  :.        if sNe
b6b0: 67 50 61 74 74 65 72 6e 20 3d 3d 20 22 2a 22 3a  gPattern == "*":
b6c0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 20 61  .            # a
b6d0: 6c 6c 20 6d 6f 72 70 68 20 6d 75 73 74 20 6d 61  ll morph must ma
b6e0: 74 63 68 20 73 50 61 74 74 65 72 6e 0a 20 20 20  tch sPattern.   
b6f0: 20 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20           if not 
b700: 6c 4d 6f 72 70 68 3a 0a 20 20 20 20 20 20 20 20  lMorph:.        
b710: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 46          return F
b720: 61 6c 73 65 0a 20 20 20 20 20 20 20 20 20 20 20  alse.           
b730: 20 7a 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63   zPattern = re.c
b740: 6f 6d 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29  ompile(sPattern)
b750: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
b760: 75 72 6e 20 61 6c 6c 28 7a 50 61 74 74 65 72 6e  urn all(zPattern
b770: 2e 73 65 61 72 63 68 28 73 4d 6f 72 70 68 29 20  .search(sMorph) 
b780: 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c   for sMorph in l
b790: 4d 6f 72 70 68 29 0a 20 20 20 20 20 20 20 20 65  Morph).        e
b7a0: 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  lse:.           
b7b0: 20 7a 4e 65 67 50 61 74 74 65 72 6e 20 3d 20 72   zNegPattern = r
b7c0: 65 2e 63 6f 6d 70 69 6c 65 28 73 4e 65 67 50 61  e.compile(sNegPa
b7d0: 74 74 65 72 6e 29 0a 20 20 20 20 20 20 20 20 20  ttern).         
b7e0: 20 20 20 69 66 20 61 6e 79 28 7a 4e 65 67 50 61     if any(zNegPa
b7f0: 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73 4d 6f  ttern.search(sMo
b800: 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70 68  rph)  for sMorph
b810: 20 69 6e 20 6c 4d 6f 72 70 68 29 3a 0a 20 20 20   in lMorph):.   
b820: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74               ret
b830: 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 23 20  urn False.    # 
b840: 73 65 61 72 63 68 20 73 50 61 74 74 65 72 6e 0a  search sPattern.
b850: 20 20 20 20 7a 50 61 74 74 65 72 6e 20 3d 20 72      zPattern = r
b860: 65 2e 63 6f 6d 70 69 6c 65 28 73 50 61 74 74 65  e.compile(sPatte
b870: 72 6e 29 0a 20 20 20 20 72 65 74 75 72 6e 20 61  rn).    return a
b880: 6e 79 28 7a 50 61 74 74 65 72 6e 2e 73 65 61 72  ny(zPattern.sear
b890: 63 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72 20  ch(sMorph)  for 
b8a0: 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68  sMorph in lMorph
b8b0: 29 0a 0a 0a 64 65 66 20 67 5f 61 6e 61 6c 79 73  )...def g_analys
b8c0: 65 20 28 64 54 6f 6b 65 6e 2c 20 73 50 61 74 74  e (dToken, sPatt
b8d0: 65 72 6e 2c 20 73 4e 65 67 50 61 74 74 65 72 6e  ern, sNegPattern
b8e0: 3d 22 22 2c 20 6e 4c 65 66 74 3d 4e 6f 6e 65 2c  ="", nLeft=None,
b8f0: 20 6e 52 69 67 68 74 3d 4e 6f 6e 65 2c 20 62 4d   nRight=None, bM
b900: 65 6d 6f 72 69 7a 65 4d 6f 72 70 68 3d 54 72 75  emorizeMorph=Tru
b910: 65 29 3a 0a 20 20 20 20 22 61 6e 61 6c 79 73 65  e):.    "analyse
b920: 20 61 20 74 6f 6b 65 6e 2c 20 72 65 74 75 72 6e   a token, return
b930: 20 54 72 75 65 20 69 66 20 3c 73 4e 65 67 50 61   True if <sNegPa
b940: 74 74 65 72 6e 3e 20 6e 6f 74 20 69 6e 20 6d 6f  ttern> not in mo
b950: 72 70 68 6f 6c 6f 67 69 65 73 20 61 6e 64 20 3c  rphologies and <
b960: 73 50 61 74 74 65 72 6e 3e 20 69 6e 20 6d 6f 72  sPattern> in mor
b970: 70 68 6f 6c 6f 67 69 65 73 20 28 64 69 73 61 6d  phologies (disam
b980: 62 69 67 75 61 74 69 6f 6e 20 6f 66 66 29 22 0a  biguation off)".
b990: 20 20 20 20 69 66 20 6e 4c 65 66 74 20 69 73 20      if nLeft is 
b9a0: 6e 6f 74 20 4e 6f 6e 65 3a 0a 20 20 20 20 20 20  not None:.      
b9b0: 20 20 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53 70 65    lMorph = _oSpe
b9c0: 6c 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72  llChecker.getMor
b9d0: 70 68 28 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75  ph(dToken["sValu
b9e0: 65 22 5d 5b 73 6c 69 63 65 28 6e 4c 65 66 74 2c  e"][slice(nLeft,
b9f0: 20 6e 52 69 67 68 74 29 5d 29 0a 20 20 20 20 20   nRight)]).     
ba00: 20 20 20 69 66 20 62 4d 65 6d 6f 72 69 7a 65 4d     if bMemorizeM
ba10: 6f 72 70 68 3a 0a 20 20 20 20 20 20 20 20 20 20  orph:.          
ba20: 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68    dToken["lMorph
ba30: 22 5d 20 3d 20 6c 4d 6f 72 70 68 0a 20 20 20 20  "] = lMorph.    
ba40: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 6c 4d  else:.        lM
ba50: 6f 72 70 68 20 3d 20 5f 6f 53 70 65 6c 6c 43 68  orph = _oSpellCh
ba60: 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 64  ecker.getMorph(d
ba70: 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29  Token["sValue"])
ba80: 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72  .    if not lMor
ba90: 70 68 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75  ph:.        retu
baa0: 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 23 20 63  rn False.    # c
bab0: 68 65 63 6b 20 6e 65 67 61 74 69 76 65 20 63 6f  heck negative co
bac0: 6e 64 69 74 69 6f 6e 0a 20 20 20 20 69 66 20 73  ndition.    if s
bad0: 4e 65 67 50 61 74 74 65 72 6e 3a 0a 20 20 20 20  NegPattern:.    
bae0: 20 20 20 20 69 66 20 73 4e 65 67 50 61 74 74 65      if sNegPatte
baf0: 72 6e 20 3d 3d 20 22 2a 22 3a 0a 20 20 20 20 20  rn == "*":.     
bb00: 20 20 20 20 20 20 20 23 20 61 6c 6c 20 6d 6f 72         # all mor
bb10: 70 68 20 6d 75 73 74 20 6d 61 74 63 68 20 73 50  ph must match sP
bb20: 61 74 74 65 72 6e 0a 20 20 20 20 20 20 20 20 20  attern.         
bb30: 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68     if not lMorph
bb40: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
bb50: 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20    return False. 
bb60: 20 20 20 20 20 20 20 20 20 20 20 7a 50 61 74 74             zPatt
bb70: 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69 6c 65  ern = re.compile
bb80: 28 73 50 61 74 74 65 72 6e 29 0a 20 20 20 20 20  (sPattern).     
bb90: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 61 6c         return al
bba0: 6c 28 7a 50 61 74 74 65 72 6e 2e 73 65 61 72 63  l(zPattern.searc
bbb0: 68 28 73 4d 6f 72 70 68 29 20 20 66 6f 72 20 73  h(sMorph)  for s
bbc0: 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29  Morph in lMorph)
bbd0: 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20  .        else:. 
bbe0: 20 20 20 20 20 20 20 20 20 20 20 7a 4e 65 67 50             zNegP
bbf0: 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70  attern = re.comp
bc00: 69 6c 65 28 73 4e 65 67 50 61 74 74 65 72 6e 29  ile(sNegPattern)
bc10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
bc20: 61 6e 79 28 7a 4e 65 67 50 61 74 74 65 72 6e 2e  any(zNegPattern.
bc30: 73 65 61 72 63 68 28 73 4d 6f 72 70 68 29 20 20  search(sMorph)  
bc40: 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d  for sMorph in lM
bc50: 6f 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20 20  orph):.         
bc60: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 46 61         return Fa
bc70: 6c 73 65 0a 20 20 20 20 23 20 73 65 61 72 63 68  lse.    # search
bc80: 20 73 50 61 74 74 65 72 6e 0a 20 20 20 20 7a 50   sPattern.    zP
bc90: 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70  attern = re.comp
bca0: 69 6c 65 28 73 50 61 74 74 65 72 6e 29 0a 20 20  ile(sPattern).  
bcb0: 20 20 72 65 74 75 72 6e 20 61 6e 79 28 7a 50 61    return any(zPa
bcc0: 74 74 65 72 6e 2e 73 65 61 72 63 68 28 73 4d 6f  ttern.search(sMo
bcd0: 72 70 68 29 20 20 66 6f 72 20 73 4d 6f 72 70 68  rph)  for sMorph
bce0: 20 69 6e 20 6c 4d 6f 72 70 68 29 0a 0a 0a 64 65   in lMorph)...de
bcf0: 66 20 67 5f 6d 65 72 67 65 64 5f 61 6e 61 6c 79  f g_merged_analy
bd00: 73 65 20 28 64 54 6f 6b 65 6e 31 2c 20 64 54 6f  se (dToken1, dTo
bd10: 6b 65 6e 32 2c 20 63 4d 65 72 67 65 72 2c 20 73  ken2, cMerger, s
bd20: 50 61 74 74 65 72 6e 2c 20 73 4e 65 67 50 61 74  Pattern, sNegPat
bd30: 74 65 72 6e 3d 22 22 2c 20 62 53 65 74 4d 6f 72  tern="", bSetMor
bd40: 70 68 3d 54 72 75 65 29 3a 0a 20 20 20 20 22 6d  ph=True):.    "m
bd50: 65 72 67 65 20 74 77 6f 20 74 6f 6b 65 6e 20 76  erge two token v
bd60: 61 6c 75 65 73 2c 20 72 65 74 75 72 6e 20 54 72  alues, return Tr
bd70: 75 65 20 69 66 20 3c 73 4e 65 67 50 61 74 74 65  ue if <sNegPatte
bd80: 72 6e 3e 20 6e 6f 74 20 69 6e 20 6d 6f 72 70 68  rn> not in morph
bd90: 6f 6c 6f 67 69 65 73 20 61 6e 64 20 3c 73 50 61  ologies and <sPa
bda0: 74 74 65 72 6e 3e 20 69 6e 20 6d 6f 72 70 68 6f  ttern> in morpho
bdb0: 6c 6f 67 69 65 73 20 28 64 69 73 61 6d 62 69 67  logies (disambig
bdc0: 75 61 74 69 6f 6e 20 6f 66 66 29 22 0a 20 20 20  uation off)".   
bdd0: 20 6c 4d 6f 72 70 68 20 3d 20 5f 6f 53 70 65 6c   lMorph = _oSpel
bde0: 6c 43 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70  lChecker.getMorp
bdf0: 68 28 64 54 6f 6b 65 6e 31 5b 22 73 56 61 6c 75  h(dToken1["sValu
be00: 65 22 5d 20 2b 20 63 4d 65 72 67 65 72 20 2b 20  e"] + cMerger + 
be10: 64 54 6f 6b 65 6e 32 5b 22 73 56 61 6c 75 65 22  dToken2["sValue"
be20: 5d 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d  ]).    if not lM
be30: 6f 72 70 68 3a 0a 20 20 20 20 20 20 20 20 72 65  orph:.        re
be40: 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 23  turn False.    #
be50: 20 63 68 65 63 6b 20 6e 65 67 61 74 69 76 65 20   check negative 
be60: 63 6f 6e 64 69 74 69 6f 6e 0a 20 20 20 20 69 66  condition.    if
be70: 20 73 4e 65 67 50 61 74 74 65 72 6e 3a 0a 20 20   sNegPattern:.  
be80: 20 20 20 20 20 20 69 66 20 73 4e 65 67 50 61 74        if sNegPat
be90: 74 65 72 6e 20 3d 3d 20 22 2a 22 3a 0a 20 20 20  tern == "*":.   
bea0: 20 20 20 20 20 20 20 20 20 23 20 61 6c 6c 20 6d           # all m
beb0: 6f 72 70 68 20 6d 75 73 74 20 6d 61 74 63 68 20  orph must match 
bec0: 73 50 61 74 74 65 72 6e 0a 20 20 20 20 20 20 20  sPattern.       
bed0: 20 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72       if not lMor
bee0: 70 68 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ph:.            
bef0: 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65      return False
bf00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 7a 50 61  .            zPa
bf10: 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d 70 69  ttern = re.compi
bf20: 6c 65 28 73 50 61 74 74 65 72 6e 29 0a 20 20 20  le(sPattern).   
bf30: 20 20 20 20 20 20 20 20 20 62 52 65 73 75 6c 74           bResult
bf40: 20 3d 20 61 6c 6c 28 7a 50 61 74 74 65 72 6e 2e   = all(zPattern.
bf50: 73 65 61 72 63 68 28 73 4d 6f 72 70 68 29 20 20  search(sMorph)  
bf60: 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d  for sMorph in lM
bf70: 6f 72 70 68 29 0a 20 20 20 20 20 20 20 20 20 20  orph).          
bf80: 20 20 69 66 20 62 52 65 73 75 6c 74 20 61 6e 64    if bResult and
bf90: 20 62 53 65 74 4d 6f 72 70 68 3a 0a 20 20 20 20   bSetMorph:.    
bfa0: 20 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b              dTok
bfb0: 65 6e 31 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20  en1["lMorph"] = 
bfc0: 6c 4d 6f 72 70 68 0a 20 20 20 20 20 20 20 20 20  lMorph.         
bfd0: 20 20 20 72 65 74 75 72 6e 20 62 52 65 73 75 6c     return bResul
bfe0: 74 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a  t.        else:.
bff0: 20 20 20 20 20 20 20 20 20 20 20 20 7a 4e 65 67              zNeg
c000: 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d  Pattern = re.com
c010: 70 69 6c 65 28 73 4e 65 67 50 61 74 74 65 72 6e  pile(sNegPattern
c020: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  ).            if
c030: 20 61 6e 79 28 7a 4e 65 67 50 61 74 74 65 72 6e   any(zNegPattern
c040: 2e 73 65 61 72 63 68 28 73 4d 6f 72 70 68 29 20  .search(sMorph) 
c050: 20 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c   for sMorph in l
c060: 4d 6f 72 70 68 29 3a 0a 20 20 20 20 20 20 20 20  Morph):.        
c070: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 46          return F
c080: 61 6c 73 65 0a 20 20 20 20 23 20 73 65 61 72 63  alse.    # searc
c090: 68 20 73 50 61 74 74 65 72 6e 0a 20 20 20 20 7a  h sPattern.    z
c0a0: 50 61 74 74 65 72 6e 20 3d 20 72 65 2e 63 6f 6d  Pattern = re.com
c0b0: 70 69 6c 65 28 73 50 61 74 74 65 72 6e 29 0a 20  pile(sPattern). 
c0c0: 20 20 20 62 52 65 73 75 6c 74 20 3d 20 61 6e 79     bResult = any
c0d0: 28 7a 50 61 74 74 65 72 6e 2e 73 65 61 72 63 68  (zPattern.search
c0e0: 28 73 4d 6f 72 70 68 29 20 20 66 6f 72 20 73 4d  (sMorph)  for sM
c0f0: 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68 29 0a  orph in lMorph).
c100: 20 20 20 20 69 66 20 62 52 65 73 75 6c 74 20 61      if bResult a
c110: 6e 64 20 62 53 65 74 4d 6f 72 70 68 3a 0a 20 20  nd bSetMorph:.  
c120: 20 20 20 20 20 20 64 54 6f 6b 65 6e 31 5b 22 6c        dToken1["l
c130: 4d 6f 72 70 68 22 5d 20 3d 20 6c 4d 6f 72 70 68  Morph"] = lMorph
c140: 0a 20 20 20 20 72 65 74 75 72 6e 20 62 52 65 73  .    return bRes
c150: 75 6c 74 0a 0a 0a 64 65 66 20 67 5f 74 61 67 5f  ult...def g_tag_
c160: 62 65 66 6f 72 65 20 28 64 54 6f 6b 65 6e 2c 20  before (dToken, 
c170: 64 54 61 67 73 2c 20 73 54 61 67 29 3a 0a 20 20  dTags, sTag):.  
c180: 20 20 69 66 20 73 54 61 67 20 6e 6f 74 20 69 6e    if sTag not in
c190: 20 64 54 61 67 73 3a 0a 20 20 20 20 20 20 20 20   dTags:.        
c1a0: 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20 20 20  return False.   
c1b0: 20 69 66 20 64 54 6f 6b 65 6e 5b 22 69 22 5d 20   if dToken["i"] 
c1c0: 3e 20 64 54 61 67 73 5b 73 54 61 67 5d 5b 30 5d  > dTags[sTag][0]
c1d0: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
c1e0: 20 54 72 75 65 0a 20 20 20 20 72 65 74 75 72 6e   True.    return
c1f0: 20 46 61 6c 73 65 0a 0a 0a 64 65 66 20 67 5f 74   False...def g_t
c200: 61 67 5f 61 66 74 65 72 20 28 64 54 6f 6b 65 6e  ag_after (dToken
c210: 2c 20 64 54 61 67 73 2c 20 73 54 61 67 29 3a 0a  , dTags, sTag):.
c220: 20 20 20 20 69 66 20 73 54 61 67 20 6e 6f 74 20      if sTag not 
c230: 69 6e 20 64 54 61 67 73 3a 0a 20 20 20 20 20 20  in dTags:.      
c240: 20 20 72 65 74 75 72 6e 20 46 61 6c 73 65 0a 20    return False. 
c250: 20 20 20 69 66 20 64 54 6f 6b 65 6e 5b 22 69 22     if dToken["i"
c260: 5d 20 3c 20 64 54 61 67 73 5b 73 54 61 67 5d 5b  ] < dTags[sTag][
c270: 31 5d 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75  1]:.        retu
c280: 72 6e 20 54 72 75 65 0a 20 20 20 20 72 65 74 75  rn True.    retu
c290: 72 6e 20 46 61 6c 73 65 0a 0a 0a 64 65 66 20 67  rn False...def g
c2a0: 5f 74 61 67 20 28 64 54 6f 6b 65 6e 2c 20 73 54  _tag (dToken, sT
c2b0: 61 67 29 3a 0a 20 20 20 20 72 65 74 75 72 6e 20  ag):.    return 
c2c0: 22 74 61 67 73 22 20 69 6e 20 64 54 6f 6b 65 6e  "tags" in dToken
c2d0: 20 61 6e 64 20 73 54 61 67 20 69 6e 20 64 54 61   and sTag in dTa
c2e0: 67 73 5b 22 74 61 67 73 22 5d 0a 0a 0a 64 65 66  gs["tags"]...def
c2f0: 20 67 5f 73 70 61 63 65 5f 62 65 74 77 65 65 6e   g_space_between
c300: 5f 74 6f 6b 65 6e 73 20 28 64 54 6f 6b 65 6e 31  _tokens (dToken1
c310: 2c 20 64 54 6f 6b 65 6e 32 2c 20 6e 4d 69 6e 2c  , dToken2, nMin,
c320: 20 6e 4d 61 78 3d 4e 6f 6e 65 29 3a 0a 20 20 20   nMax=None):.   
c330: 20 6e 53 70 61 63 65 20 3d 20 64 54 6f 6b 65 6e   nSpace = dToken
c340: 32 5b 22 6e 53 74 61 72 74 22 5d 20 2d 20 64 54  2["nStart"] - dT
c350: 6f 6b 65 6e 31 5b 22 6e 45 6e 64 22 5d 0a 20 20  oken1["nEnd"].  
c360: 20 20 69 66 20 6e 53 70 61 63 65 20 3c 20 6e 4d    if nSpace < nM
c370: 69 6e 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75  in:.        retu
c380: 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 69 66 20  rn False.    if 
c390: 6e 4d 61 78 20 69 73 20 6e 6f 74 20 4e 6f 6e 65  nMax is not None
c3a0: 20 61 6e 64 20 6e 53 70 61 63 65 20 3e 20 6e 4d   and nSpace > nM
c3b0: 61 78 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75  ax:.        retu
c3c0: 72 6e 20 46 61 6c 73 65 0a 20 20 20 20 72 65 74  rn False.    ret
c3d0: 75 72 6e 20 54 72 75 65 0a 0a 0a 64 65 66 20 67  urn True...def g
c3e0: 5f 74 6f 6b 65 6e 20 28 6c 54 6f 6b 65 6e 2c 20  _token (lToken, 
c3f0: 69 29 3a 0a 20 20 20 20 69 66 20 69 20 3c 20 30  i):.    if i < 0
c400: 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  :.        return
c410: 20 6c 54 6f 6b 65 6e 5b 30 5d 0a 20 20 20 20 69   lToken[0].    i
c420: 66 20 69 20 3e 3d 20 6c 65 6e 28 6c 54 6f 6b 65  f i >= len(lToke
c430: 6e 29 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75  n):.        retu
c440: 72 6e 20 6c 54 6f 6b 65 6e 5b 2d 31 5d 0a 20 20  rn lToken[-1].  
c450: 20 20 72 65 74 75 72 6e 20 6c 54 6f 6b 65 6e 5b    return lToken[
c460: 69 5d 0a 0a 0a 0a 23 23 23 23 20 44 69 73 61 6d  i]....#### Disam
c470: 62 69 67 75 61 74 6f 72 0a 0a 64 65 66 20 67 5f  biguator..def g_
c480: 73 65 6c 65 63 74 20 28 64 54 6f 6b 65 6e 2c 20  select (dToken, 
c490: 73 50 61 74 74 65 72 6e 2c 20 6c 44 65 66 61 75  sPattern, lDefau
c4a0: 6c 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20 22 73  lt=None):.    "s
c4b0: 65 6c 65 63 74 20 6d 6f 72 70 68 6f 6c 6f 67 69  elect morphologi
c4c0: 65 73 20 66 6f 72 20 3c 64 54 6f 6b 65 6e 3e 20  es for <dToken> 
c4d0: 61 63 63 6f 72 64 69 6e 67 20 74 6f 20 3c 73 50  according to <sP
c4e0: 61 74 74 65 72 6e 3e 2c 20 61 6c 77 61 79 73 20  attern>, always 
c4f0: 72 65 74 75 72 6e 20 54 72 75 65 22 0a 20 20 20  return True".   
c500: 20 6c 4d 6f 72 70 68 20 3d 20 64 54 6f 6b 65 6e   lMorph = dToken
c510: 5b 22 6c 4d 6f 72 70 68 22 5d 20 20 69 66 20 22  ["lMorph"]  if "
c520: 6c 4d 6f 72 70 68 22 20 69 6e 20 64 54 6f 6b 65  lMorph" in dToke
c530: 6e 20 20 65 6c 73 65 20 5f 6f 53 70 65 6c 6c 43  n  else _oSpellC
c540: 68 65 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28  hecker.getMorph(
c550: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
c560: 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c 4d 6f  ).    if not lMo
c570: 72 70 68 20 6f 72 20 6c 65 6e 28 6c 4d 6f 72 70  rph or len(lMorp
c580: 68 29 20 3d 3d 20 31 3a 0a 20 20 20 20 20 20 20  h) == 1:.       
c590: 20 69 66 20 6c 44 65 66 61 75 6c 74 3a 0a 20 20   if lDefault:.  
c5a0: 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65 6e            dToken
c5b0: 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 44 65  ["lMorph"] = lDe
c5c0: 66 61 75 6c 74 0a 20 20 20 20 20 20 20 20 20 20  fault.          
c5d0: 20 20 23 70 72 69 6e 74 28 22 44 41 3a 22 2c 20    #print("DA:", 
c5e0: 64 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d  dToken["sValue"]
c5f0: 2c 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68  , dToken["lMorph
c600: 22 5d 29 0a 20 20 20 20 20 20 20 20 72 65 74 75  "]).        retu
c610: 72 6e 20 54 72 75 65 0a 20 20 20 20 6c 53 65 6c  rn True.    lSel
c620: 65 63 74 20 3d 20 5b 20 73 4d 6f 72 70 68 20 20  ect = [ sMorph  
c630: 66 6f 72 20 73 4d 6f 72 70 68 20 69 6e 20 6c 4d  for sMorph in lM
c640: 6f 72 70 68 20 20 69 66 20 72 65 2e 73 65 61 72  orph  if re.sear
c650: 63 68 28 73 50 61 74 74 65 72 6e 2c 20 73 4d 6f  ch(sPattern, sMo
c660: 72 70 68 29 20 5d 0a 20 20 20 20 69 66 20 6c 53  rph) ].    if lS
c670: 65 6c 65 63 74 3a 0a 20 20 20 20 20 20 20 20 69  elect:.        i
c680: 66 20 6c 65 6e 28 6c 53 65 6c 65 63 74 29 20 21  f len(lSelect) !
c690: 3d 20 6c 65 6e 28 6c 4d 6f 72 70 68 29 3a 0a 20  = len(lMorph):. 
c6a0: 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65             dToke
c6b0: 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 53  n["lMorph"] = lS
c6c0: 65 6c 65 63 74 0a 20 20 20 20 65 6c 69 66 20 6c  elect.    elif l
c6d0: 44 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 20  Default:.       
c6e0: 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22   dToken["lMorph"
c6f0: 5d 20 3d 20 6c 44 65 66 61 75 6c 74 0a 20 20 20  ] = lDefault.   
c700: 20 23 70 72 69 6e 74 28 22 44 41 3a 22 2c 20 64   #print("DA:", d
c710: 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2c  Token["sValue"],
c720: 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22   dToken["lMorph"
c730: 5d 29 0a 20 20 20 20 72 65 74 75 72 6e 20 54 72  ]).    return Tr
c740: 75 65 0a 0a 0a 64 65 66 20 67 5f 65 78 63 6c 75  ue...def g_exclu
c750: 64 65 20 28 64 54 6f 6b 65 6e 2c 20 73 50 61 74  de (dToken, sPat
c760: 74 65 72 6e 2c 20 6c 44 65 66 61 75 6c 74 3d 4e  tern, lDefault=N
c770: 6f 6e 65 29 3a 0a 20 20 20 20 22 73 65 6c 65 63  one):.    "selec
c780: 74 20 6d 6f 72 70 68 6f 6c 6f 67 69 65 73 20 66  t morphologies f
c790: 6f 72 20 3c 64 54 6f 6b 65 6e 3e 20 61 63 63 6f  or <dToken> acco
c7a0: 72 64 69 6e 67 20 74 6f 20 3c 73 50 61 74 74 65  rding to <sPatte
c7b0: 72 6e 3e 2c 20 61 6c 77 61 79 73 20 72 65 74 75  rn>, always retu
c7c0: 72 6e 20 54 72 75 65 22 0a 20 20 20 20 6c 4d 6f  rn True".    lMo
c7d0: 72 70 68 20 3d 20 64 54 6f 6b 65 6e 5b 22 6c 4d  rph = dToken["lM
c7e0: 6f 72 70 68 22 5d 20 20 69 66 20 22 6c 4d 6f 72  orph"]  if "lMor
c7f0: 70 68 22 20 69 6e 20 64 54 6f 6b 65 6e 20 20 65  ph" in dToken  e
c800: 6c 73 65 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b  lse _oSpellCheck
c810: 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b  er.getMorph(dTok
c820: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 0a 20 20  en["sValue"]).  
c830: 20 20 69 66 20 6e 6f 74 20 6c 4d 6f 72 70 68 20    if not lMorph 
c840: 6f 72 20 6c 65 6e 28 6c 4d 6f 72 70 68 29 20 3d  or len(lMorph) =
c850: 3d 20 31 3a 0a 20 20 20 20 20 20 20 20 69 66 20  = 1:.        if 
c860: 6c 44 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20  lDefault:.      
c870: 20 20 20 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d        dToken["lM
c880: 6f 72 70 68 22 5d 20 3d 20 6c 44 65 66 61 75 6c  orph"] = lDefaul
c890: 74 0a 20 20 20 20 20 20 20 20 20 20 20 20 23 70  t.            #p
c8a0: 72 69 6e 74 28 22 44 41 3a 22 2c 20 64 54 6f 6b  rint("DA:", dTok
c8b0: 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2c 20 64 54  en["sValue"], dT
c8c0: 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 29 0a  oken["lMorph"]).
c8d0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 54          return T
c8e0: 72 75 65 0a 20 20 20 20 6c 53 65 6c 65 63 74 20  rue.    lSelect 
c8f0: 3d 20 5b 20 73 4d 6f 72 70 68 20 20 66 6f 72 20  = [ sMorph  for 
c900: 73 4d 6f 72 70 68 20 69 6e 20 6c 4d 6f 72 70 68  sMorph in lMorph
c910: 20 20 69 66 20 6e 6f 74 20 72 65 2e 73 65 61 72    if not re.sear
c920: 63 68 28 73 50 61 74 74 65 72 6e 2c 20 73 4d 6f  ch(sPattern, sMo
c930: 72 70 68 29 20 5d 0a 20 20 20 20 69 66 20 6c 53  rph) ].    if lS
c940: 65 6c 65 63 74 3a 0a 20 20 20 20 20 20 20 20 69  elect:.        i
c950: 66 20 6c 65 6e 28 6c 53 65 6c 65 63 74 29 20 21  f len(lSelect) !
c960: 3d 20 6c 65 6e 28 6c 4d 6f 72 70 68 29 3a 0a 20  = len(lMorph):. 
c970: 20 20 20 20 20 20 20 20 20 20 20 64 54 6f 6b 65             dToke
c980: 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d 20 6c 53  n["lMorph"] = lS
c990: 65 6c 65 63 74 0a 20 20 20 20 65 6c 69 66 20 6c  elect.    elif l
c9a0: 44 65 66 61 75 6c 74 3a 0a 20 20 20 20 20 20 20  Default:.       
c9b0: 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22   dToken["lMorph"
c9c0: 5d 20 3d 20 6c 44 65 66 61 75 6c 74 0a 20 20 20  ] = lDefault.   
c9d0: 20 23 70 72 69 6e 74 28 22 44 41 3a 22 2c 20 64   #print("DA:", d
c9e0: 54 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 2c  Token["sValue"],
c9f0: 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22   dToken["lMorph"
ca00: 5d 29 0a 20 20 20 20 72 65 74 75 72 6e 20 54 72  ]).    return Tr
ca10: 75 65 0a 0a 0a 64 65 66 20 67 5f 64 65 66 69 6e  ue...def g_defin
ca20: 65 20 28 64 54 6f 6b 65 6e 2c 20 6c 4d 6f 72 70  e (dToken, lMorp
ca30: 68 29 3a 0a 20 20 20 20 22 73 65 74 20 6d 6f 72  h):.    "set mor
ca40: 70 68 6f 6c 6f 67 69 65 73 20 6f 66 20 3c 64 54  phologies of <dT
ca50: 6f 6b 65 6e 3e 2c 20 61 6c 77 61 79 73 20 72 65  oken>, always re
ca60: 74 75 72 6e 20 54 72 75 65 22 0a 20 20 20 20 64  turn True".    d
ca70: 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20  Token["lMorph"] 
ca80: 3d 20 6c 4d 6f 72 70 68 0a 20 20 20 20 23 70 72  = lMorph.    #pr
ca90: 69 6e 74 28 22 44 41 3a 22 2c 20 64 54 6f 6b 65  int("DA:", dToke
caa0: 6e 5b 22 73 56 61 6c 75 65 22 5d 2c 20 6c 4d 6f  n["sValue"], lMo
cab0: 72 70 68 29 0a 20 20 20 20 72 65 74 75 72 6e 20  rph).    return 
cac0: 54 72 75 65 0a 0a 0a 64 65 66 20 67 5f 64 65 66  True...def g_def
cad0: 69 6e 65 5f 66 72 6f 6d 20 28 64 54 6f 6b 65 6e  ine_from (dToken
cae0: 2c 20 6e 4c 65 66 74 3d 4e 6f 6e 65 2c 20 6e 52  , nLeft=None, nR
caf0: 69 67 68 74 3d 4e 6f 6e 65 29 3a 0a 20 20 20 20  ight=None):.    
cb00: 69 66 20 6e 4c 65 66 74 20 69 73 20 6e 6f 74 20  if nLeft is not 
cb10: 4e 6f 6e 65 3a 0a 20 20 20 20 20 20 20 20 64 54  None:.        dT
cb20: 6f 6b 65 6e 5b 22 6c 4d 6f 72 70 68 22 5d 20 3d  oken["lMorph"] =
cb30: 20 5f 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 2e   _oSpellChecker.
cb40: 67 65 74 4d 6f 72 70 68 28 64 54 6f 6b 65 6e 5b  getMorph(dToken[
cb50: 22 73 56 61 6c 75 65 22 5d 5b 73 6c 69 63 65 28  "sValue"][slice(
cb60: 6e 4c 65 66 74 2c 20 6e 52 69 67 68 74 29 5d 29  nLeft, nRight)])
cb70: 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20  .    else:.     
cb80: 20 20 20 64 54 6f 6b 65 6e 5b 22 6c 4d 6f 72 70     dToken["lMorp
cb90: 68 22 5d 20 3d 20 5f 6f 53 70 65 6c 6c 43 68 65  h"] = _oSpellChe
cba0: 63 6b 65 72 2e 67 65 74 4d 6f 72 70 68 28 64 54  cker.getMorph(dT
cbb0: 6f 6b 65 6e 5b 22 73 56 61 6c 75 65 22 5d 29 0a  oken["sValue"]).
cbc0: 20 20 20 20 72 65 74 75 72 6e 20 54 72 75 65 0a      return True.
cbd0: 0a 0a 23 23 23 23 20 47 52 41 4d 4d 41 52 20 43  ..#### GRAMMAR C
cbe0: 48 45 43 4b 45 52 20 50 4c 55 47 49 4e 53 0a 0a  HECKER PLUGINS..
cbf0: 24 7b 70 6c 75 67 69 6e 73 7d 0a 0a 0a 23 23 23  ${plugins}...###
cc00: 23 20 43 41 4c 4c 41 42 4c 45 53 20 46 4f 52 20  # CALLABLES FOR 
cc10: 52 45 47 45 58 20 52 55 4c 45 53 20 28 67 65 6e  REGEX RULES (gen
cc20: 65 72 61 74 65 64 20 63 6f 64 65 29 0a 0a 24 7b  erated code)..${
cc30: 63 61 6c 6c 61 62 6c 65 73 7d 0a 0a 0a 23 23 23  callables}...###
cc40: 23 20 43 41 4c 4c 41 42 4c 45 53 20 46 4f 52 20  # CALLABLES FOR 
cc50: 47 52 41 50 48 20 52 55 4c 45 53 20 28 67 65 6e  GRAPH RULES (gen
cc60: 65 72 61 74 65 64 20 63 6f 64 65 29 0a 0a 24 7b  erated code)..${
cc70: 67 72 61 70 68 5f 63 61 6c 6c 61 62 6c 65 73 7d  graph_callables}
cc80: 0a                                               .