def _find_phrases( self, sentence, syntax_layer, cutPhrases, cutMaxThreshold ):
        ''' Detects NP phrases by relying on local dependency relations:
        
            1) Identifies potential heads of NP phrases;
            2) Identifies consecutive words that can form an NP phrase:
               2.1) potential attribute + potential head;
               2.2) quantity word or phrase + nominal;
            3) Identifies non-consecutive words (word1 __ wordN) that
               can form a complete phrase (including the gap part);
            4) Applies post-corrections;
            
            Returns a list of tags, which contains a B-I-O style phrase 
            tag for each word in the sentence ('B'-begins phrase, 'I'-
            inside phrase, or ''-not in phrase);
        '''
        NPattribPos = [ 'Y', 'S', 'A', 'C', 'G', 'H', 'N', 'O', 'K', 'D', 'P' ]
        NPheadPos   = [ 'S', 'Y', 'H' ]
        NPlabels = [ '' for i in range(len(sentence)) ]
        #
        # 0 Faas: M2rgistame k6ik s6nad, mis v6iksid olla nimis6nafraasi peas6nad, nt:
        #        Kas [venelaste] [ambitsioon] on [siiras] ?
        #        [Raskused] algasid [aastal] 2009 , mil oli [majanduskriis] .
        #        [Põllumaad] on ka , aga [kartulikasvatamisega] on üksjagu [jamamist] .
        #
        for i in range(len(sentence)):
            pos1 = self._getPOS(sentence[i])
            if pos1 in NPheadPos:
                NPlabels[i] = 'B'
            # Lisaks märgistame ka peasõnadena ka üksikud pronoomenid, kuigi 
            # eeldame, et need on peasõnadena vaid üksikutes fraasides;
            elif pos1 == 'P':
                NPlabels[i] = 'B'
        #
        # I Faas: liidame yheks nimis6nafraasiks k6ik k6rvutiseisvad nimis6nafraasi
        #     sobivad s6nad, kui esimene on järgmise vahetu alluv, nt:
        #        [Venemaa otsus] alustada Süürias õhurünnakuid ...
        #        Kas [venelaste ambitsioon] on siiras ?
        #        [Järgmine hoop] tuli 2012-2013 ...
        #        [Eelmise nädala reedel] , [19. septembril] leidsid [kolleegid] ...
        #        
        for i in range(len(sentence)):
            label1  = i
            parent1 = syntax_layer[i][PARSER_OUT][0][1]
            #label1  = sentence[i][SYNTAX_LABEL]
            #parent1 = sentence[i][SYNTAX_HEAD]
            if i+1 < len(sentence):
                label2  = i+1
                parent2 = syntax_layer[i+1][PARSER_OUT][0][1]
                #label2  = sentence[i+1][SYNTAX_LABEL]
                #parent2 = sentence[i+1][SYNTAX_HEAD]
                pos1 = self._getPOS(sentence[i])
                pos2 = self._getPOS(sentence[i+1])
                if int(parent1) == int(label2) and pos1 in NPattribPos and \
                   pos2 in NPheadPos:
                    if 'K' in pos1 and NPlabels[i] == '':
                        #
                        #   1) erandjuht: 
                        #    K fraasi alguses viitab peaaegu alati mingile jamale, 
                        #    seega katkestame, et vältida selliseid asju nagu:
                        #      ... , mille [kohta Eestiski] piisavalt näiteid .
                        #      ... lähedaste majandussidemete [tõttu Brasiiliaga] .
                        #      ... kultuuri allutamise [vastu rahavõimule] , vaid töötavad
                        # 
                        pass
                    elif 'D' in pos1 and not self._AdvStartingPhrase.matches(sentence[i]):
                        #
                        #   2) erandjuht: 
                        #   Lubame ainult teatud adverbe fraasi algusesse, et vältida selliseid
                        #   juhte nagu nt:
                        #      ... said sõna [ka lapsed] , aga kingitust
                        #      ... kättesaamatuks [nii Nehatu hamburgeriputka] ,
                        #      ... osta [ka hinnaga 1 kr] 
                        #      ... ette [just Los Angelese autonäitusel] ,
                        
                        #   TODO: M6nikord me ikkagi tahame, et D ka sees oleks, nt:
                        #      ... filmis " Tagasi [tulevikku] " ...
                        pass
                    else:
                        if NPlabels[i] == '':
                            NPlabels[i] = 'B'
                        NPlabels[i+1] = 'I'
        #
        # II Faas: Koondame kõrvutipaiknevad ja üksteisega alluvussuhtes olevad arvsõnad/numbrid 
        #     üheks arvudest koosnevaks "NP-fraasiks", nt:
        #       [Sada nelikümmend viis]
        #       [10 405 miljonit]
        #       [kaheksa miljardit]
        #     
        for i in range(len(sentence)):
            label1  = i
            parent1 = syntax_layer[i][PARSER_OUT][0][1]
            #label1  = sentence[i][SYNTAX_LABEL]
            #parent1 = sentence[i][SYNTAX_HEAD]
            pos1 = self._getPOS(sentence[i])
            if pos1 in ['N', 'O']  and  i+1 < len(sentence):
                label2  = i+1
                parent2 = syntax_layer[i+1][PARSER_OUT][0][1]
                #label2  = sentence[i+1][SYNTAX_LABEL]
                #parent2 = sentence[i+1][SYNTAX_HEAD]
                pos2 = self._getPOS(sentence[i+1])
                if pos2 in ['N', 'O'] and ( int(parent2) == int(label1) or \
                   int(parent1) == int(label2) ):
                    if NPlabels[i] == '':
                        NPlabels[i] = 'B'
                    NPlabels[i+1] = 'I'
        #
        # III Faas: Kleebime otsa NP-fraaside otsa järeltäienditena esinevad numbrilised 
        #     arvud, nt:
        #        Üritus kandis nime [Rahu Missioon 2007.]
        #        Allkirjastas [1. jaanuaril 2004.]
        #        Saabus [uus Peugeot 307] , millest [aastatel 1987-1997] ei osatud unistadagi .
        #        [Perioodil 1997-2001] oli neid rohkem , [vt tabel 1.]
        #
        for i in range(len(sentence)):
            label1  = i
            parent1 = syntax_layer[i][PARSER_OUT][0][1]
            #label1  = sentence[i][SYNTAX_LABEL]
            #parent1 = sentence[i][SYNTAX_HEAD]
            pos1 = self._getPOS(sentence[i])
            if pos1 in ['N', 'O']  and  i-1 > -1:
                label2  = i-1
                parent2 = syntax_layer[i-1][PARSER_OUT][0][1]
                #label2  = sentence[i-1][SYNTAX_LABEL]
                #parent2 = sentence[i-1][SYNTAX_HEAD]
                if int(parent1) == int(label2) and NPlabels[i-1] != '':
                    NPlabels[i] = 'I'
        #
        # IV Faas: Kleebime arvufraaside(hulgafraaside) otsa järeltäienditena esinevad 
        #     nimisõnad, nt:
        #        Meri laius [100 kilomeetri] pikkusena .
        #        Aasta alguseks oli mahust järel [30-40 protsenti] .
        #        Jah , [kümne aasta] tagusega ei maksa siin üldse võrrelda .
        #        Mees nõudis [10 miljonit dollarit] kahjutasu [10-15 cm] kaugusele .
        #        Eelmisel nädalal võttis endalt elu veel [kaks politseiametnikku] .
        #        Kujutlesin [kaheksa miljonit aastat] vana küpressimetsa [mitukümmend aastat] nooremana .
        #
        for i in range(len(sentence)):
            label1  = i
            parent1 = syntax_layer[i][PARSER_OUT][0][1]
            #label1  = sentence[i][SYNTAX_LABEL]
            #parent1 = sentence[i][SYNTAX_HEAD]
            pos1 = self._getPOS(sentence[i])
            if pos1 in ['N', 'O']  and  i+1 < len(sentence):
                label2  = i+1
                parent2 = syntax_layer[i+1][PARSER_OUT][0][1]
                #label2  = sentence[i+1][SYNTAX_LABEL]
                #parent2 = sentence[i+1][SYNTAX_HEAD]
                pos2    = self._getPOS(sentence[i+1])
                if int(parent2) == int(label1) and NPlabels[i+1] != '' and pos2 != 'P':
                    if NPlabels[i]=='':
                        NPlabels[i] = 'B'
                    NPlabels[i+1] = 'I'
        # 
        # V Faas: Kui NP-fraasi l6pus on arvu/numbrifraas ( N_Y voi N_S ), siis t6stame arvufraasi
        #         lahku, isegi kui see teatud m22ral l6huks NP-fraasi, nt 
        #               [pindala 48 ha]            ==> [pindala] [48 ha]
        #               [Järvamaal 36 283 inimest] ==> [Järvamaal] [36 283 inimest]
        #               [kasahhid 3 %]             ==> [kasahhid] [3 %]
        #               [Tallinna Lihatööstuse aktsiatest 80 protsenti] ==>
        #                      [Tallinna Lihatööstuse aktsiatest] [80 protsenti]
        #
        for i in range( len(sentence) ):
            if NPlabels[i] == 'B':
                phrase, indices = self._getPhrase( i, sentence, NPlabels )
                posTags = [ self._getPOS(tok) for tok in phrase ]
                if len(phrase)>2 and posTags[-1] in ['S','Y'] and posTags[-2]=='N' and \
                   posTags[0] not in ['N', 'O']:
                    #
                    # Lisakontroll: tegu ei tohiks olla aastarvuga, nt:
                    #    [Eesti Tervishoiuprojekt] [2015 Lisaks]
                    #    [Prantsusmaa loobumine EXPO] [2004 korraldamisest]
                    # 
                    yearCheck = re.match('.*\d\d\d\d.*', phrase[-2][TEXT])
                    #
                    # Lisakontroll: kui eelneb rohkem kui yks arv, siis tuleb 
                    #    poolitamispunkti nihutada, nt:
                    #       [Viinis 170] [000 USA dollari]
                    #       [Järvamaal 36] [283 inimest]
                    #
                    breakPoint = indices[-2]
                    j = -3
                    while posTags[j] == 'N':
                        breakPoint = indices[j]
                        j -= 1
                    if not yearCheck:
                        NPlabels[breakPoint] = 'B'

        # 
        # VI Faas: Kui NP-fraasi sobiva s6na vanem on +2 v6i rohkema s6na kaugusel s6na j2rel, 
        #          siis pole s6na veel fraasi arvatud;
        #          Arvame ta fraasi j2rgmistel juhtudel:
        #            Eelnev j2rgarv, nt:
        #                ... pühendus meenutab [teisigi] [Põhjala suurmehi] , nagu ...
        #                ... enamikus jäid [esimese] [Eesti Vabariigi aegadesse] ...
        #            Eelnev omaduss6na, nt:
        #                ... makett ühest [olulisest] [jõeäärsest tänavast] sellisena ,
        #                ... soojendades ja [suures] soojaks [köetud telgis] kuuma teed ...
        #
        for i in range(len(sentence)-1, -1, -1):
            label1  = i
            parent1 = syntax_layer[i][PARSER_OUT][0][1]
            #label1  = sentence[i][SYNTAX_LABEL]
            #parent1 = sentence[i][SYNTAX_HEAD]
            pos1 = self._getPOS(sentence[i])
            parentRelativeLoc = int(parent1) - int(label1)
            if pos1 in NPattribPos and NPlabels[i]=='' and parentRelativeLoc > 1 and \
               i+parentRelativeLoc < len(sentence):
                label2  = i+parentRelativeLoc
                parent2 = syntax_layer[i+parentRelativeLoc][PARSER_OUT][0][1]
                #label2  = sentence[i+parentRelativeLoc][SYNTAX_LABEL]
                #parent2 = sentence[i+parentRelativeLoc][SYNTAX_HEAD]
                if int(parent1) == int(label2) and NPlabels[i+parentRelativeLoc] != '':
                    #
                    #   Kogume kokku k6ik kahe s6na vahele j22vad token'id:
                    #  
                    interveningTokens   = []
                    interveningTokenIDs = []
                    j = i + 1
                    while ( j < i + parentRelativeLoc ):
                        interveningTokens.append( sentence[j] )
                        interveningTokenIDs.append( j )
                        j += 1
                    #
                    #   Eemaldame neist tokenid, mis juba kuuluvad fraasi:
                    #
                    if NPlabels[i+parentRelativeLoc] == 'I':
                        while ( len(interveningTokenIDs) > 0 ):
                            lastID = interveningTokenIDs.pop()
                            lastToken = interveningTokens.pop()
                            if NPlabels[lastID] == 'B':
                                # Kui j6udsime fraasi alguseni, siis l6petame
                                break
                    
                    #
                    #    Kontroll1: s6na ja j2rgneva s6na vahele ei tohi j22da 
                    #     punktuatsiooni ega sidendeid, kuna need j2tame alati 
                    #     fraasist v2lja;
                    #
                    punctIntervening = False
                    jaNingEgaVoi     = False
                    for interToken in interveningTokens:
                        if self._punctPos.matches( interToken ):
                            punctIntervening = True
                        if self._jaNingEgaVoi.matches( interToken ):
                            jaNingEgaVoi = True

                    #
                    #   Leiame s6na ja tema ylema vahelise k22ndeyhilduvuse;
                    #
                    caseAgreement = \
                        self._getCaseAgreement(sentence[i], sentence[i+parentRelativeLoc])

                    if pos1 == 'O' and not punctIntervening and not jaNingEgaVoi and \
                       caseAgreement != None:
                        if len(interveningTokenIDs) == 0:
                            #
                            #    VI.a.  Eelnev s6na on k22ndes yhilduv j2rgarv, nt:
                            #      ... nagu ka teised [Eesti pered] , iga ...
                            #        ... mil esimene [Tšetšeenia sõda] käis täie ...
                            #        ... ka mõnedel teistel [mineraalsetel kütetel] peale autobensiini ...
                            #        ... on pärit kolmandast [Moosese raamatust] ehk leviitide ...
                            #
                            NPlabels[i]   = 'B'
                            NPlabels[i+1] = 'I'
                        else:
                            #
                            #    VI.b.  Eelnev s6na on k22ndes yhilduv j2rgarv, ning vahele j22vad
                            #           ainult k22ndes yhilduvad s6nad, nt:
                            #        ... Teised sõjavastased [Euroopa riigid] ilmselt avaldavad ...
                            #        ... tõi ära esimesed pesuehtsad [punased värsid] . ...
                            #        ... Esimene üleriigiline [automatiseeritud haiguseregister] - vähiregister ...
                            #
                            agreements = [self._getCaseAgreement(interTok, sentence[i+parentRelativeLoc]) for interTok in interveningTokens]
                            if all(agreements):
                                NPlabels[i] = 'B'
                                j = i + 1
                                while ( j <= i + parentRelativeLoc ):
                                    NPlabels[j] = 'I'
                                    j += 1

                    if pos1 in ['A','G'] and not punctIntervening and not jaNingEgaVoi and \
                       caseAgreement != None:
                        # 
                        #   Lisakontroll 1:
                        #      Jätame algusesse lisamata kesksõnadena esinevad sõnad, kuna 
                        #      nende puhul on tõenäoliselt tegemist millegi keerukamaga (nn
                        #      lauselühendiga):
                        #        ... Pingilt sekkunud [Chris Anstey] viskas ...
                        #        ... NBA meistriks tüürinud [Phil Jackson] ...
                        #        ... kaasaegsele maailmale mittevastav [teoreetiline lähenemine] ...
                        #
                        isVerbParticle = self._verbParticle.matches(sentence[i])
                        #
                        #  Lisakontroll 2:
                        #      Kui omaduss6na ja fraasi vahele j22b ka teisi s6nu, teeme 
                        #      kindlaks, et need s6nad poleks s6naliikidest V, D, J, mis
                        #      on probleemsed, nt:
                        #       D : ...  skreipi nii [pärilik] kui ka [nakkav haigus]  ...
                        #       V : ...  2002. aasta [keskmine] purunenud [terade saak]  ...
                        #       J : ...  oleks maakondadele [sobilik] kuni [14-rühmaline loend] Eesti  ...
                        #
                        interveningProblematicPOS = False
                        if len(interveningTokenIDs) > 0:
                            iPosTags = [ a[POSTAG] for t1 in interveningTokens for a in t1[ANALYSIS] ]
                            interveningProblematicPOS = \
                              'V' in iPosTags or 'D' in iPosTags or 'J' in iPosTags or 'Z' in iPosTags
                        if not isVerbParticle and len(interveningTokenIDs) == 0:
                            #
                            #    VI.c.  Eelnev s6na on k22ndes yhilduv ja vahetult eelnev 
                            #           omaduss6na (v.a. kesks6na), nt:
                            #           ... peeti pidu karmi [vene korra] ajal ning ...
                            #           ... äravajunud , arhailisest [Suurbritannia nurgast] ...
                            #           ... , võimaldades uutel [vapratel riikidel] kahel pool ...
                            #
                            NPlabels[i]   = 'B'
                            NPlabels[i+1] = 'I'
                        elif not isVerbParticle and len(interveningTokenIDs) > 0 and \
                            not interveningProblematicPOS:
                            #
                            #    VI.d.  Eelnev s6na on k22ndes yhilduv omaduss6na (v.a. kesks6na) 
                            #           ning vahele j22b veel v2hemalt yks sobiva POS tag'iga
                            #           s6na, nt:
                            #           ... korral on [tavaline] tugev [päevane unisus] , ...
                            #           ... mõjus silmadele [vana] mustvalge pisike [ekraan] ...
                            #           ... on enesekindel [valgete] higiste [kätega intelligent] ...
                            #
                            NPlabels[i] = 'B'
                            j = i + 1
                            while ( j <= i + parentRelativeLoc ):
                                NPlabels[j] = 'I'
                                j += 1
                                
                    if pos1 in ['C'] and not punctIntervening and not jaNingEgaVoi and \
                       caseAgreement != None:
                        if i - 1 > -1  and  self._k6ige.matches( sentence[i - 1] ):
                            #
                            #    VI.e.  Eelnev s6na on k22ndes yhilduv keskv6rde omaduss6na, 
                            #           millele eelneb yliv6rde tunnus 'k6ige', nt:
                            #           ... juhib perekonda kõige noorem [täiskasvanud naine] . ...
                            #           ... Kõige suurem [akustiline erinevus] oli vokaalide ...
                            #           ... on kõige levinumad [antikolinergilised ravimid] ...
                            #
                            NPlabels[i-1] = 'B'
                            j = i
                            while ( j <= i + parentRelativeLoc ):
                                NPlabels[j] = 'I'
                                j += 1
                        elif re.match('^(pl\s.+|sg\s(ab|abl|ad|all|el|es|ill|in|kom|ter|tr))$', \
                             caseAgreement):
                            #
                            #    VI.f.  Eelnev s6na on k22ndes yhilduv keskv6rde omaduss6na, 
                            #           mis on kas mitmuses v6i yhildub semantilise k22ndega, nt:
                            #           ... olnud üks aktiivsemaid [NATO rahupartnereid] . ...
                            #           ... meestel lisandub halvemale [füüsilisele tervisele] veel ...
                            #           ... Varasemates [samalaadsetes uurimustes] on laste ...
                            #          (grammatilise ainsusek22nde puhul ei pruugi nii kindel
                            #           olla, et kuulub just nimis6nafraasi juurde: v6ib kuuluda
                            #           ka (olema) verbifraasi juurde)
                            #
                            NPlabels[i] = 'B'
                            j = i + 1
                            while ( j <= i + parentRelativeLoc ):
                                NPlabels[j] = 'I'
                                j += 1
                            
                            #ex = self.__debug_extract_NP_from_pos(sentence, NPlabels, i-1, i+parentRelativeLoc)
                            #try:
                            #    print(sentence[i][TEXT]+' | '+sentence[i+parentRelativeLoc][TEXT]+' | '+pos1+" | "+ex)
                            #except:
                            #    print(' ### Err ###')
                       


        #
        #   Viimane faas: rakendame nn j2relparandusi, proovime pahna v2lja visata ...
        #
        self._apply_post_fixes( sentence, NPlabels, cutPhrases, cutMaxThreshold )
        return NPlabels