Index: compile_rules_graph.py ================================================================== --- compile_rules_graph.py +++ compile_rules_graph.py @@ -12,18 +12,10 @@ def prepareFunction (s): s = s.replace("__also__", "bCondMemo") s = s.replace("__else__", "not bCondMemo") - s = re.sub(r"isStart *\(\)", 'before(["", ","])', s) - s = re.sub(r"isRealStart *\(\)", 'before([""])', s) - s = re.sub(r"isStart0 *\(\)", 'before0(["", ","])', s) - s = re.sub(r"isRealStart0 *\(\)", 'before0([""])', s) - s = re.sub(r"isEnd *\(\)", 'after(["", ","])', s) - s = re.sub(r"isRealEnd *\(\)", 'after([""])', s) - s = re.sub(r"isEnd0 *\(\)", 'after0(["", ","])', s) - s = re.sub(r"isRealEnd0 *\(\)", 'after0([""])', s) s = re.sub(r"(select|exclude|define)[(][\\](\d+)", 'g_\\1(lToken[\\2+nTokenOffset]', s) s = re.sub(r"(morph|displayInfo)[(]\\(\d+)", 'g_\\1(lToken[\\2+nTokenOffset]', s) s = re.sub(r"token\(\s*(\d)", 'nextToken(\\1', s) # token(n) s = re.sub(r"token\(\s*-(\d)", 'prevToken(\\1', s) # token(-n) s = re.sub(r"before\(\s*", 'look(s[:m.start()], ', s) # before(s) @@ -30,13 +22,10 @@ s = re.sub(r"after\(\s*", 'look(s[m.end():], ', s) # after(s) s = re.sub(r"textarea\(\s*", 'look(s, ', s) # textarea(s) s = re.sub(r"before_chk1\(\s*", 'look_chk1(dDA, s[:m.start()], 0, ', s) # before_chk1(s) s = re.sub(r"after_chk1\(\s*", 'look_chk1(dDA, s[m.end():], m.end(), ', s) # after_chk1(s) s = re.sub(r"textarea_chk1\(\s*", 'look_chk1(dDA, s, 0, ', s) # textarea_chk1(s) - #s = re.sub(r"isEndOfNG\(\s*\)", 'isEndOfNG(dDA, s[m.end():], m.end())', s) # isEndOfNG(s) - #s = re.sub(r"isNextNotCOD\(\s*\)", 'isNextNotCOD(dDA, s[m.end():], m.end())', s) # isNextNotCOD(s) - #s = re.sub(r"isNextVerb\(\s*\)", 'isNextVerb(dDA, s[m.end():], m.end())', s) # isNextVerb(s) s = re.sub(r"\bspell *[(]", '_oSpellChecker.isValid(', s) s = re.sub(r"[\\](\d+)", 'lToken[\\1]', s) return s @@ -236,40 +225,58 @@ exit() # removing comments, zeroing empty lines, creating definitions, storing tests, merging rule lines print(" parsing rules...") global dDEF - lLine = [] - lRuleLine = [] lTest = [] - lOpt = [] lTokenLine = [] sActions = "" nPriority = 4 + dAllGraph = {} + sGraphName = "" for i, sLine in enumerate(lRules, 1): sLine = sLine.rstrip() if "\t" in sLine: + # tabulation not allowed print("Error. Tabulation at line: ", i) - break + exit() if sLine.startswith('#END'): + # arbitrary end printBookmark(0, "BREAK BY #END", i) break elif sLine.startswith("#"): + # comments pass + elif sLine.startswith("GRAPH_NAME: "): + # Graph name + m = re.match("GRAPH_NAME: +([a-zA-Z_][a-zA-Z_0-9]*)+", sLine.strip()) + if m: + sGraphName = m.group(1) + if sGraphName in dAllGraph: + print("Error. Group name " + sGraphName + " already exists.") + exit() + dAllGraph[sGraphName] = [] + else: + print("Error. Graph name not found in", sLine.strip()) + exit() elif sLine.startswith("DEF:"): + # definition m = re.match("DEF: +([a-zA-Z_][a-zA-Z_0-9]*) +(.+)$", sLine.strip()) if m: dDEF["{"+m.group(1)+"}"] = m.group(2) else: print("Error in definition: ", end="") print(sLine.strip()) elif sLine.startswith("TEST:"): + # test lTest.append("g{:<7}".format(i) + " " + sLine[5:].strip()) elif sLine.startswith("TODO:"): + # todo pass elif sLine.startswith("!!"): + # bookmarks m = re.search("^!!+", sLine) nExMk = len(m.group(0)) if sLine[nExMk:].strip(): printBookmark(nExMk-2, sLine[nExMk:].strip(), i) elif sLine.startswith("__") and sLine.endswith("__"): @@ -281,13 +288,21 @@ else: print("Error at rule group: ", sLine, " -- line:", i) break elif re.match("[  ]*$", sLine): # empty line to end merging - for i, sTokenLine in lTokenLine: - lRuleLine.append((i, sRuleName, sTokenLine, sActions, nPriority)) - lTokenLine = [] + if not lTokenLine: + continue + if not sActions: + print("Error. No action found at line:", i) + exit() + if not sGraphName: + print("Error. All rules must belong to a named graph. Line: ", i) + exit() + for j, sTokenLine in lTokenLine: + dAllGraph[sGraphName].append((j, sRuleName, sTokenLine, sActions, nPriority)) + lTokenLine.clear() sActions = "" sRuleName = "" nPriority = 4 elif sLine.startswith((" ")): # actions @@ -300,21 +315,21 @@ sGCTests = "\n".join(lTest) sGCTestsJS = '{ "aData2": ' + json.dumps(lTest, ensure_ascii=False) + " }\n" # processing rules print(" preparing rules...") - lPreparedRule = [] - for i, sRuleGroup, sTokenLine, sActions, nPriority in lRuleLine: - for lRule in createRule(i, sRuleGroup, sTokenLine, sActions, nPriority): - lPreparedRule.append(lRule) - - # Graph creation - for e in lPreparedRule: - print(e) - - oDARG = darg.DARG(lPreparedRule, sLang) - oRuleGraph = oDARG.createGraph() + for sGraphName, lRuleLine in dAllGraph.items(): + lPreparedRule = [] + for i, sRuleGroup, sTokenLine, sActions, nPriority in lRuleLine: + for lRule in createRule(i, sRuleGroup, sTokenLine, sActions, nPriority): + lPreparedRule.append(lRule) + # Show rules + for e in lPreparedRule: + print(e) + # Graph creation + oDARG = darg.DARG(lPreparedRule, sLang) + dAllGraph[sGraphName] = oDARG.createGraph() # creating file with all functions callable by rules print(" creating callables...") sPyCallables = "# generated code, do not edit\n" #sJSCallables = "// generated code, do not edit\nconst oEvalFunc = {\n" @@ -344,12 +359,12 @@ # Result d = { "graph_callables": sPyCallables, "graph_gctests": sGCTests, - "rules_graph": oRuleGraph, + "rules_graphs": dAllGraph, "rules_actions": dACTIONS } return d 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 @@ -11,11 +11,11 @@ from ..graphspell.spellchecker import SpellChecker from ..graphspell.echo import echo from . import gc_options from ..graphspell.tokenizer import Tokenizer -from .gc_rules_graph import dGraph, dRule +from .gc_rules_graph import dAllGraph, dRule try: # LibreOffice / OpenOffice from com.sun.star.linguistic2 import SingleProofreadingError from com.sun.star.text.TextMarkupType import PROOFREADING @@ -138,11 +138,11 @@ # regex parser _, errs = _proofread(sText[iStart:iEnd], sRealText[iStart:iEnd], iStart, False, dDA, dPriority, sCountry, dOpt, bShowRuleId, bDebug, bContext) aErrors.update(errs) # token parser oSentence = TokenSentence(sText[iStart:iEnd], sRealText[iStart:iEnd], iStart) - bChange, errs = oSentence.parse(dPriority, sCountry, dOpt, bShowRuleId, bDebug, bContext) + bChange, errs = oSentence.parse(dAllGraph["test_graph"], dPriority, sCountry, dOpt, bShowRuleId, bDebug, bContext) aErrors.update(errs) if bChange: oSentence.rewrite() if bDebug: print("~", oSentence.sSentence) @@ -577,11 +577,11 @@ self.sSentence0 = sSentence0 self.nOffset = nOffset self.lToken = list(_oTokenizer.genTokens(sSentence, True)) self.createError = self._createWriterError if _bWriterError else self._createDictError - def _getNextMatchingNodes (self, dToken, dNode): + def _getNextMatchingNodes (self, dToken, dGraph, dNode): "generator: return nodes where “values” match arcs" # token value if dToken["sValue"] in dNode: #print("value found: ", dToken["sValue"]) yield dGraph[dNode[dToken["sValue"]]] @@ -619,36 +619,36 @@ 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): + def parse (self, dGraph, 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 lPointer = [] bChange = False for dToken in self.lToken: # check arcs for each existing pointer lNextPointer = [] for dPointer in lPointer: - for dNode in self._getNextMatchingNodes(dToken, dPointer["dNode"]): + for dNode in self._getNextMatchingNodes(dToken, dGraph, dPointer["dNode"]): lNextPointer.append({"iToken": dPointer["iToken"], "dNode": dNode}) lPointer = lNextPointer # check arcs of first nodes - for dNode in self._getNextMatchingNodes(dToken, dGraph[0]): + for dNode in self._getNextMatchingNodes(dToken, dGraph, dGraph[0]): lPointer.append({"iToken": dToken["i"], "dNode": dNode}) # check if there is rules to check for each pointer for dPointer in lPointer: if "" in dPointer["dNode"]: - bHasChanged, errs = self._executeActions(dPointer["dNode"][""], dPointer["iToken"]-1, dPriority, dOpt, sCountry, bShowRuleId, bDebug, bContext) + bHasChanged, errs = self._executeActions(dGraph, dPointer["dNode"][""], dPointer["iToken"]-1, dPriority, dOpt, sCountry, bShowRuleId, bDebug, bContext) dErr.update(errs) if bHasChanged: bChange = True return (bChange, dErr) - def _executeActions (self, dNode, nTokenOffset, dPriority, dOpt, sCountry, bShowRuleId, bDebug, bContext): + def _executeActions (self, dGraph, dNode, nTokenOffset, dPriority, dOpt, sCountry, bShowRuleId, bDebug, bContext): "execute actions found in the DARG" dErrs = {} bChange = False for sLineId, nextNodeKey in dNode.items(): for sRuleId in dGraph[nextNodeKey]: Index: gc_core/py/lang_core/gc_rules_graph.py ================================================================== --- gc_core/py/lang_core/gc_rules_graph.py +++ gc_core/py/lang_core/gc_rules_graph.py @@ -1,5 +1,5 @@ # generated code, do not edit -dGraph = ${rules_graph} +dAllGraph = ${rules_graphs} dRule = ${rules_actions} Index: gc_lang/fr/rules_graph.grx ================================================================== --- gc_lang/fr/rules_graph.grx +++ gc_lang/fr/rules_graph.grx @@ -36,10 +36,12 @@ # Fin d’interprétation du fichier avec une ligne commençant par #END # ERREURS COURANTES # http://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Fautes_d%27orthographe/Courantes + +GRAPH_NAME: test_graph __da1__ ne >donner <<- =>> select(\2, ":V")