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 @@ -695,14 +695,27 @@ #print("value regex matching: ", sRegex) yield dGraph[dNode[""][sRegex]] # regex morph arcs if "" in dNode: for sRegex in dNode[""]: - for sMorph in _oSpellChecker.getMorph(dToken["sValue"]): - if re.search(sRegex, sMorph): - #print("morph regex matching: ", sRegex) + if "¬" not in sRegex: + # no anti-pattern + if any(re.search(sRegex, sMorph) for sMorph in _oSpellChecker.getMorph(dToken["sValue"])): yield dGraph[dNode[""][sRegex]] + else: + # there is an anti-pattern + sPattern, sNegPattern = sRegex.split("¬", 1) + if sNegPattern == "*": + # all morphologies must match with + if all(re.search(sPattern, sMorph) for sMorph in _oSpellChecker.getMorph(dToken["sValue"])): + yield dGraph[dNode[""][sRegex]] + else: + if sNegPattern and any(re.search(sNegPattern, sMorph) for sMorph in _oSpellChecker.getMorph(dToken["sValue"])): + continue + if any(re.search(sPattern, sMorph) for sMorph in _oSpellChecker.getMorph(dToken["sValue"])): + yield dGraph[dNode[""][sRegex]] + def parse (self, dPriority, sCountry="${country_default}", dOptions=None, bShowRuleId=False, bDebug=False, bContext=False): dErr = {} dPriority = {} # Key = position; value = priority dOpt = _dOptions if not dOptions else dOptions Index: gc_lang/fr/rules_graph.grx ================================================================== --- gc_lang/fr/rules_graph.grx +++ gc_lang/fr/rules_graph.grx @@ -68,9 +68,9 @@ TEST: Ça me fait {{plaisirs}}. __test__ - je ~préf[éè]r [que|qu’] @(?::Os|:M) @:I + je ~préf[éè]r [que|qu’] @(?::Os|:M)¬:X @:I <<- morph(\1, ":V", False) and morphex(\4, ":Os|:M", ":X") -5>> SUBJONCTIF # SUBJONCTIF. TEST: je préférerais qu’Isabelle {{est}} partie.