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
@@ -113,19 +113,19 @@
 
 
 def parse (sText, sCountry="${country_default}", bDebug=False, dOptions=None, bContext=False):
     "analyses the paragraph sText and returns list of errors"
     #sText = unicodedata.normalize("NFC", sText)
-    aErrors = None
+    dErrors = {}
     sRealText = sText
     dPriority = {}  # Key = position; value = priority
     dOpt = _dOptions  if not dOptions  else dOptions
     bShowRuleId = option('idrule')
 
     # parse paragraph
     try:
-        sNew, aErrors = _proofread(None, sText, sRealText, 0, True, dPriority, sCountry, dOpt, bShowRuleId, bDebug, bContext)
+        sNew, dErrors = _proofread(None, sText, sRealText, 0, True, dErrors, dPriority, sCountry, dOpt, bShowRuleId, bDebug, bContext)
         if sNew:
             sText = sNew
     except:
         raise
 
@@ -142,33 +142,32 @@
     # parse sentences
     for iStart, iEnd in _getSentenceBoundaries(sText):
         if 4 < (iEnd - iStart) < 2000:
             try:
                 oSentence = TokenSentence(sText[iStart:iEnd], sRealText[iStart:iEnd], iStart)
-                _, errs = _proofread(oSentence, sText[iStart:iEnd], sRealText[iStart:iEnd], iStart, False, dPriority, sCountry, dOpt, bShowRuleId, bDebug, bContext)
-                aErrors.update(errs)
+                _, dErrors = _proofread(oSentence, sText[iStart:iEnd], sRealText[iStart:iEnd], iStart, False, dErrors, dPriority, sCountry, dOpt, bShowRuleId, bDebug, bContext)
             except:
                 raise
-    return aErrors.values() # this is a view (iterable)
+    return dErrors.values() # this is a view (iterable)
 
 
-def _proofread (oSentence, s, sx, nOffset, bParagraph, dPriority, sCountry, dOptions, bShowRuleId, bDebug, bContext):
-    dErrs = {}
+def _proofread (oSentence, s, sx, nOffset, bParagraph, dErrors, dPriority, sCountry, dOptions, bShowRuleId, bDebug, bContext):
     bParagraphChange = False
     bSentenceChange = False
     dTokenPos = oSentence.dTokenPos if oSentence else {}
     for sOption, lRuleGroup in _getRules(bParagraph):
         if sOption == "@@@@":
             # graph rules
+            oSentence.dError = dErrors
             if not bParagraph and bSentenceChange:
                 oSentence.update(s, bDebug)
                 bSentenceChange = False
             for sGraphName, sLineId in lRuleGroup:
                 if bDebug:
                     print("\n>>>> GRAPH:", sGraphName, sLineId)
                 bParagraphChange, s = oSentence.parse(dAllGraph[sGraphName], dPriority, sCountry, dOptions, bShowRuleId, bDebug, bContext)
-                dErrs.update(oSentence.dError)
+                dErrors.update(oSentence.dError)
                 dTokenPos = oSentence.dTokenPos
         elif not sOption or dOptions.get(sOption, False):
             # regex rules
             for zRegex, bUppercase, sLineId, sRuleId, nPriority, lActions in lRuleGroup:
                 if sRuleId not in _aIgnoredRules:
@@ -182,12 +181,12 @@
                                     if bDebug:
                                         print("RULE:", sLineId)
                                     if cActionType == "-":
                                         # grammar error
                                         nErrorStart = nOffset + m.start(eAct[0])
-                                        if nErrorStart not in dErrs or nPriority > dPriority.get(nErrorStart, -1):
-                                            dErrs[nErrorStart] = _createError(s, sx, sWhat, nOffset, m, eAct[0], sLineId, sRuleId, bUppercase, eAct[1], eAct[2], bShowRuleId, sOption, bContext)
+                                        if nErrorStart not in dErrors or nPriority > dPriority.get(nErrorStart, -1):
+                                            dErrors[nErrorStart] = _createError(s, sx, sWhat, nOffset, m, eAct[0], sLineId, sRuleId, bUppercase, eAct[1], eAct[2], bShowRuleId, sOption, bContext)
                                             dPriority[nErrorStart] = nPriority
                                     elif cActionType == "~":
                                         # text processor
                                         s = _rewrite(s, sWhat, eAct[0], m, bUppercase)
                                         bParagraphChange = True
@@ -208,12 +207,12 @@
                                 elif cActionType == ">":
                                     break
                             except Exception as e:
                                 raise Exception(str(e), "# " + sLineId + " # " + sRuleId)
     if bParagraphChange:
