Index: compile_rules_graph.py ================================================================== --- compile_rules_graph.py +++ compile_rules_graph.py @@ -12,12 +12,13 @@ def prepareFunction (s, bTokenValue=False): s = s.replace("__also__", "bCondMemo") s = s.replace("__else__", "not bCondMemo") - s = re.sub(r"(select|exclude|define)[(][\\](\d+)", 'g_\\1(lToken[\\2+nTokenOffset]', s) s = re.sub(r"(morph|analyse|displayInfo)[(]\\(\d+)", 'g_\\1(lToken[\\2+nTokenOffset]', s) + s = re.sub(r"(select|exclude|define)[(][\\](\d+)", 'g_\\1(lToken[\\2+nTokenOffset]', s) + s = re.sub(r"(tag_before|tag_after)[(][\\](\d+)", 'g_\\1(lToken[\\2+nTokenOffset]', s) s = re.sub(r"(switchGender|has(?:Mas|Fem)Form)[(]\\(\d+)", '\\1(lToken[\\2+nTokenOffset]["sValue"]', s) s = re.sub(r"(morph|analyse)\(>1", 'g_\\1(lToken[nLastToken+1]', s) # next token s = re.sub(r"(morph|analyse)\(<1", 'g_\\1(lToken[nTokenOffset]', s) # previous token s = re.sub(r"before\(\s*", 'look(s[:m.start()], ', s) # before(s) s = re.sub(r"after\(\s*", 'look(s[m.end():], ', s) # after(s) @@ -145,11 +146,11 @@ m = re.match("/(\\w+)/", sAction) if m: sOption = m.group(1) sAction = sAction[m.end():].strip() # valid action? - m = re.search("(?P[-~=])(?P\\d+|)(?P:\\d+|)>> ", sAction) + m = re.search("(?P[-~=/])(?P\\d+|)(?P:\\d+|)>> ", sAction) if not m: print(" # Error. No action found at: ", sActionId) print(" ==", sAction, "==") return None # Condition @@ -230,10 +231,13 @@ if sAction[0:1] == "=": dFUNCTIONS["g_p_"+sActionId] = sAction[1:] sAction = "=g_p_"+sActionId elif sAction.startswith('"') and sAction.endswith('"'): sAction = sAction[1:-1] + return [sOption, sCondition, cAction, sAction, iStartAction, iEndAction] + elif cAction == "/": + ## tags return [sOption, sCondition, cAction, sAction, iStartAction, iEndAction] elif cAction == "=": ## disambiguator if sAction[0:1] == "=": sAction = sAction[1:] @@ -335,11 +339,11 @@ print(" creating callables...") sPyCallables = "# generated code, do not edit\n" #sJSCallables = "// generated code, do not edit\nconst oEvalFunc = {\n" for sFuncName, sReturn in dFUNCTIONS.items(): if sFuncName.startswith("g_c_"): # condition - sParams = "lToken, nTokenOffset, nLastToken, sCountry, bCondMemo" + sParams = "lToken, nTokenOffset, nLastToken, sCountry, bCondMemo, dTags" elif sFuncName.startswith("g_m_"): # message sParams = "lToken, nTokenOffset" elif sFuncName.startswith("g_s_"): # suggestion sParams = "lToken, nTokenOffset" elif sFuncName.startswith("g_p_"): # preprocessor 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 @@ -588,11 +588,13 @@ self.sSentence = sSentence self.sSentence0 = sSentence0 self.nOffsetWithinParagraph = nOffset self.lToken = list(_oTokenizer.genTokens(sSentence, True)) self.dTokenPos = { dToken["nStart"]: dToken for dToken in self.lToken } + self.dTags = {} self.createError = self._createWriterError if _bWriterError else self._createDictError + def update (self, sSentence): self.sSentence = sSentence self.lToken = list(_oTokenizer.genTokens(sSentence, True)) @@ -704,13 +706,17 @@ try: if bDebug: print("ACTION:", sRuleId) print(dRule[sRuleId]) sOption, sFuncCond, cActionType, sWhat, *eAct = dRule[sRuleId] - # action in lActions: [ condition, action type, replacement/suggestion/action[, iTokenStart, iTokenEnd[, nPriority, message, URL]] ] + # Suggestion [ option, condition, "-", replacement/suggestion/action, iTokenStart, iTokenEnd, nPriority, message, URL ] + # TextProcessor [ option, condition, "~", replacement/suggestion/action, iTokenStart, iTokenEnd ] + # Disambiguator [ option, condition, "=", replacement/suggestion/action ] + # Tag [ option, condition, "/", replacement/suggestion/action, iTokenStart, iTokenEnd ] + # Test [ option, condition, ">", "" ] if not sOption or dOptions.get(sOption, False): - bCondMemo = not sFuncCond or globals()[sFuncCond](self.lToken, nTokenOffset, nLastToken, sCountry, bCondMemo) + bCondMemo = not sFuncCond or globals()[sFuncCond](self.lToken, nTokenOffset, nLastToken, sCountry, bCondMemo, self.dTags) if bCondMemo: if cActionType == "-": # grammar error nTokenErrorStart = nTokenOffset + eAct[0] nTokenErrorEnd = (nTokenOffset + eAct[1]) if eAct[1] else nLastToken @@ -736,10 +742,19 @@ elif cActionType == ">": # we do nothing, this test is just a condition to apply all following actions if bDebug: print(">", sRuleId) pass + elif cActionType == "/": + # tags + nTokenTag = nTokenOffset + eAct[0] + if sWhat not in self.dTags: + self.dTags[sWhat] = (nTokenTag, nTokenTag) + elif nTokenTag > self.dTags[sWhat][1]: + self.dTags[sWhat] = (self.dTags[sWhat][0], nTokenTag) + if bDebug: + print("/", sRuleId) else: print("# error: unknown action at " + sLineId) elif cActionType == ">": if bDebug: print(">!", sRuleId) @@ -934,10 +949,25 @@ return False # search sPattern zPattern = re.compile(sPattern) return any(zPattern.search(sMorph) for sMorph in lMorph) + +def g_tag_before (dToken, sTag, dTags): + if sTag not in dTags: + return False + if dToken["nStart"] > dTags[sTag][0]: + return True + return False + + +def g_tag_after (dToken, sTag, dTags): + if sTag not in dTags: + return False + if dToken["nStart"] < dTags[sTag][1]: + return True + return False #### Disambiguator def g_select (dToken, sPattern, lDefault=None): Index: gc_lang/fr/rules.grx ================================================================== --- gc_lang/fr/rules.grx +++ gc_lang/fr/rules.grx @@ -4673,10 +4673,44 @@ @@@@GRAPH: graphe1 @@@@ @@@@ @@@@ @@@@ + + +__tag_sujets__ + [je|j’] + moi qui + moi [seul|seule] + <<- />> 1s + + tu + toi ?,¿ qui + toi [seul|seule] + <<- />> 2s + + nous + nous ?,¿ qui + nous-même + nous-mêmes + nous [seul|seuls|seules] + et moi + ni moi + moi et + <<- />> 1p + + vous + vous ?,¿ qui + vous-même + vous-mêmes + vous [seul|seule|seuls|seules] + et toi + ni toi + toi et + <<- />> 2p + + !! !! !!!! Locutions invariables !!