Grammalecte  Hex Artifact Content

Artifact d8be0874f6cd0cc71dcf53e4b0dd745dd3ff737c8829cedb39753592ac40f707:


0000: 22 22 22 0a 47 72 61 6d 6d 61 6c 65 63 74 65 3a  """.Grammalecte:
0010: 20 63 6f 6d 70 69 6c 65 20 72 75 6c 65 73 0a 22   compile rules."
0020: 22 22 0a 0a 69 6d 70 6f 72 74 20 72 65 0a 69 6d  ""..import re.im
0030: 70 6f 72 74 20 6f 73 0a 69 6d 70 6f 72 74 20 74  port os.import t
0040: 72 61 63 65 62 61 63 6b 0a 69 6d 70 6f 72 74 20  raceback.import 
0050: 6a 73 6f 6e 0a 69 6d 70 6f 72 74 20 63 6f 6c 6f  json.import colo
0060: 72 73 79 73 0a 69 6d 70 6f 72 74 20 74 69 6d 65  rsys.import time
0070: 0a 69 6d 70 6f 72 74 20 68 61 73 68 6c 69 62 0a  .import hashlib.
0080: 0a 69 6d 70 6f 72 74 20 63 6f 6d 70 69 6c 65 5f  .import compile_
0090: 72 75 6c 65 73 5f 6a 73 5f 63 6f 6e 76 65 72 74  rules_js_convert
00a0: 20 61 73 20 6a 73 63 6f 6e 76 0a 69 6d 70 6f 72   as jsconv.impor
00b0: 74 20 63 6f 6d 70 69 6c 65 5f 72 75 6c 65 73 5f  t compile_rules_
00c0: 67 72 61 70 68 20 61 73 20 63 72 67 0a 0a 0a 64  graph as crg...d
00d0: 44 45 46 49 4e 49 54 49 4f 4e 53 20 3d 20 7b 7d  DEFINITIONS = {}
00e0: 0a 64 44 45 43 4c 45 4e 53 49 4f 4e 53 20 3d 20  .dDECLENSIONS = 
00f0: 7b 7d 0a 6c 46 55 4e 43 54 49 4f 4e 53 20 3d 20  {}.lFUNCTIONS = 
0100: 5b 5d 0a 0a 61 52 55 4c 45 53 45 54 20 3d 20 73  []..aRULESET = s
0110: 65 74 28 29 20 20 20 20 20 23 20 73 65 74 20 6f  et()     # set o
0120: 66 20 72 75 6c 65 2d 69 64 73 20 74 6f 20 63 68  f rule-ids to ch
0130: 65 63 6b 20 69 66 20 74 68 65 72 65 20 69 73 20  eck if there is 
0140: 73 65 76 65 72 61 6c 20 72 75 6c 65 73 20 77 69  several rules wi
0150: 74 68 20 74 68 65 20 73 61 6d 65 20 69 64 0a 0a  th the same id..
0160: 64 4a 53 52 45 47 45 58 45 53 20 3d 20 7b 7d 0a  dJSREGEXES = {}.
0170: 0a 73 57 4f 52 44 4c 49 4d 49 54 4c 45 46 54 20  .sWORDLIMITLEFT 
0180: 20 3d 20 72 22 28 3f 3c 21 5b 5c 77 2e 2c e2 80   = r"(?<![\w.,..
0190: 93 2d 5d 29 22 20 20 20 23 20 72 22 28 3f 3c 21  .-])"   # r"(?<!
01a0: 5b 2d 2e 2c e2 80 94 5d 29 5c 62 22 20 20 73 65  [-.,...])\b"  se
01b0: 65 6d 73 20 73 6c 6f 77 65 72 0a 73 57 4f 52 44  ems slower.sWORD
01c0: 4c 49 4d 49 54 52 49 47 48 54 20 3d 20 72 22 28  LIMITRIGHT = r"(
01d0: 3f 21 5b 5c 77 e2 80 93 2d 5d 29 22 20 20 20 20  ?![\w...-])"    
01e0: 20 20 23 20 72 22 5c 62 28 3f 21 2d e2 80 94 29    # r"\b(?!-...)
01f0: 22 20 20 20 20 20 20 20 73 65 65 6d 73 20 73 6c  "       seems sl
0200: 6f 77 65 72 0a 0a 0a 64 65 66 20 63 6f 6e 76 65  ower...def conve
0210: 72 74 52 47 42 54 6f 49 6e 74 65 67 65 72 20 28  rtRGBToInteger (
0220: 72 2c 20 67 2c 20 62 29 3a 0a 20 20 20 20 22 72  r, g, b):.    "r
0230: 62 67 20 28 69 6e 74 2c 20 69 6e 74 2c 20 69 6e  bg (int, int, in
0240: 74 29 20 2d 3e 20 69 6e 74 22 0a 20 20 20 20 72  t) -> int".    r
0250: 65 74 75 72 6e 20 28 72 20 26 20 32 35 35 29 20  eturn (r & 255) 
0260: 3c 3c 20 31 36 20 7c 20 28 67 20 26 20 32 35 35  << 16 | (g & 255
0270: 29 20 3c 3c 20 38 20 7c 20 28 62 20 26 20 32 35  ) << 8 | (b & 25
0280: 35 29 0a 0a 0a 64 65 66 20 63 6f 6e 76 65 72 74  5)...def convert
0290: 48 53 4c 54 6f 52 42 47 20 28 68 2c 20 73 2c 20  HSLToRBG (h, s, 
02a0: 6c 29 3a 0a 20 20 20 20 22 68 73 6c 20 28 69 6e  l):.    "hsl (in
02b0: 74 2c 20 69 6e 74 2c 20 69 6e 74 29 20 2d 3e 20  t, int, int) -> 
02c0: 5b 69 6e 74 2c 20 69 6e 74 2c 20 69 6e 74 5d 22  [int, int, int]"
02d0: 0a 20 20 20 20 72 2c 20 67 2c 20 62 20 3d 20 63  .    r, g, b = c
02e0: 6f 6c 6f 72 73 79 73 2e 68 6c 73 5f 74 6f 5f 72  olorsys.hls_to_r
02f0: 67 62 28 68 2f 33 36 30 2c 20 6c 2f 31 30 30 2c  gb(h/360, l/100,
0300: 20 73 2f 31 30 30 29 0a 20 20 20 20 72 65 74 75   s/100).    retu
0310: 72 6e 20 5b 72 6f 75 6e 64 28 72 2a 32 35 35 29  rn [round(r*255)
0320: 2c 20 72 6f 75 6e 64 28 67 2a 32 35 35 29 2c 20  , round(g*255), 
0330: 72 6f 75 6e 64 28 62 2a 32 35 35 29 5d 0a 0a 0a  round(b*255)]...
0340: 64 65 66 20 63 72 65 61 74 65 43 6f 6c 6f 72 73  def createColors
0350: 20 28 64 43 6f 6c 6f 72 29 3a 0a 20 20 20 20 22   (dColor):.    "
0360: 64 69 63 74 69 6f 6e 61 72 79 20 6f 66 20 63 6f  dictionary of co
0370: 6c 6f 72 73 20 7b 63 6f 6c 6f 72 5f 6e 61 6d 65  lors {color_name
0380: 3a 20 5b 68 2c 20 73 2c 20 6c 5d 7d 20 2d 3e 20  : [h, s, l]} -> 
0390: 72 65 74 75 72 6e 73 20 64 69 63 74 69 6f 6e 61  returns dictiona
03a0: 72 79 20 6f 66 20 63 6f 6c 6f 72 73 20 61 73 20  ry of colors as 
03b0: 64 69 63 74 69 6f 6e 61 72 69 65 73 20 6f 66 20  dictionaries of 
03c0: 63 6f 6c 6f 72 20 74 79 70 65 73 22 0a 20 20 20  color types".   
03d0: 20 64 43 6f 6c 6f 72 54 79 70 65 20 3d 20 7b 0a   dColorType = {.
03e0: 20 20 20 20 20 20 20 20 22 61 48 53 4c 22 3a 20          "aHSL": 
03f0: 7b 7d 2c 20 20 20 20 20 23 20 64 69 63 74 69 6f  {},     # dictio
0400: 6e 61 72 79 20 6f 66 20 63 6f 6c 6f 72 73 20 61  nary of colors a
0410: 73 20 48 53 4c 20 6c 69 73 74 0a 20 20 20 20 20  s HSL list.     
0420: 20 20 20 22 73 43 53 53 22 3a 20 7b 7d 2c 20 20     "sCSS": {},  
0430: 20 20 20 23 20 64 69 63 74 69 6f 6e 61 72 79 20     # dictionary 
0440: 6f 66 20 63 6f 6c 6f 72 73 20 61 73 20 73 74 72  of colors as str
0450: 69 6e 67 73 20 66 6f 72 20 48 54 4d 4c 2f 43 53  ings for HTML/CS
0460: 53 20 28 65 78 61 6d 70 6c 65 3a 20 68 73 6c 28  S (example: hsl(
0470: 30 2c 20 35 30 25 2c 20 35 30 25 29 29 0a 20 20  0, 50%, 50%)).  
0480: 20 20 20 20 20 20 22 61 52 47 42 22 3a 20 7b 7d        "aRGB": {}
0490: 2c 20 20 20 20 20 23 20 64 69 63 74 69 6f 6e 61  ,     # dictiona
04a0: 72 79 20 6f 66 20 63 6f 6c 6f 72 73 20 61 73 20  ry of colors as 
04b0: 52 47 42 20 6c 69 73 74 0a 20 20 20 20 20 20 20  RGB list.       
04c0: 20 22 6e 49 6e 74 22 3a 20 7b 7d 20 20 20 20 20   "nInt": {}     
04d0: 20 23 20 64 69 63 74 69 6f 6e 61 72 79 20 6f 66   # dictionary of
04e0: 20 63 6f 6c 6f 72 73 20 61 73 20 69 6e 74 65 67   colors as integ
04f0: 65 72 20 76 61 6c 75 65 73 20 28 66 6f 72 20 57  er values (for W
0500: 72 69 74 65 72 29 0a 20 20 20 20 7d 0a 20 20 20  riter).    }.   
0510: 20 66 6f 72 20 73 4b 65 79 2c 20 61 48 53 4c 20   for sKey, aHSL 
0520: 69 6e 20 64 43 6f 6c 6f 72 2e 69 74 65 6d 73 28  in dColor.items(
0530: 29 3a 0a 20 20 20 20 20 20 20 20 64 43 6f 6c 6f  ):.        dColo
0540: 72 54 79 70 65 5b 22 61 48 53 4c 22 5d 5b 73 4b  rType["aHSL"][sK
0550: 65 79 5d 20 3d 20 61 48 53 4c 0a 20 20 20 20 20  ey] = aHSL.     
0560: 20 20 20 64 43 6f 6c 6f 72 54 79 70 65 5b 22 73     dColorType["s
0570: 43 53 53 22 5d 5b 73 4b 65 79 5d 20 3d 20 22 68  CSS"][sKey] = "h
0580: 73 6c 28 7b 7d 2c 20 7b 7d 25 2c 20 7b 7d 25 29  sl({}, {}%, {}%)
0590: 22 2e 66 6f 72 6d 61 74 28 2a 61 48 53 4c 29 0a  ".format(*aHSL).
05a0: 20 20 20 20 20 20 20 20 64 43 6f 6c 6f 72 54 79          dColorTy
05b0: 70 65 5b 22 61 52 47 42 22 5d 5b 73 4b 65 79 5d  pe["aRGB"][sKey]
05c0: 20 3d 20 63 6f 6e 76 65 72 74 48 53 4c 54 6f 52   = convertHSLToR
05d0: 42 47 28 2a 61 48 53 4c 29 0a 20 20 20 20 20 20  BG(*aHSL).      
05e0: 20 20 64 43 6f 6c 6f 72 54 79 70 65 5b 22 6e 49    dColorType["nI
05f0: 6e 74 22 5d 5b 73 4b 65 79 5d 20 3d 20 63 6f 6e  nt"][sKey] = con
0600: 76 65 72 74 52 47 42 54 6f 49 6e 74 65 67 65 72  vertRGBToInteger
0610: 28 2a 64 43 6f 6c 6f 72 54 79 70 65 5b 22 61 52  (*dColorType["aR
0620: 47 42 22 5d 5b 73 4b 65 79 5d 29 0a 20 20 20 20  GB"][sKey]).    
0630: 72 65 74 75 72 6e 20 64 43 6f 6c 6f 72 54 79 70  return dColorTyp
0640: 65 0a 0a 0a 64 65 66 20 70 72 65 70 61 72 65 46  e...def prepareF
0650: 75 6e 63 74 69 6f 6e 20 28 73 29 3a 0a 20 20 20  unction (s):.   
0660: 20 22 63 6f 6e 76 65 72 74 20 73 69 6d 70 6c 65   "convert simple
0670: 20 72 75 6c 65 20 73 79 6e 74 61 78 20 74 6f 20   rule syntax to 
0680: 61 20 73 74 72 69 6e 67 20 6f 66 20 50 79 74 68  a string of Pyth
0690: 6f 6e 20 63 6f 64 65 22 0a 20 20 20 20 73 20 3d  on code".    s =
06a0: 20 73 2e 72 65 70 6c 61 63 65 28 22 5f 5f 61 6c   s.replace("__al
06b0: 73 6f 5f 5f 22 2c 20 22 62 43 6f 6e 64 4d 65 6d  so__", "bCondMem
06c0: 6f 22 29 0a 20 20 20 20 73 20 3d 20 73 2e 72 65  o").    s = s.re
06d0: 70 6c 61 63 65 28 22 5f 5f 65 6c 73 65 5f 5f 22  place("__else__"
06e0: 2c 20 22 6e 6f 74 20 62 43 6f 6e 64 4d 65 6d 6f  , "not bCondMemo
06f0: 22 29 0a 20 20 20 20 73 20 3d 20 73 2e 72 65 70  ").    s = s.rep
0700: 6c 61 63 65 28 22 73 43 6f 6e 74 65 78 74 22 2c  lace("sContext",
0710: 20 22 5f 73 41 70 70 43 6f 6e 74 65 78 74 22 29   "_sAppContext")
0720: 0a 20 20 20 20 73 20 3d 20 72 65 2e 73 75 62 28  .    s = re.sub(
0730: 72 22 69 73 53 74 61 72 74 20 2a 5c 28 5c 29 22  r"isStart *\(\)"
0740: 2c 20 27 62 65 66 6f 72 65 28 22 5e 20 2a 24 7c  , 'before("^ *$|
0750: 2c 20 2a 24 22 29 27 2c 20 73 29 0a 20 20 20 20  , *$")', s).    
0760: 73 20 3d 20 72 65 2e 73 75 62 28 72 22 69 73 52  s = re.sub(r"isR
0770: 65 61 6c 53 74 61 72 74 20 2a 5c 28 5c 29 22 2c  ealStart *\(\)",
0780: 20 27 62 65 66 6f 72 65 28 22 5e 20 2a 24 22 29   'before("^ *$")
0790: 27 2c 20 73 29 0a 20 20 20 20 73 20 3d 20 72 65  ', s).    s = re
07a0: 2e 73 75 62 28 72 22 69 73 53 74 61 72 74 30 20  .sub(r"isStart0 
07b0: 2a 5c 28 5c 29 22 2c 20 27 62 65 66 6f 72 65 30  *\(\)", 'before0
07c0: 28 22 5e 20 2a 24 7c 2c 20 2a 24 22 29 27 2c 20  ("^ *$|, *$")', 
07d0: 73 29 0a 20 20 20 20 73 20 3d 20 72 65 2e 73 75  s).    s = re.su
07e0: 62 28 72 22 69 73 52 65 61 6c 53 74 61 72 74 30  b(r"isRealStart0
07f0: 20 2a 5c 28 5c 29 22 2c 20 27 62 65 66 6f 72 65   *\(\)", 'before
0800: 30 28 22 5e 20 2a 24 22 29 27 2c 20 73 29 0a 20  0("^ *$")', s). 
0810: 20 20 20 73 20 3d 20 72 65 2e 73 75 62 28 72 22     s = re.sub(r"
0820: 69 73 45 6e 64 20 2a 5c 28 5c 29 22 2c 20 27 61  isEnd *\(\)", 'a
0830: 66 74 65 72 28 22 5e 20 2a 24 7c 5e 2c 22 29 27  fter("^ *$|^,")'
0840: 2c 20 73 29 0a 20 20 20 20 73 20 3d 20 72 65 2e  , s).    s = re.
0850: 73 75 62 28 72 22 69 73 52 65 61 6c 45 6e 64 20  sub(r"isRealEnd 
0860: 2a 5c 28 5c 29 22 2c 20 27 61 66 74 65 72 28 22  *\(\)", 'after("
0870: 5e 20 2a 24 22 29 27 2c 20 73 29 0a 20 20 20 20  ^ *$")', s).    
0880: 73 20 3d 20 72 65 2e 73 75 62 28 72 22 69 73 45  s = re.sub(r"isE
0890: 6e 64 30 20 2a 5c 28 5c 29 22 2c 20 27 61 66 74  nd0 *\(\)", 'aft
08a0: 65 72 30 28 22 5e 20 2a 24 7c 5e 2c 22 29 27 2c  er0("^ *$|^,")',
08b0: 20 73 29 0a 20 20 20 20 73 20 3d 20 72 65 2e 73   s).    s = re.s
08c0: 75 62 28 72 22 69 73 52 65 61 6c 45 6e 64 30 20  ub(r"isRealEnd0 
08d0: 2a 5c 28 5c 29 22 2c 20 27 61 66 74 65 72 30 28  *\(\)", 'after0(
08e0: 22 5e 20 2a 24 22 29 27 2c 20 73 29 0a 20 20 20  "^ *$")', s).   
08f0: 20 73 20 3d 20 72 65 2e 73 75 62 28 72 22 28 73   s = re.sub(r"(s
0900: 65 6c 65 63 74 7c 65 78 63 6c 75 64 65 29 5b 28  elect|exclude)[(
0910: 5d 5b 5c 5c 5d 28 5c 64 2b 29 22 2c 20 27 5c 5c  ][\\](\d+)", '\\
0920: 31 28 64 54 6f 6b 65 6e 50 6f 73 2c 20 6d 2e 73  1(dTokenPos, m.s
0930: 74 61 72 74 28 5c 5c 32 29 2c 20 6d 2e 67 72 6f  tart(\\2), m.gro
0940: 75 70 28 5c 5c 32 29 27 2c 20 73 29 0a 20 20 20  up(\\2)', s).   
0950: 20 73 20 3d 20 72 65 2e 73 75 62 28 72 22 64 65   s = re.sub(r"de
0960: 66 69 6e 65 5b 28 5d 5b 5c 5c 5d 28 5c 64 2b 29  fine[(][\\](\d+)
0970: 22 2c 20 27 64 65 66 69 6e 65 28 64 54 6f 6b 65  ", 'define(dToke
0980: 6e 50 6f 73 2c 20 6d 2e 73 74 61 72 74 28 5c 5c  nPos, m.start(\\
0990: 31 29 27 2c 20 73 29 0a 20 20 20 20 73 20 3d 20  1)', s).    s = 
09a0: 72 65 2e 73 75 62 28 72 22 28 6d 6f 72 70 68 7c  re.sub(r"(morph|
09b0: 64 69 73 70 6c 61 79 49 6e 66 6f 29 5b 28 5d 5b  displayInfo)[(][
09c0: 5c 5c 5d 28 5c 64 2b 29 22 2c 20 27 5c 5c 31 28  \\](\d+)", '\\1(
09d0: 28 6d 2e 73 74 61 72 74 28 5c 5c 32 29 2c 20 6d  (m.start(\\2), m
09e0: 2e 67 72 6f 75 70 28 5c 5c 32 29 29 27 2c 20 73  .group(\\2))', s
09f0: 29 0a 20 20 20 20 73 20 3d 20 72 65 2e 73 75 62  ).    s = re.sub
0a00: 28 72 22 28 6d 6f 72 70 68 7c 64 69 73 70 6c 61  (r"(morph|displa
0a10: 79 49 6e 66 6f 29 5b 28 5d 22 2c 20 27 5c 5c 31  yInfo)[(]", '\\1
0a20: 28 64 54 6f 6b 65 6e 50 6f 73 2c 20 27 2c 20 73  (dTokenPos, ', s
0a30: 29 0a 20 20 20 20 73 20 3d 20 72 65 2e 73 75 62  ).    s = re.sub
0a40: 28 72 22 28 73 75 67 67 5c 77 2b 7c 73 77 69 74  (r"(sugg\w+|swit
0a50: 63 68 5c 77 2b 29 5c 28 40 22 2c 20 27 5c 5c 31  ch\w+)\(@", '\\1
0a60: 28 6d 2e 67 72 6f 75 70 28 69 5b 34 5d 29 27 2c  (m.group(i[4])',
0a70: 20 73 29 0a 20 20 20 20 73 20 3d 20 72 65 2e 73   s).    s = re.s
0a80: 75 62 28 72 22 77 6f 72 64 5c 28 5c 73 2a 31 5c  ub(r"word\(\s*1\
0a90: 62 22 2c 20 27 6e 65 78 74 77 6f 72 64 31 28 73  b", 'nextword1(s
0aa0: 53 65 6e 74 65 6e 63 65 2c 20 6d 2e 65 6e 64 28  Sentence, m.end(
0ab0: 29 27 2c 20 73 29 20 20 20 20 20 20 20 20 20 20  )', s)          
0ac0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ad0: 20 20 20 20 20 20 20 20 23 20 77 6f 72 64 28 31          # word(1
0ae0: 29 0a 20 20 20 20 73 20 3d 20 72 65 2e 73 75 62  ).    s = re.sub
0af0: 28 72 22 77 6f 72 64 5c 28 5c 73 2a 2d 31 5c 62  (r"word\(\s*-1\b
0b00: 22 2c 20 27 70 72 65 76 77 6f 72 64 31 28 73 53  ", 'prevword1(sS
0b10: 65 6e 74 65 6e 63 65 2c 20 6d 2e 73 74 61 72 74  entence, m.start
0b20: 28 29 27 2c 20 73 29 20 20 20 20 20 20 20 20 20  ()', s)         
0b30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0b40: 20 20 20 20 20 20 23 20 77 6f 72 64 28 2d 31 29        # word(-1)
0b50: 0a 20 20 20 20 73 20 3d 20 72 65 2e 73 75 62 28  .    s = re.sub(
0b60: 72 22 77 6f 72 64 5c 28 5c 73 2a 28 5c 64 29 22  r"word\(\s*(\d)"
0b70: 2c 20 27 6e 65 78 74 77 6f 72 64 28 73 53 65 6e  , 'nextword(sSen
0b80: 74 65 6e 63 65 2c 20 6d 2e 65 6e 64 28 29 2c 20  tence, m.end(), 
0b90: 5c 5c 31 27 2c 20 73 29 20 20 20 20 20 20 20 20  \\1', s)        
0ba0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0bb0: 20 20 20 20 20 23 20 77 6f 72 64 28 6e 29 0a 20       # word(n). 
0bc0: 20 20 20 73 20 3d 20 72 65 2e 73 75 62 28 72 22     s = re.sub(r"
0bd0: 77 6f 72 64 5c 28 5c 73 2a 2d 28 5c 64 29 22 2c  word\(\s*-(\d)",
0be0: 20 27 70 72 65 76 77 6f 72 64 28 73 53 65 6e 74   'prevword(sSent
0bf0: 65 6e 63 65 2c 20 6d 2e 73 74 61 72 74 28 29 2c  ence, m.start(),
0c00: 20 5c 5c 31 27 2c 20 73 29 20 20 20 20 20 20 20   \\1', s)       
0c10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0c20: 20 20 20 23 20 77 6f 72 64 28 2d 6e 29 0a 20 20     # word(-n).  
0c30: 20 20 73 20 3d 20 72 65 2e 73 75 62 28 72 22 62    s = re.sub(r"b
0c40: 65 66 6f 72 65 5c 28 5c 73 2a 22 2c 20 27 6c 6f  efore\(\s*", 'lo
0c50: 6f 6b 28 73 53 65 6e 74 65 6e 63 65 5b 3a 6d 2e  ok(sSentence[:m.
0c60: 73 74 61 72 74 28 29 5d 2c 20 27 2c 20 73 29 20  start()], ', s) 
0c70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0c80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0c90: 20 20 23 20 62 65 66 6f 72 65 28 73 53 65 6e 74    # before(sSent
0ca0: 65 6e 63 65 29 0a 20 20 20 20 73 20 3d 20 72 65  ence).    s = re
0cb0: 2e 73 75 62 28 72 22 61 66 74 65 72 5c 28 5c 73  .sub(r"after\(\s
0cc0: 2a 22 2c 20 27 6c 6f 6f 6b 28 73 53 65 6e 74 65  *", 'look(sSente
0cd0: 6e 63 65 5b 6d 2e 65 6e 64 28 29 3a 5d 2c 20 27  nce[m.end():], '
0ce0: 2c 20 73 29 20 20 20 20 20 20 20 20 20 20 20 20  , s)            
0cf0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0d00: 20 20 20 20 20 20 20 20 20 20 23 20 61 66 74 65            # afte
0d10: 72 28 73 53 65 6e 74 65 6e 63 65 29 0a 20 20 20  r(sSentence).   
0d20: 20 73 20 3d 20 72 65 2e 73 75 62 28 72 22 74 65   s = re.sub(r"te
0d30: 78 74 61 72 65 61 5c 28 5c 73 2a 22 2c 20 27 6c  xtarea\(\s*", 'l
0d40: 6f 6f 6b 28 73 53 65 6e 74 65 6e 63 65 2c 20 27  ook(sSentence, '
0d50: 2c 20 73 29 20 20 20 20 20 20 20 20 20 20 20 20  , s)            
0d60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0d80: 20 23 20 74 65 78 74 61 72 65 61 28 73 53 65 6e   # textarea(sSen
0d90: 74 65 6e 63 65 29 0a 20 20 20 20 73 20 3d 20 72  tence).    s = r
0da0: 65 2e 73 75 62 28 72 22 2f 30 22 2c 20 27 73 53  e.sub(r"/0", 'sS
0db0: 65 6e 74 65 6e 63 65 30 5b 6d 2e 73 74 61 72 74  entence0[m.start
0dc0: 28 29 3a 6d 2e 65 6e 64 28 29 5d 27 2c 20 73 29  ():m.end()]', s)
0dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0de0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0df0: 20 20 20 20 20 20 20 20 20 20 20 23 20 2f 30 0a             # /0.
0e00: 20 20 20 20 73 20 3d 20 72 65 2e 73 75 62 28 72      s = re.sub(r
0e10: 22 62 65 66 6f 72 65 30 5c 28 5c 73 2a 22 2c 20  "before0\(\s*", 
0e20: 27 6c 6f 6f 6b 28 73 53 65 6e 74 65 6e 63 65 30  'look(sSentence0
0e30: 5b 3a 6d 2e 73 74 61 72 74 28 29 5d 2c 20 27 2c  [:m.start()], ',
0e40: 20 73 29 20 20 20 20 20 20 20 20 20 20 20 20 20   s)             
0e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0e60: 20 20 20 20 23 20 62 65 66 6f 72 65 30 28 73 53      # before0(sS
0e70: 65 6e 74 65 6e 63 65 29 0a 20 20 20 20 73 20 3d  entence).    s =
0e80: 20 72 65 2e 73 75 62 28 72 22 61 66 74 65 72 30   re.sub(r"after0
0e90: 5c 28 5c 73 2a 22 2c 20 27 6c 6f 6f 6b 28 73 53  \(\s*", 'look(sS
0ea0: 65 6e 74 65 6e 63 65 30 5b 6d 2e 65 6e 64 28 29  entence0[m.end()
0eb0: 3a 5d 2c 20 27 2c 20 73 29 20 20 20 20 20 20 20  :], ', s)       
0ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 23 20 61               # a
0ee0: 66 74 65 72 30 28 73 53 65 6e 74 65 6e 63 65 29  fter0(sSentence)
0ef0: 0a 20 20 20 20 73 20 3d 20 72 65 2e 73 75 62 28  .    s = re.sub(
0f00: 72 22 74 65 78 74 61 72 65 61 30 5c 28 5c 73 2a  r"textarea0\(\s*
0f10: 22 2c 20 27 6c 6f 6f 6b 28 73 53 65 6e 74 65 6e  ", 'look(sSenten
0f20: 63 65 30 2c 20 27 2c 20 73 29 20 20 20 20 20 20  ce0, ', s)      
0f30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0f40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0f50: 20 20 20 20 20 23 20 74 65 78 74 61 72 65 61 30       # textarea0
0f60: 28 73 53 65 6e 74 65 6e 63 65 29 0a 20 20 20 20  (sSentence).    
0f70: 73 20 3d 20 72 65 2e 73 75 62 28 72 22 5c 62 73  s = re.sub(r"\bs
0f80: 70 65 6c 6c 20 2a 5b 28 5d 22 2c 20 27 5f 6f 53  pell *[(]", '_oS
0f90: 70 65 6c 6c 43 68 65 63 6b 65 72 2e 69 73 56 61  pellChecker.isVa
0fa0: 6c 69 64 28 27 2c 20 73 29 0a 20 20 20 20 73 20  lid(', s).    s 
0fb0: 3d 20 72 65 2e 73 75 62 28 72 22 5b 5c 5c 5d 28  = re.sub(r"[\\](
0fc0: 5c 64 2b 29 22 2c 20 27 6d 2e 67 72 6f 75 70 28  \d+)", 'm.group(
0fd0: 5c 5c 31 29 27 2c 20 73 29 0a 20 20 20 20 72 65  \\1)', s).    re
0fe0: 74 75 72 6e 20 73 0a 0a 0a 64 65 66 20 75 70 70  turn s...def upp
0ff0: 65 72 63 61 73 65 20 28 73 54 65 78 74 2c 20 73  ercase (sText, s
1000: 4c 61 6e 67 29 3a 0a 20 20 20 20 22 28 66 6c 61  Lang):.    "(fla
1010: 67 20 69 20 69 73 20 6e 6f 74 20 65 6e 6f 75 67  g i is not enoug
1020: 68 29 3a 20 63 6f 6e 76 65 72 74 73 20 72 65 67  h): converts reg
1030: 65 78 20 74 6f 20 75 70 70 65 72 63 61 73 65 20  ex to uppercase 
1040: 72 65 67 65 78 3a 20 27 66 6f 6f 27 20 62 65 63  regex: 'foo' bec
1050: 6f 6d 65 73 20 27 5b 46 66 5d 5b 4f 6f 5d 5b 4f  omes '[Ff][Oo][O
1060: 6f 5d 27 2c 20 62 75 74 20 27 42 61 72 27 20 62  o]', but 'Bar' b
1070: 65 63 6f 6d 65 73 20 27 42 5b 41 61 5d 5b 52 72  ecomes 'B[Aa][Rr
1080: 5d 27 2e 22 0a 20 20 20 20 73 55 70 20 3d 20 22  ]'.".    sUp = "
1090: 22 0a 20 20 20 20 6e 53 74 61 74 65 20 3d 20 30  ".    nState = 0
10a0: 0a 20 20 20 20 66 6f 72 20 69 2c 20 63 20 69 6e  .    for i, c in
10b0: 20 65 6e 75 6d 65 72 61 74 65 28 73 54 65 78 74   enumerate(sText
10c0: 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20 63 20  ):.        if c 
10d0: 3d 3d 20 22 5b 22 3a 0a 20 20 20 20 20 20 20 20  == "[":.        
10e0: 20 20 20 20 6e 53 74 61 74 65 20 3d 20 31 0a 20      nState = 1. 
10f0: 20 20 20 20 20 20 20 69 66 20 6e 53 74 61 74 65         if nState
1100: 20 3d 3d 20 31 20 61 6e 64 20 63 20 3d 3d 20 22   == 1 and c == "
1110: 5d 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ]":.            
1120: 6e 53 74 61 74 65 20 3d 20 30 0a 20 20 20 20 20  nState = 0.     
1130: 20 20 20 69 66 20 63 20 3d 3d 20 22 3c 22 20 61     if c == "<" a
1140: 6e 64 20 69 20 3e 20 33 20 61 6e 64 20 73 54 65  nd i > 3 and sTe
1150: 78 74 5b 69 2d 33 3a 69 5d 20 3d 3d 20 22 28 3f  xt[i-3:i] == "(?
1160: 50 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  P":.            
1170: 6e 53 74 61 74 65 20 3d 20 32 0a 20 20 20 20 20  nState = 2.     
1180: 20 20 20 69 66 20 6e 53 74 61 74 65 20 3d 3d 20     if nState == 
1190: 32 20 61 6e 64 20 63 20 3d 3d 20 22 3e 22 3a 0a  2 and c == ">":.
11a0: 20 20 20 20 20 20 20 20 20 20 20 20 6e 53 74 61              nSta
11b0: 74 65 20 3d 20 30 0a 20 20 20 20 20 20 20 20 69  te = 0.        i
11c0: 66 20 63 20 3d 3d 20 22 3f 22 20 61 6e 64 20 69  f c == "?" and i
11d0: 20 3e 20 30 20 61 6e 64 20 73 54 65 78 74 5b 69   > 0 and sText[i
11e0: 2d 31 3a 69 5d 20 3d 3d 20 22 28 22 20 61 6e 64  -1:i] == "(" and
11f0: 20 73 54 65 78 74 5b 69 2b 31 3a 69 2b 32 5d 20   sText[i+1:i+2] 
1200: 21 3d 20 22 3a 22 3a 0a 20 20 20 20 20 20 20 20  != ":":.        
1210: 20 20 20 20 6e 53 74 61 74 65 20 3d 20 35 0a 20      nState = 5. 
1220: 20 20 20 20 20 20 20 69 66 20 6e 53 74 61 74 65         if nState
1230: 20 3d 3d 20 35 20 61 6e 64 20 63 20 3d 3d 20 22   == 5 and c == "
1240: 29 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  )":.            
1250: 6e 53 74 61 74 65 20 3d 20 30 0a 20 20 20 20 20  nState = 0.     
1260: 20 20 20 69 66 20 63 2e 69 73 61 6c 70 68 61 28     if c.isalpha(
1270: 29 20 61 6e 64 20 63 2e 69 73 6c 6f 77 65 72 28  ) and c.islower(
1280: 29 20 61 6e 64 20 6e 53 74 61 74 65 20 3d 3d 20  ) and nState == 
1290: 30 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  0:.            i
12a0: 66 20 63 20 3d 3d 20 22 69 22 20 61 6e 64 20 73  f c == "i" and s
12b0: 4c 61 6e 67 20 69 6e 20 28 22 74 72 22 2c 20 22  Lang in ("tr", "
12c0: 61 7a 22 29 3a 0a 20 20 20 20 20 20 20 20 20 20  az"):.          
12d0: 20 20 20 20 20 20 73 55 70 20 2b 3d 20 22 5b c4        sUp += "[.
12e0: b0 22 20 2b 20 63 20 2b 20 22 5d 22 0a 20 20 20  ." + c + "]".   
12f0: 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20           else:. 
1300: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
1310: 55 70 20 2b 3d 20 22 5b 22 20 2b 20 63 2e 75 70  Up += "[" + c.up
1320: 70 65 72 28 29 20 2b 20 63 20 2b 20 22 5d 22 0a  per() + c + "]".
1330: 20 20 20 20 20 20 20 20 65 6c 69 66 20 63 2e 69          elif c.i
1340: 73 61 6c 70 68 61 28 29 20 61 6e 64 20 63 2e 69  salpha() and c.i
1350: 73 6c 6f 77 65 72 28 29 20 61 6e 64 20 6e 53 74  slower() and nSt
1360: 61 74 65 20 3d 3d 20 31 20 61 6e 64 20 73 54 65  ate == 1 and sTe
1370: 78 74 5b 69 2b 31 3a 69 2b 32 5d 20 21 3d 20 22  xt[i+1:i+2] != "
1380: 2d 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  -":.            
1390: 69 66 20 73 54 65 78 74 5b 69 2d 31 3a 69 5d 20  if sText[i-1:i] 
13a0: 3d 3d 20 22 2d 22 20 61 6e 64 20 73 54 65 78 74  == "-" and sText
13b0: 5b 69 2d 32 3a 69 2d 31 5d 2e 69 73 6c 6f 77 65  [i-2:i-1].islowe
13c0: 72 28 29 3a 20 20 23 20 5b 61 2d 7a 5d 20 2d 3e  r():  # [a-z] ->
13d0: 20 5b 61 2d 7a 41 2d 5a 5d 0a 20 20 20 20 20 20   [a-zA-Z].      
13e0: 20 20 20 20 20 20 20 20 20 20 73 55 70 20 2b 3d            sUp +=
13f0: 20 63 20 2b 20 73 54 65 78 74 5b 69 2d 32 3a 69   c + sText[i-2:i
1400: 2d 31 5d 2e 75 70 70 65 72 28 29 20 2b 20 22 2d  -1].upper() + "-
1410: 22 20 2b 20 63 2e 75 70 70 65 72 28 29 0a 20 20  " + c.upper().  
1420: 20 20 20 20 20 20 20 20 20 20 65 6c 69 66 20 63            elif c
1430: 20 3d 3d 20 22 69 22 20 61 6e 64 20 73 4c 61 6e   == "i" and sLan
1440: 67 20 69 6e 20 28 22 74 72 22 2c 20 22 61 7a 22  g in ("tr", "az"
1450: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ):.             
1460: 20 20 20 73 55 70 20 2b 3d 20 22 c4 b0 22 20 2b     sUp += ".." +
1470: 20 63 0a 20 20 20 20 20 20 20 20 20 20 20 20 65   c.            e
1480: 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20  lse:.           
1490: 20 20 20 20 20 73 55 70 20 2b 3d 20 63 2e 75 70       sUp += c.up
14a0: 70 65 72 28 29 20 2b 20 63 0a 20 20 20 20 20 20  per() + c.      
14b0: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
14c0: 20 20 20 20 73 55 70 20 2b 3d 20 63 0a 20 20 20      sUp += c.   
14d0: 20 20 20 20 20 69 66 20 63 20 3d 3d 20 22 5c 5c       if c == "\\
14e0: 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 6e  ":.            n
14f0: 53 74 61 74 65 20 3d 20 34 0a 20 20 20 20 20 20  State = 4.      
1500: 20 20 65 6c 69 66 20 6e 53 74 61 74 65 20 3d 3d    elif nState ==
1510: 20 34 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20   4:.            
1520: 6e 53 74 61 74 65 20 3d 20 30 0a 20 20 20 20 72  nState = 0.    r
1530: 65 74 75 72 6e 20 73 55 70 0a 0a 0a 64 65 66 20  eturn sUp...def 
1540: 63 6f 75 6e 74 47 72 6f 75 70 49 6e 52 65 67 65  countGroupInRege
1550: 78 20 28 73 52 65 67 65 78 29 3a 0a 20 20 20 20  x (sRegex):.    
1560: 22 72 65 74 75 72 6e 73 20 74 68 65 20 6e 75 6d  "returns the num
1570: 62 65 72 20 6f 66 20 67 72 6f 75 70 73 20 69 6e  ber of groups in
1580: 20 3c 73 52 65 67 65 78 3e 22 0a 20 20 20 20 74   <sRegex>".    t
1590: 72 79 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75  ry:.        retu
15a0: 72 6e 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 52  rn re.compile(sR
15b0: 65 67 65 78 29 2e 67 72 6f 75 70 73 0a 20 20 20  egex).groups.   
15c0: 20 65 78 63 65 70 74 20 72 65 2e 65 72 72 6f 72   except re.error
15d0: 3a 0a 20 20 20 20 20 20 20 20 74 72 61 63 65 62  :.        traceb
15e0: 61 63 6b 2e 70 72 69 6e 74 5f 65 78 63 28 29 0a  ack.print_exc().
15f0: 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 73 52          print(sR
1600: 65 67 65 78 29 0a 20 20 20 20 72 65 74 75 72 6e  egex).    return
1610: 20 30 0a 0a 0a 64 65 66 20 63 72 65 61 74 65 52   0...def createR
1620: 75 6c 65 20 28 73 2c 20 6e 49 64 4c 69 6e 65 2c  ule (s, nIdLine,
1630: 20 73 4c 61 6e 67 2c 20 62 50 61 72 61 67 72 61   sLang, bParagra
1640: 70 68 2c 20 64 4f 70 74 50 72 69 6f 72 69 74 79  ph, dOptPriority
1650: 29 3a 0a 20 20 20 20 22 72 65 74 75 72 6e 73 20  ):.    "returns 
1660: 72 75 6c 65 20 61 73 20 6c 69 73 74 20 5b 6f 70  rule as list [op
1670: 74 69 6f 6e 20 6e 61 6d 65 2c 20 72 65 67 65 78  tion name, regex
1680: 2c 20 62 43 61 73 65 49 6e 73 65 6e 73 69 74 69  , bCaseInsensiti
1690: 76 65 2c 20 69 64 65 6e 74 69 66 69 65 72 2c 20  ve, identifier, 
16a0: 6c 69 73 74 20 6f 66 20 61 63 74 69 6f 6e 73 5d  list of actions]
16b0: 22 0a 20 20 20 20 67 6c 6f 62 61 6c 20 64 4a 53  ".    global dJS
16c0: 52 45 47 45 58 45 53 0a 0a 20 20 20 20 73 4c 69  REGEXES..    sLi
16d0: 6e 65 49 64 20 3d 20 66 22 23 7b 6e 49 64 4c 69  neId = f"#{nIdLi
16e0: 6e 65 7d 22 20 2b 20 28 22 70 22 20 69 66 20 62  ne}" + ("p" if b
16f0: 50 61 72 61 67 72 61 70 68 20 65 6c 73 65 20 22  Paragraph else "
1700: 73 22 29 0a 20 20 20 20 73 52 75 6c 65 49 64 20  s").    sRuleId 
1710: 3d 20 73 4c 69 6e 65 49 64 0a 0a 20 20 20 20 23  = sLineId..    #
1720: 23 23 23 20 47 52 41 50 48 20 43 41 4c 4c 0a 20  ### GRAPH CALL. 
1730: 20 20 20 69 66 20 73 2e 73 74 61 72 74 73 77 69     if s.startswi
1740: 74 68 28 22 40 40 40 40 22 29 3a 0a 20 20 20 20  th("@@@@"):.    
1750: 20 20 20 20 69 66 20 62 50 61 72 61 67 72 61 70      if bParagrap
1760: 68 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 70  h:.            p
1770: 72 69 6e 74 28 22 45 72 72 6f 72 2e 20 47 72 61  rint("Error. Gra
1780: 70 68 20 63 61 6c 6c 20 63 61 6e 20 62 65 20 6d  ph call can be m
1790: 61 64 65 20 6f 6e 6c 79 20 61 66 74 65 72 20 74  ade only after t
17a0: 68 65 20 66 69 72 73 74 20 70 61 73 73 20 28 73  he first pass (s
17b0: 65 6e 74 65 6e 63 65 20 62 79 20 73 65 6e 74 65  entence by sente
17c0: 6e 63 65 29 22 29 0a 20 20 20 20 20 20 20 20 20  nce)").         
17d0: 20 20 20 65 78 69 74 28 29 0a 20 20 20 20 20 20     exit().      
17e0: 20 20 72 65 74 75 72 6e 20 5b 22 40 40 40 40 22    return ["@@@@"
17f0: 2c 20 73 5b 34 3a 5d 2c 20 73 4c 69 6e 65 49 64  , s[4:], sLineId
1800: 5d 0a 0a 20 20 20 20 23 23 23 23 20 4f 50 54 49  ]..    #### OPTI
1810: 4f 4e 53 0a 20 20 20 20 73 4f 70 74 69 6f 6e 20  ONS.    sOption 
1820: 3d 20 22 22 20 20 20 20 20 20 20 20 20 20 20 20  = ""            
1830: 23 20 65 6d 70 74 79 20 73 74 72 69 6e 67 20 6f  # empty string o
1840: 72 20 5b 61 2d 7a 30 2d 39 5d 2b 20 6e 61 6d 65  r [a-z0-9]+ name
1850: 0a 20 20 20 20 6e 50 72 69 6f 72 69 74 79 20 3d  .    nPriority =
1860: 20 34 20 20 20 20 20 20 20 20 20 20 20 23 20 44   4           # D
1870: 65 66 61 75 6c 74 20 69 73 20 34 2c 20 76 61 6c  efault is 4, val
1880: 75 65 20 6d 75 73 74 20 62 65 20 62 65 74 77 65  ue must be betwe
1890: 65 6e 20 30 20 61 6e 64 20 39 0a 20 20 20 20 74  en 0 and 9.    t
18a0: 47 72 6f 75 70 73 20 3d 20 4e 6f 6e 65 20 20 20  Groups = None   
18b0: 20 20 20 20 20 20 20 23 20 63 6f 64 65 20 66 6f         # code fo
18c0: 72 20 67 72 6f 75 70 73 20 70 6f 73 69 74 69 6f  r groups positio
18d0: 6e 69 6e 67 20 28 6f 6e 6c 79 20 75 73 65 66 75  ning (only usefu
18e0: 6c 20 66 6f 72 20 4a 61 76 61 53 63 72 69 70 74  l for JavaScript
18f0: 29 0a 20 20 20 20 63 43 61 73 65 4d 6f 64 65 20  ).    cCaseMode 
1900: 3d 20 27 69 27 20 20 20 20 20 20 20 20 20 23 20  = 'i'         # 
1910: 69 3a 20 63 61 73 65 20 69 6e 73 65 6e 73 69 74  i: case insensit
1920: 69 76 65 2c 20 20 73 3a 20 63 61 73 65 20 73 65  ive,  s: case se
1930: 6e 73 69 74 69 76 65 2c 20 20 75 3a 20 75 70 70  nsitive,  u: upp
1940: 65 72 63 61 73 69 6e 67 20 61 6c 6c 6f 77 65 64  ercasing allowed
1950: 0a 20 20 20 20 63 57 6f 72 64 4c 69 6d 69 74 4c  .    cWordLimitL
1960: 65 66 74 20 3d 20 27 5b 27 20 20 20 20 23 20 5b  eft = '['    # [
1970: 3a 20 77 6f 72 64 20 6c 69 6d 69 74 2c 20 3c 3a  : word limit, <:
1980: 20 6e 6f 20 73 70 65 63 69 66 69 63 20 6c 69 6d   no specific lim
1990: 69 74 0a 20 20 20 20 63 57 6f 72 64 4c 69 6d 69  it.    cWordLimi
19a0: 74 52 69 67 68 74 20 3d 20 27 5d 27 20 20 20 23  tRight = ']'   #
19b0: 20 5d 3a 20 77 6f 72 64 20 6c 69 6d 69 74 2c 20   ]: word limit, 
19c0: 3e 3a 20 6e 6f 20 73 70 65 63 69 66 69 63 20 6c  >: no specific l
19d0: 69 6d 69 74 0a 20 20 20 20 6d 20 3d 20 72 65 2e  imit.    m = re.
19e0: 6d 61 74 63 68 28 22 5e 5f 5f 28 3f 50 3c 62 6f  match("^__(?P<bo
19f0: 72 64 65 72 73 5f 61 6e 64 5f 63 61 73 65 3e 5b  rders_and_case>[
1a00: 5c 5c 5b 3c 5d 5c 5c 77 5b 5c 5c 5d 3e 5d 29 28  \\[<]\\w[\\]>])(
1a10: 3f 50 3c 6f 70 74 69 6f 6e 3e 2f 5b 61 2d 7a 41  ?P<option>/[a-zA
1a20: 2d 5a 30 2d 39 5d 2b 7c 29 28 3f 50 3c 72 75 6c  -Z0-9]+|)(?P<rul
1a30: 65 69 64 3e 5c 5c 28 5c 5c 77 2b 5c 5c 29 29 28  eid>\\(\\w+\\))(
1a40: 3f 50 3c 70 72 69 6f 72 69 74 79 3e 21 5b 30 2d  ?P<priority>![0-
1a50: 39 5d 7c 29 5f 5f 20 2a 22 2c 20 73 29 0a 20 20  9]|)__ *", s).  
1a60: 20 20 69 66 20 6d 3a 0a 20 20 20 20 20 20 20 20    if m:.        
1a70: 63 57 6f 72 64 4c 69 6d 69 74 4c 65 66 74 20 3d  cWordLimitLeft =
1a80: 20 6d 2e 67 72 6f 75 70 28 27 62 6f 72 64 65 72   m.group('border
1a90: 73 5f 61 6e 64 5f 63 61 73 65 27 29 5b 30 5d 0a  s_and_case')[0].
1aa0: 20 20 20 20 20 20 20 20 63 43 61 73 65 4d 6f 64          cCaseMod
1ab0: 65 20 3d 20 6d 2e 67 72 6f 75 70 28 27 62 6f 72  e = m.group('bor
1ac0: 64 65 72 73 5f 61 6e 64 5f 63 61 73 65 27 29 5b  ders_and_case')[
1ad0: 31 5d 0a 20 20 20 20 20 20 20 20 63 57 6f 72 64  1].        cWord
1ae0: 4c 69 6d 69 74 52 69 67 68 74 20 3d 20 6d 2e 67  LimitRight = m.g
1af0: 72 6f 75 70 28 27 62 6f 72 64 65 72 73 5f 61 6e  roup('borders_an
1b00: 64 5f 63 61 73 65 27 29 5b 32 5d 0a 20 20 20 20  d_case')[2].    
1b10: 20 20 20 20 73 4f 70 74 69 6f 6e 20 3d 20 6d 2e      sOption = m.
1b20: 67 72 6f 75 70 28 27 6f 70 74 69 6f 6e 27 29 5b  group('option')[
1b30: 31 3a 5d 20 20 69 66 20 6d 2e 67 72 6f 75 70 28  1:]  if m.group(
1b40: 27 6f 70 74 69 6f 6e 27 29 20 20 65 6c 73 65 20  'option')  else 
1b50: 22 22 0a 20 20 20 20 20 20 20 20 73 52 75 6c 65  "".        sRule
1b60: 49 64 20 3d 20 20 6d 2e 67 72 6f 75 70 28 27 72  Id =  m.group('r
1b70: 75 6c 65 69 64 27 29 5b 31 3a 2d 31 5d 0a 20 20  uleid')[1:-1].  
1b80: 20 20 20 20 20 20 69 66 20 73 52 75 6c 65 49 64        if sRuleId
1b90: 20 69 6e 20 61 52 55 4c 45 53 45 54 3a 0a 20 20   in aRULESET:.  
1ba0: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28            print(
1bb0: 66 22 23 20 45 72 72 6f 72 2e 20 53 65 76 65 72  f"# Error. Sever
1bc0: 61 6c 20 72 75 6c 65 73 20 68 61 76 65 20 74 68  al rules have th
1bd0: 65 20 73 61 6d 65 20 69 64 3a 20 7b 73 52 75 6c  e same id: {sRul
1be0: 65 49 64 7d 22 29 0a 20 20 20 20 20 20 20 20 20  eId}").         
1bf0: 20 20 20 65 78 69 74 28 29 0a 20 20 20 20 20 20     exit().      
1c00: 20 20 61 52 55 4c 45 53 45 54 2e 61 64 64 28 73    aRULESET.add(s
1c10: 52 75 6c 65 49 64 29 0a 20 20 20 20 20 20 20 20  RuleId).        
1c20: 6e 50 72 69 6f 72 69 74 79 20 3d 20 64 4f 70 74  nPriority = dOpt
1c30: 50 72 69 6f 72 69 74 79 2e 67 65 74 28 73 4f 70  Priority.get(sOp
1c40: 74 69 6f 6e 2c 20 34 29 0a 20 20 20 20 20 20 20  tion, 4).       
1c50: 20 69 66 20 6d 2e 67 72 6f 75 70 28 27 70 72 69   if m.group('pri
1c60: 6f 72 69 74 79 27 29 3a 0a 20 20 20 20 20 20 20  ority'):.       
1c70: 20 20 20 20 20 6e 50 72 69 6f 72 69 74 79 20 3d       nPriority =
1c80: 20 69 6e 74 28 6d 2e 67 72 6f 75 70 28 27 70 72   int(m.group('pr
1c90: 69 6f 72 69 74 79 27 29 5b 31 3a 5d 29 0a 20 20  iority')[1:]).  
1ca0: 20 20 20 20 20 20 73 20 3d 20 73 5b 6d 2e 65 6e        s = s[m.en
1cb0: 64 28 30 29 3a 5d 0a 20 20 20 20 65 6c 73 65 3a  d(0):].    else:
1cc0: 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 66  .        print(f
1cd0: 22 23 20 57 61 72 6e 69 6e 67 2e 20 52 75 6c 65  "# Warning. Rule
1ce0: 20 77 72 6f 6e 67 6c 79 20 73 68 61 70 65 64 20   wrongly shaped 
1cf0: 61 74 20 6c 69 6e 65 3a 20 7b 73 4c 69 6e 65 49  at line: {sLineI
1d00: 64 7d 22 29 0a 20 20 20 20 20 20 20 20 65 78 69  d}").        exi
1d10: 74 28 29 0a 0a 20 20 20 20 23 23 23 23 20 52 45  t()..    #### RE
1d20: 47 45 58 20 54 52 49 47 47 45 52 0a 20 20 20 20  GEX TRIGGER.    
1d30: 69 20 3d 20 73 2e 66 69 6e 64 28 22 20 3c 3c 2d  i = s.find(" <<-
1d40: 22 29 0a 20 20 20 20 69 66 20 69 20 3d 3d 20 2d  ").    if i == -
1d50: 31 3a 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74  1:.        print
1d60: 28 66 22 23 20 45 72 72 6f 72 3a 20 6e 6f 20 63  (f"# Error: no c
1d70: 6f 6e 64 69 74 69 6f 6e 20 61 74 20 6c 69 6e 65  ondition at line
1d80: 20 7b 73 4c 69 6e 65 49 64 7d 22 29 0a 20 20 20   {sLineId}").   
1d90: 20 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e 65       return None
1da0: 0a 20 20 20 20 73 52 65 67 65 78 20 3d 20 73 5b  .    sRegex = s[
1db0: 3a 69 5d 2e 73 74 72 69 70 28 29 0a 20 20 20 20  :i].strip().    
1dc0: 73 20 3d 20 73 5b 69 2b 34 3a 5d 0a 0a 20 20 20  s = s[i+4:]..   
1dd0: 20 23 20 4a 53 20 67 72 6f 75 70 73 20 70 6f 73   # JS groups pos
1de0: 69 74 69 6f 6e 69 6e 67 20 63 6f 64 65 73 0a 20  itioning codes. 
1df0: 20 20 20 6d 20 3d 20 72 65 2e 73 65 61 72 63 68     m = re.search
1e00: 28 22 40 40 5c 5c 53 2b 22 2c 20 73 52 65 67 65  ("@@\\S+", sRege
1e10: 78 29 0a 20 20 20 20 69 66 20 6d 3a 0a 20 20 20  x).    if m:.   
1e20: 20 20 20 20 20 74 47 72 6f 75 70 73 20 3d 20 6a       tGroups = j
1e30: 73 63 6f 6e 76 2e 67 72 6f 75 70 73 50 6f 73 69  sconv.groupsPosi
1e40: 74 69 6f 6e 69 6e 67 43 6f 64 65 54 6f 4c 69 73  tioningCodeToLis
1e50: 74 28 73 52 65 67 65 78 5b 6d 2e 73 74 61 72 74  t(sRegex[m.start
1e60: 28 29 2b 32 3a 5d 29 0a 20 20 20 20 20 20 20 20  ()+2:]).        
1e70: 73 52 65 67 65 78 20 3d 20 73 52 65 67 65 78 5b  sRegex = sRegex[
1e80: 3a 6d 2e 73 74 61 72 74 28 29 5d 2e 73 74 72 69  :m.start()].stri
1e90: 70 28 29 0a 20 20 20 20 23 20 4a 53 20 72 65 67  p().    # JS reg
1ea0: 65 78 0a 20 20 20 20 6d 20 3d 20 72 65 2e 73 65  ex.    m = re.se
1eb0: 61 72 63 68 28 22 3c 6a 73 3e 2e 2b 3c 2f 6a 73  arch("<js>.+</js
1ec0: 3e 69 3f 22 2c 20 73 52 65 67 65 78 29 0a 20 20  >i?", sRegex).  
1ed0: 20 20 69 66 20 6d 3a 0a 20 20 20 20 20 20 20 20    if m:.        
1ee0: 64 4a 53 52 45 47 45 58 45 53 5b 73 4c 69 6e 65  dJSREGEXES[sLine
1ef0: 49 64 5d 20 3d 20 6d 2e 67 72 6f 75 70 28 30 29  Id] = m.group(0)
1f00: 0a 20 20 20 20 20 20 20 20 73 52 65 67 65 78 20  .        sRegex 
1f10: 3d 20 73 52 65 67 65 78 5b 3a 6d 2e 73 74 61 72  = sRegex[:m.star
1f20: 74 28 29 5d 2e 73 74 72 69 70 28 29 0a 20 20 20  t()].strip().   
1f30: 20 69 66 20 22 3c 6a 73 3e 22 20 69 6e 20 73 52   if "<js>" in sR
1f40: 65 67 65 78 20 6f 72 20 22 3c 2f 6a 73 3e 22 20  egex or "</js>" 
1f50: 69 6e 20 73 52 65 67 65 78 3a 0a 20 20 20 20 20  in sRegex:.     
1f60: 20 20 20 70 72 69 6e 74 28 66 22 23 20 45 72 72     print(f"# Err
1f70: 6f 72 3a 20 4a 61 76 61 53 63 72 69 70 74 20 72  or: JavaScript r
1f80: 65 67 65 78 20 6e 6f 74 20 64 65 6c 69 6d 69 74  egex not delimit
1f90: 65 64 20 61 74 20 6c 69 6e 65 20 7b 73 4c 69 6e  ed at line {sLin
1fa0: 65 49 64 7d 22 29 0a 20 20 20 20 20 20 20 20 72  eId}").        r
1fb0: 65 74 75 72 6e 20 4e 6f 6e 65 0a 0a 20 20 20 20  eturn None..    
1fc0: 23 20 71 75 6f 74 65 73 20 3f 0a 20 20 20 20 69  # quotes ?.    i
1fd0: 66 20 73 52 65 67 65 78 2e 73 74 61 72 74 73 77  f sRegex.startsw
1fe0: 69 74 68 28 27 22 27 29 20 61 6e 64 20 73 52 65  ith('"') and sRe
1ff0: 67 65 78 2e 65 6e 64 73 77 69 74 68 28 27 22 27  gex.endswith('"'
2000: 29 3a 0a 20 20 20 20 20 20 20 20 73 52 65 67 65  ):.        sRege
2010: 78 20 3d 20 73 52 65 67 65 78 5b 31 3a 2d 31 5d  x = sRegex[1:-1]
2020: 0a 0a 20 20 20 20 23 23 20 64 65 66 69 6e 69 74  ..    ## definit
2030: 69 6f 6e 73 0a 20 20 20 20 66 6f 72 20 73 44 65  ions.    for sDe
2040: 66 2c 20 73 52 65 70 6c 20 69 6e 20 64 44 45 46  f, sRepl in dDEF
2050: 49 4e 49 54 49 4f 4e 53 2e 69 74 65 6d 73 28 29  INITIONS.items()
2060: 3a 0a 20 20 20 20 20 20 20 20 73 52 65 67 65 78  :.        sRegex
2070: 20 3d 20 73 52 65 67 65 78 2e 72 65 70 6c 61 63   = sRegex.replac
2080: 65 28 73 44 65 66 2c 20 73 52 65 70 6c 29 0a 0a  e(sDef, sRepl)..
2090: 20 20 20 20 23 23 20 63 6f 75 6e 74 20 6e 75 6d      ## count num
20a0: 62 65 72 20 6f 66 20 67 72 6f 75 70 73 20 28 6d  ber of groups (m
20b0: 75 73 74 20 62 65 20 64 6f 6e 65 20 62 65 66 6f  ust be done befo
20c0: 72 65 20 6d 6f 64 69 66 79 69 6e 67 20 74 68 65  re modifying the
20d0: 20 72 65 67 65 78 29 0a 20 20 20 20 6e 47 72 6f   regex).    nGro
20e0: 75 70 20 3d 20 63 6f 75 6e 74 47 72 6f 75 70 49  up = countGroupI
20f0: 6e 52 65 67 65 78 28 73 52 65 67 65 78 29 0a 20  nRegex(sRegex). 
2100: 20 20 20 69 66 20 6e 47 72 6f 75 70 20 3e 20 30     if nGroup > 0
2110: 3a 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74  :.        if not
2120: 20 74 47 72 6f 75 70 73 3a 0a 20 20 20 20 20 20   tGroups:.      
2130: 20 20 20 20 20 20 70 72 69 6e 74 28 66 22 23 20        print(f"# 
2140: 57 61 72 6e 69 6e 67 3a 20 67 72 6f 75 70 73 20  Warning: groups 
2150: 70 6f 73 69 74 69 6f 6e 69 6e 67 20 63 6f 64 65  positioning code
2160: 20 66 6f 72 20 4a 61 76 61 53 63 72 69 70 74 20   for JavaScript 
2170: 73 68 6f 75 6c 64 20 62 65 20 64 65 66 69 6e 65  should be define
2180: 64 20 61 74 20 6c 69 6e 65 20 7b 73 4c 69 6e 65  d at line {sLine
2190: 49 64 7d 22 29 0a 20 20 20 20 20 20 20 20 65 6c  Id}").        el
21a0: 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  se:.            
21b0: 69 66 20 6e 47 72 6f 75 70 20 21 3d 20 6c 65 6e  if nGroup != len
21c0: 28 74 47 72 6f 75 70 73 29 3a 0a 20 20 20 20 20  (tGroups):.     
21d0: 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74             print
21e0: 28 66 22 23 20 45 72 72 6f 72 3a 20 67 72 6f 75  (f"# Error: grou
21f0: 70 73 20 70 6f 73 69 74 69 6f 6e 69 6e 67 20 63  ps positioning c
2200: 6f 64 65 20 69 72 72 65 6c 65 76 61 6e 74 20 61  ode irrelevant a
2210: 74 20 6c 69 6e 65 20 7b 73 4c 69 6e 65 49 64 7d  t line {sLineId}
2220: 22 29 0a 0a 20 20 20 20 23 23 20 77 6f 72 64 20  ")..    ## word 
2230: 6c 69 6d 69 74 0a 20 20 20 20 69 66 20 63 57 6f  limit.    if cWo
2240: 72 64 4c 69 6d 69 74 4c 65 66 74 20 3d 3d 20 27  rdLimitLeft == '
2250: 5b 27 20 61 6e 64 20 6e 6f 74 20 73 52 65 67 65  [' and not sRege
2260: 78 2e 73 74 61 72 74 73 77 69 74 68 28 28 22 5e  x.startswith(("^
2270: 22 2c 20 27 e2 80 99 27 2c 20 22 27 22 2c 20 22  ", '...', "'", "
2280: 2c 22 29 29 3a 0a 20 20 20 20 20 20 20 20 73 52  ,")):.        sR
2290: 65 67 65 78 20 3d 20 73 57 4f 52 44 4c 49 4d 49  egex = sWORDLIMI
22a0: 54 4c 45 46 54 20 2b 20 73 52 65 67 65 78 0a 20  TLEFT + sRegex. 
22b0: 20 20 20 69 66 20 63 57 6f 72 64 4c 69 6d 69 74     if cWordLimit
22c0: 52 69 67 68 74 20 3d 3d 20 27 5d 27 20 61 6e 64  Right == ']' and
22d0: 20 6e 6f 74 20 73 52 65 67 65 78 2e 65 6e 64 73   not sRegex.ends
22e0: 77 69 74 68 28 28 22 24 22 2c 20 27 e2 80 99 27  with(("$", '...'
22f0: 2c 20 22 27 22 2c 20 22 2c 22 29 29 3a 0a 20 20  , "'", ",")):.  
2300: 20 20 20 20 20 20 73 52 65 67 65 78 20 3d 20 73        sRegex = s
2310: 52 65 67 65 78 20 2b 20 73 57 4f 52 44 4c 49 4d  Regex + sWORDLIM
2320: 49 54 52 49 47 48 54 0a 0a 20 20 20 20 23 23 20  ITRIGHT..    ## 
2330: 63 61 73 69 6e 67 20 6d 6f 64 65 0a 20 20 20 20  casing mode.    
2340: 69 66 20 63 43 61 73 65 4d 6f 64 65 20 3d 3d 20  if cCaseMode == 
2350: 22 69 22 3a 0a 20 20 20 20 20 20 20 20 62 43 61  "i":.        bCa
2360: 73 65 49 6e 73 65 6e 73 69 74 69 76 65 20 3d 20  seInsensitive = 
2370: 54 72 75 65 0a 20 20 20 20 20 20 20 20 69 66 20  True.        if 
2380: 6e 6f 74 20 73 52 65 67 65 78 2e 73 74 61 72 74  not sRegex.start
2390: 73 77 69 74 68 28 22 28 3f 69 29 22 29 3a 0a 20  swith("(?i)"):. 
23a0: 20 20 20 20 20 20 20 20 20 20 20 73 52 65 67 65             sRege
23b0: 78 20 3d 20 22 28 3f 69 29 22 20 2b 20 73 52 65  x = "(?i)" + sRe
23c0: 67 65 78 0a 20 20 20 20 65 6c 69 66 20 63 43 61  gex.    elif cCa
23d0: 73 65 4d 6f 64 65 20 3d 3d 20 22 73 22 3a 0a 20  seMode == "s":. 
23e0: 20 20 20 20 20 20 20 62 43 61 73 65 49 6e 73 65         bCaseInse
23f0: 6e 73 69 74 69 76 65 20 3d 20 46 61 6c 73 65 0a  nsitive = False.
2400: 20 20 20 20 20 20 20 20 73 52 65 67 65 78 20 3d          sRegex =
2410: 20 73 52 65 67 65 78 2e 72 65 70 6c 61 63 65 28   sRegex.replace(
2420: 22 28 3f 69 29 22 2c 20 22 22 29 0a 20 20 20 20  "(?i)", "").    
2430: 65 6c 69 66 20 63 43 61 73 65 4d 6f 64 65 20 3d  elif cCaseMode =
2440: 3d 20 22 75 22 3a 0a 20 20 20 20 20 20 20 20 62  = "u":.        b
2450: 43 61 73 65 49 6e 73 65 6e 73 69 74 69 76 65 20  CaseInsensitive 
2460: 3d 20 46 61 6c 73 65 0a 20 20 20 20 20 20 20 20  = False.        
2470: 73 52 65 67 65 78 20 3d 20 73 52 65 67 65 78 2e  sRegex = sRegex.
2480: 72 65 70 6c 61 63 65 28 22 28 3f 69 29 22 2c 20  replace("(?i)", 
2490: 22 22 29 0a 20 20 20 20 20 20 20 20 73 52 65 67  "").        sReg
24a0: 65 78 20 3d 20 75 70 70 65 72 63 61 73 65 28 73  ex = uppercase(s
24b0: 52 65 67 65 78 2c 20 73 4c 61 6e 67 29 0a 20 20  Regex, sLang).  
24c0: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
24d0: 70 72 69 6e 74 28 66 22 23 20 55 6e 6b 6e 6f 77  print(f"# Unknow
24e0: 6e 20 63 61 73 65 20 6d 6f 64 65 20 5b 7b 63 43  n case mode [{cC
24f0: 61 73 65 4d 6f 64 65 7d 5d 20 61 74 20 6c 69 6e  aseMode}] at lin
2500: 65 20 7b 73 4c 69 6e 65 49 64 7d 22 29 0a 0a 20  e {sLineId}").. 
2510: 20 20 20 23 23 20 63 68 65 63 6b 20 72 65 67 65     ## check rege
2520: 78 0a 20 20 20 20 74 72 79 3a 0a 20 20 20 20 20  x.    try:.     
2530: 20 20 20 72 65 2e 63 6f 6d 70 69 6c 65 28 73 52     re.compile(sR
2540: 65 67 65 78 29 0a 20 20 20 20 65 78 63 65 70 74  egex).    except
2550: 20 72 65 2e 65 72 72 6f 72 3a 0a 20 20 20 20 20   re.error:.     
2560: 20 20 20 70 72 69 6e 74 28 66 22 23 20 52 65 67     print(f"# Reg
2570: 65 78 20 65 72 72 6f 72 20 61 74 20 6c 69 6e 65  ex error at line
2580: 20 7b 73 4c 69 6e 65 49 64 7d 22 29 0a 20 20 20   {sLineId}").   
2590: 20 20 20 20 20 70 72 69 6e 74 28 73 52 65 67 65       print(sRege
25a0: 78 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  x).        retur
25b0: 6e 20 4e 6f 6e 65 0a 20 20 20 20 23 23 20 67 72  n None.    ## gr
25c0: 6f 75 70 73 20 69 6e 20 6e 6f 6e 20 67 72 6f 75  oups in non grou
25d0: 70 69 6e 67 20 70 61 72 65 6e 74 68 65 73 69 73  ping parenthesis
25e0: 0a 20 20 20 20 66 6f 72 20 5f 20 69 6e 20 72 65  .    for _ in re
25f0: 2e 66 69 6e 64 69 74 65 72 28 72 22 5c 28 5c 3f  .finditer(r"\(\?
2600: 3a 5b 5e 29 5d 2a 5c 28 5b 5c 5b 5c 77 20 2d 5d  :[^)]*\([\[\w -]
2610: 22 2c 20 73 52 65 67 65 78 29 3a 0a 20 20 20 20  ", sRegex):.    
2620: 20 20 20 20 70 72 69 6e 74 28 66 22 23 20 57 61      print(f"# Wa
2630: 72 6e 69 6e 67 3a 20 67 72 6f 75 70 73 20 69 6e  rning: groups in
2640: 73 69 64 65 20 6e 6f 6e 20 67 72 6f 75 70 69 6e  side non groupin
2650: 67 20 70 61 72 65 6e 74 68 65 73 69 73 20 69 6e  g parenthesis in
2660: 20 72 65 67 65 78 20 61 74 20 6c 69 6e 65 20 7b   regex at line {
2670: 73 4c 69 6e 65 49 64 7d 22 29 0a 0a 20 20 20 20  sLineId}")..    
2680: 23 23 23 23 20 50 41 52 53 45 20 41 43 54 49 4f  #### PARSE ACTIO
2690: 4e 53 0a 20 20 20 20 6c 41 63 74 69 6f 6e 73 20  NS.    lActions 
26a0: 3d 20 5b 5d 0a 20 20 20 20 6e 41 63 74 69 6f 6e  = [].    nAction
26b0: 20 3d 20 31 0a 20 20 20 20 66 6f 72 20 73 41 63   = 1.    for sAc
26c0: 74 69 6f 6e 20 69 6e 20 73 2e 73 70 6c 69 74 28  tion in s.split(
26d0: 22 20 3c 3c 2d 20 22 29 3a 0a 20 20 20 20 20 20  " <<- "):.      
26e0: 20 20 74 20 3d 20 63 72 65 61 74 65 41 63 74 69    t = createActi
26f0: 6f 6e 28 73 52 75 6c 65 49 64 20 2b 20 22 5f 22  on(sRuleId + "_"
2700: 20 2b 20 73 74 72 28 6e 41 63 74 69 6f 6e 29 2c   + str(nAction),
2710: 20 73 41 63 74 69 6f 6e 2c 20 6e 47 72 6f 75 70   sAction, nGroup
2720: 29 0a 20 20 20 20 20 20 20 20 6e 41 63 74 69 6f  ).        nActio
2730: 6e 20 2b 3d 20 31 0a 20 20 20 20 20 20 20 20 69  n += 1.        i
2740: 66 20 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20  f t:.           
2750: 20 6c 41 63 74 69 6f 6e 73 2e 61 70 70 65 6e 64   lActions.append
2760: 28 74 29 0a 20 20 20 20 69 66 20 6e 6f 74 20 6c  (t).    if not l
2770: 41 63 74 69 6f 6e 73 3a 0a 20 20 20 20 20 20 20  Actions:.       
2780: 20 72 65 74 75 72 6e 20 4e 6f 6e 65 0a 0a 20 20   return None..  
2790: 20 20 72 65 74 75 72 6e 20 5b 73 4f 70 74 69 6f    return [sOptio
27a0: 6e 2c 20 73 52 65 67 65 78 2c 20 62 43 61 73 65  n, sRegex, bCase
27b0: 49 6e 73 65 6e 73 69 74 69 76 65 2c 20 73 4c 69  Insensitive, sLi
27c0: 6e 65 49 64 2c 20 73 52 75 6c 65 49 64 2c 20 6e  neId, sRuleId, n
27d0: 50 72 69 6f 72 69 74 79 2c 20 6c 41 63 74 69 6f  Priority, lActio
27e0: 6e 73 2c 20 74 47 72 6f 75 70 73 5d 0a 0a 0a 64  ns, tGroups]...d
27f0: 65 66 20 63 68 65 63 6b 52 65 66 65 72 65 6e 63  ef checkReferenc
2800: 65 4e 75 6d 62 65 72 73 20 28 73 54 65 78 74 2c  eNumbers (sText,
2810: 20 73 41 63 74 69 6f 6e 49 64 2c 20 6e 54 6f 6b   sActionId, nTok
2820: 65 6e 29 3a 0a 20 20 20 20 22 63 68 65 63 6b 20  en):.    "check 
2830: 69 66 20 74 6f 6b 65 6e 20 72 65 66 65 72 65 6e  if token referen
2840: 63 65 73 20 69 6e 20 3c 73 54 65 78 74 3e 20 67  ces in <sText> g
2850: 72 65 61 74 65 72 20 74 68 61 6e 20 3c 6e 54 6f  reater than <nTo
2860: 6b 65 6e 3e 20 28 64 65 62 75 67 67 69 6e 67 29  ken> (debugging)
2870: 22 0a 20 20 20 20 66 6f 72 20 78 20 69 6e 20 72  ".    for x in r
2880: 65 2e 66 69 6e 64 69 74 65 72 28 72 22 5c 5c 28  e.finditer(r"\\(
2890: 5c 64 2b 29 22 2c 20 73 54 65 78 74 29 3a 0a 20  \d+)", sText):. 
28a0: 20 20 20 20 20 20 20 69 66 20 69 6e 74 28 78 2e         if int(x.
28b0: 67 72 6f 75 70 28 31 29 29 20 3e 20 6e 54 6f 6b  group(1)) > nTok
28c0: 65 6e 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  en:.            
28d0: 70 72 69 6e 74 28 66 22 23 20 45 72 72 6f 72 20  print(f"# Error 
28e0: 69 6e 20 74 6f 6b 65 6e 20 69 6e 64 65 78 20 61  in token index a
28f0: 74 20 6c 69 6e 65 20 7b 73 41 63 74 69 6f 6e 49  t line {sActionI
2900: 64 7d 20 28 7b 6e 54 6f 6b 65 6e 7d 20 74 6f 6b  d} ({nToken} tok
2910: 65 6e 73 20 6f 6e 6c 79 29 22 29 0a 20 20 20 20  ens only)").    
2920: 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 73 54          print(sT
2930: 65 78 74 29 0a 0a 0a 64 65 66 20 63 68 65 63 6b  ext)...def check
2940: 49 66 54 68 65 72 65 49 73 43 6f 64 65 20 28 73  IfThereIsCode (s
2950: 54 65 78 74 2c 20 73 41 63 74 69 6f 6e 49 64 29  Text, sActionId)
2960: 3a 0a 20 20 20 20 22 63 68 65 63 6b 20 69 66 20  :.    "check if 
2970: 74 68 65 72 65 20 69 73 20 63 6f 64 65 20 69 6e  there is code in
2980: 20 3c 73 54 65 78 74 3e 20 28 64 65 62 75 67 67   <sText> (debugg
2990: 69 6e 67 29 22 0a 20 20 20 20 69 66 20 72 65 2e  ing)".    if re.
29a0: 73 65 61 72 63 68 28 22 5b 2e 5d 5c 5c 77 2b 5b  search("[.]\\w+[
29b0: 28 5d 7c 73 75 67 67 5c 5c 77 2b 5b 28 5d 7c 5c  (]|sugg\\w+[(]|\
29c0: 5c 28 5b 30 2d 39 5d 7c 5c 5c 5b 5b 30 2d 39 5d  \([0-9]|\\[[0-9]
29d0: 22 2c 20 73 54 65 78 74 29 3a 0a 20 20 20 20 20  ", sText):.     
29e0: 20 20 20 70 72 69 6e 74 28 66 22 23 20 57 61 72     print(f"# War
29f0: 6e 69 6e 67 20 61 74 20 6c 69 6e 65 20 7b 73 41  ning at line {sA
2a00: 63 74 69 6f 6e 49 64 7d 3a 20 20 54 68 69 73 20  ctionId}:  This 
2a10: 6d 65 73 73 61 67 65 20 6c 6f 6f 6b 73 20 6c 69  message looks li
2a20: 6b 65 20 63 6f 64 65 2e 20 4c 69 6e 65 20 73 68  ke code. Line sh
2a30: 6f 75 6c 64 20 70 72 6f 62 61 62 6c 79 20 62 65  ould probably be
2a40: 67 69 6e 20 77 69 74 68 20 3d 22 29 0a 20 20 20  gin with =").   
2a50: 20 20 20 20 20 70 72 69 6e 74 28 73 54 65 78 74       print(sText
2a60: 29 0a 0a 0a 64 65 66 20 63 72 65 61 74 65 41 63  )...def createAc
2a70: 74 69 6f 6e 20 28 73 49 64 41 63 74 69 6f 6e 2c  tion (sIdAction,
2a80: 20 73 41 63 74 69 6f 6e 2c 20 6e 47 72 6f 75 70   sAction, nGroup
2a90: 29 3a 0a 20 20 20 20 22 72 65 74 75 72 6e 73 20  ):.    "returns 
2aa0: 61 6e 20 61 63 74 69 6f 6e 20 74 6f 20 70 65 72  an action to per
2ab0: 66 6f 72 6d 20 61 73 20 61 20 74 75 70 6c 65 20  form as a tuple 
2ac0: 28 63 6f 6e 64 69 74 69 6f 6e 2c 20 61 63 74 69  (condition, acti
2ad0: 6f 6e 20 74 79 70 65 2c 20 61 63 74 69 6f 6e 5b  on type, action[
2ae0: 2c 20 69 47 72 6f 75 70 20 5b 2c 20 6d 65 73 73  , iGroup [, mess
2af0: 61 67 65 2c 20 55 52 4c 20 5d 5d 29 22 0a 20 20  age, URL ]])".  
2b00: 20 20 6d 20 3d 20 72 65 2e 73 65 61 72 63 68 28    m = re.search(
2b10: 72 22 28 5b 2d 7e 3d 3e 5d 29 28 5c 64 2a 7c 29  r"([-~=>])(\d*|)
2b20: 3e 3e 22 2c 20 73 41 63 74 69 6f 6e 29 0a 20 20  >>", sAction).  
2b30: 20 20 69 66 20 6e 6f 74 20 6d 3a 0a 20 20 20 20    if not m:.    
2b40: 20 20 20 20 70 72 69 6e 74 28 66 22 23 20 4e 6f      print(f"# No
2b50: 20 61 63 74 69 6f 6e 20 61 74 20 6c 69 6e 65 20   action at line 
2b60: 7b 73 49 64 41 63 74 69 6f 6e 7d 22 29 0a 20 20  {sIdAction}").  
2b70: 20 20 20 20 20 20 72 65 74 75 72 6e 20 4e 6f 6e        return Non
2b80: 65 0a 0a 20 20 20 20 23 23 23 23 20 43 4f 4e 44  e..    #### COND
2b90: 49 54 49 4f 4e 0a 20 20 20 20 73 43 6f 6e 64 69  ITION.    sCondi
2ba0: 74 69 6f 6e 20 3d 20 73 41 63 74 69 6f 6e 5b 3a  tion = sAction[:
2bb0: 6d 2e 73 74 61 72 74 28 29 5d 2e 73 74 72 69 70  m.start()].strip
2bc0: 28 29 0a 20 20 20 20 69 66 20 73 43 6f 6e 64 69  ().    if sCondi
2bd0: 74 69 6f 6e 3a 0a 20 20 20 20 20 20 20 20 73 43  tion:.        sC
2be0: 6f 6e 64 69 74 69 6f 6e 20 3d 20 70 72 65 70 61  ondition = prepa
2bf0: 72 65 46 75 6e 63 74 69 6f 6e 28 73 43 6f 6e 64  reFunction(sCond
2c00: 69 74 69 6f 6e 29 0a 20 20 20 20 20 20 20 20 6c  ition).        l
2c10: 46 55 4e 43 54 49 4f 4e 53 2e 61 70 70 65 6e 64  FUNCTIONS.append
2c20: 28 28 22 5f 63 5f 22 2b 73 49 64 41 63 74 69 6f  (("_c_"+sIdActio
2c30: 6e 2c 20 73 43 6f 6e 64 69 74 69 6f 6e 29 29 0a  n, sCondition)).
2c40: 20 20 20 20 20 20 20 20 63 68 65 63 6b 52 65 66          checkRef
2c50: 65 72 65 6e 63 65 4e 75 6d 62 65 72 73 28 73 43  erenceNumbers(sC
2c60: 6f 6e 64 69 74 69 6f 6e 2c 20 73 49 64 41 63 74  ondition, sIdAct
2c70: 69 6f 6e 2c 20 6e 47 72 6f 75 70 29 0a 20 20 20  ion, nGroup).   
2c80: 20 20 20 20 20 69 66 20 22 2e 6d 61 74 63 68 22       if ".match"
2c90: 20 69 6e 20 73 43 6f 6e 64 69 74 69 6f 6e 3a 0a   in sCondition:.
2ca0: 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e              prin
2cb0: 74 28 22 23 20 45 72 72 6f 72 2e 20 4a 53 20 63  t("# Error. JS c
2cc0: 6f 6d 70 61 74 69 62 69 6c 69 74 79 2e 20 44 6f  ompatibility. Do
2cd0: 6e 27 74 20 75 73 65 20 2e 6d 61 74 63 68 28 29  n't use .match()
2ce0: 20 69 6e 20 63 6f 6e 64 69 74 69 6f 6e 2c 20 75   in condition, u
2cf0: 73 65 20 2e 73 65 61 72 63 68 28 29 22 29 0a 20  se .search()"). 
2d00: 20 20 20 20 20 20 20 73 43 6f 6e 64 69 74 69 6f         sConditio
2d10: 6e 20 3d 20 22 5f 63 5f 22 2b 73 49 64 41 63 74  n = "_c_"+sIdAct
2d20: 69 6f 6e 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20  ion.    else:.  
2d30: 20 20 20 20 20 20 73 43 6f 6e 64 69 74 69 6f 6e        sCondition
2d40: 20 3d 20 4e 6f 6e 65 0a 0a 20 20 20 20 23 23 23   = None..    ###
2d50: 23 20 69 47 72 6f 75 70 20 2f 20 70 6f 73 69 74  # iGroup / posit
2d60: 69 6f 6e 69 6e 67 0a 20 20 20 20 69 47 72 6f 75  ioning.    iGrou
2d70: 70 20 3d 20 69 6e 74 28 6d 2e 67 72 6f 75 70 28  p = int(m.group(
2d80: 32 29 29 20 69 66 20 6d 2e 67 72 6f 75 70 28 32  2)) if m.group(2
2d90: 29 20 65 6c 73 65 20 30 0a 20 20 20 20 69 66 20  ) else 0.    if 
2da0: 69 47 72 6f 75 70 20 3e 20 6e 47 72 6f 75 70 3a  iGroup > nGroup:
2db0: 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28 66  .        print(f
2dc0: 22 23 20 53 65 6c 65 63 74 65 64 20 67 72 6f 75  "# Selected grou
2dd0: 70 20 3e 20 67 72 6f 75 70 20 6e 75 6d 62 65 72  p > group number
2de0: 20 69 6e 20 72 65 67 65 78 20 61 74 20 6c 69 6e   in regex at lin
2df0: 65 20 7b 73 49 64 41 63 74 69 6f 6e 7d 22 29 0a  e {sIdAction}").
2e00: 0a 20 20 20 20 23 23 23 23 20 41 43 54 49 4f 4e  .    #### ACTION
2e10: 0a 20 20 20 20 73 41 63 74 69 6f 6e 20 3d 20 73  .    sAction = s
2e20: 41 63 74 69 6f 6e 5b 6d 2e 65 6e 64 28 29 3a 5d  Action[m.end():]
2e30: 2e 73 74 72 69 70 28 29 0a 20 20 20 20 63 41 63  .strip().    cAc
2e40: 74 69 6f 6e 20 3d 20 6d 2e 67 72 6f 75 70 28 31  tion = m.group(1
2e50: 29 0a 20 20 20 20 69 66 20 63 41 63 74 69 6f 6e  ).    if cAction
2e60: 20 3d 3d 20 22 2d 22 3a 0a 20 20 20 20 20 20 20   == "-":.       
2e70: 20 23 23 20 65 72 72 6f 72 0a 20 20 20 20 20 20   ## error.      
2e80: 20 20 69 4d 73 67 20 3d 20 73 41 63 74 69 6f 6e    iMsg = sAction
2e90: 2e 66 69 6e 64 28 22 20 23 20 22 29 0a 20 20 20  .find(" # ").   
2ea0: 20 20 20 20 20 69 66 20 69 4d 73 67 20 3d 3d 20       if iMsg == 
2eb0: 2d 31 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  -1:.            
2ec0: 73 4d 73 67 20 3d 20 22 23 20 45 72 72 6f 72 2e  sMsg = "# Error.
2ed0: 20 45 72 72 6f 72 20 6d 65 73 73 61 67 65 20 6e   Error message n
2ee0: 6f 74 20 66 6f 75 6e 64 2e 22 0a 20 20 20 20 20  ot found.".     
2ef0: 20 20 20 20 20 20 20 73 55 52 4c 20 3d 20 22 22         sURL = ""
2f00: 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69  .            pri
2f10: 6e 74 28 66 22 23 20 4e 6f 20 6d 65 73 73 61 67  nt(f"# No messag
2f20: 65 2e 20 41 63 74 69 6f 6e 20 69 64 3a 20 7b 73  e. Action id: {s
2f30: 49 64 41 63 74 69 6f 6e 7d 22 29 0a 20 20 20 20  IdAction}").    
2f40: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
2f50: 20 20 20 20 20 20 73 4d 73 67 20 3d 20 73 41 63        sMsg = sAc
2f60: 74 69 6f 6e 5b 69 4d 73 67 2b 33 3a 5d 2e 73 74  tion[iMsg+3:].st
2f70: 72 69 70 28 29 0a 20 20 20 20 20 20 20 20 20 20  rip().          
2f80: 20 20 73 41 63 74 69 6f 6e 20 3d 20 73 41 63 74    sAction = sAct
2f90: 69 6f 6e 5b 3a 69 4d 73 67 5d 2e 73 74 72 69 70  ion[:iMsg].strip
2fa0: 28 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 73  ().            s
2fb0: 55 52 4c 20 3d 20 22 22 0a 20 20 20 20 20 20 20  URL = "".       
2fc0: 20 20 20 20 20 6d 55 52 4c 20 3d 20 72 65 2e 73       mURL = re.s
2fd0: 65 61 72 63 68 28 22 5b 7c 5d 20 2a 28 68 74 74  earch("[|] *(htt
2fe0: 70 73 3f 3a 2f 2f 2e 2a 29 22 2c 20 73 4d 73 67  ps?://.*)", sMsg
2ff0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  ).            if
3000: 20 6d 55 52 4c 3a 0a 20 20 20 20 20 20 20 20 20   mURL:.         
3010: 20 20 20 20 20 20 20 73 55 52 4c 20 3d 20 6d 55         sURL = mU
3020: 52 4c 2e 67 72 6f 75 70 28 31 29 2e 73 74 72 69  RL.group(1).stri
3030: 70 28 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  p().            
3040: 20 20 20 20 73 4d 73 67 20 3d 20 73 4d 73 67 5b      sMsg = sMsg[
3050: 3a 6d 55 52 4c 2e 73 74 61 72 74 28 30 29 5d 2e  :mURL.start(0)].
3060: 73 74 72 69 70 28 29 0a 20 20 20 20 20 20 20 20  strip().        
3070: 20 20 20 20 63 68 65 63 6b 52 65 66 65 72 65 6e      checkReferen
3080: 63 65 4e 75 6d 62 65 72 73 28 73 4d 73 67 2c 20  ceNumbers(sMsg, 
3090: 73 49 64 41 63 74 69 6f 6e 2c 20 6e 47 72 6f 75  sIdAction, nGrou
30a0: 70 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 69  p).            i
30b0: 66 20 73 4d 73 67 5b 30 3a 31 5d 20 3d 3d 20 22  f sMsg[0:1] == "
30c0: 3d 22 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  =":.            
30d0: 20 20 20 20 73 4d 73 67 20 3d 20 70 72 65 70 61      sMsg = prepa
30e0: 72 65 46 75 6e 63 74 69 6f 6e 28 73 4d 73 67 5b  reFunction(sMsg[
30f0: 31 3a 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20  1:]).           
3100: 20 20 20 20 20 6c 46 55 4e 43 54 49 4f 4e 53 2e       lFUNCTIONS.
3110: 61 70 70 65 6e 64 28 28 22 5f 6d 5f 22 2b 73 49  append(("_m_"+sI
3120: 64 41 63 74 69 6f 6e 2c 20 73 4d 73 67 29 29 0a  dAction, sMsg)).
3130: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
3140: 73 4d 73 67 20 3d 20 22 3d 5f 6d 5f 22 2b 73 49  sMsg = "=_m_"+sI
3150: 64 41 63 74 69 6f 6e 0a 20 20 20 20 20 20 20 20  dAction.        
3160: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
3170: 20 20 20 20 20 20 20 20 20 20 63 68 65 63 6b 49            checkI
3180: 66 54 68 65 72 65 49 73 43 6f 64 65 28 73 4d 73  fThereIsCode(sMs
3190: 67 2c 20 73 49 64 41 63 74 69 6f 6e 29 0a 0a 20  g, sIdAction).. 
31a0: 20 20 20 63 68 65 63 6b 52 65 66 65 72 65 6e 63     checkReferenc
31b0: 65 4e 75 6d 62 65 72 73 28 73 41 63 74 69 6f 6e  eNumbers(sAction
31c0: 2c 20 73 49 64 41 63 74 69 6f 6e 2c 20 6e 47 72  , sIdAction, nGr
31d0: 6f 75 70 29 0a 20 20 20 20 69 66 20 73 41 63 74  oup).    if sAct
31e0: 69 6f 6e 5b 30 3a 31 5d 20 3d 3d 20 22 3d 22 20  ion[0:1] == "=" 
31f0: 6f 72 20 63 41 63 74 69 6f 6e 20 3d 3d 20 22 3d  or cAction == "=
3200: 22 3a 0a 20 20 20 20 20 20 20 20 73 41 63 74 69  ":.        sActi
3210: 6f 6e 20 3d 20 70 72 65 70 61 72 65 46 75 6e 63  on = prepareFunc
3220: 74 69 6f 6e 28 73 41 63 74 69 6f 6e 29 0a 20 20  tion(sAction).  
3230: 20 20 20 20 20 20 73 41 63 74 69 6f 6e 20 3d 20        sAction = 
3240: 73 41 63 74 69 6f 6e 2e 72 65 70 6c 61 63 65 28  sAction.replace(
3250: 22 6d 2e 67 72 6f 75 70 28 69 5b 34 5d 29 22 2c  "m.group(i[4])",
3260: 20 22 6d 2e 67 72 6f 75 70 28 22 2b 73 74 72 28   "m.group("+str(
3270: 69 47 72 6f 75 70 29 2b 22 29 22 29 0a 20 20 20  iGroup)+")").   
3280: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 63   else:.        c
3290: 68 65 63 6b 49 66 54 68 65 72 65 49 73 43 6f 64  heckIfThereIsCod
32a0: 65 28 73 41 63 74 69 6f 6e 2c 20 73 49 64 41 63  e(sAction, sIdAc
32b0: 74 69 6f 6e 29 0a 0a 20 20 20 20 69 66 20 63 41  tion)..    if cA
32c0: 63 74 69 6f 6e 20 3d 3d 20 22 3e 22 3a 0a 20 20  ction == ">":.  
32d0: 20 20 20 20 20 20 23 23 20 6e 6f 20 61 63 74 69        ## no acti
32e0: 6f 6e 2c 20 62 72 65 61 6b 20 6c 6f 6f 70 20 69  on, break loop i
32f0: 66 20 63 6f 6e 64 69 74 69 6f 6e 20 69 73 20 46  f condition is F
3300: 61 6c 73 65 0a 20 20 20 20 20 20 20 20 72 65 74  alse.        ret
3310: 75 72 6e 20 5b 73 43 6f 6e 64 69 74 69 6f 6e 2c  urn [sCondition,
3320: 20 63 41 63 74 69 6f 6e 2c 20 22 22 5d 0a 0a 20   cAction, ""].. 
3330: 20 20 20 69 66 20 6e 6f 74 20 73 41 63 74 69 6f     if not sActio
3340: 6e 3a 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74  n:.        print
3350: 28 66 22 23 20 45 72 72 6f 72 20 69 6e 20 61 63  (f"# Error in ac
3360: 74 69 6f 6e 20 61 74 20 6c 69 6e 65 20 7b 73 49  tion at line {sI
3370: 64 41 63 74 69 6f 6e 7d 3a 20 20 54 68 69 73 20  dAction}:  This 
3380: 61 63 74 69 6f 6e 20 69 73 20 65 6d 70 74 79 2e  action is empty.
3390: 22 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72  ").        retur
33a0: 6e 20 4e 6f 6e 65 0a 0a 20 20 20 20 69 66 20 63  n None..    if c
33b0: 41 63 74 69 6f 6e 20 3d 3d 20 22 2d 22 3a 0a 20  Action == "-":. 
33c0: 20 20 20 20 20 20 20 23 23 20 65 72 72 6f 72 20         ## error 
33d0: 64 65 74 65 63 74 65 64 20 2d 2d 3e 20 73 75 67  detected --> sug
33e0: 67 65 73 74 69 6f 6e 0a 20 20 20 20 20 20 20 20  gestion.        
33f0: 69 66 20 73 41 63 74 69 6f 6e 5b 30 3a 31 5d 20  if sAction[0:1] 
3400: 3d 3d 20 22 3d 22 3a 0a 20 20 20 20 20 20 20 20  == "=":.        
3410: 20 20 20 20 6c 46 55 4e 43 54 49 4f 4e 53 2e 61      lFUNCTIONS.a
3420: 70 70 65 6e 64 28 28 22 5f 73 5f 22 2b 73 49 64  ppend(("_s_"+sId
3430: 41 63 74 69 6f 6e 2c 20 73 41 63 74 69 6f 6e 5b  Action, sAction[
3440: 31 3a 5d 29 29 0a 20 20 20 20 20 20 20 20 20 20  1:])).          
3450: 20 20 73 41 63 74 69 6f 6e 20 3d 20 22 3d 5f 73    sAction = "=_s
3460: 5f 22 2b 73 49 64 41 63 74 69 6f 6e 0a 20 20 20  _"+sIdAction.   
3470: 20 20 20 20 20 65 6c 69 66 20 73 41 63 74 69 6f       elif sActio
3480: 6e 2e 73 74 61 72 74 73 77 69 74 68 28 27 22 27  n.startswith('"'
3490: 29 20 61 6e 64 20 73 41 63 74 69 6f 6e 2e 65 6e  ) and sAction.en
34a0: 64 73 77 69 74 68 28 27 22 27 29 3a 0a 20 20 20  dswith('"'):.   
34b0: 20 20 20 20 20 20 20 20 20 73 41 63 74 69 6f 6e           sAction
34c0: 20 3d 20 73 41 63 74 69 6f 6e 5b 31 3a 2d 31 5d   = sAction[1:-1]
34d0: 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20  .        if not 
34e0: 73 4d 73 67 3a 0a 20 20 20 20 20 20 20 20 20 20  sMsg:.          
34f0: 20 20 70 72 69 6e 74 28 66 22 23 20 45 72 72 6f    print(f"# Erro
3500: 72 20 69 6e 20 61 63 74 69 6f 6e 20 61 74 20 6c  r in action at l
3510: 69 6e 65 20 7b 73 49 64 41 63 74 69 6f 6e 7d 3a  ine {sIdAction}:
3520: 20 20 74 68 65 20 6d 65 73 73 61 67 65 20 69 73    the message is
3530: 20 65 6d 70 74 79 2e 22 29 0a 20 20 20 20 20 20   empty.").      
3540: 20 20 72 65 74 75 72 6e 20 5b 73 43 6f 6e 64 69    return [sCondi
3550: 74 69 6f 6e 2c 20 63 41 63 74 69 6f 6e 2c 20 73  tion, cAction, s
3560: 41 63 74 69 6f 6e 2c 20 69 47 72 6f 75 70 2c 20  Action, iGroup, 
3570: 73 4d 73 67 2c 20 73 55 52 4c 5d 0a 20 20 20 20  sMsg, sURL].    
3580: 69 66 20 63 41 63 74 69 6f 6e 20 3d 3d 20 22 7e  if cAction == "~
3590: 22 3a 0a 20 20 20 20 20 20 20 20 23 23 20 74 65  ":.        ## te
35a0: 78 74 20 70 72 6f 63 65 73 73 6f 72 0a 20 20 20  xt processor.   
35b0: 20 20 20 20 20 69 66 20 73 41 63 74 69 6f 6e 5b       if sAction[
35c0: 30 3a 31 5d 20 3d 3d 20 22 3d 22 3a 0a 20 20 20  0:1] == "=":.   
35d0: 20 20 20 20 20 20 20 20 20 6c 46 55 4e 43 54 49           lFUNCTI
35e0: 4f 4e 53 2e 61 70 70 65 6e 64 28 28 22 5f 70 5f  ONS.append(("_p_
35f0: 22 2b 73 49 64 41 63 74 69 6f 6e 2c 20 73 41 63  "+sIdAction, sAc
3600: 74 69 6f 6e 5b 31 3a 5d 29 29 0a 20 20 20 20 20  tion[1:])).     
3610: 20 20 20 20 20 20 20 73 41 63 74 69 6f 6e 20 3d         sAction =
3620: 20 22 3d 5f 70 5f 22 2b 73 49 64 41 63 74 69 6f   "=_p_"+sIdActio
3630: 6e 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 73  n.        elif s
3640: 41 63 74 69 6f 6e 2e 73 74 61 72 74 73 77 69 74  Action.startswit
3650: 68 28 27 22 27 29 20 61 6e 64 20 73 41 63 74 69  h('"') and sActi
3660: 6f 6e 2e 65 6e 64 73 77 69 74 68 28 27 22 27 29  on.endswith('"')
3670: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 41  :.            sA
3680: 63 74 69 6f 6e 20 3d 20 73 41 63 74 69 6f 6e 5b  ction = sAction[
3690: 31 3a 2d 31 5d 0a 20 20 20 20 20 20 20 20 72 65  1:-1].        re
36a0: 74 75 72 6e 20 5b 73 43 6f 6e 64 69 74 69 6f 6e  turn [sCondition
36b0: 2c 20 63 41 63 74 69 6f 6e 2c 20 73 41 63 74 69  , cAction, sActi
36c0: 6f 6e 2c 20 69 47 72 6f 75 70 5d 0a 20 20 20 20  on, iGroup].    
36d0: 69 66 20 63 41 63 74 69 6f 6e 20 3d 3d 20 22 3d  if cAction == "=
36e0: 22 3a 0a 20 20 20 20 20 20 20 20 23 23 20 64 69  ":.        ## di
36f0: 73 61 6d 62 69 67 75 61 74 6f 72 0a 20 20 20 20  sambiguator.    
3700: 20 20 20 20 69 66 20 73 41 63 74 69 6f 6e 5b 30      if sAction[0
3710: 3a 31 5d 20 3d 3d 20 22 3d 22 3a 0a 20 20 20 20  :1] == "=":.    
3720: 20 20 20 20 20 20 20 20 73 41 63 74 69 6f 6e 20          sAction 
3730: 3d 20 73 41 63 74 69 6f 6e 5b 31 3a 5d 0a 20 20  = sAction[1:].  
3740: 20 20 20 20 20 20 69 66 20 22 64 65 66 69 6e 65        if "define
3750: 22 20 69 6e 20 73 41 63 74 69 6f 6e 20 61 6e 64  " in sAction and
3760: 20 6e 6f 74 20 72 65 2e 73 65 61 72 63 68 28 72   not re.search(r
3770: 22 64 65 66 69 6e 65 5c 28 64 54 6f 6b 65 6e 50  "define\(dTokenP
3780: 6f 73 2c 20 2a 6d 5c 2e 73 74 61 72 74 2e 2a 2c  os, *m\.start.*,
3790: 20 5c 5b 2e 2a 5c 5d 20 2a 5c 29 22 2c 20 73 41   \[.*\] *\)", sA
37a0: 63 74 69 6f 6e 29 3a 0a 20 20 20 20 20 20 20 20  ction):.        
37b0: 20 20 20 20 70 72 69 6e 74 28 66 22 23 20 45 72      print(f"# Er
37c0: 72 6f 72 20 69 6e 20 61 63 74 69 6f 6e 20 61 74  ror in action at
37d0: 20 6c 69 6e 65 20 7b 73 49 64 41 63 74 69 6f 6e   line {sIdAction
37e0: 7d 3a 20 73 65 63 6f 6e 64 20 61 72 67 75 6d 65  }: second argume
37f0: 6e 74 20 66 6f 72 20 64 65 66 69 6e 65 20 6d 75  nt for define mu
3800: 73 74 20 62 65 20 61 20 6c 69 73 74 20 6f 66 20  st be a list of 
3810: 73 74 72 69 6e 67 73 22 29 0a 20 20 20 20 20 20  strings").      
3820: 20 20 20 20 20 20 70 72 69 6e 74 28 73 41 63 74        print(sAct
3830: 69 6f 6e 29 0a 20 20 20 20 20 20 20 20 6c 46 55  ion).        lFU
3840: 4e 43 54 49 4f 4e 53 2e 61 70 70 65 6e 64 28 28  NCTIONS.append((
3850: 22 5f 64 5f 22 2b 73 49 64 41 63 74 69 6f 6e 2c  "_d_"+sIdAction,
3860: 20 73 41 63 74 69 6f 6e 29 29 0a 20 20 20 20 20   sAction)).     
3870: 20 20 20 73 41 63 74 69 6f 6e 20 3d 20 22 5f 64     sAction = "_d
3880: 5f 22 2b 73 49 64 41 63 74 69 6f 6e 0a 20 20 20  _"+sIdAction.   
3890: 20 20 20 20 20 72 65 74 75 72 6e 20 5b 73 43 6f       return [sCo
38a0: 6e 64 69 74 69 6f 6e 2c 20 63 41 63 74 69 6f 6e  ndition, cAction
38b0: 2c 20 73 41 63 74 69 6f 6e 5d 0a 20 20 20 20 70  , sAction].    p
38c0: 72 69 6e 74 28 66 22 23 20 55 6e 6b 6e 6f 77 6e  rint(f"# Unknown
38d0: 20 61 63 74 69 6f 6e 20 61 74 20 6c 69 6e 65 20   action at line 
38e0: 7b 73 49 64 41 63 74 69 6f 6e 7d 22 29 0a 20 20  {sIdAction}").  
38f0: 20 20 72 65 74 75 72 6e 20 4e 6f 6e 65 0a 0a 0a    return None...
3900: 64 65 66 20 5f 63 61 6c 63 52 75 6c 65 73 53 74  def _calcRulesSt
3910: 61 74 73 20 28 6c 52 75 6c 65 73 29 3a 0a 20 20  ats (lRules):.  
3920: 20 20 22 63 6f 75 6e 74 20 72 75 6c 65 73 20 61    "count rules a
3930: 6e 64 20 61 63 74 69 6f 6e 73 22 0a 20 20 20 20  nd actions".    
3940: 64 20 3d 20 7b 27 3d 27 3a 30 2c 20 27 7e 27 3a  d = {'=':0, '~':
3950: 20 30 2c 20 27 2d 27 3a 20 30 2c 20 27 3e 27 3a   0, '-': 0, '>':
3960: 20 30 7d 0a 20 20 20 20 66 6f 72 20 61 52 75 6c   0}.    for aRul
3970: 65 20 69 6e 20 6c 52 75 6c 65 73 3a 0a 20 20 20  e in lRules:.   
3980: 20 20 20 20 20 69 66 20 61 52 75 6c 65 5b 30 5d       if aRule[0]
3990: 20 21 3d 20 22 40 40 40 40 22 3a 0a 20 20 20 20   != "@@@@":.    
39a0: 20 20 20 20 20 20 20 20 66 6f 72 20 61 41 63 74          for aAct
39b0: 69 6f 6e 20 69 6e 20 61 52 75 6c 65 5b 36 5d 3a  ion in aRule[6]:
39c0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
39d0: 20 64 5b 61 41 63 74 69 6f 6e 5b 31 5d 5d 20 3d   d[aAction[1]] =
39e0: 20 64 5b 61 41 63 74 69 6f 6e 5b 31 5d 5d 20 2b   d[aAction[1]] +
39f0: 20 31 0a 20 20 20 20 72 65 74 75 72 6e 20 28 64   1.    return (d
3a00: 2c 20 6c 65 6e 28 6c 52 75 6c 65 73 29 29 0a 0a  , len(lRules))..
3a10: 0a 64 65 66 20 64 69 73 70 6c 61 79 53 74 61 74  .def displayStat
3a20: 73 20 28 6c 50 61 72 61 67 72 61 70 68 52 75 6c  s (lParagraphRul
3a30: 65 73 2c 20 6c 53 65 6e 74 65 6e 63 65 52 75 6c  es, lSentenceRul
3a40: 65 73 29 3a 0a 20 20 20 20 22 64 69 73 70 6c 61  es):.    "displa
3a50: 79 20 72 75 6c 65 73 20 6e 75 6d 62 65 72 73 22  y rules numbers"
3a60: 0a 20 20 20 20 70 72 69 6e 74 28 22 20 20 20 20  .    print("    
3a70: 20 20 20 20 20 20 20 20 20 20 20 7b 3a 3e 31 38             {:>18
3a80: 7d 20 7b 3a 3e 31 38 7d 20 7b 3a 3e 31 38 7d 20  } {:>18} {:>18} 
3a90: 7b 3a 3e 31 38 7d 22 2e 66 6f 72 6d 61 74 28 22  {:>18}".format("
3aa0: 44 49 53 41 4d 42 49 47 55 41 54 4f 52 22 2c 20  DISAMBIGUATOR", 
3ab0: 22 54 45 58 54 20 50 52 4f 43 45 53 53 4f 52 22  "TEXT PROCESSOR"
3ac0: 2c 20 22 47 52 41 4d 4d 41 52 20 43 48 45 43 4b  , "GRAMMAR CHECK
3ad0: 49 4e 47 22 2c 20 22 52 45 47 45 58 22 29 29 0a  ING", "REGEX")).
3ae0: 20 20 20 20 64 2c 20 6e 52 75 6c 65 20 3d 20 5f      d, nRule = _
3af0: 63 61 6c 63 52 75 6c 65 73 53 74 61 74 73 28 6c  calcRulesStats(l
3b00: 50 61 72 61 67 72 61 70 68 52 75 6c 65 73 29 0a  ParagraphRules).
3b10: 20 20 20 20 70 72 69 6e 74 28 22 20 20 20 20 70      print("    p
3b20: 61 72 61 67 72 61 70 68 3a 20 7b 3a 3e 31 30 7d  aragraph: {:>10}
3b30: 20 61 63 74 69 6f 6e 73 20 7b 3a 3e 31 30 7d 20   actions {:>10} 
3b40: 61 63 74 69 6f 6e 73 20 7b 3a 3e 31 30 7d 20 61  actions {:>10} a
3b50: 63 74 69 6f 6e 73 20 20 69 6e 20 7b 3a 3e 38 7d  ctions  in {:>8}
3b60: 20 72 75 6c 65 73 22 2e 66 6f 72 6d 61 74 28 64   rules".format(d
3b70: 5b 27 3d 27 5d 2c 20 64 5b 27 7e 27 5d 2c 20 64  ['='], d['~'], d
3b80: 5b 27 2d 27 5d 2c 20 6e 52 75 6c 65 29 29 0a 20  ['-'], nRule)). 
3b90: 20 20 20 64 2c 20 6e 52 75 6c 65 20 3d 20 5f 63     d, nRule = _c
3ba0: 61 6c 63 52 75 6c 65 73 53 74 61 74 73 28 6c 53  alcRulesStats(lS
3bb0: 65 6e 74 65 6e 63 65 52 75 6c 65 73 29 0a 20 20  entenceRules).  
3bc0: 20 20 70 72 69 6e 74 28 22 20 20 20 20 73 65 6e    print("    sen
3bd0: 74 65 6e 63 65 3a 20 20 7b 3a 3e 31 30 7d 20 61  tence:  {:>10} a
3be0: 63 74 69 6f 6e 73 20 7b 3a 3e 31 30 7d 20 61 63  ctions {:>10} ac
3bf0: 74 69 6f 6e 73 20 7b 3a 3e 31 30 7d 20 61 63 74  tions {:>10} act
3c00: 69 6f 6e 73 20 20 69 6e 20 7b 3a 3e 38 7d 20 72  ions  in {:>8} r
3c10: 75 6c 65 73 22 2e 66 6f 72 6d 61 74 28 64 5b 27  ules".format(d['
3c20: 3d 27 5d 2c 20 64 5b 27 7e 27 5d 2c 20 64 5b 27  ='], d['~'], d['
3c30: 2d 27 5d 2c 20 6e 52 75 6c 65 29 29 0a 0a 0a 64  -'], nRule))...d
3c40: 65 66 20 6d 65 72 67 65 52 75 6c 65 73 42 79 4f  ef mergeRulesByO
3c50: 70 74 69 6f 6e 20 28 6c 52 75 6c 65 73 29 3a 0a  ption (lRules):.
3c60: 20 20 20 20 22 72 65 74 75 72 6e 73 20 61 20 6c      "returns a l
3c70: 69 73 74 20 6f 66 20 74 75 70 6c 65 73 20 5b 6f  ist of tuples [o
3c80: 70 74 69 6f 6e 2c 20 6c 69 73 74 20 6f 66 20 72  ption, list of r
3c90: 75 6c 65 73 5d 20 6b 65 65 70 69 6e 67 20 74 68  ules] keeping th
3ca0: 65 20 72 75 6c 65 73 20 6f 72 64 65 72 22 0a 20  e rules order". 
3cb0: 20 20 20 6c 46 69 6e 61 6c 20 3d 20 5b 5d 0a 20     lFinal = []. 
3cc0: 20 20 20 6c 54 65 6d 70 20 3d 20 5b 5d 0a 20 20     lTemp = [].  
3cd0: 20 20 73 4f 70 74 69 6f 6e 20 3d 20 4e 6f 6e 65    sOption = None
3ce0: 0a 20 20 20 20 66 6f 72 20 61 52 75 6c 65 20 69  .    for aRule i
3cf0: 6e 20 6c 52 75 6c 65 73 3a 0a 20 20 20 20 20 20  n lRules:.      
3d00: 20 20 69 66 20 61 52 75 6c 65 5b 30 5d 20 21 3d    if aRule[0] !=
3d10: 20 73 4f 70 74 69 6f 6e 3a 0a 20 20 20 20 20 20   sOption:.      
3d20: 20 20 20 20 20 20 69 66 20 73 4f 70 74 69 6f 6e        if sOption
3d30: 20 69 73 20 6e 6f 74 20 4e 6f 6e 65 3a 0a 20 20   is not None:.  
3d40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c 46                lF
3d50: 69 6e 61 6c 2e 61 70 70 65 6e 64 28 5b 73 4f 70  inal.append([sOp
3d60: 74 69 6f 6e 2c 20 6c 54 65 6d 70 5d 29 0a 20 20  tion, lTemp]).  
3d70: 20 20 20 20 20 20 20 20 20 20 23 20 6e 65 77 20            # new 
3d80: 74 75 70 6c 65 0a 20 20 20 20 20 20 20 20 20 20  tuple.          
3d90: 20 20 73 4f 70 74 69 6f 6e 20 3d 20 61 52 75 6c    sOption = aRul
3da0: 65 5b 30 5d 0a 20 20 20 20 20 20 20 20 20 20 20  e[0].           
3db0: 20 6c 54 65 6d 70 20 3d 20 5b 5d 0a 20 20 20 20   lTemp = [].    
3dc0: 20 20 20 20 6c 54 65 6d 70 2e 61 70 70 65 6e 64      lTemp.append
3dd0: 28 61 52 75 6c 65 5b 31 3a 5d 29 0a 20 20 20 20  (aRule[1:]).    
3de0: 6c 46 69 6e 61 6c 2e 61 70 70 65 6e 64 28 5b 73  lFinal.append([s
3df0: 4f 70 74 69 6f 6e 2c 20 6c 54 65 6d 70 5d 29 0a  Option, lTemp]).
3e00: 20 20 20 20 72 65 74 75 72 6e 20 6c 46 69 6e 61      return lFina
3e10: 6c 0a 0a 0a 64 65 66 20 63 72 65 61 74 65 52 75  l...def createRu
3e20: 6c 65 73 41 73 53 74 72 69 6e 67 20 28 6c 52 75  lesAsString (lRu
3e30: 6c 65 73 29 3a 0a 20 20 20 20 22 63 72 65 61 74  les):.    "creat
3e40: 65 20 72 75 6c 65 73 20 61 73 20 61 20 73 74 72  e rules as a str
3e50: 69 6e 67 20 6f 66 20 61 72 72 61 79 73 20 28 74  ing of arrays (t
3e60: 6f 20 62 65 20 62 75 6e 64 6c 65 64 20 69 6e 20  o be bundled in 
3e70: 61 20 4a 53 4f 4e 20 73 74 72 69 6e 67 29 22 0a  a JSON string)".
3e80: 20 20 20 20 73 41 72 72 61 79 20 3d 20 22 5b 5c      sArray = "[\
3e90: 6e 22 0a 20 20 20 20 66 6f 72 20 73 4f 70 74 69  n".    for sOpti
3ea0: 6f 6e 2c 20 61 52 75 6c 65 47 72 6f 75 70 20 69  on, aRuleGroup i
3eb0: 6e 20 6c 52 75 6c 65 73 3a 0a 20 20 20 20 20 20  n lRules:.      
3ec0: 20 20 73 41 72 72 61 79 20 2b 3d 20 66 27 20 20    sArray += f'  
3ed0: 5b 22 7b 73 4f 70 74 69 6f 6e 7d 22 2c 20 5b 5c  ["{sOption}", [\
3ee0: 6e 27 0a 20 20 20 20 20 20 20 20 66 6f 72 20 61  n'.        for a
3ef0: 52 75 6c 65 20 69 6e 20 61 52 75 6c 65 47 72 6f  Rule in aRuleGro
3f00: 75 70 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  up:.            
3f10: 73 41 72 72 61 79 20 2b 3d 20 66 27 20 20 20 20  sArray += f'    
3f20: 7b 61 52 75 6c 65 7d 2c 5c 6e 27 0a 20 20 20 20  {aRule},\n'.    
3f30: 20 20 20 20 73 41 72 72 61 79 20 2b 3d 20 22 20      sArray += " 
3f40: 20 5d 5d 2c 5c 6e 22 0a 20 20 20 20 73 41 72 72   ]],\n".    sArr
3f50: 61 79 20 2b 3d 20 22 5d 22 0a 20 20 20 20 72 65  ay += "]".    re
3f60: 74 75 72 6e 20 73 41 72 72 61 79 0a 0a 0a 64 65  turn sArray...de
3f70: 66 20 70 72 65 70 61 72 65 4f 70 74 69 6f 6e 73  f prepareOptions
3f80: 20 28 6c 4f 70 74 69 6f 6e 4c 69 6e 65 73 29 3a   (lOptionLines):
3f90: 0a 20 20 20 20 22 72 65 74 75 72 6e 73 20 61 20  .    "returns a 
3fa0: 64 69 63 74 69 6f 6e 61 72 79 20 77 69 74 68 20  dictionary with 
3fb0: 64 61 74 61 20 61 62 6f 75 74 20 6f 70 74 69 6f  data about optio
3fc0: 6e 73 22 0a 20 20 20 20 73 4c 61 6e 67 20 3d 20  ns".    sLang = 
3fd0: 22 22 0a 20 20 20 20 73 44 65 66 61 75 6c 74 55  "".    sDefaultU
3fe0: 49 4c 61 6e 67 20 3d 20 22 22 0a 20 20 20 20 6c  ILang = "".    l
3ff0: 53 74 72 75 63 74 4f 70 74 20 3d 20 5b 5d 0a 20  StructOpt = []. 
4000: 20 20 20 6c 4f 70 74 20 3d 20 5b 5d 0a 20 20 20     lOpt = [].   
4010: 20 6c 4f 70 74 43 6f 6c 6f 72 20 3d 20 5b 5d 0a   lOptColor = [].
4020: 20 20 20 20 64 43 6f 6c 6f 72 20 3d 20 7b 7d 0a      dColor = {}.
4030: 20 20 20 20 64 4f 70 74 4c 61 62 65 6c 20 3d 20      dOptLabel = 
4040: 7b 7d 0a 20 20 20 20 64 4f 70 74 50 72 69 6f 72  {}.    dOptPrior
4050: 69 74 79 20 3d 20 7b 7d 0a 20 20 20 20 66 6f 72  ity = {}.    for
4060: 20 73 4c 69 6e 65 20 69 6e 20 6c 4f 70 74 69 6f   sLine in lOptio
4070: 6e 4c 69 6e 65 73 3a 0a 20 20 20 20 20 20 20 20  nLines:.        
4080: 73 4c 69 6e 65 20 3d 20 73 4c 69 6e 65 2e 73 74  sLine = sLine.st
4090: 72 69 70 28 29 0a 20 20 20 20 20 20 20 20 69 66  rip().        if
40a0: 20 73 4c 69 6e 65 2e 73 74 61 72 74 73 77 69 74   sLine.startswit
40b0: 68 28 22 4f 50 54 47 52 4f 55 50 2f 22 29 3a 0a  h("OPTGROUP/"):.
40c0: 20 20 20 20 20 20 20 20 20 20 20 20 6d 20 3d 20              m = 
40d0: 72 65 2e 6d 61 74 63 68 28 22 4f 50 54 47 52 4f  re.match("OPTGRO
40e0: 55 50 2f 28 5b 61 2d 7a 30 2d 39 5d 2b 29 3a 28  UP/([a-z0-9]+):(
40f0: 2e 2b 29 24 22 2c 20 73 4c 69 6e 65 29 0a 20 20  .+)$", sLine).  
4100: 20 20 20 20 20 20 20 20 20 20 6c 53 74 72 75 63            lStruc
4110: 74 4f 70 74 2e 61 70 70 65 6e 64 28 20 5b 6d 2e  tOpt.append( [m.
4120: 67 72 6f 75 70 28 31 29 2c 20 6c 69 73 74 28 6d  group(1), list(m
4130: 61 70 28 73 74 72 2e 73 70 6c 69 74 2c 20 6d 2e  ap(str.split, m.
4140: 67 72 6f 75 70 28 32 29 2e 73 70 6c 69 74 28 22  group(2).split("
4150: 2c 22 29 29 29 5d 20 29 0a 20 20 20 20 20 20 20  ,")))] ).       
4160: 20 65 6c 69 66 20 73 4c 69 6e 65 2e 73 74 61 72   elif sLine.star
4170: 74 73 77 69 74 68 28 22 4f 50 54 53 4f 46 54 57  tswith("OPTSOFTW
4180: 41 52 45 3a 22 29 3a 0a 20 20 20 20 20 20 20 20  ARE:"):.        
4190: 20 20 20 20 6c 4f 70 74 20 3d 20 5b 20 5b 73 2c      lOpt = [ [s,
41a0: 20 7b 7d 5d 20 20 66 6f 72 20 73 20 69 6e 20 73   {}]  for s in s
41b0: 4c 69 6e 65 5b 31 32 3a 5d 2e 73 74 72 69 70 28  Line[12:].strip(
41c0: 29 2e 73 70 6c 69 74 28 29 20 5d 20 20 23 20 64  ).split() ]  # d
41d0: 6f 6e e2 80 99 74 20 75 73 65 20 74 75 70 6c 65  on...t use tuple
41e0: 73 20 28 73 2c 20 7b 7d 29 2c 20 62 65 63 61 75  s (s, {}), becau
41f0: 73 65 20 75 6e 6b 6e 6f 77 6e 20 74 6f 20 4a 53  se unknown to JS
4200: 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 73 4c  .        elif sL
4210: 69 6e 65 2e 73 74 61 72 74 73 77 69 74 68 28 22  ine.startswith("
4220: 4f 50 54 2f 22 29 3a 0a 20 20 20 20 20 20 20 20  OPT/"):.        
4230: 20 20 20 20 6d 20 3d 20 72 65 2e 6d 61 74 63 68      m = re.match
4240: 28 22 4f 50 54 2f 28 5b 61 2d 7a 30 2d 39 5d 2b  ("OPT/([a-z0-9]+
4250: 29 3a 28 2e 2b 29 24 22 2c 20 73 4c 69 6e 65 29  ):(.+)$", sLine)
4260: 0a 20 20 20 20 20 20 20 20 20 20 20 20 66 6f 72  .            for
4270: 20 69 2c 20 73 4f 70 74 20 69 6e 20 65 6e 75 6d   i, sOpt in enum
4280: 65 72 61 74 65 28 6d 2e 67 72 6f 75 70 28 32 29  erate(m.group(2)
4290: 2e 73 70 6c 69 74 28 29 29 3a 0a 20 20 20 20 20  .split()):.     
42a0: 20 20 20 20 20 20 20 20 20 20 20 6c 4f 70 74 5b             lOpt[
42b0: 69 5d 5b 31 5d 5b 6d 2e 67 72 6f 75 70 28 31 29  i][1][m.group(1)
42c0: 5d 20 3d 20 73 4f 70 74 20 69 6e 20 28 22 54 72  ] = sOpt in ("Tr
42d0: 75 65 22 2c 20 22 74 72 75 65 22 2c 20 22 59 65  ue", "true", "Ye
42e0: 73 22 2c 20 22 79 65 73 22 29 0a 20 20 20 20 20  s", "yes").     
42f0: 20 20 20 65 6c 69 66 20 73 4c 69 6e 65 2e 73 74     elif sLine.st
4300: 61 72 74 73 77 69 74 68 28 22 4f 50 54 43 4f 4c  artswith("OPTCOL
4310: 4f 52 54 48 45 4d 45 3a 22 29 3a 0a 20 20 20 20  ORTHEME:"):.    
4320: 20 20 20 20 20 20 20 20 6c 4f 70 74 43 6f 6c 6f          lOptColo
4330: 72 20 3d 20 5b 20 5b 73 2c 20 7b 7d 5d 20 20 66  r = [ [s, {}]  f
4340: 6f 72 20 73 20 69 6e 20 73 4c 69 6e 65 5b 31 34  or s in sLine[14
4350: 3a 5d 2e 73 74 72 69 70 28 29 2e 73 70 6c 69 74  :].strip().split
4360: 28 29 20 5d 20 20 23 20 64 6f 6e e2 80 99 74 20  () ]  # don...t 
4370: 75 73 65 20 74 75 70 6c 65 73 20 28 73 2c 20 7b  use tuples (s, {
4380: 7d 29 2c 20 62 65 63 61 75 73 65 20 75 6e 6b 6e  }), because unkn
4390: 6f 77 6e 20 74 6f 20 4a 53 0a 20 20 20 20 20 20  own to JS.      
43a0: 20 20 65 6c 69 66 20 73 4c 69 6e 65 2e 73 74 61    elif sLine.sta
43b0: 72 74 73 77 69 74 68 28 22 4f 50 54 43 4f 4c 4f  rtswith("OPTCOLO
43c0: 52 2f 22 29 3a 0a 20 20 20 20 20 20 20 20 20 20  R/"):.          
43d0: 20 20 6d 20 3d 20 72 65 2e 6d 61 74 63 68 28 22    m = re.match("
43e0: 4f 50 54 43 4f 4c 4f 52 2f 28 5b 61 2d 7a 30 2d  OPTCOLOR/([a-z0-
43f0: 39 5d 2b 29 3a 28 2e 2b 29 24 22 2c 20 73 4c 69  9]+):(.+)$", sLi
4400: 6e 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ne).            
4410: 66 6f 72 20 69 2c 20 73 43 6f 6c 6f 72 20 69 6e  for i, sColor in
4420: 20 65 6e 75 6d 65 72 61 74 65 28 6d 2e 67 72 6f   enumerate(m.gro
4430: 75 70 28 32 29 2e 73 70 6c 69 74 28 29 29 3a 0a  up(2).split()):.
4440: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4450: 6c 4f 70 74 43 6f 6c 6f 72 5b 69 5d 5b 31 5d 5b  lOptColor[i][1][
4460: 6d 2e 67 72 6f 75 70 28 31 29 5d 20 3d 20 73 43  m.group(1)] = sC
4470: 6f 6c 6f 72 0a 20 20 20 20 20 20 20 20 65 6c 69  olor.        eli
4480: 66 20 73 4c 69 6e 65 2e 73 74 61 72 74 73 77 69  f sLine.startswi
4490: 74 68 28 22 43 4f 4c 4f 52 2f 22 29 3a 0a 20 20  th("COLOR/"):.  
44a0: 20 20 20 20 20 20 20 20 20 20 6d 20 3d 20 72 65            m = re
44b0: 2e 6d 61 74 63 68 28 22 43 4f 4c 4f 52 2f 28 5b  .match("COLOR/([
44c0: 61 2d 7a 41 2d 5a 30 2d 39 5f 5d 2b 29 3a 28 2e  a-zA-Z0-9_]+):(.
44d0: 2b 29 24 22 2c 20 73 4c 69 6e 65 29 0a 20 20 20  +)$", sLine).   
44e0: 20 20 20 20 20 20 20 20 20 64 43 6f 6c 6f 72 5b           dColor[
44f0: 6d 2e 67 72 6f 75 70 28 31 29 5d 20 3d 20 5b 20  m.group(1)] = [ 
4500: 69 6e 74 28 73 29 20 66 6f 72 20 73 20 69 6e 20  int(s) for s in 
4510: 6d 2e 67 72 6f 75 70 28 32 29 2e 73 74 72 69 70  m.group(2).strip
4520: 28 29 2e 73 70 6c 69 74 28 22 2c 22 29 20 5d 0a  ().split(",") ].
4530: 20 20 20 20 20 20 20 20 65 6c 69 66 20 73 4c 69          elif sLi
4540: 6e 65 2e 73 74 61 72 74 73 77 69 74 68 28 22 4f  ne.startswith("O
4550: 50 54 50 52 49 4f 52 49 54 59 2f 22 29 3a 0a 20  PTPRIORITY/"):. 
4560: 20 20 20 20 20 20 20 20 20 20 20 6d 20 3d 20 72             m = r
4570: 65 2e 6d 61 74 63 68 28 22 4f 50 54 50 52 49 4f  e.match("OPTPRIO
4580: 52 49 54 59 2f 28 5b 61 2d 7a 30 2d 39 5d 2b 29  RITY/([a-z0-9]+)
4590: 3a 20 2a 28 5b 30 2d 39 5d 29 24 22 2c 20 73 4c  : *([0-9])$", sL
45a0: 69 6e 65 29 0a 20 20 20 20 20 20 20 20 20 20 20  ine).           
45b0: 20 64 4f 70 74 50 72 69 6f 72 69 74 79 5b 6d 2e   dOptPriority[m.
45c0: 67 72 6f 75 70 28 31 29 5d 20 3d 20 69 6e 74 28  group(1)] = int(
45d0: 6d 2e 67 72 6f 75 70 28 32 29 29 0a 20 20 20 20  m.group(2)).    
45e0: 20 20 20 20 65 6c 69 66 20 73 4c 69 6e 65 2e 73      elif sLine.s
45f0: 74 61 72 74 73 77 69 74 68 28 22 4f 50 54 4c 41  tartswith("OPTLA
4600: 4e 47 2f 22 29 3a 0a 20 20 20 20 20 20 20 20 20  NG/"):.         
4610: 20 20 20 6d 20 3d 20 72 65 2e 6d 61 74 63 68 28     m = re.match(
4620: 22 4f 50 54 4c 41 4e 47 2f 28 5b 61 2d 7a 5d 5b  "OPTLANG/([a-z][
4630: 61 2d 7a 5d 28 3f 3a 5f 5b 41 2d 5a 5d 5b 41 2d  a-z](?:_[A-Z][A-
4640: 5a 5d 7c 29 29 3a 28 2e 2b 29 24 22 2c 20 73 4c  Z]|)):(.+)$", sL
4650: 69 6e 65 29 0a 20 20 20 20 20 20 20 20 20 20 20  ine).           
4660: 20 73 4c 61 6e 67 20 3d 20 6d 2e 67 72 6f 75 70   sLang = m.group
4670: 28 31 29 5b 3a 32 5d 0a 20 20 20 20 20 20 20 20  (1)[:2].        
4680: 20 20 20 20 64 4f 70 74 4c 61 62 65 6c 5b 73 4c      dOptLabel[sL
4690: 61 6e 67 5d 20 3d 20 7b 20 22 5f 5f 6f 70 74 69  ang] = { "__opti
46a0: 6f 6e 74 69 74 6c 65 5f 5f 22 3a 20 6d 2e 67 72  ontitle__": m.gr
46b0: 6f 75 70 28 32 29 2e 73 74 72 69 70 28 29 20 7d  oup(2).strip() }
46c0: 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 73 4c  .        elif sL
46d0: 69 6e 65 2e 73 74 61 72 74 73 77 69 74 68 28 22  ine.startswith("
46e0: 4f 50 54 44 45 46 41 55 4c 54 55 49 4c 41 4e 47  OPTDEFAULTUILANG
46f0: 3a 22 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  :"):.           
4700: 20 6d 20 3d 20 72 65 2e 6d 61 74 63 68 28 22 4f   m = re.match("O
4710: 50 54 44 45 46 41 55 4c 54 55 49 4c 41 4e 47 3a  PTDEFAULTUILANG:
4720: 20 2a 28 5b 61 2d 7a 5d 5b 61 2d 7a 5d 28 3f 3a   *([a-z][a-z](?:
4730: 5f 5b 41 2d 5a 5d 5b 41 2d 5a 5d 7c 29 29 24 22  _[A-Z][A-Z]|))$"
4740: 2c 20 73 4c 69 6e 65 29 0a 20 20 20 20 20 20 20  , sLine).       
4750: 20 20 20 20 20 73 44 65 66 61 75 6c 74 55 49 4c       sDefaultUIL
4760: 61 6e 67 20 3d 20 6d 2e 67 72 6f 75 70 28 31 29  ang = m.group(1)
4770: 5b 3a 32 5d 0a 20 20 20 20 20 20 20 20 65 6c 69  [:2].        eli
4780: 66 20 73 4c 69 6e 65 2e 73 74 61 72 74 73 77 69  f sLine.startswi
4790: 74 68 28 22 4f 50 54 4c 41 42 45 4c 2f 22 29 3a  th("OPTLABEL/"):
47a0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 6d 20 3d  .            m =
47b0: 20 72 65 2e 6d 61 74 63 68 28 22 4f 50 54 4c 41   re.match("OPTLA
47c0: 42 45 4c 2f 28 5b 61 2d 7a 30 2d 39 5d 2b 29 3a  BEL/([a-z0-9]+):
47d0: 28 2e 2b 29 24 22 2c 20 73 4c 69 6e 65 29 0a 20  (.+)$", sLine). 
47e0: 20 20 20 20 20 20 20 20 20 20 20 64 4f 70 74 4c             dOptL
47f0: 61 62 65 6c 5b 73 4c 61 6e 67 5d 5b 6d 2e 67 72  abel[sLang][m.gr
4800: 6f 75 70 28 31 29 5d 20 3d 20 6c 69 73 74 28 6d  oup(1)] = list(m
4810: 61 70 28 73 74 72 2e 73 74 72 69 70 2c 20 6d 2e  ap(str.strip, m.
4820: 67 72 6f 75 70 28 32 29 2e 73 70 6c 69 74 28 22  group(2).split("
4830: 7c 22 29 29 29 20 20 69 66 20 22 7c 22 20 69 6e  |")))  if "|" in
4840: 20 6d 2e 67 72 6f 75 70 28 32 29 20 20 65 6c 73   m.group(2)  els
4850: 65 20 20 5b 6d 2e 67 72 6f 75 70 28 32 29 2e 73  e  [m.group(2).s
4860: 74 72 69 70 28 29 2c 20 22 22 5d 0a 20 20 20 20  trip(), ""].    
4870: 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20      else:.      
4880: 20 20 20 20 20 20 70 72 69 6e 74 28 22 23 20 45        print("# E
4890: 72 72 6f 72 2e 20 57 72 6f 6e 67 20 6f 70 74 69  rror. Wrong opti
48a0: 6f 6e 20 6c 69 6e 65 20 69 6e 3a 5c 6e 20 20 22  on line in:\n  "
48b0: 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 72  ).            pr
48c0: 69 6e 74 28 73 4c 69 6e 65 29 0a 20 20 20 20 70  int(sLine).    p
48d0: 72 69 6e 74 28 22 20 20 6f 70 74 69 6f 6e 73 20  rint("  options 
48e0: 64 65 66 69 6e 65 64 20 66 6f 72 3a 20 22 20 2b  defined for: " +
48f0: 20 22 2c 20 22 2e 6a 6f 69 6e 28 5b 20 74 5b 30   ", ".join([ t[0
4900: 5d 20 66 6f 72 20 74 20 69 6e 20 6c 4f 70 74 20  ] for t in lOpt 
4910: 5d 29 29 0a 20 20 20 20 64 4f 70 74 69 6f 6e 73  ])).    dOptions
4920: 20 3d 20 7b 0a 20 20 20 20 20 20 20 20 22 6c 53   = {.        "lS
4930: 74 72 75 63 74 4f 70 74 22 3a 20 6c 53 74 72 75  tructOpt": lStru
4940: 63 74 4f 70 74 2c 20 22 64 4f 70 74 4c 61 62 65  ctOpt, "dOptLabe
4950: 6c 22 3a 20 64 4f 70 74 4c 61 62 65 6c 2c 20 22  l": dOptLabel, "
4960: 73 44 65 66 61 75 6c 74 55 49 4c 61 6e 67 22 3a  sDefaultUILang":
4970: 20 73 44 65 66 61 75 6c 74 55 49 4c 61 6e 67 2c   sDefaultUILang,
4980: 20 5c 0a 20 20 20 20 20 20 20 20 22 64 43 6f 6c   \.        "dCol
4990: 6f 72 54 79 70 65 22 3a 20 63 72 65 61 74 65 43  orType": createC
49a0: 6f 6c 6f 72 73 28 64 43 6f 6c 6f 72 29 2c 20 22  olors(dColor), "
49b0: 64 4f 70 74 43 6f 6c 6f 72 22 3a 20 7b 20 73 3a  dOptColor": { s:
49c0: 20 64 20 20 66 6f 72 20 73 2c 20 64 20 69 6e 20   d  for s, d in 
49d0: 6c 4f 70 74 43 6f 6c 6f 72 20 7d 0a 20 20 20 20  lOptColor }.    
49e0: 7d 0a 20 20 20 20 64 4f 70 74 69 6f 6e 73 2e 75  }.    dOptions.u
49f0: 70 64 61 74 65 28 7b 20 22 64 4f 70 74 22 2b 6b  pdate({ "dOpt"+k
4a00: 3a 20 76 20 20 66 6f 72 20 6b 2c 20 76 20 69 6e  : v  for k, v in
4a10: 20 6c 4f 70 74 20 7d 29 0a 20 20 20 20 72 65 74   lOpt }).    ret
4a20: 75 72 6e 20 64 4f 70 74 69 6f 6e 73 2c 20 64 4f  urn dOptions, dO
4a30: 70 74 50 72 69 6f 72 69 74 79 0a 0a 0a 64 65 66  ptPriority...def
4a40: 20 70 72 69 6e 74 42 6f 6f 6b 6d 61 72 6b 20 28   printBookmark (
4a50: 6e 4c 65 76 65 6c 2c 20 73 43 6f 6d 6d 65 6e 74  nLevel, sComment
4a60: 2c 20 6e 4c 69 6e 65 29 3a 0a 20 20 20 20 22 70  , nLine):.    "p
4a70: 72 69 6e 74 20 62 6f 6f 6b 6d 61 72 6b 20 77 69  rint bookmark wi
4a80: 74 68 69 6e 20 74 68 65 20 72 75 6c 65 73 20 66  thin the rules f
4a90: 69 6c 65 22 0a 20 20 20 20 70 72 69 6e 74 28 22  ile".    print("
4aa0: 20 20 7b 3a 3e 36 7d 3a 20 20 7b 7d 22 2e 66 6f    {:>6}:  {}".fo
4ab0: 72 6d 61 74 28 6e 4c 69 6e 65 2c 20 22 20 20 22  rmat(nLine, "  "
4ac0: 20 2a 20 6e 4c 65 76 65 6c 20 2b 20 73 43 6f 6d   * nLevel + sCom
4ad0: 6d 65 6e 74 29 29 0a 0a 0a 64 65 66 20 6d 61 6b  ment))...def mak
4ae0: 65 20 28 73 70 4c 61 6e 67 2c 20 73 4c 61 6e 67  e (spLang, sLang
4af0: 2c 20 62 55 73 65 43 61 63 68 65 3d 4e 6f 6e 65  , bUseCache=None
4b00: 29 3a 0a 20 20 20 20 22 63 6f 6d 70 69 6c 65 20  ):.    "compile 
4b10: 72 75 6c 65 73 2c 20 72 65 74 75 72 6e 73 20 61  rules, returns a
4b20: 20 64 69 63 74 69 6f 6e 61 72 79 20 6f 66 20 76   dictionary of v
4b30: 61 6c 75 65 73 22 0a 20 20 20 20 23 20 66 6f 72  alues".    # for
4b40: 20 63 6c 61 72 69 74 79 20 70 75 72 70 6f 73 65   clarity purpose
4b50: 2c 20 64 6f 6e e2 80 99 74 20 63 72 65 61 74 65  , don...t create
4b60: 20 61 6e 79 20 66 69 6c 65 20 68 65 72 65 20 28   any file here (
4b70: 65 78 63 65 70 74 20 63 61 63 68 65 29 0a 0a 20  except cache).. 
4b80: 20 20 20 64 43 61 63 68 65 56 61 72 73 20 3d 20     dCacheVars = 
4b90: 4e 6f 6e 65 0a 0a 20 20 20 20 69 66 20 6f 73 2e  None..    if os.
4ba0: 70 61 74 68 2e 69 73 66 69 6c 65 28 22 5f 62 75  path.isfile("_bu
4bb0: 69 6c 64 2f 64 61 74 61 5f 63 61 63 68 65 2e 6a  ild/data_cache.j
4bc0: 73 6f 6e 22 29 3a 0a 20 20 20 20 20 20 20 20 70  son"):.        p
4bd0: 72 69 6e 74 28 22 3e 20 64 61 74 61 20 63 61 63  rint("> data cac
4be0: 68 65 20 66 6f 75 6e 64 22 29 0a 20 20 20 20 20  he found").     
4bf0: 20 20 20 73 4a 53 4f 4e 20 3d 20 6f 70 65 6e 28     sJSON = open(
4c00: 22 5f 62 75 69 6c 64 2f 64 61 74 61 5f 63 61 63  "_build/data_cac
4c10: 68 65 2e 6a 73 6f 6e 22 2c 20 22 72 22 2c 20 65  he.json", "r", e
4c20: 6e 63 6f 64 69 6e 67 3d 22 75 74 66 2d 38 22 29  ncoding="utf-8")
4c30: 2e 72 65 61 64 28 29 0a 20 20 20 20 20 20 20 20  .read().        
4c40: 64 43 61 63 68 65 56 61 72 73 20 3d 20 6a 73 6f  dCacheVars = jso
4c50: 6e 2e 6c 6f 61 64 73 28 73 4a 53 4f 4e 29 0a 20  n.loads(sJSON). 
4c60: 20 20 20 20 20 20 20 73 42 75 69 6c 64 44 61 74         sBuildDat
4c70: 65 20 3d 20 74 69 6d 65 2e 73 74 72 66 74 69 6d  e = time.strftim
4c80: 65 28 22 25 59 2d 25 6d 2d 25 64 20 25 48 3a 25  e("%Y-%m-%d %H:%
4c90: 4d 3a 25 53 22 2c 20 74 69 6d 65 2e 67 6d 74 69  M:%S", time.gmti
4ca0: 6d 65 28 64 43 61 63 68 65 56 61 72 73 2e 67 65  me(dCacheVars.ge
4cb0: 74 28 22 66 42 75 69 6c 64 54 69 6d 65 22 2c 20  t("fBuildTime", 
4cc0: 30 29 29 29 0a 20 20 20 20 20 20 20 20 69 66 20  0))).        if 
4cd0: 62 55 73 65 43 61 63 68 65 3a 0a 20 20 20 20 20  bUseCache:.     
4ce0: 20 20 20 20 20 20 20 70 72 69 6e 74 28 22 3e 20         print("> 
4cf0: 75 73 65 20 63 61 63 68 65 20 28 6e 6f 20 72 65  use cache (no re
4d00: 62 75 69 6c 64 20 61 73 6b 65 64 29 22 29 0a 20  build asked)"). 
4d10: 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74             print
4d20: 28 22 20 20 62 75 69 6c 64 20 6d 61 64 65 20 61  ("  build made a
4d30: 74 3a 20 22 20 2b 20 73 42 75 69 6c 64 44 61 74  t: " + sBuildDat
4d40: 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 72  e).            r
4d50: 65 74 75 72 6e 20 64 43 61 63 68 65 56 61 72 73  eturn dCacheVars
4d60: 0a 0a 20 20 20 20 70 72 69 6e 74 28 22 3e 20 72  ..    print("> r
4d70: 65 61 64 20 72 75 6c 65 73 20 66 69 6c 65 2e 2e  ead rules file..
4d80: 2e 22 29 0a 20 20 20 20 74 72 79 3a 0a 20 20 20  .").    try:.   
4d90: 20 20 20 20 20 73 46 69 6c 65 43 6f 6e 74 65 6e       sFileConten
4da0: 74 20 3d 20 6f 70 65 6e 28 73 70 4c 61 6e 67 20  t = open(spLang 
4db0: 2b 20 22 2f 72 75 6c 65 73 2e 67 72 78 22 2c 20  + "/rules.grx", 
4dc0: 27 72 27 2c 20 65 6e 63 6f 64 69 6e 67 3d 22 75  'r', encoding="u
4dd0: 74 66 2d 38 22 29 2e 72 65 61 64 28 29 0a 20 20  tf-8").read().  
4de0: 20 20 65 78 63 65 70 74 20 4f 53 45 72 72 6f 72    except OSError
4df0: 3a 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28  :.        print(
4e00: 66 22 23 20 45 72 72 6f 72 2e 20 52 75 6c 65 73  f"# Error. Rules
4e10: 20 66 69 6c 65 20 69 6e 20 70 72 6f 6a 65 63 74   file in project
4e20: 20 3c 7b 73 4c 61 6e 67 7d 3e 20 6e 6f 74 20 66   <{sLang}> not f
4e30: 6f 75 6e 64 2e 22 29 0a 20 20 20 20 20 20 20 20  ound.").        
4e40: 65 78 69 74 28 29 0a 0a 20 20 20 20 23 20 63 61  exit()..    # ca
4e50: 6c 63 75 6c 61 74 65 20 68 61 73 68 20 6f 66 20  lculate hash of 
4e60: 6c 6f 61 64 65 64 20 66 69 6c 65 0a 20 20 20 20  loaded file.    
4e70: 78 48 61 73 68 65 72 20 3d 20 68 61 73 68 6c 69  xHasher = hashli
4e80: 62 2e 6e 65 77 28 22 73 68 61 33 5f 35 31 32 22  b.new("sha3_512"
4e90: 29 0a 20 20 20 20 78 48 61 73 68 65 72 2e 75 70  ).    xHasher.up
4ea0: 64 61 74 65 28 73 46 69 6c 65 43 6f 6e 74 65 6e  date(sFileConten
4eb0: 74 2e 65 6e 63 6f 64 65 28 22 75 74 66 2d 38 22  t.encode("utf-8"
4ec0: 29 29 0a 20 20 20 20 73 46 69 6c 65 48 61 73 68  )).    sFileHash
4ed0: 20 3d 20 78 48 61 73 68 65 72 2e 68 65 78 64 69   = xHasher.hexdi
4ee0: 67 65 73 74 28 29 0a 0a 20 20 20 20 69 66 20 64  gest()..    if d
4ef0: 43 61 63 68 65 56 61 72 73 20 61 6e 64 20 62 55  CacheVars and bU
4f00: 73 65 43 61 63 68 65 20 21 3d 20 46 61 6c 73 65  seCache != False
4f10: 20 61 6e 64 20 73 46 69 6c 65 48 61 73 68 20 3d   and sFileHash =
4f20: 3d 20 64 43 61 63 68 65 56 61 72 73 2e 67 65 74  = dCacheVars.get
4f30: 28 22 73 46 69 6c 65 48 61 73 68 22 2c 20 22 22  ("sFileHash", ""
4f40: 29 3a 0a 20 20 20 20 20 20 20 20 23 20 69 66 20  ):.        # if 
4f50: 3c 62 55 73 65 43 61 63 68 65 3e 20 69 73 20 4e  <bUseCache> is N
4f60: 6f 6e 65 20 6f 72 20 54 72 75 65 2c 20 77 65 20  one or True, we 
4f70: 63 61 6e 20 75 73 65 20 74 68 65 20 63 61 63 68  can use the cach
4f80: 65 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28  e.        print(
4f90: 22 3e 20 63 61 63 68 65 20 68 61 73 68 20 69 64  "> cache hash id
4fa0: 65 6e 74 69 63 61 6c 20 74 6f 20 66 69 6c 65 20  entical to file 
4fb0: 68 61 73 68 2c 20 75 73 65 20 63 61 63 68 65 22  hash, use cache"
4fc0: 29 0a 20 20 20 20 20 20 20 20 70 72 69 6e 74 28  ).        print(
4fd0: 22 20 20 62 75 69 6c 64 20 6d 61 64 65 20 61 74  "  build made at
4fe0: 3a 20 22 20 2b 20 73 42 75 69 6c 64 44 61 74 65  : " + sBuildDate
4ff0: 29 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ).        return
5000: 20 64 43 61 63 68 65 56 61 72 73 0a 0a 20 20 20   dCacheVars..   
5010: 20 23 20 72 65 6d 6f 76 69 6e 67 20 63 6f 6d 6d   # removing comm
5020: 65 6e 74 73 2c 20 7a 65 72 6f 69 6e 67 20 65 6d  ents, zeroing em
5030: 70 74 79 20 6c 69 6e 65 73 2c 20 63 72 65 61 74  pty lines, creat
5040: 69 6e 67 20 64 65 66 69 6e 69 74 69 6f 6e 73 2c  ing definitions,
5050: 20 73 74 6f 72 69 6e 67 20 74 65 73 74 73 2c 20   storing tests, 
5060: 6d 65 72 67 69 6e 67 20 72 75 6c 65 20 6c 69 6e  merging rule lin
5070: 65 73 0a 20 20 20 20 70 72 69 6e 74 28 22 20 20  es.    print("  
5080: 70 61 72 73 69 6e 67 20 72 75 6c 65 73 2e 2e 2e  parsing rules...
5090: 22 29 0a 20 20 20 20 66 42 75 69 6c 64 54 69 6d  ").    fBuildTim
50a0: 65 20 3d 20 74 69 6d 65 2e 74 69 6d 65 28 29 0a  e = time.time().
50b0: 20 20 20 20 6c 52 75 6c 65 4c 69 6e 65 20 3d 20      lRuleLine = 
50c0: 5b 5d 0a 20 20 20 20 6c 54 65 73 74 20 3d 20 5b  [].    lTest = [
50d0: 5d 0a 20 20 20 20 6c 4f 70 74 20 3d 20 5b 5d 0a  ].    lOpt = [].
50e0: 20 20 20 20 62 47 72 61 70 68 20 3d 20 46 61 6c      bGraph = Fal
50f0: 73 65 0a 20 20 20 20 6c 47 72 61 70 68 52 75 6c  se.    lGraphRul
5100: 65 20 3d 20 5b 5d 0a 0a 20 20 20 20 66 6f 72 20  e = []..    for 
5110: 69 2c 20 73 4c 69 6e 65 20 69 6e 20 65 6e 75 6d  i, sLine in enum
5120: 65 72 61 74 65 28 73 46 69 6c 65 43 6f 6e 74 65  erate(sFileConte
5130: 6e 74 2e 73 70 6c 69 74 28 22 5c 6e 22 29 2c 20  nt.split("\n"), 
5140: 31 29 3a 0a 20 20 20 20 20 20 20 20 69 66 20 73  1):.        if s
5150: 4c 69 6e 65 2e 73 74 61 72 74 73 77 69 74 68 28  Line.startswith(
5160: 27 23 45 4e 44 27 29 3a 0a 20 20 20 20 20 20 20  '#END'):.       
5170: 20 20 20 20 20 23 20 61 72 62 69 74 72 61 72 79       # arbitrary
5180: 20 65 6e 64 0a 20 20 20 20 20 20 20 20 20 20 20   end.           
5190: 20 70 72 69 6e 74 42 6f 6f 6b 6d 61 72 6b 28 30   printBookmark(0
51a0: 2c 20 22 42 52 45 41 4b 20 42 59 20 23 45 4e 44  , "BREAK BY #END
51b0: 22 2c 20 69 29 0a 20 20 20 20 20 20 20 20 20 20  ", i).          
51c0: 20 20 62 72 65 61 6b 0a 20 20 20 20 20 20 20 20    break.        
51d0: 65 6c 69 66 20 73 4c 69 6e 65 2e 73 74 61 72 74  elif sLine.start
51e0: 73 77 69 74 68 28 22 23 22 29 3a 0a 20 20 20 20  swith("#"):.    
51f0: 20 20 20 20 20 20 20 20 23 20 63 6f 6d 6d 65 6e          # commen
5200: 74 0a 20 20 20 20 20 20 20 20 20 20 20 20 70 61  t.            pa
5210: 73 73 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20  ss.        elif 
5220: 73 4c 69 6e 65 2e 73 74 61 72 74 73 77 69 74 68  sLine.startswith
5230: 28 22 44 45 46 3a 22 29 3a 0a 20 20 20 20 20 20  ("DEF:"):.      
5240: 20 20 20 20 20 20 23 20 64 65 66 69 6e 69 74 69        # definiti
5250: 6f 6e 0a 20 20 20 20 20 20 20 20 20 20 20 20 6d  on.            m
5260: 20 3d 20 72 65 2e 6d 61 74 63 68 28 22 44 45 46   = re.match("DEF
5270: 3a 20 2b 28 5b 61 2d 7a 41 2d 5a 5f 5d 5b 61 2d  : +([a-zA-Z_][a-
5280: 7a 41 2d 5a 5f 30 2d 39 5d 2a 29 20 2b 28 2e 2b  zA-Z_0-9]*) +(.+
5290: 29 24 22 2c 20 73 4c 69 6e 65 2e 73 74 72 69 70  )$", sLine.strip
52a0: 28 29 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ()).            
52b0: 69 66 20 6d 3a 0a 20 20 20 20 20 20 20 20 20 20  if m:.          
52c0: 20 20 20 20 20 20 64 44 45 46 49 4e 49 54 49 4f        dDEFINITIO
52d0: 4e 53 5b 22 7b 22 2b 6d 2e 67 72 6f 75 70 28 31  NS["{"+m.group(1
52e0: 29 2b 22 7d 22 5d 20 3d 20 6d 2e 67 72 6f 75 70  )+"}"] = m.group
52f0: 28 32 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  (2).            
5300: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
5310: 20 20 20 20 20 20 70 72 69 6e 74 28 22 23 20 45        print("# E
5320: 72 72 6f 72 20 69 6e 20 64 65 66 69 6e 69 74 69  rror in definiti
5330: 6f 6e 3a 20 22 2c 20 65 6e 64 3d 22 22 29 0a 20  on: ", end=""). 
5340: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
5350: 72 69 6e 74 28 73 4c 69 6e 65 2e 73 74 72 69 70  rint(sLine.strip
5360: 28 29 29 0a 20 20 20 20 20 20 20 20 65 6c 69 66  ()).        elif
5370: 20 73 4c 69 6e 65 2e 73 74 61 72 74 73 77 69 74   sLine.startswit
5380: 68 28 22 44 45 43 4c 3a 22 29 3a 0a 20 20 20 20  h("DECL:"):.    
5390: 20 20 20 20 20 20 20 20 23 20 64 65 63 6c 65 6e          # declen
53a0: 73 69 6f 6e 73 0a 20 20 20 20 20 20 20 20 20 20  sions.          
53b0: 20 20 6d 20 3d 20 72 65 2e 6d 61 74 63 68 28 72    m = re.match(r
53c0: 22 44 45 43 4c 3a 20 2b 28 5c 2b 5c 77 2b 29 20  "DECL: +(\+\w+) 
53d0: 28 2e 2b 29 24 22 2c 20 73 4c 69 6e 65 2e 73 74  (.+)$", sLine.st
53e0: 72 69 70 28 29 29 0a 20 20 20 20 20 20 20 20 20  rip()).         
53f0: 20 20 20 69 66 20 6d 3a 0a 20 20 20 20 20 20 20     if m:.       
5400: 20 20 20 20 20 20 20 20 20 64 44 45 43 4c 45 4e           dDECLEN
5410: 53 49 4f 4e 53 5b 6d 2e 67 72 6f 75 70 28 31 29  SIONS[m.group(1)
5420: 5d 20 3d 20 6d 2e 67 72 6f 75 70 28 32 29 2e 73  ] = m.group(2).s
5430: 74 72 69 70 28 29 2e 73 70 6c 69 74 28 29 0a 20  trip().split(). 
5440: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
5450: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5460: 20 70 72 69 6e 74 28 22 45 72 72 6f 72 20 69 6e   print("Error in
5470: 20 64 65 63 6c 65 6e 73 69 6f 6e 20 6c 69 73 74   declension list
5480: 3a 20 22 2c 20 65 6e 64 3d 22 22 29 0a 20 20 20  : ", end="").   
5490: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69               pri
54a0: 6e 74 28 73 4c 69 6e 65 2e 73 74 72 69 70 28 29  nt(sLine.strip()
54b0: 29 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 73  ).        elif s
54c0: 4c 69 6e 65 2e 73 74 61 72 74 73 77 69 74 68 28  Line.startswith(
54d0: 22 54 45 53 54 3a 22 29 3a 0a 20 20 20 20 20 20  "TEST:"):.      
54e0: 20 20 20 20 20 20 23 20 74 65 73 74 0a 20 20 20        # test.   
54f0: 20 20 20 20 20 20 20 20 20 6c 54 65 73 74 2e 61           lTest.a
5500: 70 70 65 6e 64 28 22 7b 3a 3c 38 7d 22 2e 66 6f  ppend("{:<8}".fo
5510: 72 6d 61 74 28 69 29 20 2b 20 22 20 20 22 20 2b  rmat(i) + "  " +
5520: 20 73 4c 69 6e 65 5b 35 3a 5d 2e 73 74 72 69 70   sLine[5:].strip
5530: 28 29 29 0a 20 20 20 20 20 20 20 20 65 6c 69 66  ()).        elif
5540: 20 73 4c 69 6e 65 2e 73 74 61 72 74 73 77 69 74   sLine.startswit
5550: 68 28 22 54 4f 44 4f 3a 22 29 3a 0a 20 20 20 20  h("TODO:"):.    
5560: 20 20 20 20 20 20 20 20 23 20 74 6f 64 6f 0a 20          # todo. 
5570: 20 20 20 20 20 20 20 20 20 20 20 70 61 73 73 0a             pass.
5580: 20 20 20 20 20 20 20 20 65 6c 69 66 20 73 4c 69          elif sLi
5590: 6e 65 2e 73 74 61 72 74 73 77 69 74 68 28 28 22  ne.startswith(("
55a0: 4f 50 54 47 52 4f 55 50 2f 22 2c 20 22 4f 50 54  OPTGROUP/", "OPT
55b0: 53 4f 46 54 57 41 52 45 3a 22 2c 20 22 4f 50 54  SOFTWARE:", "OPT
55c0: 2f 22 2c 20 5c 0a 20 20 20 20 20 20 20 20 20 20  /", \.          
55d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
55e0: 20 20 20 20 20 20 22 43 4f 4c 4f 52 2f 22 2c 20        "COLOR/", 
55f0: 22 4f 50 54 43 4f 4c 4f 52 54 48 45 4d 45 3a 22  "OPTCOLORTHEME:"
5600: 2c 20 22 4f 50 54 43 4f 4c 4f 52 2f 22 2c 20 5c  , "OPTCOLOR/", \
5610: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5620: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5630: 20 22 4f 50 54 4c 41 4e 47 2f 22 2c 20 22 4f 50   "OPTLANG/", "OP
5640: 54 44 45 46 41 55 4c 54 55 49 4c 41 4e 47 3a 22  TDEFAULTUILANG:"
5650: 2c 20 5c 0a 20 20 20 20 20 20 20 20 20 20 20 20  , \.            
5660: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5670: 20 20 20 20 22 4f 50 54 4c 41 42 45 4c 2f 22 2c      "OPTLABEL/",
5680: 20 22 4f 50 54 50 52 49 4f 52 49 54 59 2f 22 29   "OPTPRIORITY/")
5690: 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 23  ):.            #
56a0: 20 6f 70 74 69 6f 6e 73 0a 20 20 20 20 20 20 20   options.       
56b0: 20 20 20 20 20 6c 4f 70 74 2e 61 70 70 65 6e 64       lOpt.append
56c0: 28 73 4c 69 6e 65 29 0a 20 20 20 20 20 20 20 20  (sLine).        
56d0: 65 6c 69 66 20 73 4c 69 6e 65 2e 73 74 61 72 74  elif sLine.start
56e0: 73 77 69 74 68 28 22 21 21 22 29 3a 0a 20 20 20  swith("!!"):.   
56f0: 20 20 20 20 20 20 20 20 20 23 20 62 6f 6f 6b 6d           # bookm
5700: 61 72 6b 0a 20 20 20 20 20 20 20 20 20 20 20 20  ark.            
5710: 6d 20 3d 20 72 65 2e 6d 61 74 63 68 28 22 21 21  m = re.match("!!
5720: 2b 22 2c 20 73 4c 69 6e 65 29 0a 20 20 20 20 20  +", sLine).     
5730: 20 20 20 20 20 20 20 6e 45 78 4d 6b 20 3d 20 6c         nExMk = l
5740: 65 6e 28 6d 2e 67 72 6f 75 70 28 30 29 29 0a 20  en(m.group(0)). 
5750: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 73 4c             if sL
5760: 69 6e 65 5b 6e 45 78 4d 6b 3a 5d 2e 73 74 72 69  ine[nExMk:].stri
5770: 70 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20  p():.           
5780: 20 20 20 20 20 70 72 69 6e 74 42 6f 6f 6b 6d 61       printBookma
5790: 72 6b 28 6e 45 78 4d 6b 2d 32 2c 20 73 4c 69 6e  rk(nExMk-2, sLin
57a0: 65 5b 6e 45 78 4d 6b 3a 2d 33 5d 2e 73 74 72 69  e[nExMk:-3].stri
57b0: 70 28 29 2c 20 69 29 0a 20 20 20 20 20 20 20 20  p(), i).        
57c0: 23 20 47 72 61 70 68 20 72 75 6c 65 73 0a 20 20  # Graph rules.  
57d0: 20 20 20 20 20 20 65 6c 69 66 20 73 4c 69 6e 65        elif sLine
57e0: 2e 73 74 61 72 74 73 77 69 74 68 28 22 40 40 40  .startswith("@@@
57f0: 40 47 52 41 50 48 3a 22 29 3a 0a 20 20 20 20 20  @GRAPH:"):.     
5800: 20 20 20 20 20 20 20 23 20 72 75 6c 65 73 20 67         # rules g
5810: 72 61 70 68 20 63 61 6c 6c 0a 20 20 20 20 20 20  raph call.      
5820: 20 20 20 20 20 20 6d 20 3d 20 72 65 2e 6d 61 74        m = re.mat
5830: 63 68 28 72 22 40 40 40 40 47 52 41 50 48 3a 20  ch(r"@@@@GRAPH: 
5840: 2a 28 5c 77 2b 29 22 2c 20 73 4c 69 6e 65 2e 73  *(\w+)", sLine.s
5850: 74 72 69 70 28 29 29 0a 20 20 20 20 20 20 20 20  trip()).        
5860: 20 20 20 20 69 66 20 6d 3a 0a 20 20 20 20 20 20      if m:.      
5870: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 42            printB
5880: 6f 6f 6b 6d 61 72 6b 28 30 2c 20 22 47 52 41 50  ookmark(0, "GRAP
5890: 48 3a 20 22 20 2b 20 6d 2e 67 72 6f 75 70 28 31  H: " + m.group(1
58a0: 29 2c 20 69 29 0a 20 20 20 20 20 20 20 20 20 20  ), i).          
58b0: 20 20 20 20 20 20 6c 52 75 6c 65 4c 69 6e 65 2e        lRuleLine.
58c0: 61 70 70 65 6e 64 28 5b 69 2c 20 22 40 40 40 40  append([i, "@@@@
58d0: 22 2b 6d 2e 67 72 6f 75 70 28 31 29 5d 29 0a 20  "+m.group(1)]). 
58e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c                 l
58f0: 47 72 61 70 68 52 75 6c 65 2e 61 70 70 65 6e 64  GraphRule.append
5900: 28 5b 69 2c 20 73 4c 69 6e 65 5d 29 0a 20 20 20  ([i, sLine]).   
5910: 20 20 20 20 20 20 20 20 20 20 20 20 20 62 47 72               bGr
5920: 61 70 68 20 3d 20 54 72 75 65 0a 20 20 20 20 20  aph = True.     
5930: 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20 20         else:.   
5940: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 72 69               pri
5950: 6e 74 28 22 47 72 61 70 68 20 65 72 72 6f 72 20  nt("Graph error 
5960: 61 74 20 6c 69 6e 65 22 2c 20 69 29 0a 20 20 20  at line", i).   
5970: 20 20 20 20 20 65 6c 69 66 20 73 4c 69 6e 65 2e       elif sLine.
5980: 73 74 61 72 74 73 77 69 74 68 28 28 22 40 40 40  startswith(("@@@
5990: 40 45 4e 44 5f 47 52 41 50 48 22 2c 20 22 40 40  @END_GRAPH", "@@
59a0: 40 40 45 4e 44 47 52 41 50 48 22 29 29 3a 0a 20  @@ENDGRAPH")):. 
59b0: 20 20 20 20 20 20 20 20 20 20 20 23 6c 47 72 61             #lGra
59c0: 70 68 52 75 6c 65 2e 61 70 70 65 6e 64 28 5b 69  phRule.append([i
59d0: 2c 20 73 4c 69 6e 65 5d 29 0a 20 20 20 20 20 20  , sLine]).      
59e0: 20 20 20 20 20 20 70 72 69 6e 74 42 6f 6f 6b 6d        printBookm
59f0: 61 72 6b 28 30 2c 20 22 45 4e 44 47 52 41 50 48  ark(0, "ENDGRAPH
5a00: 22 2c 20 69 29 0a 20 20 20 20 20 20 20 20 20 20  ", i).          
5a10: 20 20 62 47 72 61 70 68 20 3d 20 46 61 6c 73 65    bGraph = False
5a20: 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 72 65  .        elif re
5a30: 2e 6d 61 74 63 68 28 22 40 40 40 40 20 2a 24 22  .match("@@@@ *$"
5a40: 2c 20 73 4c 69 6e 65 29 3a 0a 20 20 20 20 20 20  , sLine):.      
5a50: 20 20 20 20 20 20 70 61 73 73 0a 20 20 20 20 20        pass.     
5a60: 20 20 20 65 6c 69 66 20 62 47 72 61 70 68 3a 0a     elif bGraph:.
5a70: 20 20 20 20 20 20 20 20 20 20 20 20 6c 47 72 61              lGra
5a80: 70 68 52 75 6c 65 2e 61 70 70 65 6e 64 28 5b 69  phRule.append([i
5a90: 2c 20 73 4c 69 6e 65 5d 29 0a 20 20 20 20 20 20  , sLine]).      
5aa0: 20 20 23 20 52 65 67 65 78 20 72 75 6c 65 73 0a    # Regex rules.
5ab0: 20 20 20 20 20 20 20 20 65 6c 69 66 20 72 65 2e          elif re.
5ac0: 6d 61 74 63 68 28 22 5b 20 c2 a0 5c 74 5d 2a 24  match("[ ..\t]*$
5ad0: 22 2c 20 73 4c 69 6e 65 29 3a 0a 20 20 20 20 20  ", sLine):.     
5ae0: 20 20 20 20 20 20 20 23 20 65 6d 70 74 79 20 6c         # empty l
5af0: 69 6e 65 0a 20 20 20 20 20 20 20 20 20 20 20 20  ine.            
5b00: 70 61 73 73 0a 20 20 20 20 20 20 20 20 65 6c 69  pass.        eli
5b10: 66 20 73 4c 69 6e 65 2e 73 74 61 72 74 73 77 69  f sLine.startswi
5b20: 74 68 28 22 20 20 20 20 22 29 3a 0a 20 20 20 20  th("    "):.    
5b30: 20 20 20 20 20 20 20 20 23 20 72 75 6c 65 20 28          # rule (
5b40: 63 6f 6e 74 69 6e 75 61 74 69 6f 6e 29 0a 20 20  continuation).  
5b50: 20 20 20 20 20 20 20 20 20 20 6c 52 75 6c 65 4c            lRuleL
5b60: 69 6e 65 5b 2d 31 5d 5b 31 5d 20 2b 3d 20 22 20  ine[-1][1] += " 
5b70: 22 20 2b 20 73 4c 69 6e 65 2e 73 74 72 69 70 28  " + sLine.strip(
5b80: 29 0a 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a  ).        else:.
5b90: 20 20 20 20 20 20 20 20 20 20 20 20 23 20 6e 65              # ne
5ba0: 77 20 72 75 6c 65 0a 20 20 20 20 20 20 20 20 20  w rule.         
5bb0: 20 20 20 6c 52 75 6c 65 4c 69 6e 65 2e 61 70 70     lRuleLine.app
5bc0: 65 6e 64 28 5b 69 2c 20 73 4c 69 6e 65 2e 73 74  end([i, sLine.st
5bd0: 72 69 70 28 29 5d 29 0a 0a 20 20 20 20 23 20 67  rip()])..    # g
5be0: 65 6e 65 72 61 74 69 6e 67 20 6f 70 74 69 6f 6e  enerating option
5bf0: 73 20 66 69 6c 65 73 0a 20 20 20 20 70 72 69 6e  s files.    prin
5c00: 74 28 22 20 20 70 61 72 73 69 6e 67 20 6f 70 74  t("  parsing opt
5c10: 69 6f 6e 73 2e 2e 2e 22 29 0a 20 20 20 20 64 4f  ions...").    dO
5c20: 70 74 69 6f 6e 73 2c 20 64 4f 70 74 50 72 69 6f  ptions, dOptPrio
5c30: 72 69 74 79 20 3d 20 70 72 65 70 61 72 65 4f 70  rity = prepareOp
5c40: 74 69 6f 6e 73 28 6c 4f 70 74 29 0a 0a 20 20 20  tions(lOpt)..   
5c50: 20 23 20 74 65 73 74 73 0a 20 20 20 20 70 72 69   # tests.    pri
5c60: 6e 74 28 22 20 20 6c 69 73 74 20 74 65 73 74 73  nt("  list tests
5c70: 2e 2e 2e 22 29 0a 20 20 20 20 73 47 43 54 65 73  ...").    sGCTes
5c80: 74 73 20 3d 20 22 5c 6e 22 2e 6a 6f 69 6e 28 6c  ts = "\n".join(l
5c90: 54 65 73 74 29 0a 20 20 20 20 73 47 43 54 65 73  Test).    sGCTes
5ca0: 74 73 4a 53 20 3d 20 27 7b 20 22 61 44 61 74 61  tsJS = '{ "aData
5cb0: 22 3a 20 27 20 2b 20 6a 73 6f 6e 2e 64 75 6d 70  ": ' + json.dump
5cc0: 73 28 6c 54 65 73 74 2c 20 65 6e 73 75 72 65 5f  s(lTest, ensure_
5cd0: 61 73 63 69 69 3d 46 61 6c 73 65 29 20 2b 20 22  ascii=False) + "
5ce0: 20 7d 5c 6e 22 0a 0a 20 20 20 20 23 20 70 72 6f   }\n"..    # pro
5cf0: 63 65 73 73 69 6e 67 0a 20 20 20 20 70 72 69 6e  cessing.    prin
5d00: 74 28 22 20 20 70 72 65 70 61 72 69 6e 67 20 72  t("  preparing r
5d10: 75 6c 65 73 2e 2e 2e 22 29 0a 20 20 20 20 62 50  ules...").    bP
5d20: 61 72 61 67 72 61 70 68 20 3d 20 54 72 75 65 0a  aragraph = True.
5d30: 20 20 20 20 6c 50 61 72 61 67 72 61 70 68 52 75      lParagraphRu
5d40: 6c 65 73 20 3d 20 5b 5d 0a 20 20 20 20 6c 53 65  les = [].    lSe
5d50: 6e 74 65 6e 63 65 52 75 6c 65 73 20 3d 20 5b 5d  ntenceRules = []
5d60: 0a 20 20 20 20 6c 50 61 72 61 67 72 61 70 68 52  .    lParagraphR
5d70: 75 6c 65 73 4a 53 20 3d 20 5b 5d 0a 20 20 20 20  ulesJS = [].    
5d80: 6c 53 65 6e 74 65 6e 63 65 52 75 6c 65 73 4a 53  lSentenceRulesJS
5d90: 20 3d 20 5b 5d 0a 0a 20 20 20 20 66 6f 72 20 6e   = []..    for n
5da0: 4c 69 6e 65 2c 20 73 4c 69 6e 65 20 69 6e 20 6c  Line, sLine in l
5db0: 52 75 6c 65 4c 69 6e 65 3a 0a 20 20 20 20 20 20  RuleLine:.      
5dc0: 20 20 69 66 20 73 4c 69 6e 65 3a 0a 20 20 20 20    if sLine:.    
5dd0: 20 20 20 20 20 20 20 20 69 66 20 73 4c 69 6e 65          if sLine
5de0: 20 3d 3d 20 22 5b 2b 2b 5d 22 3a 0a 20 20 20 20   == "[++]":.    
5df0: 20 20 20 20 20 20 20 20 20 20 20 20 62 50 61 72              bPar
5e00: 61 67 72 61 70 68 20 3d 20 46 61 6c 73 65 0a 20  agraph = False. 
5e10: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
5e20: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5e30: 20 61 52 75 6c 65 20 3d 20 63 72 65 61 74 65 52   aRule = createR
5e40: 75 6c 65 28 73 4c 69 6e 65 2c 20 6e 4c 69 6e 65  ule(sLine, nLine
5e50: 2c 20 73 4c 61 6e 67 2c 20 62 50 61 72 61 67 72  , sLang, bParagr
5e60: 61 70 68 2c 20 64 4f 70 74 50 72 69 6f 72 69 74  aph, dOptPriorit
5e70: 79 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  y).             
5e80: 20 20 20 69 66 20 61 52 75 6c 65 3a 0a 20 20 20     if aRule:.   
5e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ea0: 20 69 66 20 62 50 61 72 61 67 72 61 70 68 3a 0a   if bParagraph:.
5eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5ec0: 20 20 20 20 20 20 20 20 6c 50 61 72 61 67 72 61          lParagra
5ed0: 70 68 52 75 6c 65 73 2e 61 70 70 65 6e 64 28 61  phRules.append(a
5ee0: 52 75 6c 65 29 0a 20 20 20 20 20 20 20 20 20 20  Rule).          
5ef0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c 50                lP
5f00: 61 72 61 67 72 61 70 68 52 75 6c 65 73 4a 53 2e  aragraphRulesJS.
5f10: 61 70 70 65 6e 64 28 6a 73 63 6f 6e 76 2e 70 79  append(jsconv.py
5f20: 52 75 6c 65 54 6f 4a 53 28 61 52 75 6c 65 2c 20  RuleToJS(aRule, 
5f30: 64 4a 53 52 45 47 45 58 45 53 2c 20 73 57 4f 52  dJSREGEXES, sWOR
5f40: 44 4c 49 4d 49 54 4c 45 46 54 29 29 0a 20 20 20  DLIMITLEFT)).   
5f50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5f60: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
5f70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c                 l
5f80: 53 65 6e 74 65 6e 63 65 52 75 6c 65 73 2e 61 70  SentenceRules.ap
5f90: 70 65 6e 64 28 61 52 75 6c 65 29 0a 20 20 20 20  pend(aRule).    
5fa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5fb0: 20 20 20 20 6c 53 65 6e 74 65 6e 63 65 52 75 6c      lSentenceRul
5fc0: 65 73 4a 53 2e 61 70 70 65 6e 64 28 6a 73 63 6f  esJS.append(jsco
5fd0: 6e 76 2e 70 79 52 75 6c 65 54 6f 4a 53 28 61 52  nv.pyRuleToJS(aR
5fe0: 75 6c 65 2c 20 64 4a 53 52 45 47 45 58 45 53 2c  ule, dJSREGEXES,
5ff0: 20 73 57 4f 52 44 4c 49 4d 49 54 4c 45 46 54 29   sWORDLIMITLEFT)
6000: 29 0a 0a 20 20 20 20 23 20 63 72 65 61 74 69 6e  )..    # creatin
6010: 67 20 66 69 6c 65 20 77 69 74 68 20 61 6c 6c 20  g file with all 
6020: 66 75 6e 63 74 69 6f 6e 73 20 63 61 6c 6c 61 62  functions callab
6030: 6c 65 20 62 79 20 72 75 6c 65 73 0a 20 20 20 20  le by rules.    
6040: 70 72 69 6e 74 28 22 20 20 63 72 65 61 74 69 6e  print("  creatin
6050: 67 20 63 61 6c 6c 61 62 6c 65 73 20 66 6f 72 20  g callables for 
6060: 72 65 67 65 78 20 72 75 6c 65 73 2e 2e 2e 22 29  regex rules...")
6070: 0a 20 20 20 20 73 50 79 43 61 6c 6c 61 62 6c 65  .    sPyCallable
6080: 73 20 3d 20 22 22 0a 20 20 20 20 73 4a 53 43 61  s = "".    sJSCa
6090: 6c 6c 61 62 6c 65 73 20 3d 20 22 22 0a 20 20 20  llables = "".   
60a0: 20 66 6f 72 20 73 46 75 6e 63 4e 61 6d 65 2c 20   for sFuncName, 
60b0: 73 52 65 74 75 72 6e 20 69 6e 20 6c 46 55 4e 43  sReturn in lFUNC
60c0: 54 49 4f 4e 53 3a 0a 20 20 20 20 20 20 20 20 69  TIONS:.        i
60d0: 66 20 73 46 75 6e 63 4e 61 6d 65 2e 73 74 61 72  f sFuncName.star
60e0: 74 73 77 69 74 68 28 22 5f 63 5f 22 29 3a 20 23  tswith("_c_"): #
60f0: 20 63 6f 6e 64 69 74 69 6f 6e 0a 20 20 20 20 20   condition.     
6100: 20 20 20 20 20 20 20 73 50 61 72 61 6d 73 20 3d         sParams =
6110: 20 22 73 53 65 6e 74 65 6e 63 65 2c 20 73 53 65   "sSentence, sSe
6120: 6e 74 65 6e 63 65 30 2c 20 6d 2c 20 64 54 6f 6b  ntence0, m, dTok
6130: 65 6e 50 6f 73 2c 20 73 43 6f 75 6e 74 72 79 2c  enPos, sCountry,
6140: 20 62 43 6f 6e 64 4d 65 6d 6f 22 0a 20 20 20 20   bCondMemo".    
6150: 20 20 20 20 65 6c 69 66 20 73 46 75 6e 63 4e 61      elif sFuncNa
6160: 6d 65 2e 73 74 61 72 74 73 77 69 74 68 28 22 5f  me.startswith("_
6170: 6d 5f 22 29 3a 20 23 20 6d 65 73 73 61 67 65 0a  m_"): # message.
6180: 20 20 20 20 20 20 20 20 20 20 20 20 73 50 61 72              sPar
6190: 61 6d 73 20 3d 20 22 73 53 65 6e 74 65 6e 63 65  ams = "sSentence
61a0: 2c 20 6d 22 0a 20 20 20 20 20 20 20 20 65 6c 69  , m".        eli
61b0: 66 20 73 46 75 6e 63 4e 61 6d 65 2e 73 74 61 72  f sFuncName.star
61c0: 74 73 77 69 74 68 28 22 5f 73 5f 22 29 3a 20 23  tswith("_s_"): #
61d0: 20 73 75 67 67 65 73 74 69 6f 6e 0a 20 20 20 20   suggestion.    
61e0: 20 20 20 20 20 20 20 20 73 50 61 72 61 6d 73 20          sParams 
61f0: 3d 20 22 73 53 65 6e 74 65 6e 63 65 2c 20 6d 22  = "sSentence, m"
6200: 0a 20 20 20 20 20 20 20 20 65 6c 69 66 20 73 46  .        elif sF
6210: 75 6e 63 4e 61 6d 65 2e 73 74 61 72 74 73 77 69  uncName.startswi
6220: 74 68 28 22 5f 70 5f 22 29 3a 20 23 20 70 72 65  th("_p_"): # pre
6230: 70 72 6f 63 65 73 73 6f 72 0a 20 20 20 20 20 20  processor.      
6240: 20 20 20 20 20 20 73 50 61 72 61 6d 73 20 3d 20        sParams = 
6250: 22 73 53 65 6e 74 65 6e 63 65 2c 20 6d 22 0a 20  "sSentence, m". 
6260: 20 20 20 20 20 20 20 65 6c 69 66 20 73 46 75 6e         elif sFun
6270: 63 4e 61 6d 65 2e 73 74 61 72 74 73 77 69 74 68  cName.startswith
6280: 28 22 5f 64 5f 22 29 3a 20 23 20 64 69 73 61 6d  ("_d_"): # disam
6290: 62 69 67 75 61 74 6f 72 0a 20 20 20 20 20 20 20  biguator.       
62a0: 20 20 20 20 20 73 50 61 72 61 6d 73 20 3d 20 22       sParams = "
62b0: 73 53 65 6e 74 65 6e 63 65 2c 20 6d 2c 20 64 54  sSentence, m, dT
62c0: 6f 6b 65 6e 50 6f 73 22 0a 20 20 20 20 20 20 20  okenPos".       
62d0: 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20   else:.         
62e0: 20 20 20 70 72 69 6e 74 28 66 22 23 20 55 6e 6b     print(f"# Unk
62f0: 6e 6f 77 6e 20 66 75 6e 63 74 69 6f 6e 20 74 79  nown function ty
6300: 70 65 20 69 6e 20 3c 7b 73 46 75 6e 63 4e 61 6d  pe in <{sFuncNam
6310: 65 7d 3e 22 29 0a 20 20 20 20 20 20 20 20 20 20  e}>").          
6320: 20 20 63 6f 6e 74 69 6e 75 65 0a 20 20 20 20 20    continue.     
6330: 20 20 20 23 20 50 79 74 68 6f 6e 0a 20 20 20 20     # Python.    
6340: 20 20 20 20 73 50 79 43 61 6c 6c 61 62 6c 65 73      sPyCallables
6350: 20 2b 3d 20 66 22 64 65 66 20 7b 73 46 75 6e 63   += f"def {sFunc
6360: 4e 61 6d 65 7d 20 28 7b 73 50 61 72 61 6d 73 7d  Name} ({sParams}
6370: 29 3a 5c 6e 22 0a 20 20 20 20 20 20 20 20 73 50  ):\n".        sP
6380: 79 43 61 6c 6c 61 62 6c 65 73 20 2b 3d 20 66 22  yCallables += f"
6390: 20 20 20 20 72 65 74 75 72 6e 20 7b 73 52 65 74      return {sRet
63a0: 75 72 6e 7d 5c 6e 22 0a 20 20 20 20 20 20 20 20  urn}\n".        
63b0: 23 20 4a 61 76 61 53 63 72 69 70 74 0a 20 20 20  # JavaScript.   
63c0: 20 20 20 20 20 73 4a 53 43 61 6c 6c 61 62 6c 65       sJSCallable
63d0: 73 20 2b 3d 20 66 22 20 20 20 20 7b 73 46 75 6e  s += f"    {sFun
63e0: 63 4e 61 6d 65 7d 3a 20 66 75 6e 63 74 69 6f 6e  cName}: function
63f0: 20 28 7b 73 50 61 72 61 6d 73 7d 29 20 7b 7b 5c   ({sParams}) {{\
6400: 6e 22 0a 20 20 20 20 20 20 20 20 73 4a 53 43 61  n".        sJSCa
6410: 6c 6c 61 62 6c 65 73 20 2b 3d 20 22 20 20 20 20  llables += "    
6420: 20 20 20 20 72 65 74 75 72 6e 20 22 20 2b 20 6a      return " + j
6430: 73 63 6f 6e 76 2e 70 79 32 6a 73 28 73 52 65 74  sconv.py2js(sRet
6440: 75 72 6e 29 20 2b 20 22 3b 5c 6e 22 0a 20 20 20  urn) + ";\n".   
6450: 20 20 20 20 20 73 4a 53 43 61 6c 6c 61 62 6c 65       sJSCallable
6460: 73 20 2b 3d 20 22 20 20 20 20 7d 2c 5c 6e 22 0a  s += "    },\n".
6470: 0a 20 20 20 20 64 69 73 70 6c 61 79 53 74 61 74  .    displayStat
6480: 73 28 6c 50 61 72 61 67 72 61 70 68 52 75 6c 65  s(lParagraphRule
6490: 73 2c 20 6c 53 65 6e 74 65 6e 63 65 52 75 6c 65  s, lSentenceRule
64a0: 73 29 0a 0a 20 20 20 20 64 56 61 72 73 20 3d 20  s)..    dVars = 
64b0: 7b 0a 20 20 20 20 20 20 20 20 22 66 42 75 69 6c  {.        "fBuil
64c0: 64 54 69 6d 65 22 3a 20 66 42 75 69 6c 64 54 69  dTime": fBuildTi
64d0: 6d 65 2c 0a 20 20 20 20 20 20 20 20 22 73 46 69  me,.        "sFi
64e0: 6c 65 48 61 73 68 22 3a 20 73 46 69 6c 65 48 61  leHash": sFileHa
64f0: 73 68 2c 0a 20 20 20 20 20 20 20 20 22 63 61 6c  sh,.        "cal
6500: 6c 61 62 6c 65 73 22 3a 20 73 50 79 43 61 6c 6c  lables": sPyCall
6510: 61 62 6c 65 73 2c 0a 20 20 20 20 20 20 20 20 22  ables,.        "
6520: 63 61 6c 6c 61 62 6c 65 73 4a 53 22 3a 20 73 4a  callablesJS": sJ
6530: 53 43 61 6c 6c 61 62 6c 65 73 2c 0a 20 20 20 20  SCallables,.    
6540: 20 20 20 20 22 67 63 74 65 73 74 73 22 3a 20 73      "gctests": s
6550: 47 43 54 65 73 74 73 2c 0a 20 20 20 20 20 20 20  GCTests,.       
6560: 20 22 67 63 74 65 73 74 73 4a 53 22 3a 20 73 47   "gctestsJS": sG
6570: 43 54 65 73 74 73 4a 53 2c 0a 20 20 20 20 20 20  CTestsJS,.      
6580: 20 20 22 70 61 72 61 67 72 61 70 68 5f 72 75 6c    "paragraph_rul
6590: 65 73 22 3a 20 63 72 65 61 74 65 52 75 6c 65 73  es": createRules
65a0: 41 73 53 74 72 69 6e 67 28 6d 65 72 67 65 52 75  AsString(mergeRu
65b0: 6c 65 73 42 79 4f 70 74 69 6f 6e 28 6c 50 61 72  lesByOption(lPar
65c0: 61 67 72 61 70 68 52 75 6c 65 73 29 29 2c 0a 20  agraphRules)),. 
65d0: 20 20 20 20 20 20 20 22 73 65 6e 74 65 6e 63 65         "sentence
65e0: 5f 72 75 6c 65 73 22 3a 20 63 72 65 61 74 65 52  _rules": createR
65f0: 75 6c 65 73 41 73 53 74 72 69 6e 67 28 6d 65 72  ulesAsString(mer
6600: 67 65 52 75 6c 65 73 42 79 4f 70 74 69 6f 6e 28  geRulesByOption(
6610: 6c 53 65 6e 74 65 6e 63 65 52 75 6c 65 73 29 29  lSentenceRules))
6620: 2c 0a 20 20 20 20 20 20 20 20 22 70 61 72 61 67  ,.        "parag
6630: 72 61 70 68 5f 72 75 6c 65 73 5f 4a 53 22 3a 20  raph_rules_JS": 
6640: 6a 73 63 6f 6e 76 2e 77 72 69 74 65 52 75 6c 65  jsconv.writeRule
6650: 73 54 6f 4a 53 41 72 72 61 79 28 6d 65 72 67 65  sToJSArray(merge
6660: 52 75 6c 65 73 42 79 4f 70 74 69 6f 6e 28 6c 50  RulesByOption(lP
6670: 61 72 61 67 72 61 70 68 52 75 6c 65 73 4a 53 29  aragraphRulesJS)
6680: 29 2c 0a 20 20 20 20 20 20 20 20 22 73 65 6e 74  ),.        "sent
6690: 65 6e 63 65 5f 72 75 6c 65 73 5f 4a 53 22 3a 20  ence_rules_JS": 
66a0: 6a 73 63 6f 6e 76 2e 77 72 69 74 65 52 75 6c 65  jsconv.writeRule
66b0: 73 54 6f 4a 53 41 72 72 61 79 28 6d 65 72 67 65  sToJSArray(merge
66c0: 52 75 6c 65 73 42 79 4f 70 74 69 6f 6e 28 6c 53  RulesByOption(lS
66d0: 65 6e 74 65 6e 63 65 52 75 6c 65 73 4a 53 29 29  entenceRulesJS))
66e0: 0a 20 20 20 20 7d 0a 20 20 20 20 64 56 61 72 73  .    }.    dVars
66f0: 2e 75 70 64 61 74 65 28 64 4f 70 74 69 6f 6e 73  .update(dOptions
6700: 29 0a 0a 20 20 20 20 23 20 63 6f 6d 70 69 6c 65  )..    # compile
6710: 20 67 72 61 70 68 20 72 75 6c 65 73 0a 20 20 20   graph rules.   
6720: 20 64 56 61 72 73 32 20 3d 20 63 72 67 2e 6d 61   dVars2 = crg.ma
6730: 6b 65 28 6c 47 72 61 70 68 52 75 6c 65 2c 20 73  ke(lGraphRule, s
6740: 4c 61 6e 67 2c 20 64 44 45 46 49 4e 49 54 49 4f  Lang, dDEFINITIO
6750: 4e 53 2c 20 64 44 45 43 4c 45 4e 53 49 4f 4e 53  NS, dDECLENSIONS
6760: 2c 20 64 4f 70 74 50 72 69 6f 72 69 74 79 29 0a  , dOptPriority).
6770: 20 20 20 20 64 56 61 72 73 2e 75 70 64 61 74 65      dVars.update
6780: 28 64 56 61 72 73 32 29 0a 0a 20 20 20 20 77 69  (dVars2)..    wi
6790: 74 68 20 6f 70 65 6e 28 22 5f 62 75 69 6c 64 2f  th open("_build/
67a0: 64 61 74 61 5f 63 61 63 68 65 2e 6a 73 6f 6e 22  data_cache.json"
67b0: 2c 20 22 77 22 2c 20 65 6e 63 6f 64 69 6e 67 3d  , "w", encoding=
67c0: 22 75 74 66 2d 38 22 29 20 61 73 20 68 44 73 74  "utf-8") as hDst
67d0: 3a 0a 20 20 20 20 20 20 20 20 68 44 73 74 2e 77  :.        hDst.w
67e0: 72 69 74 65 28 6a 73 6f 6e 2e 64 75 6d 70 73 28  rite(json.dumps(
67f0: 64 56 61 72 73 2c 20 65 6e 73 75 72 65 5f 61 73  dVars, ensure_as
6800: 63 69 69 3d 46 61 6c 73 65 29 29 0a 20 20 20 20  cii=False)).    
6810: 72 65 74 75 72 6e 20 64 56 61 72 73 0a           return dVars.