Index: compile_rules_graph.py ================================================================== --- compile_rules_graph.py +++ compile_rules_graph.py @@ -36,12 +36,12 @@ if sCode[0:1] == "=": sCode = sCode[1:] sCode = sCode.replace("__also__", "bCondMemo") sCode = sCode.replace("__else__", "not bCondMemo") sCode = sCode.replace("sContext", "_sAppContext") - sCode = re.sub(r"\b(morph0?|morphVC|value|tag|meta|info)[(]\\(\d+)", 'g_\\1(lToken[nTokenOffset+\\2]', sCode) - sCode = re.sub(r"\b(morph0?|morphVC|value|tag|meta|info)[(]\\-(\d+)", 'g_\\1(lToken[nLastToken-\\2+1]', sCode) + sCode = re.sub(r"\b(morph[02x]?|morphVC|value|tag|meta|info)[(]\\(\d+)", 'g_\\1(lToken[nTokenOffset+\\2]', sCode) + sCode = re.sub(r"\b(morph[02x]?|morphVC|value|tag|meta|info)[(]\\-(\d+)", 'g_\\1(lToken[nLastToken-\\2+1]', sCode) sCode = re.sub(r"\b(select|define|definefrom|rewrite|addmorph|setmeta)[(][\\](\d+)", 'g_\\1(lToken[nTokenOffset+\\2]', sCode) sCode = re.sub(r"\b(select|define|definefrom|rewrite|addmorph|setmeta)[(][\\]-(\d+)", 'g_\\1(lToken[nLastToken-\\2+1]', sCode) sCode = re.sub(r"\b(agreement|suggAgree)[(][\\](\d+), *[\\](\d+)", 'g_\\1(lToken[nTokenOffset+\\2], lToken[nTokenOffset+\\3]', sCode) sCode = re.sub(r"\b(agreement|suggAgree)[(][\\](\d+), *[\\]-(\d+)", 'g_\\1(lToken[nTokenOffset+\\2], lToken[nLastToken-\\3+1]', sCode) sCode = re.sub(r"\b(agreement|suggAgree)[(][\\]-(\d+), *[\\](\d+)", 'g_\\1(lToken[nLastToken-\\2+1], lToken[nTokenOffset+\\3]', sCode) 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 @@ -778,14 +778,14 @@ "nTokenStart": nTokenStart, "nTokenEnd": nTokenEnd, "lTokens": this.lTokens.slice(nTokenStart, nTokenEnd+1), "lMorph": (sAction) ? sAction.split("|") : [":HM"] } - this.lTokens[nTokenStart]["nMultiStartTo"] = nTokenEnd - this.lTokens[nTokenEnd]["nMultiEndFrom"] = nTokenStart - this.lTokens[nTokenStart]["dMultiToken"] = dMultiToken - this.lTokens[nTokenEnd]["dMultiToken"] = dMultiToken + this.lTokens[nTokenStart]["nMultiStartTo"] = nTokenEnd; + this.lTokens[nTokenEnd]["nMultiEndFrom"] = nTokenStart; + this.lTokens[nTokenStart]["oMultiToken"] = oMultiToken; + this.lTokens[nTokenEnd]["oMultiToken"] = oMultiToken; } else { console.log("# error: unknown action at " + sLineId); } } Index: gc_core/js/lang_core/gc_functions.js ================================================================== --- gc_core/js/lang_core/gc_functions.js +++ gc_core/js/lang_core/gc_functions.js @@ -219,10 +219,35 @@ lMorph = gc_engine.oSpellChecker.getMorph(oToken["sValue"]); } } if (lMorph.length == 0) { return false; + } + // check negative condition + if (sNegPattern) { + if (sNegPattern == "*") { + // all morph must match sPattern + return lMorph.every(sMorph => (sMorph.search(sPattern) !== -1)); + } + else { + if (lMorph.some(sMorph => (sMorph.search(sNegPattern) !== -1))) { + return false; + } + } + } + // search sPattern + return lMorph.some(sMorph => (sMorph.search(sPattern) !== -1)); +} + +function g_morphx (oToken, sPattern, sNegPattern="", nLeft=null, nRight=null) { + // analyse a multi-token, return True if not in morphologies and in morphologies + if (!oToken.hasOwnProperty("oMultiToken")) { + return false; + } + let lMorph = oToken["oMultiToken"]["lMorph"]; + if (lMorph.length == 0) { + return false; } // check negative condition if (sNegPattern) { if (sNegPattern == "*") { // all morph must match sPattern Index: gc_core/py/lang_core/gc_functions.py ================================================================== --- gc_core/py/lang_core/gc_functions.py +++ gc_core/py/lang_core/gc_functions.py @@ -198,10 +198,31 @@ if bMemorizeMorph: dToken["lMorph"] = lMorph else: lMorph = _oSpellChecker.getMorph(dToken["sValue"]) if not lMorph: + return False + # check negative condition + if sNegPattern: + if sNegPattern == "*": + # all morph must match sPattern + zPattern = re.compile(sPattern) + return all(zPattern.search(sMorph) for sMorph in lMorph) + zNegPattern = re.compile(sNegPattern) + if any(zNegPattern.search(sMorph) for sMorph in lMorph): + return False + # search sPattern + zPattern = re.compile(sPattern) + return any(zPattern.search(sMorph) for sMorph in lMorph) + + +def g_morphx (dToken, sPattern, sNegPattern): + "analyse a multi-token, return True if not in morphologies and in morphologies" + if not "dMultiToken" in dToken: + return False + lMorph = dToken["dMultiToken"]["lMorph"] + if not lMorph: return False # check negative condition if sNegPattern: if sNegPattern == "*": # all morph must match sPattern