docs: def _expandOlemaVerbChains( clauseTokens, clauseID, foundChains ):
      '''
           Meetod, mis proovib laiendada 'olema'-l6pulisi (predikaadi) verbiahelaid, lisades 
          võimalusel nende otsa teisi verbe, nt 
              "on olnud" + "tehtud", "ei olnud" + "tehtud", "ei oleks" + "arvatud";
          Vastavalt leitud laiendustele t2iendab andmeid sisendlistis foundChains;
      '''
      verbOle       = WordTemplate({ROOT:'^ole$',POSTAG:'V'})
      verbOleJarel1 = WordTemplate({POSTAG:'V',FORM:'(nud)$'})
      verbOleJarel2 = WordTemplate({POSTAG:'V',FORM:'^(mas|tud)$'})
      verbMata      = WordTemplate({POSTAG:'V',FORM:'^(mata)$'})
      verbMaDa      = WordTemplate({POSTAG:'V',FORM:'^(da|ma)$'})
      # J22dvustame s6nad, mis kuuluvad juba mingi tuvastatud verbifraasi koosseisu
      annotatedWords = []
      for verbObj in foundChains:
          if verbObj[CLAUSE_IDX] != clauseID:
              continue
          if (len(verbObj[PATTERN])==1 and re.match('^(ei|ära|ega)$', verbObj[PATTERN][0])):
              # V2lja j22vad yksikuna esinevad ei/ära/ega, kuna need tõenäoliselt ei sega
              continue
          annotatedWords.extend( verbObj[PHRASE] )
      for verbObj in foundChains:
          if verbObj[CLAUSE_IDX] != clauseID:
              continue
          if verbObj[PATTERN][-1] == 'ole' and verbObj[OTHER_VERBS]:
              #
              #  Kui on tegemist 'olema' l6pulise verbiahelaga, mille kontekstis on teisi verbe,
              #  st saab veel laiendada ...
              #
              eiOlePattern = (len(verbObj[PATTERN])==2 and verbObj[PATTERN][0] == 'ei')
              lastVerbWID = verbObj[PHRASE][-1]
              lastTokIndex = [i for i in range(len(clauseTokens)) if clauseTokens[i][WORD_ID] == lastVerbWID]
              lastTokIndex = lastTokIndex[0]
              expansion   = None
              appliedRule = 0
              if not _isClauseFinal( lastVerbWID, clauseTokens ):
                  maDaVerbsBetween = 0
                  oleInfFollowing  = 0
                  for i in range(lastTokIndex + 1, len(clauseTokens)):
                      token = clauseTokens[i]
                      tokenWID = token[WORD_ID]
                      if tokenWID in annotatedWords:
                          break
                      if verbMaDa.matches(token):
                          maDaVerbsBetween += 1
                      if (verbOleJarel1.matches(token)) or verbOleJarel2.matches(token):
                          #
                          #    Heuristik:
                          #      Kui olema j2rel, osalause l6pus on nud/tud/mas ja nende vahel pole yhtegi 
                          #     punktuatsioonim2rki, sides6na, adverbe aga/kuid/vaid, juba m2rgendatud verbiahelat
                          #     ega teist nud/tud/mas s6na, loeme selle s6na olema-fraasi laienduseks:
                          #
                          #           Pere ei_0 ole_0 Eestis toimuvast vaimustatud_0 .
                          #           " Viimasel ajal on_0 see asi jälle susisema hakanud_0 " ,
                          #           Esiteks ei_0 olnud_0 vajalikul ajal tavaliselt bussi tulemas_0
                          #
                          if _isClauseFinal(tokenWID, clauseTokens ) and \
                             not _isSeparatedByPossibleClauseBreakers( clauseTokens, verbObj[PHRASE][-1], \
                             tokenWID, True, True, True):
                             expansion = token
                             #   Veakoht: kui -mas j2rel on da/ma, pole kindel, et tegu otsese rektsiooniseosega:
                             #      Islamlannale on_0 harjumatu näha meest midagi maast korjamas_0 ,
                          elif verbOleJarel1.matches(token) and eiOlePattern and i-lastTokIndex<=2:
                             #
                             #   Heuristik: "ei"+"ole"-ahela j2rel "nud" ning nende vahel pole rohkem kui
                             #   yks muu s6na:
                             #            Tagantjärele mõeldes ei_0 oleks_0 ma pidanud_0 seda tegema .
                             #            Mina ei_0 ole_0 suutnud_0 siiani maad osta .
                             #
                             expansion = token
                          oleInfFollowing += 1
                          break
                      elif verbMata.matches(token) and maDaVerbsBetween == 0:
                          #
                          #    Heuristik:
                          #      Kui olema j2rel, osalause l6pus on mata ja nende vahel pole yhtegi 
                          #     punktuatsioonim2rki, sides6na, adverbe aga/kuid/vaid, juba m2rgendatud 
                          #     verbiahelat, m6nd nud/tud/mas/ma/da verbi, loeme selle s6na olema-fraasi 
                          #     laienduseks:
                          #
                          #           Maanaine on_0 veel leidmata_0 .
                          #           linnaarhitekti koht oli_0 aasta aega täitmata_0
                          #
                          if _isClauseFinal(tokenWID, clauseTokens ) and \
                             not _isSeparatedByPossibleClauseBreakers( clauseTokens, verbObj[PHRASE][-1], \
                             tokenWID, True, True, True):
                              expansion = token
                              break
                              #   Veakoht: kui vahel on 'ilma', siis see heuristik eksib t6en2oliselt:
                              #          on_0 lihtsalt tõlgendatavad ka ilma situatsioonis osalemata_0
                          oleInfFollowing += 1
                  #
                  #    Heuristik:
                  #     Kui osalauses ei j2rgne 'olema'-verbiga yhilduvaid verbe, kyll aga eelneb vahetult 
                  #    m6ni selline ning seda pole veel m2rgendatud, loeme selle potentsiaalselt olema-verbiga
                  #    yhilduvaks, nt:
                  #
                  #                Unustatud_0 ei_0 ole_0 ka mänge .
                  #                Tõhustatud_0 on_0 ka turvameetmeid .
                  #                milleks looja ta maailma loonud_0 on_0 , nimelt soo jätkamiseks .
                  #
                  if oleInfFollowing == 0 and not expansion:
                      minWID = min( verbObj[PHRASE] )
                      lastTokIndex = [i for i in range(len(clauseTokens)) if clauseTokens[i][WORD_ID] == minWID]
                      lastTokIndex = lastTokIndex[0]
                      token = clauseTokens[lastTokIndex-1]
                      if lastTokIndex-1 > -1 and token[WORD_ID] not in annotatedWords:
                          if (verbOleJarel1.matches(token) or verbOleJarel2.matches(token)):
                              expansion = token
                              appliedRule = 1
                      
                  #
                  #    Eituse (aga ka vastavates jaatuse) fraasides j22vad siin eraldamata 
                  #       ei + ole + Adv/Nom + Verb_da    
                  #    mustrid, nt:
                  #       Ei_0 ole_0 mõtet teha sellist söögikohta .
                  #       Ei_0 ole_0 võimalik väiksema vastu vahetada .
                  #       Ei_0 ole_0 pankuril vaja teada .
                  #    Nendega proovime tegeleda hiljem.
                  #
              else:
                  #
                  #   Leiame ahela alguspunkti (minimaalse ID-ga verbi)
                  #
                  minWID = min( verbObj[PHRASE] )
                  lastTokIndex = [i for i in range(len(clauseTokens)) if clauseTokens[i][WORD_ID] == minWID]
                  if lastTokIndex:
                      lastTokIndex = lastTokIndex[0]
                      if lastTokIndex-1 > -1 and clauseTokens[lastTokIndex-1][WORD_ID] not in annotatedWords:
                          #
                          #    Heuristik:
                          #   Kui "olema"-l6puline ahel on osalause l6pus, ning vahetult eelneb nud/tud/mas,
                          #  siis loeme selle olema juurde kuuluvaks, nt:
                          #          mis juba olnud ja veel tulemas_0 on_0 ,
                          #          Eesti selle alamprojektiga seotud_0 ei_0 ole_0 .
                          #          trombootilisi episoode kordunud_0 ei_0 ole_0 .
                          #  (Yldiselt paistab suhteliselt v2heproduktiivne reegel olevat)
                          # 
                          token = clauseTokens[lastTokIndex-1]
                          if (verbOleJarel1.matches(token) or verbOleJarel2.matches(token)):
                              expansion = token
              if expansion:
                  tokenWID = expansion[WORD_ID]
                  verbObj[PHRASE].append( tokenWID )
                  verbObj[ANALYSIS_IDS].append( _getMatchingAnalysisIDs( expansion, [verbOleJarel1, verbOleJarel2, verbMata] ) )
                  if verbOle.matches(expansion):
                      verbObj[PATTERN].append('ole')
                  else:
                      verbObj[PATTERN].append('verb')
                  annotatedWords.append( tokenWID )