Index: compile_rules_graph.py ================================================================== --- compile_rules_graph.py +++ compile_rules_graph.py @@ -152,13 +152,13 @@ else: lToken.append(sToken) return lToken -def createRule (iLine, sRuleName, sTokenLine, iActionBlock, sActions, nPriority, dOptPriority, dDef, dDecl): +def createRule (iLine, sRuleName, sTokenLine, iActionBlock, lActions, nPriority, dOptPriority, dDef, dDecl): "generator: create rule as list" - # print(iLine, "//", sRuleName, "//", sTokenLine, "//", sActions, "//", nPriority) + # print(iLine, "//", sRuleName, "//", sTokenLine, "//", lActions, "//", nPriority) if sTokenLine.startswith("!!") and sTokenLine.endswith("¡¡"): # antipattern sTokenLine = sTokenLine[2:-2].strip() if sRuleName not in dANTIPATTERNS: dANTIPATTERNS[sRuleName]= [] @@ -180,15 +180,15 @@ lToken[i] = sToken[1:-1] iGroup += 1 dPos[iGroup] = i + 1 # we add 1, for we count tokens from 1 to n (not from 0) # Parse actions - for iAction, sAction in enumerate(sActions.split(" <<- ")): + for iAction, (iActionLine, sAction) in enumerate(lActions): sAction = sAction.strip() if sAction: sActionId = sRuleName + "__b" + str(iActionBlock) + "_a" + str(iAction) - aAction = createAction(sActionId, sAction, nPriority, dOptPriority, len(lToken), dPos) + aAction = createAction(sActionId, sAction, nPriority, dOptPriority, len(lToken), dPos, iActionLine) if aAction: sActionName = storeAction(sActionId, aAction) lResult = list(lToken) lResult.extend(["##"+str(iLine), sActionName]) #if iLine == 13341: @@ -195,11 +195,13 @@ # print(" ".join(lToken)) # print(sActionId, aAction) yield lResult else: print(" # Error on action at line:", iLine) - print(sTokenLine, "\n", sActions) + print(sTokenLine, "\n", lActions) + else: + print("No action found for ", iActionLine) def changeReferenceToken (sText, dPos): "change group reference in with values in " if "\\" not in sText: @@ -222,11 +224,11 @@ if re.search(r"[.]\w+[(]|sugg\w+[(]|\(\\[0-9]|\[[0-9]", sText): print("# Warning at line " + sActionId + ": This message looks like code. Line should probably begin with =") print(sText) -def createAction (sActionId, sAction, nPriority, dOptPriority, nToken, dPos): +def createAction (sActionId, sAction, nPriority, dOptPriority, nToken, dPos, iActionLine): "create action rule as a list" # Option sOption = False m = re.match("/(\\w+)/", sAction) if m: @@ -306,13 +308,15 @@ checkIfThereIsCode(sMsg, sActionId) # checking consistancy checkTokenNumbers(sAction, sActionId, nToken) + sLineId = "#" + str(iActionLine) + if cAction == ">": ## no action, break loop if condition is False - return [sOption, sCondition, cAction, ""] + return [sLineId, sOption, sCondition, cAction, ""] if not sAction and cAction != "!": print("\n# Error in action at line <" + sActionId + ">: This action is empty.") if sAction[0:1] != "=" and cAction != "=": @@ -324,11 +328,11 @@ sAction = createFunction("sugg", sAction, True) elif sAction.startswith('"') and sAction.endswith('"'): sAction = sAction[1:-1] if not sMsg: print("\n# Error in action at line <" + sActionId + ">: The message is empty.") - return [sOption, sCondition, cAction, sAction, iStartAction, iEndAction, cStartLimit, cEndLimit, bCaseSensitivity, nPriority, sMsg, sURL] + return [sLineId, sOption, sCondition, cAction, sAction, iStartAction, iEndAction, cStartLimit, cEndLimit, bCaseSensitivity, nPriority, sMsg, sURL] if cAction == "~": ## text processor if sAction[0:1] == "=": sAction = createFunction("tp", sAction, True) elif sAction.startswith('"') and sAction.endswith('"'): @@ -338,20 +342,20 @@ if iStartAction > 0 and iEndAction > 0: if (iEndAction - iStartAction + 1) != nToken: print("\n# Error in action at line <" + sActionId + ">: numbers of modified tokens modified.") elif iStartAction < 0 or iEndAction < 0 and iStartAction != iEndAction: print("\n# Warning in action at line <" + sActionName + ">: rewriting with possible token position modified.") - return [sOption, sCondition, cAction, sAction, iStartAction, iEndAction, bCaseSensitivity] + return [sLineId, sOption, sCondition, cAction, sAction, iStartAction, iEndAction, bCaseSensitivity] if cAction in "!/": ## tags - return [sOption, sCondition, cAction, sAction, iStartAction, iEndAction] + return [sLineId, sOption, sCondition, cAction, sAction, iStartAction, iEndAction] if cAction == "=": ## disambiguator if "define(" in sAction and not re.search(r"define\(\\-?\d+ *, *\[.*\] *\)", sAction): print("\n# Error in action at line <" + sActionId + ">: second argument for must be a list of strings") sAction = createFunction("da", sAction) - return [sOption, sCondition, cAction, sAction] + return [sLineId, sOption, sCondition, cAction, sAction] print("\n# Unknown action.", sActionId) return None def make (lRule, sLang, dDef, dDecl, dOptPriority): @@ -359,88 +363,100 @@ # for clarity purpose, don’t create any file here # removing comments, zeroing empty lines, creating definitions, storing tests, merging rule lines print(" parsing rules...") lTokenLine = [] - sActions = "" + lActions = [] + bActionBlock = False nPriority = -1 dAllGraph = {} sGraphName = "" iActionBlock = 0 aRuleName = set() - for i, sLine in lRule: + for iLine, sLine in lRule: sLine = sLine.rstrip() if "\t" in sLine: # tabulation not allowed - print("Error. Tabulation at line: ", i) + print("Error. Tabulation at line: ", iLine) exit() elif sLine.startswith("@@@@GRAPH: "): # rules graph call m = re.match(r"@@@@GRAPH: *(\w+)", sLine.strip()) if m: sGraphName = m.group(1) if sGraphName in dAllGraph: - print("Error at line " + i + ". Graph name <" + sGraphName + "> already exists.") + print("Error at line " + iLine + ". Graph name <" + sGraphName + "> already exists.") exit() dAllGraph[sGraphName] = [] else: - print("Error. Graph name not found at line", i) + print("Error. Graph name not found at line", iLine) exit() elif sLine.startswith("__") and sLine.endswith("__"): # new rule group m = re.match("__(\\w+)(!\\d|)__", sLine) if m: sRuleName = m.group(1) if sRuleName in aRuleName: - print("Error at line " + str(i) + ". Rule name <" + sRuleName + "> already exists.") + print("Error at line " + str(iLine) + ". Rule name <" + sRuleName + "> already exists.") exit() aRuleName.add(sRuleName) iActionBlock = 1 nPriority = int(m.group(2)[1:]) if m.group(2) else -1 else: - print("Syntax error in rule group: ", sLine, " -- line:", i) + print("Syntax error in rule group: ", sLine, " -- line:", iLine) exit() - elif re.search("^ +<<- ", sLine) or (sLine.startswith(" ") and not sLine.startswith(" ||")) \ - or re.search("^ +#", sLine) or re.search(r"[-=~/!>](?:-?\d\.?(?::\.?-?\d+|)|)>> ", sLine) : + elif re.match(" \\S", sLine): + # tokens line + lTokenLine.append([iLine, sLine.strip()]) + elif sLine.startswith(" ||"): + # tokens line continuation + iPrevLine, sPrevLine = lTokenLine[-1] + lTokenLine[-1] = [iPrevLine, sPrevLine + " " + sLine.strip()[2:]] + elif sLine.startswith(" <<- "): # actions - sActions += " " + sLine.strip() + lActions.append([iLine, sLine[12:].strip()]) + if not re.search(r"[-=~/!>](?:-?\d\.?(?::\.?-?\d+|)|):?>>", sLine): + bActionBlock = True + elif sLine.startswith(" # "): + # action message + iPrevLine, sPrevLine = lActions[-1] + lActions[-1] = [iPrevLine, sPrevLine + sLine] + elif sLine.startswith(" ") and bActionBlock: + # action line continuation + iPrevLine, sPrevLine = lActions[-1] + lActions[-1] = [iPrevLine, sPrevLine + " " + sLine.strip()] + if re.search(r"[-=~/!>](?:-?\d\.?(?::\.?-?\d+|)|):?>>", sLine): + bActionBlock = False elif re.match("[  ]*$", sLine): # empty line to end merging if not lTokenLine: continue - if not sActions: - print("Error. No action found at line:", i) + if bActionBlock or not lActions: + print("Error. No action found at line:", iLine) + print(bActionBlock, lActions) exit() if not sGraphName: - print("Error. All rules must belong to a named graph. Line: ", i) + print("Error. All rules must belong to a named graph. Line: ", iLine) exit() for j, sTokenLine in lTokenLine: - dAllGraph[sGraphName].append((j, sRuleName, sTokenLine, iActionBlock, sActions, nPriority)) + dAllGraph[sGraphName].append((j, sRuleName, sTokenLine, iActionBlock, list(lActions), nPriority)) lTokenLine.clear() - sActions = "" + lActions.clear() iActionBlock += 1 - elif sLine.startswith(" "): - # tokens - sLine = sLine.strip() - if sLine.startswith("||"): - iPrevLine, sPrevLine = lTokenLine[-1] - lTokenLine[-1] = [iPrevLine, sPrevLine + " " + sLine[2:]] - else: - lTokenLine.append([i, sLine]) - else: - print("Unknown line:") + else: + print("Unknown line at:", iLine) print(sLine) # processing rules print(" preparing rules...") nRule = 0 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 aRule in createRule(i, sRuleGroup, sTokenLine, iActionBlock, sActions, nPriority, dOptPriority, dDef, dDecl): + for i, sRuleGroup, sTokenLine, iActionBlock, lActions, nPriority in lRuleLine: + for aRule in createRule(i, sRuleGroup, sTokenLine, iActionBlock, lActions, nPriority, dOptPriority, dDef, dDecl): lPreparedRule.append(aRule) nRule += len(lRuleLine) # Graph creation oDARG = darg.DARG(lPreparedRule, sLang) dAllGraph[sGraphName] = oDARG.createGraph() @@ -487,10 +503,12 @@ print("\nActions:") for sActionName, aAction in dACTIONS.items(): print(sActionName, aAction) print("\nFunctions:") print(sPyCallables) + + print("Nombre d’actions: ", len(dACTIONS)) # Result return { "graph_callables": sPyCallables, "graph_callablesJS": sJSCallables, Index: compile_rules_js_convert.py ================================================================== --- compile_rules_js_convert.py +++ compile_rules_js_convert.py @@ -166,9 +166,9 @@ def pyActionsToString (dActions): "returns dictionary as string (nbsp -> nnbsp, True -> true, etc.)" for _, aValue in dActions.items(): - if aValue[2] == "-": - aValue[3] = aValue[3].replace(" ", " ") # nbsp --> nnbsp - aValue[10] = aValue[10].replace("« ", "« ").replace(" »", " »").replace(" :", " :").replace(" :", " :") + if aValue[3] == "-": + aValue[4] = aValue[4].replace(" ", " ") # nbsp --> nnbsp + aValue[11] = aValue[11].replace("« ", "« ").replace(" »", " »").replace(" :", " :").replace(" :", " :") return str(dActions).replace("True", "true").replace("False", "false") Index: gc_core/js/lang_core/gc_engine.js ================================================================== --- gc_core/js/lang_core/gc_engine.js +++ gc_core/js/lang_core/gc_engine.js @@ -668,11 +668,11 @@ for (let sRuleId of oGraph[nextNodeKey]) { try { if (bDebug) { console.log(" >TRY: " + sRuleId + " " + sLineId); } - let [sOption, sFuncCond, cActionType, sWhat, ...eAct] = gc_rules_graph.dRule[sRuleId]; + let [_, sOption, sFuncCond, cActionType, sWhat, ...eAct] = gc_rules_graph.dRule[sRuleId]; // Suggestion [ option, condition, "-", replacement/suggestion/action, iTokenStart, iTokenEnd, cStartLimit, cEndLimit, bCaseSvty, nPriority, sMessage, sURL ] // TextProcessor [ option, condition, "~", replacement/suggestion/action, iTokenStart, iTokenEnd, bCaseSvty ] // Disambiguator [ option, condition, "=", replacement/suggestion/action ] // Tag [ option, condition, "/", replacement/suggestion/action, iTokenStart, iTokenEnd ] // Immunity [ option, condition, "!", "", iTokenStart, iTokenEnd ] Index: gc_core/py/lang_core/gc_engine.py ================================================================== --- gc_core/py/lang_core/gc_engine.py +++ gc_core/py/lang_core/gc_engine.py @@ -144,13 +144,13 @@ for _, _, sLineId, sRuleId, _, _ in lRuleGroup: if not sFilter or zFilter.search(sRuleId): yield ("RegEx", sOption, sLineId, sRuleId) # tokens rules for sRuleName, lActions in _rules_graph.dRule.items(): - sOption, _, cActionType, *_ = lActions + sLineId, sOption, _, cActionType, *_ = lActions if cActionType == "-": - yield("Tokens", sOption, "", sRuleName) + yield("Tokens", sOption, sLineId, sRuleName) def displayRules (sFilter=None): "display the name of rules, with the filter " echo("List of rules. Filter: << " + str(sFilter) + " >>") @@ -585,11 +585,11 @@ bCondMemo = None for sRuleId in dGraph[nextNodeKey]: try: if bDebug: echo(" >TRY: " + sRuleId + " " + sLineId) - sOption, sFuncCond, cActionType, sWhat, *eAct = _rules_graph.dRule[sRuleId] + _, sOption, sFuncCond, cActionType, sWhat, *eAct = _rules_graph.dRule[sRuleId] # Suggestion [ option, condition, "-", replacement/suggestion/action, iTokenStart, iTokenEnd, cStartLimit, cEndLimit, bCaseSvty, nPriority, sMessage, sURL ] # TextProcessor [ option, condition, "~", replacement/suggestion/action, iTokenStart, iTokenEnd, bCaseSvty ] # Disambiguator [ option, condition, "=", replacement/suggestion/action ] # Tag [ option, condition, "/", replacement/suggestion/action, iTokenStart, iTokenEnd ] # Immunity [ option, condition, "!", "", iTokenStart, iTokenEnd ] Index: gc_lang/fr/rules.grx ================================================================== --- gc_lang/fr/rules.grx +++ gc_lang/fr/rules.grx @@ -2493,12 +2493,12 @@ # Note: l’option “mapos” cherche les apostrophes manquantes après les lettres l, d, n, m, t, s, j, c, ç __ocr_lettres_isolées2!2__ [á|â|ä|b|c|ç|d|e|é|è|ê|ë|f|g|h|i|í|ì|î|ï|j|k|l|m|n|o|ó|ò|ô|ö|p|q|r|s|t|u|ú|ù|û|ü|v|w|x|z] - <<- not before("\\d[   ]+$") and not (\1.isupper() and value(>1, "|.||")) - ->> _ # Lettre isolée : erreur de numérisation ? + <<- not before("\\d[   ]+$") and not (\1.isupper() and value(>1, "|.||")) + ->> _ # Lettre isolée : erreur de numérisation ? TEST: __ocr__ des verres luisent sur {{i}} le bureau blanc. TEST: __ocr__ la voix, {{e}} est celle de… TEST: __ocr__ ressemble {{h}} une fenêtre de serre. TEST: __ocr__ Ça a duré 3 h. @@ -3238,11 +3238,11 @@ # tandis que / taudis __ocr_tandis__ taudis [que|qu’] - <<- /ocr/ -1>> tandis # Erreur de numérisation ? + <<- /ocr/ -1>> tandis # Erreur de numérisation ? TEST: __ocr__ mais {{taudis}} qu’elle œuvrait à leur salut, les nuages s’amoncelaient. # l’est / Test @@ -17164,11 +17164,11 @@ __conf_a_à_faim_peur_honte_soif_chaud_froid__ à [faim|peur|honte|soif|sommeil] <<- /conf/ -1>> a # Avoir “\2”. Confusion : “à” est une préposition. Pour le verbe avoir, écrivez “a”. elle à [chaud|froid] - <<- /conf/ -3>> a # Avoir “\4”. Confusion : “à” est une préposition. Pour le verbe avoir, écrivez “a”. + <<- /conf/ -3>> a # Avoir “\4”. Confusion : “à” est une préposition. Pour le verbe avoir, écrivez “a”. TEST: Elle {{à}} chaud. TEST: Elle {{à}} froid. TEST: cet homme {{à}} faim TEST: Votre réaction à froid ? @@ -17545,11 +17545,11 @@ # en butte à / but / bute __conf_en_butte_à_au__ en [>but|>bute] [à|au|aux] - <<- /conf/ -2>> butte # Confusion. Écrivez « en butte \3 ». + <<- /conf/ -2>> butte # Confusion. Écrivez « en butte \3 ». TEST: Et moi toujours en {{but}} à de nouveaux dangers # cane / canne (from LanguageTool) @@ -18247,11 +18247,11 @@ sans-gènes sans-gène <<- /conf/ ->> sans-gêne # Confusion. Les gènes sont des éléments des chromosomes. Pour le synonyme d’embarras, écrivez “gêne”. [ces|des|mes|tes|ses|nos|vos|leurs] gênes - <<- /conf/ -2>> gènes # Confusion probable. La gêne est un embarras. Pour parles des éléments des chromosomes, écrivez “gènes”. + <<- /conf/ -2>> gènes # Confusion probable. La gêne est un embarras. Pour parles des éléments des chromosomes, écrivez “gènes”. TEST: Quel {{sans gène}}, celui-là ! TEST: Il croit que ses {{gênes}} décident de sa santé… @@ -22005,16 +22005,16 @@ TEST: Ils avaient barre sur lui. __ppas_nous_vous_avoir__ [nous|vous] ?[ne|n’]¿ ?[lui|leur]¿ >avoir *WORD - <<- /ppas/ morph(\1, ":Os") - and not value(\-1, "|barre|confiance|charge|cours|envie|peine|prise|crainte|cure|affaire|hâte|force|recours|") - and value(<1, "||,|comme|comment|et|lorsque|mais|où|ou|quand|qui|pourquoi|puisque|quoique|si|sinon|") - and not \-1.isupper() and morph(\-1, ":(?:[123][sp]|Q.*:[fp])", ":(?:G|W|Q.*:m:[si])") - --1>> =suggVerbPpas(\-1, ":m:s") - # Ce verbe devrait être un participe passé au masculin singulier.|http://fr.wikipedia.org/wiki/Accord_du_participe_pass%C3%A9_en_fran%C3%A7ais + <<- /ppas/ morph(\1, ":Os") + and not value(\-1, "|barre|confiance|charge|cours|envie|peine|prise|crainte|cure|affaire|hâte|force|recours|") + and value(<1, "||,|comme|comment|et|lorsque|mais|où|ou|quand|qui|pourquoi|puisque|quoique|si|sinon|") + and not \-1.isupper() and morph(\-1, ":(?:[123][sp]|Q.*:[fp])", ":(?:G|W|Q.*:m:[si])") + --1>> =suggVerbPpas(\-1, ":m:s") + # Ce verbe devrait être un participe passé au masculin singulier.|http://fr.wikipedia.org/wiki/Accord_du_participe_pass%C3%A9_en_fran%C3%A7ais TEST: Nous avons {{donne}} tout notre potentiel. TEST: mais nous avons {{était}} surpris par cette annonce. TEST: Nous lui avons {{donnée}} un cadeau. TEST: Vous lui avez {{donnés}} un cadeau. @@ -22022,16 +22022,16 @@ TEST: D’un côté, le modèle occidental, […], nous a libérés de […] __ppas_det_nom_avoir__ [un|une|des|le|la|l’|les|ce|cet|cette|ces|mon|ton|son|ma|ta|sa|mes|tes|ses|notre|votre|nos|vos|leur|leurs|certains|certaines|quelques|plusieurs] *WORD ?[ne|n’]¿ ?[lui|leur]¿ >avoir *WORD - <<- /ppas/ not value(\-1, "|barre|confiance|charge|cours|envie|peine|prise|crainte|cure|affaire|hâte|force|recours|") - and value(<1, "||,|comme|comment|et|lorsque|mais|où|ou|quand|qui|pourquoi|puisque|quoique|si|sinon|") - and morph(\2, ":[NA]", ":G") and not \-1.isupper() and morph(\-1, ":(?:[123][sp]|Y|Q.*:[fp])", ":(?:G|W|Q.*:m:[si])") - and not (\-2 == "avions" and morph(\-1, ":3[sp]")) - --1>> =suggVerbPpas(\-1, ":m:s") - # Ce verbe devrait être un participe passé au masculin singulier.|http://fr.wikipedia.org/wiki/Accord_du_participe_pass%C3%A9_en_fran%C3%A7ais + <<- /ppas/ not value(\-1, "|barre|confiance|charge|cours|envie|peine|prise|crainte|cure|affaire|hâte|force|recours|") + and value(<1, "||,|comme|comment|et|lorsque|mais|où|ou|quand|qui|pourquoi|puisque|quoique|si|sinon|") + and morph(\2, ":[NA]", ":G") and not \-1.isupper() and morph(\-1, ":(?:[123][sp]|Y|Q.*:[fp])", ":(?:G|W|Q.*:m:[si])") + and not (\-2 == "avions" and morph(\-1, ":3[sp]")) + --1>> =suggVerbPpas(\-1, ":m:s") + # Ce verbe devrait être un participe passé au masculin singulier.|http://fr.wikipedia.org/wiki/Accord_du_participe_pass%C3%A9_en_fran%C3%A7ais TEST: Les femmes lui avait {{conseillées}} de se taire. TEST: le mur avait {{était}} détruit TEST: Lorsque les femmes ont {{apprit}} la nouvelle… TEST: Les élèves lui ont {{données}}. @@ -23697,12 +23697,12 @@ -2:3>> \2-je # Forme interrogative ? Mettez un trait d’union. *WORD ~.[is]$ je [|,] *WORD ~.[is]$ je @:¬:1s <<- /inte/ space_after(\2, 1, 1) and morph(\2, ":V.*:1s", ":[GNW]") and not value(\1, "|je|j’|tu|") - -2:3>> \2-je - # Forme interrogative ? Mettez un trait d’union. + -2:3>> \2-je # Forme interrogative ? Mettez un trait d’union. + TEST: quel animal {{dessine je}} TEST: {{mangé je}} {{ça}} avec dégoût ? TEST: {{viendrais je}} à la fête ? TEST: {{ai je}} enfin trouvé la réponse à mes questions ? TEST: quel amour {{connaîtrai je}} si je juge sans cesse ?