1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
-
-
-
+
-
+
|
"""
Grammalecte: compile rules
Create a Direct Acyclic Rule Graphs (DARGs)
"""
import re
import traceback
import json
import darg
import compile_rules_js_convert as jsconv
dACTIONS = {}
dFUNCTIONS = {}
dFUNCNAME = {}
def createFunction (sType, sActionId, sCode, bStartWithEqual=False):
def createFunction (sType, sCode, bStartWithEqual=False):
"create a function (stored in <dFUNCTIONS>) and return function name"
sCode = prepareFunction(sCode)
if sType not in dFUNCNAME:
dFUNCNAME[sType] = {}
if sCode not in dFUNCNAME[sType]:
dFUNCNAME[sType][sCode] = len(dFUNCNAME[sType])+1
sFuncName = "_g_" + sType + "_" + str(dFUNCNAME[sType][sCode])
dFUNCTIONS[sFuncName] = sCode
return sFuncName if not bStartWithEqual else "="+sFuncName
def storeAction (sActionId, aAction):
"store <aAction> in <dACTIONS> avoiding duplicates"
nVar = 0
while True:
sActionName = sActionId + "_" + str(nVar)
if sActionName not in dACTIONS:
dACTIONS[sActionName] = aAction
return sActionName
elif aAction == dACTIONS[sActionName]:
if aAction == dACTIONS[sActionName]:
return sActionName
nVar += 1
def prepareFunction (sCode):
"convert simple rule syntax to a string of Python code"
if sCode[0:1] == "=":
|
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
|
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
|
-
-
-
-
+
+
+
-
-
-
-
|
if not m.group("end"):
iEndAction = iStartAction
else:
if m.group("end").startswith(":."):
cEndLimit = "<"
iEndAction = int(m.group("end").lstrip(":."))
if dPos and m.group("start"):
try:
iStartAction = dPos.get(iStartAction, iStartAction)
if iEndAction:
iEndAction = dPos.get(iEndAction, iEndAction)
iStartAction = dPos.get(iStartAction, iStartAction)
if iEndAction:
iEndAction = dPos.get(iEndAction, iEndAction)
except:
print("# Error. Wrong groups in: " + sActionId)
print(" iStartAction:", iStartAction, "iEndAction:", iEndAction)
print(" ", dPos)
if iStartAction < 0:
iStartAction += 1
if iEndAction < 0:
iEndAction += 1
if cAction == "-":
## error
|
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
|
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
|
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
+
+
|
sURL = ""
mURL = re.search("[|] *(https?://.*)", sMsg)
if mURL:
sURL = mURL.group(1).strip()
sMsg = sMsg[:mURL.start(0)].strip()
checkTokenNumbers(sMsg, sActionId, nToken)
if sMsg[0:1] == "=":
sMsg = createFunction("msg", sActionId, sMsg, True)
sMsg = createFunction("msg", sMsg, True)
else:
checkIfThereIsCode(sMsg, sActionId)
# checking consistancy
checkTokenNumbers(sAction, sActionId, nToken)
if cAction == ">":
## no action, break loop if condition is False
return [sOption, sCondition, cAction, ""]
if not sAction and cAction != "%":
print("# Error in action at line " + sActionId + ": This action is empty.")
if sAction[0:1] != "=" and cAction != "=":
checkIfThereIsCode(sAction, sActionId)
if cAction == "-":
## error detected --> suggestion
if sAction[0:1] == "=":
sAction = createFunction("sugg", sActionId, sAction, True)
sAction = createFunction("sugg", sAction, True)
elif sAction.startswith('"') and sAction.endswith('"'):
sAction = sAction[1:-1]
if not sMsg:
print("# Error in action at line " + sActionId + ": The message is empty.")
return [sOption, sCondition, cAction, sAction, iStartAction, iEndAction, cStartLimit, cEndLimit, bCaseSensitivity, nPriority, sMsg, sURL]
elif cAction == "~":
if cAction == "~":
## text processor
if sAction[0:1] == "=":
sAction = createFunction("tp", sActionId, sAction, True)
sAction = createFunction("tp", sAction, True)
elif sAction.startswith('"') and sAction.endswith('"'):
sAction = sAction[1:-1]
return [sOption, sCondition, cAction, sAction, iStartAction, iEndAction, bCaseSensitivity]
elif cAction == "%" or cAction == "/":
if cAction in "%/":
## tags
return [sOption, sCondition, cAction, sAction, iStartAction, iEndAction]
elif cAction == "=":
if cAction == "=":
## disambiguator
if "define(" in sAction and not re.search(r"define\(\\-?\d+ *, *\[.*\] *\)", sAction):
print("# Error in action at line " + sActionId + ": second argument for <define> must be a list of strings")
sAction = createFunction("da", sActionId, sAction)
sAction = createFunction("da", sAction)
return [sOption, sCondition, cAction, sAction]
else:
print(" # Unknown action.", sActionId)
return None
print(" # Unknown action.", sActionId)
return None
def make (lRule, dDef, sLang, dOptPriority):
"compile rules, returns a dictionary of values"
# for clarity purpose, don’t create any file here
# removing comments, zeroing empty lines, creating definitions, storing tests, merging rule lines
|
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
|
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
|
-
-
+
+
|
# processing rules
print(" preparing rules...")
for sGraphName, lRuleLine in dAllGraph.items():
print("{:>8,} rules in {:<24} ".format(len(lRuleLine), "<"+sGraphName+">"), end="")
lPreparedRule = []
for i, sRuleGroup, sTokenLine, iActionBlock, sActions, nPriority in lRuleLine:
for lRule in createRule(i, sRuleGroup, sTokenLine, iActionBlock, sActions, nPriority, dOptPriority, dDef):
lPreparedRule.append(lRule)
for aRule in createRule(i, sRuleGroup, sTokenLine, iActionBlock, sActions, nPriority, dOptPriority, dDef):
lPreparedRule.append(aRule)
# Graph creation
oDARG = darg.DARG(lPreparedRule, sLang)
dAllGraph[sGraphName] = oDARG.createGraph()
# Debugging
if False:
print("\nRULES:")
for e in lPreparedRule:
|