Index: compile_rules_graph.py
==================================================================
--- compile_rules_graph.py
+++ compile_rules_graph.py
@@ -102,11 +102,11 @@
     # print(iLine, "//", sRuleName, "//", sTokenLine, "//", sActions, "//", nPriority)
     for lToken in genTokenLines(sTokenLine, dDef):
         # Calculate positions
         dPos = {}   # key: iGroup, value: iToken
         iGroup = 0
-        #if iLine == 2211: # debug
+        #if iLine == 3971: # debug
         #    print(lToken)
         for i, sToken in enumerate(lToken):
             if sToken.startswith("(") and sToken.endswith(")"):
                 lToken[i] = sToken[1:-1]
                 iGroup += 1
@@ -175,31 +175,42 @@
         sCondition = ""
     # Action
     cAction = m.group("action")
     sAction = sAction[m.end():].strip()
     sAction = changeReferenceToken(sAction, dPos)
+    # target
+    cStartLimit = "<"
+    cEndLimit = ">"
     if not m.group("start"):
         iStartAction = 1
         iEndAction = 0
     else:
         if cAction != "-" and (m.group("start").endswith(".") or m.group("end").startswith(":.")):
             print(" # Error. Wrong selection on tokens.", sActionId)
             return None
-        iStartAction = int(m.group("start"))  if not m.group("start").endswith(".")  else int("-"+m.group("start")[:-1])
+        if m.group("start").endswith("."):
+            cStartLimit = ">"
+        iStartAction = int(m.group("start").rstrip("."))
         if not m.group("end"):
             iEndAction = iStartAction
         else:
-            iEndAction = int(m.group("end")[1:])  if not m.group("end").startswith(":.")  else int("-" + m.group("end")[2:])
+            if m.group("end").startswith(":."):
+                cEndLimit = "<"
+            iEndAction = int(m.group("end").lstrip(":."))
     if dPos and m.group("start"):
         try:
-            iStartAction = dPos[iStartAction]
+            iStartAction = dPos.get(iStartAction, iStartAction)
             if iEndAction:
-                iEndAction = dPos[iEndAction]
+                iEndAction = dPos.get(iEndAction, iEndAction)
         except:
             print("# Error. Wrong groups in: " + sActionId)
             print("  iStartAction:", iStartAction, "iEndAction:", iEndAction)
             print(" ", dPos)
+    if iStartAction < 0:
+        iStartAction += 1
+    if iEndAction < 0:
+        iEndAction += 1
 
     if cAction == "-":
         ## error
         iMsg = sAction.find(" # ")
         if iMsg == -1:
@@ -243,11 +254,11 @@
             sAction = "=_g_s_"+sActionId
         elif sAction.startswith('"') and sAction.endswith('"'):
             sAction = sAction[1:-1]
         if not sMsg:
             print("# Error in action at line " + sActionId + ":  The message is empty.")
-        return [sOption, sCondition, cAction, sAction, iStartAction, iEndAction, nPriority, sMsg, sURL]
+        return [sOption, sCondition, cAction, sAction, iStartAction, iEndAction, cStartLimit, cEndLimit, nPriority, sMsg, sURL]
     elif cAction == "~":
         ## text processor
         if sAction[0:1] == "=":
             sAction = prepareFunction(sAction)
             dFUNCTIONS["_g_p_"+sActionId] = sAction[1:]

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
@@ -772,28 +772,29 @@
             for sRuleId in dGraph[nextNodeKey]:
                 try:
                     if bDebug:
                         print("  TRY:", sRuleId)
                     sOption, sFuncCond, cActionType, sWhat, *eAct = dRule[sRuleId]
-                    # Suggestion    [ option, condition, "-", replacement/suggestion/action, iTokenStart, iTokenEnd, nPriority, message, URL ]
+                    # Suggestion    [ option, condition, "-", replacement/suggestion/action, iTokenStart, iTokenEnd, cStartLimit, cEndLimit, nPriority, sMessage, sURL ]
                     # TextProcessor [ option, condition, "~", replacement/suggestion/action, iTokenStart, iTokenEnd ]
                     # Disambiguator [ option, condition, "=", replacement/suggestion/action ]
                     # Sentence 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, self.dTags, self.sSentence, self.sSentence0)
                         if bCondMemo:
                             if cActionType == "-":
                                 # grammar error
-                                nTokenErrorStart = nTokenOffset + abs(eAct[0])
+                                iTokenStart, iTokenEnd, cStartLimit, cEndLimit, nPriority, sMessage, sURL = eAct
+                                nTokenErrorStart = nTokenOffset + iTokenStart  if iTokenStart > 0  else nLastToken + iTokenStart
                                 if "bImmune" not in self.lToken[nTokenErrorStart]:
-                                    nTokenErrorEnd = (nTokenOffset + abs(eAct[1]))  if eAct[1]  else nLastToken
-                                    nErrorStart = self.nOffsetWithinParagraph + (self.lToken[nTokenErrorStart]["nStart"] if eAct[0] >= 0  else self.lToken[nTokenErrorStart]["nStart"])
-                                    nErrorEnd = self.nOffsetWithinParagraph + (self.lToken[nTokenErrorEnd]["nEnd"] if eAct[1] >= 0  else self.lToken[nTokenErrorEnd]["nStart"])
-                                    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]
+                                    nTokenErrorEnd = nTokenOffset + iTokenEnd  if iTokenEnd > 0  else nLastToken + iTokenEnd
+                                    nErrorStart = self.nOffsetWithinParagraph + (self.lToken[nTokenErrorStart]["nStart"] if cStartLimit == "<"  else self.lToken[nTokenErrorStart]["nEnd"])
+                                    nErrorEnd = self.nOffsetWithinParagraph + (self.lToken[nTokenErrorEnd]["nEnd"] if cEndLimit == ">"  else self.lToken[nTokenErrorEnd]["nStart"])
+                                    if nErrorStart not in self.dError or nPriority > dPriority.get(nErrorStart, -1):
+                                        self.dError[nErrorStart] = self._createError(sWhat, nTokenOffset, nTokenErrorStart, nErrorStart, nErrorEnd, sLineId, sRuleId, True, sMessage, sURL, bShowRuleId, "notype", bContext)
+                                        dPriority[nErrorStart] = nPriority
                                         if bDebug:
                                             print("  NEW_ERROR:", self.dError[nErrorStart], "\n  ", dRule[sRuleId])
                             elif cActionType == "~":
                                 # text processor
                                 if bDebug: