Index: compile_rules_graph.py ================================================================== --- compile_rules_graph.py +++ compile_rules_graph.py @@ -18,11 +18,13 @@ "convert simple rule syntax to a string of Python code" s = s.replace("__also__", "bCondMemo") s = s.replace("__else__", "not bCondMemo") s = s.replace("sContext", "_sAppContext") s = re.sub(r"(morph|morphVC|analyse|value|displayInfo)[(]\\(\d+)", 'g_\\1(lToken[\\2+nTokenOffset]', s) + s = re.sub(r"(morph|morphVC|analyse|value|displayInfo)[(]\\-(\d+)", 'g_\\1(lToken[nLastToken-\\2+1]', s) s = re.sub(r"(select|exclude|define|define_from)[(][\\](\d+)", 'g_\\1(lToken[\\2+nTokenOffset]', s) + s = re.sub(r"(select|exclude|define|define_from)[(][\\]-(\d+)", 'g_\\1(lToken[nLastToken-\\2+1]', s) s = re.sub(r"(tag_before|tag_after)[(][\\](\d+)", 'g_\\1(lToken[\\2+nTokenOffset], dTags', s) s = re.sub(r"space_after[(][\\](\d+)", 'g_space_between_tokens(lToken[\\1+nTokenOffset], lToken[\\1+nTokenOffset+1]', s) s = re.sub(r"analyse_with_next[(][\\](\d+)", 'g_merged_analyse(lToken[\\1+nTokenOffset], lToken[\\1+nTokenOffset+1]', s) s = re.sub(r"(morph|analyse|value)\(>1", 'g_\\1(lToken[nLastToken+1]', s) # next token s = re.sub(r"(morph|analyse|value)\(<1", 'g_\\1(lToken[nTokenOffset]', s) # previous token @@ -32,10 +34,11 @@ s = re.sub(r"\bbefore\(\s*", 'look(sSentence[:lToken[1+nTokenOffset]["nStart"]], ', s) # before(s) s = re.sub(r"\bafter\(\s*", 'look(sSentence[lToken[nLastToken]["nEnd"]:], ', s) # after(s) s = re.sub(r"\bbefore0\(\s*", 'look(sSentence0[:lToken[1+nTokenOffset]["nStart"]], ', s) # before0(s) s = re.sub(r"\bafter0\(\s*", 'look(sSentence[lToken[nLastToken]["nEnd"]:], ', s) # after0(s) s = re.sub(r"[\\](\d+)", 'lToken[\\1+nTokenOffset]["sValue"]', s) + s = re.sub(r"[\\]-(\d+)", 'lToken[nLastToken-\\1+1]["sValue"]', s) return s def genTokenLines (sTokenLine, dDef): "tokenize a string and return a list of lines of tokens" @@ -158,11 +161,11 @@ sOption = m.group(1) sAction = sAction[m.end():].strip() if nPriority == -1: nPriority = dOptPriority.get(sOption, 4) # valid action? - m = re.search(r"(?P[-~=/%>])(?P\d+\.?|)(?P:\.?\d+|)>>", sAction) + m = re.search(r"(?P[-~=/%>])(?P-?\d+\.?|)(?P:\.?-?\d+|)>>", sAction) if not m: print(" # Error. No action found at: ", sActionId) return None # Condition sCondition = sAction[:m.start()].strip() @@ -380,11 +383,11 @@ if sFuncName.startswith("_g_c_"): # condition sParams = "lToken, nTokenOffset, nLastToken, sCountry, bCondMemo, dTags, sSentence, sSentence0" elif sFuncName.startswith("g_m_"): # message sParams = "lToken, nTokenOffset" elif sFuncName.startswith("_g_s_"): # suggestion - sParams = "lToken, nTokenOffset" + sParams = "lToken, nTokenOffset, nLastToken" elif sFuncName.startswith("_g_p_"): # preprocessor sParams = "lToken, nTokenOffset" elif sFuncName.startswith("_g_d_"): # disambiguator sParams = "lToken, nTokenOffset" else: 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 @@ -789,11 +789,11 @@ if "bImmune" not in self.lToken[nTokenErrorStart]: nTokenErrorEnd = nTokenOffset + iTokenEnd if iTokenEnd > 0 else nLastToken + iTokenEnd nErrorStart = self.nOffsetWithinParagraph + (self.lToken[nTokenErrorStart]["nStart"] if cStartLimit == "<" else self.lToken[nTokenErrorStart]["nEnd"]) nErrorEnd = self.nOffsetWithinParagraph + (self.lToken[nTokenErrorEnd]["nEnd"] if cEndLimit == ">" else self.lToken[nTokenErrorEnd]["nStart"]) if nErrorStart not in self.dError or nPriority > dPriority.get(nErrorStart, -1): - self.dError[nErrorStart] = self._createError(sWhat, nTokenOffset, nTokenErrorStart, nErrorStart, nErrorEnd, sLineId, sRuleId, True, sMessage, sURL, bShowRuleId, "notype", bContext) + self.dError[nErrorStart] = self._createError(sWhat, nTokenOffset, nLastToken, nTokenErrorStart, nErrorStart, nErrorEnd, sLineId, sRuleId, True, sMessage, sURL, bShowRuleId, "notype", bContext) dPriority[nErrorStart] = nPriority if bDebug: print(" NEW_ERROR:", self.dError[nErrorStart], "\n ", dRule[sRuleId]) elif cActionType == "~": # text processor @@ -839,14 +839,14 @@ break except Exception as e: raise Exception(str(e), sLineId, sRuleId, self.sSentence) return bChange - def _createError (self, sSugg, nTokenOffset, iFirstToken, nStart, nEnd, sLineId, sRuleId, bUppercase, sMsg, sURL, bShowRuleId, sOption, bContext): + def _createError (self, sSugg, nTokenOffset, nLastToken, iFirstToken, nStart, nEnd, sLineId, sRuleId, bUppercase, sMsg, sURL, bShowRuleId, sOption, bContext): # suggestions if sSugg[0:1] == "=": - sSugg = globals()[sSugg[1:]](self.lToken, nTokenOffset) + sSugg = globals()[sSugg[1:]](self.lToken, nTokenOffset, nLastToken) lSugg = sSugg.split("|") if sSugg else [] elif sSugg == "_": lSugg = [] else: lSugg = self._expand(sSugg, nTokenOffset).split("|") Index: gc_lang/fr/rules.grx ================================================================== --- gc_lang/fr/rules.grx +++ gc_lang/fr/rules.grx @@ -11072,13 +11072,12 @@ # desceller / déceler / desseller __erreur_déceler_desseller_desceller__ [>erreur|>faute|>incohérence|>problème|>bug|>bogue|>faille|>maladie|>défaut|>défaillance|>perturbation|>irrégularité] <> [>desseller|>desceller] - <<- /conf/ - -1>> =\1.replace("escell", "écel").replace("essell", "écel") - # Confusion probable. Desceller signifie briser un sceau, un cachet… Desseller signifie ôter une selle. Si vous voulez dire “remarquer”, “dévoiler”, “découvrir”, écrivez “déceler”.|http://fr.wiktionary.org/wiki/déceler + <<- /conf/ --1>> =\-1.replace("escell", "écel").replace("essell", "écel") + # Confusion probable si ce verbe se rapporte à “\1”. Desceller signifie briser un sceau, un cachet… Desseller signifie ôter une selle. Si vous voulez dire “remarquer”, “dévoiler”, “découvrir”, écrivez “déceler”.|http://fr.wiktionary.org/wiki/déceler [>desseller|>desceller] [l’|@:[BD]] [>petite|>grande|>énorme|>dangeureuse|>formidable|>forte|>légère|>merveilleuse|>nouvelle|>vrai|>réelle|>sévère|>véritable] [>acidité|>activité|>allergie|>anévrisme|>anomalie|>arnaque|>appendicite|>atrophie|>baisse|>bébé|>blessure|>bug|>bogue|>carie|>cancer|>cause|>changement|>complot|>comète|>concentration|>corrélation|>croissance|>défaut|>défaillance|>demande|>dépression|>diabète|>différence|>diminution|>effluve|>épilepsie|>erreur|>essai|>existence|>grossesse|>grosseur|>faille|>faute|>fuite|>fraude|>grippe|>handicap|>hausse|>hémorragie|>hostilité|>hypertrophie|>incompatibilité|>incohérence|>infection|>infraction|>indice|>infidélité|>insuffisance|>intrigue|>irrégularité|>leucémie|>lésion|>lueur|>lumière|>maladie|>malformation|>manœuvre|>manipulation|>molécule|>mensonge|>mutation|>once|>perturbation|>personnalité|>piste|>perte|>planète|>exoplanète|>présence|>qualité|>odeur|>opportunité|>otite|>problème|>surdité|>talent|>tendance|>tentative|>tumeur|>utilisation|hoax|>variation|>vie|virus] <<- /conf/ -1>> =\1.replace("escell", "écel").replace("essell", "écel") # Confusion probable si ce mot se rapporte à “\3 \4”. Desceller signifie briser un sceau, un cachet… Desseller signifie ôter une selle.|http://fr.wiktionary.org/wiki/déceler