docs: def _expandVerbChainsBySubcat( clauseTokens, clauseID, foundChains, verbSubcat, \
                                                          skipQuestionable=False, \
                                                          breakOnPunctuation=True ):
      ''' 
          Meetod, mis proovib laiendada (mitte-'olema') verbidega l6ppevaid predikaadifraase, 
          lisades nende lõppu rektsiooniseoste järgi uusi infiniitverbe, 
          nt "kutsub" + "langetama"
             "püütakse" + "keelustada" "või" "takistada"
             "ei julgenud" + "arvata", 
             "ei hakka" + "tülitama";
  
          Sisend 'clauseTokens' on list, mis sisaldab yhe osalause k6iki s6nu (pyvabamorfi poolt
          tehtud s6na-analyyse); Sisend 'verbSubcat' sisaldab andmeid verb-infiniitverb 
          rektsiooniseoste kohta;
          Tulemusena t2iendatakse olemasolevat verbijadade listi (foundChains), pikendades seal
          olevaid verbiga lõppevaid fraase, millal võimalik;
      '''
      global _breakerJaNingEgaVoi, _breakerKomaLopus, _breakerPunktuats
      verb      = WordTemplate({POSTAG:'V'})
      verbInf1  = WordTemplate({POSTAG:'V', FORM:'^(da|ma|maks|mas|mast|mata)$'})
      verbOlema = WordTemplate({POSTAG:'V', ROOT:'^(ole)$'})
      sonaMitte = WordTemplate({ROOT:'^mitte$',POSTAG:'D'})
      # J22dvustame s6nad, mis kuuluvad juba mingi tuvastatud verbifraasi koosseisu
      annotatedWords = []
      for verbObj in foundChains:
          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] )
      # Leiame, millised verbid on veel vabad (st v6ivad potentsiaalselt liituda)
      freeVerbsWIDs = [t[WORD_ID] for t in clauseTokens if verbInf1.matches(t) and t[WORD_ID] not in annotatedWords]
      for verbObj in foundChains:
          # Leiame, kas fraas kuulub antud osalausesse ning on laiendatav
          if _isVerbExpansible(verbObj, clauseTokens, clauseID):
              # Leiame viimasele s6nale vastava token'i, selle lemma ja vormitunnuse
              lastToken = [token for token in clauseTokens if token[WORD_ID] == verbObj[PHRASE][-1]]
              lastIndex = [i for i in range(len(clauseTokens)) if clauseTokens[i][WORD_ID] == verbObj[PHRASE][-1]]
              lastToken = lastToken[0]
              lastIndex = lastIndex[0]
              mainVerb  = [(analysis[ROOT], analysis[FORM]) for analysis in verb.matchingAnalyses(lastToken)]
              mainVerbLemma = mainVerb[0][0]
              mainVerbForm  = mainVerb[0][1]
              positivePhrase = (verbObj[POLARITY] == 'POS')
              egaPhrase      = (verbObj[PATTERN][0] == 'ega')
              #  Teeme kindlaks, kas verbi lemma on ylesm2rgitud rektsiooniseoste leksikoni
              if mainVerbLemma in verbSubcat:
                  subcatForms = verbSubcat[ mainVerbLemma ]
                  for subcatForm in subcatForms:
                      foundSubcatChain = []
                      addingCompleted = False
                      #  Kui on tegu vaieldava rektsiooniseosega: j2tame vahele v6i, kui vaieldavad
                      #  on lubatud, eemaldame vaieldavuse m2rgi 
                      if re.match("^.+\?$", subcatForm):
                          if skipQuestionable:
                              continue
                          else:
                              subcatForm = subcatForm.replace('?', '')
                      #
                      #  1) Otsime sobivat verbi v6i verbifraasi s6na tagant, osalause teisest poolest
                      #
                      j = lastIndex + 1
                      while (j < len(clauseTokens)):
                          token = clauseTokens[j]
                          tokenWID = token[WORD_ID]
                          #  Katkestame kui:
                          #  *) satume juba m2rgendatud s6nale;
                          #  *) satume punktuatsioonile;
                          if tokenWID in annotatedWords:
                              break
                          if breakOnPunctuation and _breakerPunktuats.matches(token):
                              break
                          #  Lisame kui:
                          #  *) satume konjunktsioonile;
                          #  *) satume sobivas vormis verbile;
                          if _breakerJaNingEgaVoi.matches(token):
                              foundSubcatChain.append(('&', token))
                          if verb.matches(token):
                              tokenForms = [analysis[FORM] for analysis in verb.matchingAnalyses(token)]
                              if subcatForm in tokenForms:
                                  foundSubcatChain.append( (subcatForm, token) )
                          #  Katkestame kui:
                          #  *) satume komale (kuna koma v6ib kinnituda sobiva s6na l6ppu);
                          if _breakerKomaLopus.matches(token):
                              break
                          j += 1
                      #
                      #     Kui osalause teisest poolest midagi ei leidnud, vaatame 
                      #     osalause esimest poolt:
                      #
                      #  2) Otsime sobivat verbi v6i verbifraasi vahetult s6na algusest
                      #     (seda vaid siis, kui tegemist pole nö 'ega'-verbifraasiga - 
                      #      nondele midagi eelneda ei saagi);
                      #     ( NB! 'ega' fraaside puhul tuleks tegelikult ka tagasi vaadata,
                      #       aga ainult verbi ja 'ega' vahele, ja mitte mingil juhul 
                      #       'ega'-st ettepoole );
                      #
                      if not _suitableVerbExpansion( foundSubcatChain ) and not egaPhrase:
                          minWid = min( verbObj[PHRASE] )
                          j = lastIndex - 1
                          while (j > -1):
                              token = clauseTokens[j]
                              tokenWID = token[WORD_ID]
                              #  Katkestame kui:
                              #  *) satume juba m2rgendatud s6nale (mis pole sellest fraasist);
                              #  *) satume komale v6i muule punktuatsioonile;
                              #  *) satume s6nale, mis on k6ige esimesest fraasiliikmest tagapool kui 2 s6na;
                              if tokenWID in annotatedWords and tokenWID not in verbObj[PHRASE]:
                                  break
                              if _breakerKomaLopus.matches(token) or (breakOnPunctuation and _breakerPunktuats.matches(token)):
                                  break
                              if token[WORD_ID]+1 < minWid:
                                  break
                              #  Lisame kui:
                              #  *) satume konjunktsioonile;
                              #  *) satume sobivas vormis verbile;
                              if _breakerJaNingEgaVoi.matches(token):
                                  foundSubcatChain.append(('&', token))
                              if verb.matches(token):
                                  tokenForms = [analysis[FORM] for analysis in verb.matchingAnalyses(token)]
                                  if subcatForm in tokenForms:
                                      foundSubcatChain.append( (subcatForm, token) )
                              j -= 1
                      suitablePhrase = _suitableVerbExpansion( foundSubcatChain )
                      if suitablePhrase:
                          #
                          #   Kui sobiv fraasikandidaat leidus, teostamine liitmise
                          #
                          for token in suitablePhrase:
                              tokenWID = token[WORD_ID]
                              verbObj[PHRASE].append( tokenWID )
                              annotatedWords.append( tokenWID )
                              if _breakerJaNingEgaVoi.matches(token):
                                  verbObj[PATTERN].append('&')
                                  verbObj[ANALYSIS_IDS].append( _getMatchingAnalysisIDs( token, _breakerJaNingEgaVoi ) )
                              elif len(suitablePhrase) == 1 and verbOlema.matches(token):
                                  verbObj[PATTERN].append('ole')
                                  verbObj[ANALYSIS_IDS].append( _getMatchingAnalysisIDs( token, verbOlema ) )
                                  freeVerbsWIDs.remove( tokenWID )
                              else:
                                  verbObj[PATTERN].append('verb')
                                  analysisIDs = [i for i in range(len(token[ANALYSIS])) if subcatForm == token[ANALYSIS][i][FORM]]
                                  assert len(analysisIDs) > 0
                                  verbObj[ANALYSIS_IDS].append( analysisIDs )
                                  freeVerbsWIDs.remove( tokenWID )
                          if not freeVerbsWIDs:
                              verbObj[OTHER_VERBS] = False
                          addingCompleted = True
                      if addingCompleted:
                          break