-        return (s, dErrs)
-    return (False, dErrs)
+        return (s, dErrors)
+    return (False, dErrors)
 
 
 def _createError (s, sx, sRepl, nOffset, m, iGroup, sLineId, sRuleId, bUppercase, sMsg, sURL, bShowRuleId, sOption, bContext):
     nStart = nOffset + m.start(iGroup)
     nEnd = nOffset + m.end(iGroup)
@@ -701,12 +700,10 @@
                         print("  MATCH: *" + sMeta)
                     yield dGraph[dNode["<meta>"][sMeta]]
 
     def parse (self, dGraph, dPriority, sCountry="${country_default}", dOptions=None, bShowRuleId=False, bDebug=False, bContext=False):
         "parse tokens from the text and execute actions encountered"
-        self.dError = {}
-        dPriority = {}  # Key = position; value = priority
         dOpt = _dOptions  if not dOptions  else dOptions
         lPointer = []
         bTagAndRewrite = False
         for dToken in self.lToken:
             if bDebug:
@@ -723,12 +720,11 @@
             # check if there is rules to check for each pointer
             for dPointer in lPointer:
                 #if bDebug:
                 #    print("+", dPointer)
                 if "<rules>" in dPointer["dNode"]:
-                    bChange, dErr = self._executeActions(dGraph, dPointer["dNode"]["<rules>"], dPointer["iToken"]-1, dToken["i"], dPriority, dOpt, sCountry, bShowRuleId, bDebug, bContext)
-                    self.dError.update(dErr)
+                    bChange = self._executeActions(dGraph, dPointer["dNode"]["<rules>"], dPointer["iToken"]-1, dToken["i"], dPriority, dOpt, sCountry, bShowRuleId, bDebug, bContext)
                     if bChange:
                         bTagAndRewrite = True
         if bTagAndRewrite:
             self.rewrite(bDebug)
         if bDebug:
@@ -735,11 +731,10 @@
             print(self)
         return (bTagAndRewrite, self.sSentence)
 
     def _executeActions (self, dGraph, dNode, nTokenOffset, nLastToken, dPriority, dOptions, sCountry, bShowRuleId, bDebug, bContext):
         "execute actions found in the DARG"
-        dError = {}
         bChange = False
         for sLineId, nextNodeKey in dNode.items():
             bCondMemo = None
             for sRuleId in dGraph[nextNodeKey]:
                 try:
@@ -759,15 +754,15 @@
                                 nTokenErrorStart = nTokenOffset + eAct[0]
                                 if "bImmune" not in self.lToken[nTokenErrorStart]:
                                     nTokenErrorEnd = (nTokenOffset + eAct[1])  if eAct[1]  else nLastToken
                                     nErrorStart = self.nOffsetWithinParagraph + self.lToken[nTokenErrorStart]["nStart"]
                                     nErrorEnd = self.nOffsetWithinParagraph + self.lToken[nTokenErrorEnd]["nEnd"]
-                                    if nErrorStart not in dError or eAct[2] > dPriority.get(nErrorStart, -1):
-                                        dError[nErrorStart] = self._createError(sWhat, nTokenOffset, nTokenErrorStart, nErrorStart, nErrorEnd, sLineId, sRuleId, True, eAct[3], eAct[4], bShowRuleId, "notype", bContext)
+                                    if nErrorStart not in self.dError or eAct[2] > dPriority.get(nErrorStart, -1):
+                                        self.dError[nErrorStart] = self._createError(sWhat, nTokenOffset, nTokenErrorStart, nErrorStart, nErrorEnd, sLineId, sRuleId, True, eAct[3], eAct[4], bShowRuleId, "notype", bContext)
                                         dPriority[nErrorStart] = eAct[2]
                                         if bDebug:
-                                            print("  NEW_ERROR:", dError[nErrorStart], "\n  ", dRule[sRuleId])
+                                            print("  NEW_ERROR:", self.dError[nErrorStart], "\n  ", dRule[sRuleId])
                             elif cActionType == "~":
                                 # text processor
                                 if bDebug:
                                     print("  TAG_PREPARE:\n  ", dRule[sRuleId])
                                 nEndToken = (nTokenOffset + eAct[1])  if eAct[1]  else nLastToken
@@ -798,11 +793,11 @@
                             if bDebug:
                                 print("  COND_BREAK")
                             break
                 except Exception as e:
                     raise Exception(str(e), sLineId, sRuleId, self.sSentence)
-        return bChange, dError
+        return bChange
 
     def _createError (self, sSugg, nTokenOffset, iFirstToken, nStart, nEnd, sLineId, sRuleId, bUppercase, sMsg, sURL, bShowRuleId, sOption, bContext):
         # suggestions
         if sSugg[0:1] == "=":
             sSugg = globals()[sSugg[1:]](self.lToken, nTokenOffset)