# SDK Pullenti Lingvo, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved.
# Non-Commercial Freeware and Commercial Software.
# This class is generated using the converter Unisharping (www.unisharping.ru) from Pullenti C# project.
# The latest version of the code is available on the site www.pullenti.ru

import typing
import xml.etree
import io
import math
from enum import IntEnum
from pullenti.unisharp.Utils import Utils
from pullenti.unisharp.Streams import MemoryStream
from pullenti.unisharp.Streams import Stream

from pullenti.morph.MorphNumber import MorphNumber
from pullenti.ner.core.NounPhraseParseAttr import NounPhraseParseAttr
from pullenti.ner.address.internal.AddressItemType import AddressItemType
from pullenti.ner.MorphCollection import MorphCollection
from pullenti.ner.geo.internal.Condition import Condition
from pullenti.ner.Token import Token
from pullenti.ner.address.internal.StreetItemType import StreetItemType
from pullenti.ner.MetaToken import MetaToken
from pullenti.ner.TextToken import TextToken
from pullenti.ner.ReferentToken import ReferentToken
from pullenti.ner.core.NumberHelper import NumberHelper
from pullenti.ner.core.ReferentsEqualType import ReferentsEqualType
from pullenti.ner.NumberSpellingType import NumberSpellingType
from pullenti.ner.geo.internal.GeoTokenType import GeoTokenType
from pullenti.ner.date.DateReferent import DateReferent
from pullenti.ner.core.NounPhraseHelper import NounPhraseHelper
from pullenti.ner.core.AnalyzerData import AnalyzerData
from pullenti.ner.Referent import Referent
from pullenti.morph.MorphGender import MorphGender
from pullenti.ner.core.NumberExType import NumberExType
from pullenti.ner.NumberToken import NumberToken
from pullenti.morph.MorphLang import MorphLang
from pullenti.ner.core.GetTextAttr import GetTextAttr
from pullenti.morph.LanguageHelper import LanguageHelper
from pullenti.morph.MorphWordForm import MorphWordForm
from pullenti.ner.core.MiscHelper import MiscHelper
from pullenti.ner.core.BracketParseAttr import BracketParseAttr
from pullenti.ner.core.BracketHelper import BracketHelper
from pullenti.ner.core.TerminParseAttr import TerminParseAttr
from pullenti.ner.core.Termin import Termin
from pullenti.ner.geo.internal.GeoTokenData import GeoTokenData
from pullenti.ner.geo.GeoReferent import GeoReferent
from pullenti.ner.geo.GeoAnalyzer import GeoAnalyzer
from pullenti.ner.core.TerminCollection import TerminCollection
from pullenti.ner.geo.internal.MiscLocationHelper import MiscLocationHelper
from pullenti.ner.address.internal.AddressItemToken import AddressItemToken
from pullenti.ner.core.IntOntologyCollection import IntOntologyCollection
from pullenti.ner.core.IntOntologyItem import IntOntologyItem
from pullenti.ner.address.internal.StreetItemToken import StreetItemToken
from pullenti.ner.address.internal.PullentiNerAddressInternalResourceHelper import PullentiNerAddressInternalResourceHelper
from pullenti.ner.geo.internal.TerrItemToken import TerrItemToken

class CityItemToken(MetaToken):
    
    class ItemType(IntEnum):
        PROPERNAME = 0
        CITY = 1
        NOUN = 2
        MISC = 3
        
        @classmethod
        def has_value(cls, value):
            return any(value == item.value for item in cls)
    
    @staticmethod
    def try_parse_list(t : 'Token', max_count : int, ad : 'GeoAnalyzerData'=None) -> typing.List['CityItemToken']:
        from pullenti.ner.geo.internal.OrgItemToken import OrgItemToken
        ci = CityItemToken.try_parse(t, None, False, ad)
        if (ci is None): 
            if (t is None): 
                return None
            if (((isinstance(t, TextToken)) and t.is_value("МУНИЦИПАЛЬНЫЙ", None) and t.next0_ is not None) and t.next0_.is_value("ОБРАЗОВАНИЕ", None)): 
                t1 = t.next0_.next0_
                br = False
                if (BracketHelper.can_be_start_of_sequence(t1, False, False)): 
                    br = True
                    t1 = t1.next0_
                lii = CityItemToken.try_parse_list(t1, max_count, None)
                if (lii is not None and lii[0].typ == CityItemToken.ItemType.NOUN): 
                    lii[0].begin_token = t
                    lii[0].doubtful = False
                    if (br and BracketHelper.can_be_end_of_sequence(lii[len(lii) - 1].end_token.next0_, False, None, False)): 
                        lii[len(lii) - 1].end_token = lii[len(lii) - 1].end_token.next0_
                    if (isinstance(t.previous, TextToken)): 
                        if (t.previous.is_value("ГОРОДСКОЙ", None) or t.previous.is_value("СЕЛЬСКИЙ", None)): 
                            lii[0].begin_token = t.previous
                    return lii
            return None
        if (ci.chars.is_latin_letter and ci.typ == CityItemToken.ItemType.NOUN and not t.chars.is_all_lower): 
            return None
        li = list()
        li.append(ci)
        t = ci.end_token.next0_
        first_pass4125 = True
        while True:
            if first_pass4125: first_pass4125 = False
            else: t = t.next0_
            if (not (t is not None)): break
            if (t.is_newline_before): 
                if (t.newlines_before_count > 1): 
                    break
                if (len(li) == 1 and li[0].typ == CityItemToken.ItemType.NOUN): 
                    pass
                else: 
                    break
            ci0 = CityItemToken.try_parse(t, ci, False, ad)
            if (ci0 is None): 
                if (t.is_newline_before): 
                    break
                if (ci.typ == CityItemToken.ItemType.NOUN and BracketHelper.can_be_start_of_sequence(t, True, False)): 
                    br = BracketHelper.try_parse(t, BracketParseAttr.NO, 100)
                    if ((br is not None and (br.length_char < 50) and t.next0_.chars.is_cyrillic_letter) and not t.next0_.chars.is_all_lower): 
                        ci0 = CityItemToken._new1501(br.begin_token, br.end_token, CityItemToken.ItemType.PROPERNAME)
                        tt = br.end_token.previous
                        num = None
                        if (isinstance(tt, NumberToken)): 
                            num = str(tt.value)
                            tt = tt.previous
                            if (tt is not None and tt.is_hiphen): 
                                tt = tt.previous
                        ci0.value = MiscHelper.get_text_value(br.begin_token.next0_, tt, GetTextAttr.NO)
                        if (tt != br.begin_token.next0_): 
                            ci0.alt_value = MiscHelper.get_text_value(br.begin_token.next0_, tt, GetTextAttr.NO)
                        if (Utils.isNullOrEmpty(ci0.value)): 
                            ci0 = (None)
                        elif (num is not None): 
                            ci0.value = "{0}-{1}".format(ci0.value, num)
                            if (ci0.alt_value is not None): 
                                ci0.alt_value = "{0}-{1}".format(ci0.alt_value, num)
                if ((ci0 is None and ((ci.typ == CityItemToken.ItemType.PROPERNAME or ci.typ == CityItemToken.ItemType.CITY)) and t.is_comma) and li[0] == ci): 
                    npt = MiscLocationHelper._try_parse_npt(t.next0_)
                    if (npt is not None): 
                        tt = t.next0_
                        while tt is not None and tt.end_char <= npt.end_char: 
                            ci00 = CityItemToken.try_parse(tt, ci, False, None)
                            if (ci00 is not None and ci00.typ == CityItemToken.ItemType.NOUN): 
                                ci01 = CityItemToken.try_parse(ci00.end_token.next0_, ci, False, None)
                                if (ci01 is not None): 
                                    break
                                org0_ = OrgItemToken.try_parse(ci00.end_token.next0_, None)
                                if (org0_ is not None): 
                                    break
                                ci0 = ci00
                                ci0.alt_value = MiscHelper.get_text_value(t.next0_, ci00.end_token, (GetTextAttr.IGNOREARTICLES if t.kit.base_language.is_en else GetTextAttr.FIRSTNOUNGROUPTONOMINATIVESINGLE)).lower()
                                break
                            if (not tt.chars.is_all_lower): 
                                break
                            tt = tt.next0_
                    else: 
                        ci1 = CityItemToken.try_parse(t.next0_, None, False, None)
                        if (ci1 is not None and ci1.typ == CityItemToken.ItemType.NOUN and ((ci1.end_token.next0_ is None or ci1.end_token.next0_.is_comma))): 
                            ci0 = ci1
                if (ci0 is None): 
                    break
            if ((ci0.typ == CityItemToken.ItemType.NOUN and ci0.value is not None and LanguageHelper.ends_with(ci0.value, "УСАДЬБА")) and ci.typ == CityItemToken.ItemType.NOUN): 
                ci.doubtful = False
                ci.end_token = ci0.end_token
                t = ci.end_token
                continue
            if (ci0.typ == CityItemToken.ItemType.NOUN and ci.typ == CityItemToken.ItemType.MISC and ci.value == "АДМИНИСТРАЦИЯ"): 
                ci0.doubtful = False
            if (ci.merge_with_next(ci0)): 
                t = ci.end_token
                continue
            ci = ci0
            li.append(ci)
            t = ci.end_token
            if (max_count > 0 and len(li) >= max_count): 
                break
        if (len(li) > 1 and li[0].value == "СОВЕТ"): 
            return None
        if (len(li) > 2 and li[0].typ == CityItemToken.ItemType.NOUN and li[1].typ == CityItemToken.ItemType.NOUN): 
            if (li[0].merge_with_next(li[1])): 
                del li[1]
        if (len(li) > 2 and li[0].is_newline_after): 
            del li[1:1+len(li) - 1]
        if (not li[0].geo_object_before): 
            li[0].geo_object_before = MiscLocationHelper.check_geo_object_before(li[0].begin_token, False)
        if (not li[len(li) - 1].geo_object_after): 
            li[len(li) - 1].geo_object_after = MiscLocationHelper.check_geo_object_after(li[len(li) - 1].end_token, True, False)
        if ((len(li) == 2 and li[0].typ == CityItemToken.ItemType.NOUN and li[1].typ == CityItemToken.ItemType.NOUN) and ((li[0].geo_object_before or li[1].geo_object_after))): 
            if (li[0].chars.is_capital_upper and li[1].chars.is_all_lower): 
                li[0].typ = CityItemToken.ItemType.PROPERNAME
            elif (li[1].chars.is_capital_upper and li[0].chars.is_all_lower): 
                li[1].typ = CityItemToken.ItemType.PROPERNAME
        if ((len(li) >= 2 and li[0].typ == CityItemToken.ItemType.PROPERNAME and li[1].typ == CityItemToken.ItemType.NOUN) and li[1].doubtful): 
            pass
        return li
    
    @staticmethod
    def initialize() -> None:
        from pullenti.ner.geo.internal.NameToken import NameToken
        if (CityItemToken.M_ONTOLOGY is not None): 
            return
        CityItemToken.M_ONTOLOGY = IntOntologyCollection()
        CityItemToken.M_ONTOLOGY_EX = IntOntologyCollection()
        CityItemToken.M_CITY_ADJECTIVES = TerminCollection()
        t = None
        t = Termin("ГОРОД")
        t.add_abridge("ГОР.")
        t.add_abridge("Г.")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("ГОРД")
        t.add_abridge("ГРД")
        t.add_abridge("МУН.")
        t.add_variant("ГОРОД ФЕДЕРАЛЬНОГО ЗНАЧЕНИЯ", False)
        t.add_variant("ГОРОД ГОРОДСКОЕ ПОСЕЛЕНИЕ", False)
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ГОРОДОК")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_variant("ШАХТЕРСКИЙ ГОРОДОК", False)
        t.add_variant("ПРИМОРСКИЙ ГОРОДОК", False)
        t.add_variant("МАЛЕНЬКИЙ ГОРОДОК", False)
        t.add_variant("НЕБОЛЬШОЙ ГОРОДОК", False)
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("CITY")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_variant("TOWN", False)
        t.add_variant("CAPITAL", False)
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("LOCALITY")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("VILLAGE")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("МІСТО", MorphLang.UA)
        t.add_abridge("МІС.")
        t.add_abridge("М.")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1469("ГОРОД-ГЕРОЙ", "ГОРОД")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1503("МІСТО-ГЕРОЙ", MorphLang.UA, "МІСТО")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1469("ГОРОД-КУРОРТ", "ГОРОД")
        t.add_abridge("Г.К.")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1503("МІСТО-КУРОРТ", MorphLang.UA, "МІСТО")
        t.add_abridge("М.К.")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СЕЛО")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ДЕРЕВНЯ")
        t.add_abridge("ДЕР.")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СЕЛЕНИЕ")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("СЕЛ.")
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СЕЛО", MorphLang.UA)
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ПОСЕЛЕНИЕ")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("АГРОГОРОДОК")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_variant("АГРО ГОРОДОК", False)
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ПОСЕЛОК")
        t.add_abridge("ПОС.")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_variant("ЖИЛОЙ ПОСЕЛОК", False)
        t.add_variant("КУРОРТНЫЙ ПОСЕЛОК", False)
        t.add_variant("ВАХТОВЫЙ ПОСЕЛОК", False)
        t.add_variant("ШАХТЕРСКИЙ ПОСЕЛОК", False)
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СЕЛИЩЕ", MorphLang.UA)
        t.add_abridge("СЕЛ.")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ПОСЕЛОК ГОРОДСКОГО ТИПА")
        t.acronym_smart = "ПГТ"
        t.acronym = t.acronym_smart
        t.add_abridge("ПГТ.")
        t.add_abridge("П.Г.Т.")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("ПОС.Г.Т.")
        t.add_variant("ГОРОДСКОЙ ПОСЕЛОК", False)
        t.add_abridge("ГОРОДСКОЙ ПОС.")
        t.add_abridge("ГОР.ПОС.")
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СЕЛИЩЕ МІСЬКОГО ТИПУ", MorphLang.UA)
        t.acronym_smart = "СМТ"
        t.acronym = t.acronym_smart
        t.add_abridge("СМТ.")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("РАБОЧИЙ ПОСЕЛОК")
        t.add_abridge("Р.П.")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("РАБ.П.")
        t.add_abridge("Р.ПОС.")
        t.add_abridge("РАБ.ПОС.")
        t.add_abridge("РП")
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("РОБОЧЕ СЕЛИЩЕ", MorphLang.UA)
        t.add_abridge("Р.С.")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ДАЧНЫЙ ПОСЕЛОК")
        t.add_abridge("Д.П.")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("ДАЧ.П.")
        t.add_abridge("Д.ПОС.")
        t.add_abridge("ДАЧ.ПОС.")
        t.add_variant("ЖИЛИЩНО ДАЧНЫЙ ПОСЕЛОК", False)
        t.add_variant("ДАЧНОЕ ПОСЕЛЕНИЕ", False)
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ДАЧНЕ СЕЛИЩЕ", MorphLang.UA)
        t.add_abridge("Д.С.")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("ДАЧ.С.")
        t.add_abridge("Д.СЕЛ.")
        t.add_abridge("ДАЧ.СЕЛ.")
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1506("ГОРОДСКОЕ ПОСЕЛЕНИЕ", "ГП", True)
        t.add_abridge("Г.П.")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("Г.ПОС.")
        t.add_abridge("ГОР.П.")
        t.add_abridge("ГОР.ПОС.")
        t.add_abridge("ГП.")
        t.add_variant("ГОРОДСКОЙ ПОСЕЛОК", False)
        t.add_abridge("Г.О.Г.")
        t.add_abridge("ГОРОДСКОЙ ОКРУГ Г.")
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new144("ПОСЕЛКОВОЕ ПОСЕЛЕНИЕ", "ПОСЕЛОК", CityItemToken.ItemType.NOUN)
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("МІСЬКЕ ПОСЕЛЕННЯ", MorphLang.UA)
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СЕЛЬСКОЕ ПОСЕЛЕНИЕ")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("С.ПОС.")
        t.add_abridge("С.П.")
        t.add_variant("СЕЛЬСКИЙ ПОСЕЛОК", False)
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СІЛЬСЬКЕ ПОСЕЛЕННЯ", MorphLang.UA)
        t.add_abridge("С.ПОС.")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СТАНИЦА")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("СТ-ЦА")
        t.add_abridge("СТАН-ЦА")
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СТАНИЦЯ", MorphLang.UA)
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1469("СТОЛИЦА", "ГОРОД")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1503("СТОЛИЦЯ", MorphLang.UA, "МІСТО")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СТАНЦИЯ")
        t.add_abridge("СТАНЦ.")
        t.add_abridge("СТ.")
        t.add_abridge("СТАН.")
        t.add_variant("ПЛАТФОРМА", False)
        t.add_abridge("ПЛАТФ.")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ПОЛУСТАНОК")
        t.add_abridge("П.СТ.")
        t.add_abridge("П/СТ")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СТАНЦІЯ", MorphLang.UA)
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ЖЕЛЕЗНОДОРОЖНАЯ СТАНЦИЯ")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("Ж/Д СТАНЦИЯ")
        t.add_abridge("Ж/Д СТ.")
        t.add_abridge("Ж/Д СТАНЦ.")
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ЗАЛІЗНИЧНА СТАНЦІЯ", MorphLang.UA)
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("НАСЕЛЕННЫЙ ПУНКТ")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("Н.П.")
        t.add_abridge("Б.Н.П.")
        t.add_abridge("НП")
        CityItemToken.M_NASEL_PUNKT = t
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("НАСЕЛЕНИЙ ПУНКТ", MorphLang.UA)
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("НП")
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1469("РАЙОННЫЙ ЦЕНТР", "НАСЕЛЕННЫЙ ПУНКТ")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1503("РАЙОННИЙ ЦЕНТР", MorphLang.UA, "НАСЕЛЕНИЙ ПУНКТ")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1469("ОБЛАСТНОЙ ЦЕНТР", "НАСЕЛЕННЫЙ ПУНКТ")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin._new1503("ОБЛАСНИЙ ЦЕНТР", MorphLang.UA, "НАСЕЛЕНИЙ ПУНКТ")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ПОЧИНОК")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ХУТОР")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("СЛОБОДА")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("СЛ.")
        t.add_abridge("СЛОБ.")
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("АУЛ")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ААЛ")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("КИШЛАК")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_abridge("К-К")
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("УЛУС")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("НАСЛЕГ")
        t.tag = CityItemToken.ItemType.NOUN
        t.add_variant("НАЦИОНАЛЬНЫЙ НАСЛЕГ", False)
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("АРБАН")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        t = Termin("ВЫСЕЛКИ")
        t.tag = CityItemToken.ItemType.NOUN
        CityItemToken.M_ONTOLOGY.add(t)
        for s in ["ЖИТЕЛЬ", "МЭР"]: 
            CityItemToken.M_ONTOLOGY.add(Termin._new96(s, CityItemToken.ItemType.MISC))
        for s in ["ЖИТЕЛЬ", "МЕР"]: 
            CityItemToken.M_ONTOLOGY.add(Termin._new510(s, MorphLang.UA, CityItemToken.ItemType.MISC))
        t = Termin._new96("АДМИНИСТРАЦИЯ", CityItemToken.ItemType.MISC)
        t.add_abridge("АДМ.")
        CityItemToken.M_ONTOLOGY.add(t)
        CityItemToken.M_STD_ADJECTIVES = IntOntologyCollection()
        t = Termin("ВЕЛИКИЙ")
        t.add_abridge("ВЕЛ.")
        t.add_abridge("ВЕЛИК.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("БОЛЬШОЙ")
        t.add_abridge("БОЛ.")
        t.add_abridge("БОЛЬШ.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("МАЛЫЙ")
        t.add_abridge("МАЛ.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("ВЕРХНИЙ")
        t.add_abridge("ВЕР.")
        t.add_abridge("ВЕРХ.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("НИЖНИЙ")
        t.add_abridge("НИЖ.")
        t.add_abridge("НИЖН.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("СРЕДНИЙ")
        t.add_abridge("СРЕД.")
        t.add_abridge("СРЕДН.")
        t.add_abridge("СР.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("СТАРЫЙ")
        t.add_abridge("СТ.")
        t.add_abridge("СТАР.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("НОВЫЙ")
        t.add_abridge("НОВ.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("ВЕЛИКИЙ", MorphLang.UA)
        t.add_abridge("ВЕЛ.")
        t.add_abridge("ВЕЛИК.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("МАЛИЙ", MorphLang.UA)
        t.add_abridge("МАЛ.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("ВЕРХНІЙ", MorphLang.UA)
        t.add_abridge("ВЕР.")
        t.add_abridge("ВЕРХ.")
        t.add_abridge("ВЕРХН.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("НИЖНІЙ", MorphLang.UA)
        t.add_abridge("НИЖ.")
        t.add_abridge("НИЖН.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("СЕРЕДНІЙ", MorphLang.UA)
        t.add_abridge("СЕР.")
        t.add_abridge("СЕРЕД.")
        t.add_abridge("СЕРЕДН.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("СТАРИЙ", MorphLang.UA)
        t.add_abridge("СТ.")
        t.add_abridge("СТАР.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        t = Termin("НОВИЙ", MorphLang.UA)
        t.add_abridge("НОВ.")
        CityItemToken.M_STD_ADJECTIVES.add(t)
        CityItemToken.M_STD_ADJECTIVES.add(Termin("SAN"))
        CityItemToken.M_STD_ADJECTIVES.add(Termin("LOS"))
        CityItemToken.M_SPEC_NAMES = TerminCollection()
        for s in NameToken._standard_names: 
            pp = Utils.splitString(s, ';', False)
            t = Termin._new1517(pp[0], True)
            kk = 1
            while kk < len(pp): 
                if (pp[kk].find('.') > 0): 
                    t.add_abridge(pp[kk])
                elif (t.acronym is None and (len(pp[kk]) < 4)): 
                    t.acronym = pp[kk]
                else: 
                    t.add_variant(pp[kk], False)
                kk += 1
            CityItemToken.M_SPEC_NAMES.add(t)
        CityItemToken.M_SPEC_ABBRS = TerminCollection()
        dat = PullentiNerAddressInternalResourceHelper.get_bytes("c.dat")
        if (dat is None): 
            raise Utils.newException("Not found resource file c.dat in Analyzer.Location", None)
        with MemoryStream(MiscLocationHelper._deflate(dat)) as tmp: 
            tmp.position = 0
            xml0_ = None # new XmlDocument
            xml0_ = Utils.parseXmlFromStream(tmp)
            for x in xml0_.getroot(): 
                if (Utils.getXmlName(x) == "bigcity"): 
                    CityItemToken.__load_big_city(x)
                elif (Utils.getXmlName(x) == "city"): 
                    CityItemToken.__load_city(x)
    
    @staticmethod
    def __load_city(xml0_ : xml.etree.ElementTree.Element) -> None:
        ci = IntOntologyItem(None)
        onto = CityItemToken.M_ONTOLOGY_EX
        lang = MorphLang.RU
        if (Utils.getXmlAttrByName(xml0_.attrib, "l") is not None and Utils.getXmlAttrByName(xml0_.attrib, "l")[1] == "ua"): 
            lang = MorphLang.UA
        for x in xml0_: 
            if (Utils.getXmlName(x) == "n"): 
                v = Utils.getXmlInnerText(x)
                t = Termin()
                t.init_by_normal_text(v, lang)
                ci.termins.append(t)
                t.add_std_abridges()
                if (v.startswith("SAINT ")): 
                    t.add_abridge("ST. " + v[6:])
                elif (v.startswith("SAITNE ")): 
                    t.add_abridge("STE. " + v[7:])
        onto.add_item(ci)
    
    @staticmethod
    def __load_big_city(xml0_ : xml.etree.ElementTree.Element) -> None:
        ci = IntOntologyItem(None)
        ci.misc_attr = (ci)
        adj = None
        onto = CityItemToken.M_ONTOLOGY_EX
        city_adj = CityItemToken.M_CITY_ADJECTIVES
        lang = MorphLang.RU
        if (Utils.getXmlAttrByName(xml0_.attrib, "l") is not None): 
            la = Utils.getXmlAttrByName(xml0_.attrib, "l")[1]
            if (la == "ua"): 
                lang = MorphLang.UA
            elif (la == "en"): 
                lang = MorphLang.EN
        for x in xml0_: 
            if (Utils.getXmlName(x) == "n"): 
                v = Utils.getXmlInnerText(x)
                if (Utils.isNullOrEmpty(v)): 
                    continue
                t = Termin()
                t.init_by_normal_text(v, lang)
                ci.termins.append(t)
                if (v == "САНКТ-ПЕТЕРБУРГ"): 
                    if (CityItemToken.M_ST_PETERBURG is None): 
                        CityItemToken.M_ST_PETERBURG = ci
                    t.acronym = "СПБ"
                    t.add_abridge("С.ПЕТЕРБУРГ")
                    t.add_abridge("СП-Б")
                    t.add_abridge("С-ПБ")
                    t.add_variant("ПИТЕР", False)
                    ci.termins.append(Termin("ПЕТЕРБУРГ", lang))
                elif (v.startswith("SAINT ")): 
                    t.add_abridge("ST. " + v[6:])
                elif (v.startswith("SAITNE ")): 
                    t.add_abridge("STE. " + v[7:])
                elif (v.startswith("НИЖН") and v.find(' ') > 0): 
                    ii = v.find(' ')
                    vv = v[ii + 1:]
                    t.add_abridge("Н." + vv)
                    t.add_abridge("H." + vv)
                    t.add_abridge("Н-" + vv)
                    t.add_abridge("H-" + vv)
                    t.add_abridge("НИЖ." + vv)
                    t.add_abridge("НИЖН." + vv)
                    t.add_abridge("Н" + vv)
                    t.ignore_terms_order = True
            elif (Utils.getXmlName(x) == "a"): 
                adj = Utils.getXmlInnerText(x)
        onto.add_item(ci)
        if (not Utils.isNullOrEmpty(adj)): 
            at = Termin()
            at.init_by_normal_text(adj, lang)
            at.tag = (ci)
            city_adj.add(at)
            spb = adj == "САНКТ-ПЕТЕРБУРГСКИЙ" or adj == "САНКТ-ПЕТЕРБУРЗЬКИЙ"
            if (spb): 
                city_adj.add(Termin._new510(adj[6:], lang, ci))
    
    M_ONTOLOGY = None
    
    M_ONTOLOGY_EX = None
    
    M_ST_PETERBURG = None
    
    M_CITY_ADJECTIVES = None
    
    M_STD_ADJECTIVES = None
    
    M_SPEC_NAMES = None
    
    M_SPEC_ABBRS = None
    
    M_NASEL_PUNKT = None
    
    @staticmethod
    def check_onto_item(t : 'Token') -> 'IntOntologyToken':
        if (not (isinstance(t, TextToken))): 
            return None
        li = CityItemToken.M_ONTOLOGY_EX.try_attach(t, None, False)
        if (li is not None): 
            for nt in li: 
                if (nt.item is not None): 
                    return nt
        return None
    
    @staticmethod
    def check_keyword(t : 'Token') -> 'IntOntologyToken':
        if (not (isinstance(t, TextToken))): 
            return None
        li = CityItemToken.M_ONTOLOGY.try_attach(t, None, False)
        if (li is not None): 
            for nt in li: 
                if (nt.item is None): 
                    if (nt.termin.canonic_text == "ГОРОДОК" and MiscLocationHelper.is_user_param_address(t)): 
                        return None
                    return nt
        return None
    
    @staticmethod
    def check_keyword_before(last : 'Token') -> 'MetaToken':
        cou = 5
        tt = last
        first_pass4126 = True
        while True:
            if first_pass4126: first_pass4126 = False
            else: tt = tt.previous; cou -= 1
            if (not (tt is not None and cou > 0)): break
            res = CityItemToken.check_keyword(tt)
            if (res is None): 
                continue
            if (res.end_token == last): 
                return res
        return None
    
    def __init__(self, begin : 'Token', end : 'Token') -> None:
        super().__init__(begin, end, None)
        self.typ = CityItemToken.ItemType.PROPERNAME
        self.value = None;
        self.alt_value = None;
        self.onto_item = None;
        self.doubtful = False
        self.geo_object_before = False
        self.__m_geo_object_after = False
        self.higher_geo = None;
        self.org_ref = None;
        self.orto_city = None;
        self.can_be_name = False
        self.misc = None;
        self.misc2 = None;
        self._cond = None;
    
    @property
    def geo_object_after(self) -> bool:
        return self.__m_geo_object_after
    @geo_object_after.setter
    def geo_object_after(self, value_) -> bool:
        self.__m_geo_object_after = value_
        return value_
    
    def __str__(self) -> str:
        res = io.StringIO()
        if (self._cond is not None): 
            print("[{0}] ".format(str(self._cond)), end="", file=res, flush=True)
        print("{0}".format(Utils.enumToString(self.typ)), end="", file=res, flush=True)
        if (self.value is not None): 
            print(" {0}".format(self.value), end="", file=res, flush=True)
        if (self.onto_item is not None): 
            print(" {0}".format(str(self.onto_item)), end="", file=res, flush=True)
        if (self.doubtful): 
            print(" (?)", end="", file=res)
        if (self.org_ref is not None): 
            print(" (Org: {0})".format(self.org_ref.referent), end="", file=res, flush=True)
        if (self.geo_object_before): 
            print(" GeoBefore", end="", file=res)
        if (self.geo_object_after): 
            print(" GeoAfter", end="", file=res)
        if (self.orto_city is not None): 
            print(" Orto: {0}".format(self.orto_city), end="", file=res, flush=True)
        if (self.can_be_name): 
            print(" (?name)", end="", file=res)
        return Utils.toStringStringIO(res)
    
    def merge_with_next(self, ne : 'CityItemToken') -> bool:
        if (self.typ != CityItemToken.ItemType.NOUN or ne.typ != CityItemToken.ItemType.NOUN): 
            return False
        ok = False
        if (self.value == "ГОРОДСКОЕ ПОСЕЛЕНИЕ" and ne.value == "ГОРОД"): 
            ok = True
        if (not ok): 
            return False
        self.end_token = ne.end_token
        self.doubtful = False
        return True
    
    SPEED_REGIME = False
    
    @staticmethod
    def _prepare_all_data(t0 : 'Token') -> None:
        if (not CityItemToken.SPEED_REGIME): 
            return
        ad = GeoAnalyzer._get_data(t0)
        if (ad is None): 
            return
        ad.cregime = False
        t = t0
        while t is not None: 
            d = Utils.asObjectOrNull(t.tag, GeoTokenData)
            cit = CityItemToken.try_parse(t, None, False, ad)
            if (cit is not None): 
                if (d is None): 
                    d = GeoTokenData(t)
                d.cit = cit
            t = t.next0_
        t = t0
        first_pass4127 = True
        while True:
            if first_pass4127: first_pass4127 = False
            else: t = t.next0_
            if (not (t is not None)): break
            d = Utils.asObjectOrNull(t.tag, GeoTokenData)
            if (d is None or d.cit is None or d.cit.typ != CityItemToken.ItemType.NOUN): 
                continue
            tt = d.cit.end_token.next0_
            if (tt is None): 
                continue
            dd = Utils.asObjectOrNull(tt.tag, GeoTokenData)
            cit = CityItemToken.try_parse(tt, d.cit, False, ad)
            if (cit is None): 
                continue
            if (dd is None): 
                dd = GeoTokenData(tt)
            dd.cit = cit
        ad.cregime = True
    
    @staticmethod
    def try_parse(t : 'Token', prev : 'CityItemToken'=None, dont_normalize : bool=False, ad : 'GeoAnalyzerData'=None) -> 'CityItemToken':
        from pullenti.ner.geo.internal.OrgItemToken import OrgItemToken
        from pullenti.ner.geo.internal.CityAttachHelper import CityAttachHelper
        from pullenti.ner.geo.internal.OrgTypToken import OrgTypToken
        if (t is None): 
            return None
        if (ad is None): 
            ad = GeoAnalyzer._get_data(t)
        if (ad is None): 
            return None
        d = Utils.asObjectOrNull(t.tag, GeoTokenData)
        if (t.is_value("НП", None)): 
            res0 = CityItemToken._new1519(t, t, CityItemToken.ItemType.NOUN, "населенный пункт", True)
            if (t.next0_ is not None and t.next0_.is_char('.')): 
                res0.end_token = t.next0_
            return res0
        if (d is not None and d.no_geo): 
            return None
        if ((isinstance(t, TextToken)) and t.term.startswith("УЧ")): 
            ttt = AddressItemToken.M_PLOT.try_parse(t, TerminParseAttr.NO)
            if (ttt is not None): 
                ok = False
                tt = t.previous
                while tt is not None: 
                    if (tt.is_comma): 
                        pass
                    else: 
                        geo_ = Utils.asObjectOrNull(tt.get_referent(), GeoReferent)
                        if (geo_ is not None and geo_.is_region): 
                            ok = True
                        break
                    tt = tt.previous
                if (ok): 
                    next0__ = CityItemToken.try_parse(ttt.end_token.next0_, None, False, None)
                    if (next0__ is not None and next0__.typ == CityItemToken.ItemType.PROPERNAME): 
                        return CityItemToken._new1520(t, ttt.end_token, CityItemToken.ItemType.NOUN, "участок")
        if (CityItemToken.SPEED_REGIME and ((ad.cregime or ad.all_regime)) and not dont_normalize): 
            if (d is None): 
                return None
            if (d.cit is None): 
                return None
            if (d.cit._cond is not None): 
                if (ad.check_regime): 
                    return None
                ad.check_regime = True
                b = d.cit._cond.check()
                ad.check_regime = False
                if (not b): 
                    return None
            return d.cit
        if (ad.clevel > 1): 
            return None
        ad.clevel += 1
        res = CityItemToken.__try_parse_int(t, prev, dont_normalize, ad)
        ad.clevel -= 1
        if (res is not None and res.typ == CityItemToken.ItemType.NOUN and (res.whitespaces_after_count < 2)): 
            nn = MiscLocationHelper._try_parse_npt(res.end_token.next0_)
            if (nn is not None and ((nn.end_token.is_value("ЗНАЧЕНИЕ", "ЗНАЧЕННЯ") or nn.end_token.is_value("ТИП", None) or nn.end_token.is_value("ХОЗЯЙСТВО", "ХАЗЯЙСТВО")))): 
                if (nn.begin_token != nn.end_token and ((nn.begin_token.next0_.is_comma_and or OrgTypToken.try_parse(nn.begin_token.next0_, False, None) is not None))): 
                    pass
                elif (OrgItemToken.try_parse(res.end_token.next0_, ad) is None): 
                    res.end_token = nn.end_token
            elif ((res.value == "ГОРОДСКОЕ ПОСЕЛЕНИЕ" or res.value == "СЕЛЬСКОЕ ПОСЕЛЕНИЕ")): 
                ad.clevel += 1
                next0__ = CityItemToken.__try_parse_int(res.end_token.next0_, res, dont_normalize, ad)
                ad.clevel -= 1
                if (next0__ is not None and next0__.typ == CityItemToken.ItemType.NOUN): 
                    res.end_token = next0__.end_token
                    res.alt_value = next0__.value
        if (((res is not None and res.typ == CityItemToken.ItemType.PROPERNAME and res.value is not None) and not res.doubtful and res.begin_token == res.end_token) and len(res.value) > 4): 
            if (LanguageHelper.ends_with_ex(res.value, "ГРАД", "ГОРОД", None, None)): 
                if (res.alt_value is not None and res.alt_value.endswith("А")): 
                    pass
                else: 
                    res.alt_value = (None)
                    res.typ = CityItemToken.ItemType.CITY
            elif (LanguageHelper.ends_with_ex(res.value, "СК", "ИНО", "ПОЛЬ", None) or LanguageHelper.ends_with_ex(res.value, "ВЛЬ", "АС", "ЕС", None)): 
                sits = StreetItemToken.try_parse_list(res.end_token.next0_, 3, ad)
                if (sits is not None): 
                    if (len(sits) == 1 and sits[0].typ == StreetItemType.NOUN): 
                        return res
                    if (len(sits) == 2 and sits[0].typ == StreetItemType.NUMBER and sits[1].typ == StreetItemType.NOUN): 
                        return res
                mc = res.end_token.get_morph_class_in_dictionary()
                if (mc.is_proper_geo or mc.is_undefined): 
                    res.alt_value = (None)
                    res.typ = CityItemToken.ItemType.CITY
            elif (LanguageHelper.ends_with_ex(res.value, "АНЬ", "TOWN", None, None) or res.value.startswith("SAN")): 
                res.typ = CityItemToken.ItemType.CITY
            elif (isinstance(res.end_token, TextToken)): 
                lem = res.end_token.lemma
                if (LanguageHelper.ends_with_ex(lem, "ГРАД", "ГОРОД", "СК", None) or LanguageHelper.ends_with_ex(lem, "АНЬ", "ПОЛЬ", None, None)): 
                    res.alt_value = res.value
                    res.value = lem
                    ii = res.alt_value.find('-')
                    if (ii >= 0): 
                        res.value = (res.alt_value[0:0+ii + 1] + lem)
                    if (not LanguageHelper.ends_with(res.value, "АНЬ")): 
                        res.alt_value = (None)
        if (res is None and t.is_char('(') and MiscLocationHelper.is_user_param_address(t)): 
            next0__ = CityItemToken.try_parse(t.next0_, None, False, None)
            if ((next0__ is not None and next0__.typ == CityItemToken.ItemType.NOUN and next0__.end_token.next0_ is not None) and next0__.end_token.next0_.is_char(')')): 
                next0__.begin_token = t
                next0__.end_token = next0__.end_token.next0_
                res = next0__
        if (res is None): 
            return None
        if (res.typ == CityItemToken.ItemType.NOUN and res.value == "ГОРОДОК"): 
            if (MiscLocationHelper.is_user_param_address(res)): 
                return None
        if ((res.typ != CityItemToken.ItemType.NOUN and res.end_token.next0_ is not None and res.end_token.next0_.is_char('(')) and (res.whitespaces_after_count < 3)): 
            br = BracketHelper.try_parse(res.end_token.next0_, BracketParseAttr.NO, 100)
            if (br is not None and br.end_token.next0_ is not None and (br.whitespaces_after_count < 3)): 
                nn = CityItemToken.try_parse(br.end_token.next0_, res, False, None)
                if (nn is not None and nn.typ == CityItemToken.ItemType.NOUN): 
                    li = CityItemToken.try_parse_list(br.begin_token.next0_, 3, ad)
                    if ((li is not None and len(li) == 2 and li[0].typ != CityItemToken.ItemType.NOUN) and li[1].typ == CityItemToken.ItemType.NOUN and li[1].end_token.next0_ == br.end_token): 
                        res.orto_city = CityAttachHelper.try_define(li, ad, True)
                        res.end_token = br.end_token
        if (res is not None and ((res.typ == CityItemToken.ItemType.CITY or res.typ == CityItemToken.ItemType.PROPERNAME)) and MiscLocationHelper.is_user_param_address(res)): 
            tt = res.end_token.next0_
            if (tt is not None and tt.is_hiphen and (isinstance(tt.next0_, NumberToken))): 
                res.end_token = tt.next0_
                res.value = "{0}-{1}".format((res.onto_item.canonic_text if res.onto_item is not None else res.value), res.end_token.value)
                res.typ = CityItemToken.ItemType.PROPERNAME
                res.onto_item = (None)
            else: 
                nt = None
                if (tt is not None and tt.is_hiphen): 
                    nt = NumberHelper.try_parse_roman(tt.next0_)
                elif ((res.whitespaces_after_count < 3) and tt is not None and tt.chars.is_latin_letter): 
                    nt = NumberHelper.try_parse_roman(tt)
                if (nt is not None): 
                    res.end_token = nt.end_token
                    res.value = "{0}-{1}".format((res.onto_item.canonic_text if res.onto_item is not None else res.value), nt.value)
                    res.typ = CityItemToken.ItemType.PROPERNAME
                    res.onto_item = (None)
        return res
    
    @staticmethod
    def __try_parse_int(t : 'Token', prev : 'CityItemToken', dont_normalize : bool, ad : 'GeoAnalyzerData') -> 'CityItemToken':
        from pullenti.ner.geo.internal.NameToken import NameToken
        from pullenti.ner.geo.internal.OrgItemToken import OrgItemToken
        if (t is None or (((isinstance(t, TextToken)) and not t.chars.is_letter))): 
            return None
        res = CityItemToken.__try_parse(t, prev, dont_normalize, ad)
        if ((prev is None and t.chars.is_cyrillic_letter and t.chars.is_all_upper) and t.length_char == 2): 
            if (t.is_value("ТА", None)): 
                res = CityItemToken.__try_parse(t.next0_, prev, dont_normalize, ad)
                if (res is not None): 
                    if (res.typ == CityItemToken.ItemType.NOUN): 
                        res.begin_token = t
                        res.doubtful = False
                    else: 
                        res = (None)
        if (prev is not None and prev.typ == CityItemToken.ItemType.NOUN and ((prev.value != "ГОРОД" and prev.value != "МІСТО"))): 
            if (res is None): 
                det = OrgItemToken.try_parse(t, None)
                if (det is not None): 
                    cou = 0
                    ttt = det.begin_token
                    while ttt is not None and ttt.end_char <= det.end_char: 
                        if (ttt.chars.is_letter): 
                            cou += 1
                        ttt = ttt.next0_
                    if (cou < 6): 
                        re = CityItemToken._new1501(det.begin_token, det.end_token, CityItemToken.ItemType.PROPERNAME)
                        if (det.referent.type_name == "ORGANIZATION"): 
                            re.org_ref = (det)
                        else: 
                            re.value = MiscHelper.get_text_value_of_meta_token(det, GetTextAttr.NO)
                            re.alt_value = MiscHelper.get_text_value_of_meta_token(det, GetTextAttr.FIRSTNOUNGROUPTONOMINATIVE)
                        return re
                if ((isinstance(t, NumberToken)) and (t.whitespaces_after_count < 2)): 
                    next0__ = CityItemToken.__try_parse(t.next0_, prev, dont_normalize, ad)
                    if ((next0__ is not None and next0__.typ == CityItemToken.ItemType.PROPERNAME and next0__.value is not None) and next0__.end_token.next0_ is not None): 
                        ok = False
                        if (next0__.end_token.next0_.is_comma): 
                            ok = True
                        elif (AddressItemToken.check_street_after(next0__.end_token.next0_, False)): 
                            ok = True
                        if (ok): 
                            next0__.begin_token = t
                            next0__.value = "{0}-{1}".format(next0__.value, t.value)
                            if (next0__.alt_value is not None): 
                                next0__.alt_value = "{0}-{1}".format(next0__.alt_value, t.value)
                            res = next0__
        if (res is not None and res.typ == CityItemToken.ItemType.NOUN and (res.whitespaces_after_count < 3)): 
            npt = MiscLocationHelper._try_parse_npt(res.end_token.next0_)
            if (npt is not None): 
                if (npt.end_token.is_value("ПОДЧИНЕНИЕ", "ПІДПОРЯДКУВАННЯ")): 
                    res.end_token = npt.end_token
            if (res.value == "НАСЕЛЕННЫЙ ПУНКТ"): 
                next0__ = CityItemToken.__try_parse(res.end_token.next0_, prev, dont_normalize, ad)
                if (next0__ is not None and next0__.typ == CityItemToken.ItemType.NOUN): 
                    next0__.begin_token = res.begin_token
                    return next0__
        if (res is not None and t.chars.is_all_upper and res.typ == CityItemToken.ItemType.PROPERNAME): 
            tt = t.previous
            if (tt is not None and tt.is_comma): 
                tt = tt.previous
            geo_prev = None
            if (tt is not None and (isinstance(tt.get_referent(), GeoReferent))): 
                geo_prev = (Utils.asObjectOrNull(tt.get_referent(), GeoReferent))
            if (geo_prev is not None and ((geo_prev.is_region or geo_prev.is_city))): 
                det = OrgItemToken.try_parse(t, None)
                if (det is not None): 
                    res = (None)
        if (res is not None and res.typ == CityItemToken.ItemType.PROPERNAME): 
            if ((t.is_value("ДУМА", "РАДА") or t.is_value("ГЛАВА", "ГОЛОВА") or t.is_value("АДМИНИСТРАЦИЯ", "АДМІНІСТРАЦІЯ")) or t.is_value("МЭР", "МЕР") or t.is_value("ПРЕДСЕДАТЕЛЬ", "ГОЛОВА")): 
                return None
        if (res is not None and res.value == "НАСЕЛЕННЫЙ ПУНКТ" and (res.whitespaces_after_count < 2)): 
            s = StreetItemToken.try_parse(res.end_token.next0_, None, False, None)
            if (s is not None and s.typ == StreetItemType.NOUN and s.termin.canonic_text == "ПОЧТОВОЕ ОТДЕЛЕНИЕ"): 
                res.end_token = s.end_token
        if (res is not None and res.typ == CityItemToken.ItemType.PROPERNAME and res.begin_token == res.end_token): 
            end = MiscLocationHelper.check_name_long(res)
            if (end is not None): 
                if (CityItemToken.check_keyword(end) is None): 
                    res.end_token = end
                    res.value = MiscHelper.get_text_value(res.begin_token, end, GetTextAttr.NO)
                    res.alt_value = (None)
        geo_after = None
        if (res is None): 
            if (BracketHelper.can_be_start_of_sequence(t, True, False)): 
                br = BracketHelper.try_parse(t, BracketParseAttr.NO, 100)
                if (br is not None): 
                    res = CityItemToken.__try_parse(t.next0_, None, False, ad)
                    if (res is not None and ((res.typ == CityItemToken.ItemType.PROPERNAME or res.typ == CityItemToken.ItemType.CITY))): 
                        res.begin_token = t
                        res.typ = CityItemToken.ItemType.PROPERNAME
                        res.end_token = br.end_token
                        if (res.end_token.next0_ != br.end_token): 
                            res.value = MiscHelper.get_text_value(t, br.end_token, GetTextAttr.NO)
                            res.alt_value = (None)
                        return res
            if (isinstance(t, TextToken)): 
                txt = t.term
                if (txt == "НЕТ"): 
                    return None
                if (txt == "ИМ" or txt == "ИМЕНИ"): 
                    t1 = t.next0_
                    if (t1 is not None and t1.is_char('.')): 
                        t1 = t1.next0_
                    if (t1 is None): 
                        return None
                    nnn = CityItemToken._new1501(t1, t1, CityItemToken.ItemType.NOUN)
                    res = CityItemToken.try_parse(t1, nnn, False, ad)
                    if (res is not None and ((((res.typ == CityItemToken.ItemType.CITY and res.doubtful)) or res.typ == CityItemToken.ItemType.PROPERNAME))): 
                        res.begin_token = t
                        res.morph = MorphCollection()
                        return res
                if (t.chars.is_cyrillic_letter and t.length_char == 1 and t.chars.is_all_upper): 
                    if ((t.next0_ is not None and not t.is_whitespace_after and ((t.next0_.is_hiphen or t.next0_.is_char('.')))) and (t.next0_.whitespaces_after_count < 2)): 
                        if (prev is not None and prev.typ == CityItemToken.ItemType.NOUN and (((not prev.doubtful or prev.geo_object_before or MiscLocationHelper.check_geo_object_before(prev.begin_token, False)) or MiscLocationHelper.check_geo_object_before_brief(prev.begin_token, ad)))): 
                            res1 = CityItemToken.__try_parse(t.next0_.next0_, None, False, ad)
                            if (res1 is not None and ((res1.typ == CityItemToken.ItemType.PROPERNAME or res1.typ == CityItemToken.ItemType.CITY))): 
                                if (res1.value == "ГОРЬКОГО" or res1.value == "ЛЕНИНА"): 
                                    res1.begin_token = t
                                    return res1
                                adjs = MiscLocationHelper.get_std_adj_full_str(txt, res1.morph.gender, res1.morph.number, True)
                                if (adjs is None and prev is not None and prev.typ == CityItemToken.ItemType.NOUN): 
                                    adjs = MiscLocationHelper.get_std_adj_full_str(txt, prev.morph.gender, MorphNumber.UNDEFINED, True)
                                if (adjs is None): 
                                    adjs = MiscLocationHelper.get_std_adj_full_str(txt, res1.morph.gender, res1.morph.number, False)
                                if (adjs is not None): 
                                    if (res1.value is None): 
                                        res1.value = res1.get_source_text().upper()
                                    if (res1.alt_value is not None): 
                                        res1.alt_value = "{0} {1}".format(adjs[0], res1.alt_value)
                                    elif (len(adjs) > 1): 
                                        res1.alt_value = "{0} {1}".format(adjs[1], res1.value)
                                    res1.value = "{0} {1}".format(adjs[0], res1.value)
                                    res1.begin_token = t
                                    res1.typ = CityItemToken.ItemType.PROPERNAME
                                    return res1
            tt = (t.previous if prev is None else prev.begin_token.previous)
            while tt is not None and tt.is_char_of(",."):
                tt = tt.previous
            geo_prev = None
            if (tt is not None and (isinstance(tt.get_referent(), GeoReferent))): 
                geo_prev = (Utils.asObjectOrNull(tt.get_referent(), GeoReferent))
            cond = None
            tt0 = t
            ooo = False
            has_geo_after = False
            if (geo_prev is not None): 
                ooo = True
            elif (MiscLocationHelper.check_near_before(t, ad) is not None): 
                ooo = True
            elif (MiscLocationHelper.check_geo_object_before(t, False)): 
                ooo = True
            elif (t.chars.is_letter): 
                tt = t.next0_
                if (tt is not None and tt.is_char('.')): 
                    tt = tt.next0_
                if ((isinstance(tt, TextToken)) and not tt.chars.is_all_lower): 
                    if (MiscLocationHelper.check_geo_object_after_brief(tt, ad)): 
                        has_geo_after = True
                        ooo = has_geo_after
                    elif (MiscLocationHelper.check_geo_object_after(tt, True, False)): 
                        has_geo_after = True
                        ooo = has_geo_after
                    elif (AddressItemToken.check_street_after(tt.next0_, False)): 
                        ooo = True
                    elif (ad.clevel == 0): 
                        cit2 = CityItemToken.try_parse(tt, None, False, ad)
                        if (cit2 is not None and cit2.begin_token != cit2.end_token and ((cit2.typ == CityItemToken.ItemType.PROPERNAME or cit2.typ == CityItemToken.ItemType.CITY))): 
                            if (AddressItemToken.check_street_after(cit2.end_token.next0_, False)): 
                                ooo = True
                        if (cit2 is not None and cit2.typ == CityItemToken.ItemType.CITY and tt.previous.is_char('.')): 
                            if (cit2.is_whitespace_after or ((cit2.end_token.next0_ is not None and cit2.end_token.next0_.length_char == 1))): 
                                ooo = True
                                if (cit2.onto_item is not None): 
                                    geo_after = (Utils.asObjectOrNull(cit2.onto_item.referent, GeoReferent))
            if ((ad is not None and not ooo and not ad.cregime) and CityItemToken.SPEED_REGIME): 
                if (cond is None): 
                    cond = Condition()
                cond.geo_before_token = t
                ooo = True
            if (ooo): 
                tt = t
                ttt = tt
                first_pass4128 = True
                while True:
                    if first_pass4128: first_pass4128 = False
                    else: ttt = ttt.next0_
                    if (not (ttt is not None)): break
                    if (ttt.is_char_of(",.")): 
                        tt = ttt.next0_
                        continue
                    if (ttt.is_newline_before): 
                        break
                    det = AddressItemToken.try_parse_pure_item(ttt, None, ad)
                    if (det is not None and ttt.is_value("У", None) and MiscLocationHelper.is_user_param_address(ttt)): 
                        det = (None)
                    if (det is not None and det.typ == AddressItemType.DETAIL): 
                        ttt = det.end_token
                        tt0 = det.end_token.next0_
                        tt = tt0
                        continue
                    org0_ = OrgItemToken.try_parse(ttt, None)
                    if (org0_ is not None and org0_.is_gsk): 
                        ttt = org0_.end_token
                        tt = org0_.end_token.next0_
                        tt0 = tt
                        continue
                    ait = AddressItemToken.try_parse_pure_item(ttt, None, None)
                    if (ait is not None and ait.typ == AddressItemType.PLOT): 
                        ttt = ait.end_token
                        tt = ait.end_token.next0_
                        tt0 = tt
                        continue
                    break
                if (isinstance(tt, TextToken)): 
                    dd = Utils.asObjectOrNull(tt.tag, GeoTokenData)
                    if (dd is not None and dd.no_city): 
                        return None
                    if (tt0.is_comma and tt0.next0_ is not None): 
                        tt0 = tt0.next0_
                    txt = Utils.ifNotNull(tt.term, "")
                    if (((txt == "Д" or txt == "С" or txt == "C") or txt == "П" or txt == "Х") or ((((txt == "А" or txt == "У")) and MiscLocationHelper.is_user_param_address(tt)))): 
                        if (tt.chars.is_all_lower or MiscLocationHelper.is_user_param_address(tt) or ((tt.next0_ is not None and tt.next0_.is_char_of(".,")))): 
                            ttt = tt.previous
                            while ttt is not None: 
                                if (StreetItemToken.check_keyword(ttt)): 
                                    return None
                                if (ttt.is_value("ИМЕНИ", None) or ttt.is_value("ИМ", None)): 
                                    return None
                                if (ttt.length_char > 1): 
                                    break
                                ttt = ttt.previous
                            if (NameToken.check_initial(tt) is not None): 
                                return None
                            if (tt.chars.is_all_upper): 
                                tt3 = tt.next0_
                                if (tt3 is not None and tt3.is_char('.')): 
                                    tt3 = tt3.next0_
                                sits = StreetItemToken.try_parse_list(tt3, 3, ad)
                                if (sits is not None and len(sits) == 2 and sits[1].typ == StreetItemType.NOUN): 
                                    return None
                                if (AddressItemToken.try_parse_pure_item(tt.previous, None, None) is not None): 
                                    return None
                            if (txt == "Д" or txt == "С"): 
                                tt22 = tt.next0_
                                if (tt22 is not None and tt22.is_char('.')): 
                                    tt22 = tt22.next0_
                                hou = AddressItemToken.try_parse_pure_item(tt22, None, ad)
                                if ((hou is not None and hou.typ == AddressItemType.NUMBER and not Utils.isNullOrEmpty(hou.value)) and str.isdigit(hou.value[0])): 
                                    nam = CityItemToken.try_parse(hou.end_token.next0_, None, False, None)
                                    if (nam is None or nam.typ != CityItemToken.ItemType.PROPERNAME): 
                                        pass
                                    else: 
                                        tt3 = nam.end_token.next0_
                                        if (tt3 is not None and tt3.is_comma): 
                                            tt3 = tt3.next0_
                                        ok2 = False
                                        li2 = AddressItemToken.try_parse_list(tt3, 3)
                                        if (li2 is None or len(li2) == 0): 
                                            pass
                                        elif (li2[0].typ == AddressItemType.HOUSE or li2[0].typ == AddressItemType.PLOT): 
                                            ok2 = True
                                        elif (len(li2) > 1 and li2[0].typ == AddressItemType.STREET and ((li2[1].typ == AddressItemType.HOUSE or li2[1].typ == AddressItemType.PLOT))): 
                                            ok2 = True
                                        if (ok2): 
                                            res = CityItemToken._new1520(tt, tt, CityItemToken.ItemType.NOUN, ("ДЕРЕВНЯ" if txt == "Д" else "СЕЛО"))
                                            if (tt.next0_ is not None and tt.next0_.is_char('.')): 
                                                res.end_token = tt.next0_
                                            return res
                                    return None
                            if (txt == "А" or txt == "С"): 
                                if (tt.is_newline_after and not MiscLocationHelper.is_user_param_address(tt)): 
                                    return None
                                ait = AddressItemToken.try_parse_pure_item(tt.next0_, None, ad)
                                if (ait is not None): 
                                    return None
                                st = StreetItemToken.try_parse(tt, None, False, None)
                                if (st is not None and st.typ == StreetItemType.NOUN): 
                                    return None
                                if (tt.next0_ is not None): 
                                    if (tt.next0_.is_value("ЗАКОН", None) or tt.next0_.is_value("ПОСТАНОВЛЕНИЕ", None)): 
                                        return None
                            if (txt == "У"): 
                                if (tt.whitespaces_after_count > 2): 
                                    return None
                                next0__ = CityItemToken.try_parse(tt.next0_, None, False, None)
                                if (next0__ is not None and next0__.typ == CityItemToken.ItemType.NOUN): 
                                    return None
                                ait = AddressItemToken.try_parse_pure_item(tt.next0_, None, None)
                                if (ait is not None): 
                                    return None
                            tokn = NameToken.M_ONTO.try_parse(tt, TerminParseAttr.NO)
                            if (tokn is not None): 
                                return CityItemToken._new1520(tt, tokn.end_token, CityItemToken.ItemType.PROPERNAME, tokn.termin.canonic_text)
                            tt1 = tt
                            if (tt1.next0_ is not None and tt1.next0_.is_char_of(",.")): 
                                tt1 = tt1.next0_
                            elif (txt == "С" and tt1.next0_ is not None and ((tt1.next0_.morph.case_.is_instrumental or tt1.next0_.morph.case_.is_genitive))): 
                                if (not (isinstance(tt1.next0_, TextToken))): 
                                    return None
                                if (MiscLocationHelper.is_user_param_address(tt1)): 
                                    pass
                                else: 
                                    if (not tt.chars.is_all_lower or not tt1.next0_.chars.is_capital_upper): 
                                        return None
                                    if (tt1.next0_.is_newline_after): 
                                        pass
                                    elif (AddressItemToken.check_street_after(tt1.next0_.next0_, False)): 
                                        pass
                                    else: 
                                        return None
                            tt2 = tt1.next0_
                            if ((tt2 is not None and tt2.length_char == 1 and tt2.chars.is_cyrillic_letter) and tt2.chars.is_all_upper): 
                                if (tt2.next0_ is not None and ((tt2.next0_.is_char('.') or tt2.next0_.is_hiphen)) and not tt2.is_whitespace_after): 
                                    if (tt.chars.is_all_upper): 
                                        return None
                                    tt2 = tt2.next0_.next0_
                            else: 
                                while tt2 is not None and tt2.is_comma:
                                    tt2 = tt2.next0_
                            ok = False
                            if ((txt == "Д" and (isinstance(tt2, NumberToken)) and not tt2.is_newline_before) and not tt2.previous.is_comma): 
                                ok = False
                            elif (((txt == "С" or txt == "C")) and (isinstance(tt2, TextToken)) and ((tt2.is_value("О", None) or tt2.is_value("O", None)))): 
                                ok = False
                            elif (tt2 is None or tt2.is_value("ДОМ", None)): 
                                ok = True
                            elif ((tt2.is_char(')') and t.previous is not None and t.previous.is_char('(')) and MiscLocationHelper.is_user_param_address(t)): 
                                ok = True
                            elif (tt2.is_hiphen and tt2.previous is not None and tt2.previous.is_comma): 
                                ok = True
                            elif (not tt2.chars.is_cyrillic_letter and (isinstance(tt2, TextToken))): 
                                ok = False
                            elif (tt2.is_newline_before and tt2.previous.is_comma): 
                                ok = True
                            elif (tt2.chars.is_capital_upper and (tt2.whitespaces_before_count < 2)): 
                                ok = tt.chars.is_all_lower
                                if (not ok and MiscLocationHelper.is_user_param_address(tt)): 
                                    ok = True
                            elif (AddressItemToken.check_street_after(tt2, False)): 
                                ok = True
                            elif (AddressItemToken.check_house_after(tt2, False, True)): 
                                ok = True
                            elif (tt2.chars.is_all_upper and (tt2.whitespaces_before_count < 2)): 
                                ok = True
                                if (tt.chars.is_all_upper): 
                                    rtt = tt.kit.process_referent("PERSON", tt, None)
                                    if (rtt is not None): 
                                        ok = False
                                        ttt2 = rtt.end_token.next0_
                                        if (ttt2 is not None and ttt2.is_comma): 
                                            ttt2 = ttt2.next0_
                                        if (AddressItemToken.check_house_after(ttt2, False, False) or AddressItemToken.check_street_after(ttt2, False)): 
                                            ok = True
                                        else: 
                                            tli = TerrItemToken.try_parse_list(ttt2, 3, None)
                                            if (tli is not None and len(tli) == 2): 
                                                if (tli[0].termin_item is not None or tli[1].termin_item is not None): 
                                                    ok = True
                                    elif (tt.previous is not None and tt.previous.is_char('.')): 
                                        ok = False
                                elif (tt1 == tt): 
                                    ok = False
                                if (not ok and tt1.next0_ is not None): 
                                    ttt2 = tt1.next0_.next0_
                                    if (MiscLocationHelper.is_user_param_address(tt)): 
                                        noun = CityItemToken._new1520(tt, tt, CityItemToken.ItemType.NOUN, "СЕЛО")
                                        nam = CityItemToken.__try_parse_int(tt1.next0_, noun, True, ad)
                                        if (nam is not None and nam.typ == CityItemToken.ItemType.PROPERNAME): 
                                            ttt2 = nam.end_token.next0_
                                        if (ttt2 is None or ttt2.is_newline_after or ttt2.is_comma): 
                                            ok = True
                                    if (ttt2 is not None and ttt2.is_comma): 
                                        ttt2 = ttt2.next0_
                                    if (AddressItemToken.check_house_after(ttt2, False, False) or AddressItemToken.check_street_after(ttt2, False)): 
                                        if (OrgItemToken.try_parse(tt1.next0_, None) is not None): 
                                            pass
                                        else: 
                                            ok = True
                            elif ((isinstance(tt2, NumberToken)) and tt2.previous.is_comma): 
                                ok = True
                            elif (prev is not None and prev.typ == CityItemToken.ItemType.PROPERNAME and (tt.whitespaces_before_count < 2)): 
                                if (MiscLocationHelper.check_geo_object_before(prev.begin_token.previous, False)): 
                                    ok = True
                                if (txt == "П" and tt.next0_ is not None and ((tt.next0_.is_hiphen or tt.next0_.is_char_of("\\/")))): 
                                    sit = StreetItemToken.try_parse(tt, None, False, None)
                                    if (sit is not None and sit.typ == StreetItemType.NOUN): 
                                        ok = False
                            elif (prev is None): 
                                if (MiscLocationHelper.check_geo_object_before(tt.previous, False)): 
                                    if (tt1.is_newline_after): 
                                        pass
                                    else: 
                                        ok = True
                                elif (geo_after is not None or has_geo_after): 
                                    ok = True
                                elif (MiscLocationHelper.is_user_param_address(tt)): 
                                    ok = True
                            if (tt.previous is not None and tt.previous.is_hiphen and not tt.is_whitespace_before): 
                                if (tt.next0_ is not None and tt.next0_.is_char('.')): 
                                    pass
                                else: 
                                    ok = False
                            if (ok): 
                                ii = 0
                                ttt = t.previous
                                while ttt is not None and (ii < 4): 
                                    oo = OrgItemToken.try_parse(ttt, None)
                                    if (oo is not None and oo.end_char > tt.end_char): 
                                        ok = False
                                    ttt = ttt.previous; ii += 1
                            if (ok): 
                                res = CityItemToken._new1501(tt0, tt1, CityItemToken.ItemType.NOUN)
                                if (tt1.is_comma): 
                                    res.end_token = tt1.previous
                                if (txt == "У"): 
                                    res.value = "УЛУС"
                                else: 
                                    res.value = ("ДЕРЕВНЯ" if txt == "Д" else (("ПОСЕЛОК" if txt == "П" else (("ХУТОР" if txt == "Х" else ("АУЛ" if txt == "А" else ("ГОРОД" if txt == "Г" else "СЕЛО")))))))
                                if (txt == "П"): 
                                    res.alt_value = "ПОСЕЛЕНИЕ"
                                elif (txt == "С" or txt == "C"): 
                                    res.alt_value = "СЕЛЕНИЕ"
                                    if (tt0 == tt1 and not MiscLocationHelper.is_user_param_address(tt0)): 
                                        npt = NounPhraseHelper.try_parse(tt1.next0_, NounPhraseParseAttr.PARSEPRONOUNS, 0, None)
                                        if (npt is not None and npt.morph.case_.is_instrumental): 
                                            return None
                                res.doubtful = True
                                return res
                    if ((txt == "СП" or txt == "РП" or txt == "ГП") or txt == "ДП"): 
                        if (tt.next0_ is not None and tt.next0_.is_char('.')): 
                            tt = tt.next0_
                        if (tt.next0_ is not None and tt.next0_.chars.is_capital_upper): 
                            return CityItemToken._new1528(tt0, tt, CityItemToken.ItemType.NOUN, True, Condition._new1527(t), ("РАБОЧИЙ ПОСЕЛОК" if txt == "РП" else (("ГОРОДСКОЕ ПОСЕЛЕНИЕ" if txt == "ГП" else (("ДАЧНЫЙ ПОСЕЛОК" if txt == "ДП" else "СЕЛЬСКОЕ ПОСЕЛЕНИЕ"))))))
                    if (tt0 != tt and CityItemToken.check_keyword(tt) is not None): 
                        res = CityItemToken.try_parse(tt, None, False, ad)
                        if (res is not None and res.typ == CityItemToken.ItemType.NOUN): 
                            res.geo_object_before = True
                            res.begin_token = tt0
                            return res
                    if (tt.chars.is_all_upper and tt.length_char > 2 and tt.chars.is_cyrillic_letter): 
                        return CityItemToken._new1520(tt, tt, CityItemToken.ItemType.PROPERNAME, tt.term)
            if ((isinstance(t, NumberToken)) and t.next0_ is not None): 
                net = NumberHelper.try_parse_number_with_postfix(t)
                if (net is not None and net.ex_typ == NumberExType.KILOMETER): 
                    return CityItemToken._new1520(t, net.end_token, CityItemToken.ItemType.PROPERNAME, "{0}КМ".format(math.floor(net.real_value)))
            rt = Utils.asObjectOrNull(t, ReferentToken)
            if ((rt is not None and (isinstance(rt.referent, GeoReferent)) and rt.begin_token == rt.end_token) and rt.referent.is_state): 
                if (t.previous is None): 
                    return None
                if (t.previous.morph.number == MorphNumber.SINGULAR and t.morph.case_.is_nominative and not t.morph.case_.is_genitive): 
                    return CityItemToken._new1520(t, t, CityItemToken.ItemType.PROPERNAME, rt.get_source_text().upper())
            return None
        if (res.typ == CityItemToken.ItemType.NOUN): 
            if (res.value == "СЕЛО" and (isinstance(t, TextToken))): 
                if (t.previous is None): 
                    pass
                elif (t.previous.morph.class0_.is_preposition): 
                    pass
                else: 
                    res.doubtful = True
                res.morph.gender = MorphGender.NEUTER
            if (not res.chars.is_all_lower and ((res.value == "ХУТОР" or res.value == "СЛОБОДА"))): 
                res.can_be_name = True
            if (res.value == "СТАНЦИЯ" or res.value == "СТАНЦІЯ"): 
                res.doubtful = True
            if (res.end_token.is_value("СТОЛИЦА", None) or res.end_token.is_value("СТОЛИЦЯ", None)): 
                res.doubtful = True
                if (res.end_token.next0_ is not None): 
                    geo_ = Utils.asObjectOrNull(res.end_token.next0_.get_referent(), GeoReferent)
                    if (geo_ is not None and ((geo_.is_region or geo_.is_state))): 
                        res.higher_geo = geo_
                        res.end_token = res.end_token.next0_
                        res.doubtful = False
                        res.value = "ГОРОД"
                        for it in TerrItemToken._m_capitals_by_state.termins: 
                            ge = Utils.asObjectOrNull(it.tag, GeoReferent)
                            if (ge is None or not ge.can_be_equals(geo_, ReferentsEqualType.WITHINONETEXT)): 
                                continue
                            tok = TerrItemToken._m_capitals_by_state.try_parse(res.end_token.next0_, TerminParseAttr.NO)
                            if (tok is not None and tok.termin == it): 
                                break
                            res.typ = CityItemToken.ItemType.CITY
                            res.value = it.canonic_text
                            return res
            if ((res.begin_token.length_char == 1 and res.begin_token.chars.is_all_upper and res.begin_token.next0_ is not None) and res.begin_token.next0_.is_char('.')): 
                ne = CityItemToken.__try_parse_int(res.begin_token.next0_.next0_, (res if res.value == "ГОРОД" else None), False, ad)
                if (ne is not None and ne.typ == CityItemToken.ItemType.CITY and ((not ne.doubtful or not res.doubtful or MiscLocationHelper.is_user_param_address(ne)))): 
                    pass
                elif (ne is not None and ne.typ == CityItemToken.ItemType.PROPERNAME and AddressItemToken.check_street_after(ne.end_token.next0_, False)): 
                    pass
                elif (ne is not None and ne.typ == CityItemToken.ItemType.NOUN and ne.end_token == res.end_token): 
                    pass
                elif (ne is None or ne.typ != CityItemToken.ItemType.PROPERNAME): 
                    return None
                elif (MiscLocationHelper.check_geo_object_after(ne.end_token.next0_, False, True)): 
                    pass
                elif (res.begin_token.previous is not None and res.begin_token.previous.is_value("В", None)): 
                    pass
                elif ((ne is not None and ne.typ == CityItemToken.ItemType.PROPERNAME and MiscLocationHelper.is_user_param_address(ne)) and ((ne.end_token.is_newline_after or ne.end_token.next0_.is_comma or ne.chars.is_all_upper))): 
                    tt = t.previous
                    while tt is not None: 
                        if (tt.is_newline_after): 
                            break
                        if (TerrItemToken.check_keyword(tt) is not None or TerrItemToken.check_onto_item(tt) is not None): 
                            return res
                        tt = tt.previous
                    return None
                else: 
                    return None
        if (res.typ == CityItemToken.ItemType.PROPERNAME or res.typ == CityItemToken.ItemType.CITY or res.can_be_name): 
            val = Utils.ifNotNull(res.value, ((None if res.onto_item is None else res.onto_item.canonic_text)))
            t1 = res.end_token
            num = None
            if ((not t1.is_whitespace_after and t1.next0_ is not None and t1.next0_.is_hiphen) and not t1.next0_.is_whitespace_after): 
                if ((isinstance(t1.next0_.next0_, NumberToken)) and t1.next0_.next0_.int_value is not None and (t1.next0_.next0_.int_value < 30)): 
                    num = (Utils.asObjectOrNull(t1.next0_.next0_, NumberToken))
                elif (isinstance(t1.next0_.next0_, TextToken)): 
                    num = NumberHelper.try_parse_roman(t1.next0_.next0_)
            if (num is not None): 
                res.end_token = (num.end_token if num.typ == NumberSpellingType.ROMAN else num)
                res.value = "{0}-{1}".format(val, num.value)
                if (res.alt_value is not None): 
                    res.alt_value = "{0}-{1}".format(res.alt_value, num.value)
                res.typ = CityItemToken.ItemType.PROPERNAME
                res.onto_item = (None)
            elif (t1.whitespaces_after_count == 1 and (isinstance(t1.next0_, NumberToken)) and t1.next0_.morph.class0_.is_adjective): 
                ok = False
                if (t1.next0_.next0_ is None or t1.next0_.is_newline_after): 
                    ok = True
                elif (not t1.next0_.is_whitespace_after and t1.next0_.next0_ is not None and t1.next0_.next0_.is_char_of(",")): 
                    ok = True
                elif (StreetItemToken.check_keyword(t1.next0_.next0_) and t1.whitespaces_after_count <= t1.next0_.whitespaces_after_count): 
                    if (AddressItemToken.check_street_after(t1.next0_.next0_, False)): 
                        ok = True
                elif (AddressItemToken.check_house_after(t1.next0_.next0_, False, False)): 
                    ok = True
                elif (MiscLocationHelper.check_geo_object_after_brief(t1.next0_, None)): 
                    ok = True
                if (ok): 
                    res.end_token = t1.next0_
                    res.value = "{0}-{1}".format(val, t1.next0_.value)
                    if (res.alt_value is not None): 
                        res.alt_value = "{0}-{1}".format(res.alt_value, t1.next0_.value)
                    res.typ = CityItemToken.ItemType.PROPERNAME
        if (((res.typ == CityItemToken.ItemType.CITY or res.can_be_name)) and res.begin_token == res.end_token): 
            if (res.begin_token.get_morph_class_in_dictionary().is_adjective and (isinstance(res.end_token.next0_, TextToken))): 
                ok = False
                t1 = None
                npt = MiscLocationHelper._try_parse_npt(res.begin_token)
                if (npt is not None and npt.end_token == res.end_token.next0_): 
                    t1 = npt.end_token
                    mc = t1.get_morph_class_in_dictionary()
                    if (mc.is_noun): 
                        if (res.end_token.next0_.chars.equals(res.begin_token.chars)): 
                            ok = True
                            if (res.begin_token.chars.is_all_upper): 
                                cii = CityItemToken.__try_parse_int(res.end_token.next0_, None, dont_normalize, ad)
                                if (cii is not None and cii.typ == CityItemToken.ItemType.NOUN): 
                                    ok = False
                        elif (res.end_token.next0_.chars.is_all_lower): 
                            ttt = res.end_token.next0_.next0_
                            if (ttt is None or ttt.is_char_of(",.")): 
                                ok = True
                elif (res.end_token.next0_.chars.equals(res.begin_token.chars) and res.begin_token.chars.is_capital_upper): 
                    ttt = res.end_token.next0_.next0_
                    if (ttt is None or ttt.is_char_of(",.")): 
                        ok = True
                    t1 = res.end_token.next0_
                    npt = (None)
                if (ok and t1 is not None): 
                    res.typ = CityItemToken.ItemType.PROPERNAME
                    res.onto_item = (None)
                    res.end_token = t1
                    if (npt is not None): 
                        res.value = npt.get_normal_case_text(None, MorphNumber.UNDEFINED, MorphGender.UNDEFINED, False)
                        res.morph = npt.morph
                    else: 
                        res.value = MiscHelper.get_text_value(res.begin_token, res.end_token, GetTextAttr.NO)
            if ((res.end_token.next0_ is not None and res.end_token.next0_.is_hiphen and not res.end_token.next0_.is_whitespace_after) and not res.end_token.next0_.is_whitespace_before): 
                res1 = CityItemToken.__try_parse(res.end_token.next0_.next0_, None, False, ad)
                if ((res1 is not None and res1.typ == CityItemToken.ItemType.PROPERNAME and res1.begin_token == res1.end_token) and res1.begin_token.chars.equals(res.begin_token.chars)): 
                    if (res1.onto_item is None and res.onto_item is None): 
                        res.typ = CityItemToken.ItemType.PROPERNAME
                        res.value = "{0}-{1}".format((res.value if res.onto_item is None else res.onto_item.canonic_text), res1.value)
                        if (res.alt_value is not None): 
                            res.alt_value = "{0}-{1}".format(res.alt_value, res1.value)
                        res.onto_item = (None)
                        res.end_token = res1.end_token
                        res.doubtful = False
                elif ((isinstance(res.end_token.next0_.next0_, NumberToken)) and res.end_token.next0_.next0_.int_value is not None and (res.end_token.next0_.next0_.int_value < 30)): 
                    res.typ = CityItemToken.ItemType.PROPERNAME
                    res.value = "{0}-{1}".format((res.value if res.onto_item is None else res.onto_item.canonic_text), res.end_token.next0_.next0_.value)
                    if (res.alt_value is not None): 
                        res.alt_value = "{0}-{1}".format(res.alt_value, res.end_token.next0_.next0_.value)
                    res.onto_item = (None)
                    res.end_token = res.end_token.next0_.next0_
            elif (res.begin_token.get_morph_class_in_dictionary().is_proper_name): 
                if (res.begin_token.is_value("КИЇВ", None) or res.begin_token.is_value("АСТАНА", None) or res.begin_token.is_value("АЛМАТЫ", None)): 
                    pass
                elif ((isinstance(res.end_token, TextToken)) and LanguageHelper.ends_with(res.end_token.term, "ВО")): 
                    pass
                else: 
                    res.doubtful = True
                    tt = res.begin_token.previous
                    if (tt is not None and tt.previous is not None): 
                        if (tt.is_char(',') or tt.morph.class0_.is_conjunction): 
                            geo_ = Utils.asObjectOrNull(tt.previous.get_referent(), GeoReferent)
                            if (geo_ is not None and geo_.is_city): 
                                res.doubtful = False
                    if (tt is not None and tt.is_value("В", None) and tt.chars.is_all_lower): 
                        npt1 = MiscLocationHelper._try_parse_npt(res.begin_token)
                        if (npt1 is None or npt1.end_char <= res.end_char): 
                            res.doubtful = False
            if ((res.begin_token == res.end_token and res.typ == CityItemToken.ItemType.CITY and res.onto_item is not None) and res.onto_item.canonic_text == "САНКТ - ПЕТЕРБУРГ"): 
                tt = res.begin_token.previous
                first_pass4129 = True
                while True:
                    if first_pass4129: first_pass4129 = False
                    else: tt = tt.previous
                    if (not (tt is not None)): break
                    if (tt.is_hiphen or tt.is_char('.')): 
                        continue
                    if (tt.is_value("С", None) or tt.is_value("C", None) or tt.is_value("САНКТ", None)): 
                        res.begin_token = tt
                    break
        return res
    
    @staticmethod
    def __try_parse(t : 'Token', prev : 'CityItemToken', dont_normalize : bool, ad : 'GeoAnalyzerData') -> 'CityItemToken':
        from pullenti.ner.geo.internal.OrgItemToken import OrgItemToken
        from pullenti.ner.geo.internal.CityAttachHelper import CityAttachHelper
        from pullenti.ner.geo.internal.NameToken import NameToken
        from pullenti.ner.geo.internal.TerrDefineHelper import TerrDefineHelper
        if (not (isinstance(t, TextToken))): 
            if ((isinstance(t, ReferentToken)) and (isinstance(t.get_referent(), DateReferent))): 
                aii = StreetItemToken._try_parse_spec(t, None)
                if (aii is not None): 
                    if (len(aii) > 1 and aii[0].typ == StreetItemType.NUMBER and aii[1].typ == StreetItemType.STDNAME): 
                        res2 = CityItemToken._new1501(t, aii[1].end_token, CityItemToken.ItemType.PROPERNAME)
                        res2.value = "{0} {1}".format(aii[0].value, aii[1].value)
                        return res2
            if ((((isinstance(t, NumberToken)) and prev is not None and prev.typ == CityItemToken.ItemType.NOUN) and (t.whitespaces_before_count < 3) and (t.whitespaces_after_count < 3)) and (isinstance(t.next0_, TextToken)) and t.next0_.chars.is_capital_upper): 
                if (prev.begin_token.is_value("СТ", None) or prev.begin_token.is_value("П", None)): 
                    return None
                cit1 = CityItemToken.try_parse(t.next0_, None, False, ad)
                if (cit1 is not None and cit1.typ == CityItemToken.ItemType.PROPERNAME and cit1.value is not None): 
                    cit1.begin_token = t
                    cit1.value = "{0}-{1}".format(cit1.value, t.value)
                    return cit1
            if ((isinstance(t, NumberToken)) and t.typ != NumberSpellingType.DIGIT and MiscLocationHelper.is_user_param_address(t)): 
                return CityItemToken._new1520(t, t, CityItemToken.ItemType.PROPERNAME, t.value)
            return None
        spec = CityItemToken.__try_parse_spec(t)
        if (spec is not None): 
            return spec
        li = None
        li0 = None
        is_in_loc_onto = False
        if (t.kit.ontology is not None and li is None): 
            li0 = t.kit.ontology.attach_token(GeoReferent.OBJ_TYPENAME, t)
            if ((li0) is not None): 
                li = li0
                is_in_loc_onto = True
        if (li is None): 
            li = CityItemToken.M_ONTOLOGY.try_attach(t, None, False)
            if (li is None): 
                li = CityItemToken.M_ONTOLOGY_EX.try_attach(t, None, False)
            elif (len(li) == 1 and li[0].begin_token != li[0].end_token and li[0].begin_token.next0_.is_comma): 
                li = (None)
        elif (prev is None): 
            stri = StreetItemToken.try_parse(t.previous, None, False, ad)
            if (stri is not None and stri.typ == StreetItemType.NOUN): 
                return None
            stri = StreetItemToken.try_parse(li[0].end_token.next0_, None, False, ad)
            if (stri is not None and stri.typ == StreetItemType.NOUN): 
                return None
        if ((li is None and (isinstance(t, TextToken)) and not t.term.endswith("О")) and ((t.next0_ is None or ((not t.next0_.is_hiphen and not t.next0_.is_value("ПОСАД", None)))))): 
            if (t.is_value("ИМ", None) or t.is_value("ИМЕНИ", None) or ((t.get_morph_class_in_dictionary().is_proper_name and MiscLocationHelper.is_user_param_address(t) and not t.is_value("ВЛАДИМИР", None)))): 
                nam = NameToken.try_parse(t, GeoTokenType.CITY, 0, False)
                if (nam is not None and nam.end_token != t): 
                    if (t.get_morph_class_in_dictionary().is_proper_name): 
                        ters = TerrItemToken.try_parse_list(t.next0_, 5, None)
                        if (ters is not None): 
                            ttt = TerrDefineHelper.try_define(ters, ad, False, None, None)
                            if (ttt is not None): 
                                nam = (None)
                    if (nam is not None): 
                        res1 = CityItemToken._new1520(t, nam.end_token, CityItemToken.ItemType.PROPERNAME, nam.name)
                        if (nam.misc_typ is not None): 
                            res1.misc = nam.misc_typ
                        return res1
        if (li is None and (isinstance(t, TextToken)) and t.is_value("КР", None)): 
            tt2 = t.next0_
            if (tt2 is not None and ((tt2.is_char('.') or tt2.is_hiphen))): 
                tt2 = tt2.next0_
            next0__ = CityItemToken.__try_parse_int(tt2, prev, dont_normalize, ad)
            if (next0__ is not None and next0__.typ == CityItemToken.ItemType.PROPERNAME): 
                next0__.begin_token = t
                next0__.value = ("КРАСНЫЙ " + next0__.value)
                return next0__
        if (li is not None and len(li) > 0): 
            if (isinstance(t, TextToken)): 
                for i in range(len(li) - 1, -1, -1):
                    if (li[i].item is not None): 
                        if (li[i].begin_token.is_value("ЛЮКСЕМБУРГ", None)): 
                            if (MiscLocationHelper.is_user_param_address(li[i])): 
                                del li[i]
                                continue
                            if (li[i].begin_token.previous is not None and li[i].begin_token.previous.is_value("РОЗА", None)): 
                                del li[i]
                                continue
                        if (li[i].begin_token.is_value("ГРОЗНЫЙ", None)): 
                            if (li[i].begin_token.previous is not None and ((li[i].begin_token.previous.is_value("ИВАН", None) or li[i].begin_token.previous.is_value("ЦАРЬ", None)))): 
                                del li[i]
                                continue
                        if ((li[i].begin_token == li[i].end_token and (isinstance(li[i].begin_token, TextToken)) and li[i].begin_token.term != li[i].item.canonic_text) and MiscLocationHelper.is_user_param_address(li[i])): 
                            if (li[i].begin_token.term.startswith("НН")): 
                                pass
                            else: 
                                del li[i]
                                continue
                        if (((li[i].begin_token == li[i].end_token and not li[i].is_whitespace_after and li[i].end_token.next0_ is not None) and li[i].end_token.next0_.is_hiphen and li[i].end_token.next0_.next0_ is not None) and li[i].end_token.next0_.next0_.is_value("НА", None)): 
                            del li[i]
                            continue
                        g = Utils.asObjectOrNull(li[i].item.referent, GeoReferent)
                        if (g is None): 
                            continue
                        if (not g.is_city): 
                            del li[i]
                            continue
                tt = Utils.asObjectOrNull(t, TextToken)
                for nt in li: 
                    if (nt.item is not None and nt.item.canonic_text == tt.term): 
                        if (MiscLocationHelper.is_user_param_address(nt) or MiscLocationHelper.is_user_param_quiry(nt) or not MiscHelper.is_all_characters_lower(nt.begin_token, nt.end_token, False)): 
                            ci = CityItemToken._new1535(nt.begin_token, nt.end_token, CityItemToken.ItemType.CITY, nt.item, nt.morph)
                            if (nt.begin_token == nt.end_token and not is_in_loc_onto): 
                                ci.doubtful = CityItemToken.__check_doubtful(Utils.asObjectOrNull(nt.begin_token, TextToken))
                            tt1 = nt.end_token.next0_
                            if ((((tt1 is not None and tt1.is_hiphen and not tt1.is_whitespace_before) and not tt1.is_whitespace_after and prev is not None) and prev.typ == CityItemToken.ItemType.NOUN and (isinstance(tt1.next0_, TextToken))) and tt1.previous.chars.equals(tt1.next0_.chars)): 
                                li = (None)
                                break
                            return ci
                if (li is not None): 
                    for nt in li: 
                        if (nt.item is not None): 
                            if (not MiscHelper.is_all_characters_lower(nt.begin_token, nt.end_token, False) or ((prev is not None and prev.typ == CityItemToken.ItemType.NOUN))): 
                                ci = CityItemToken._new1535(nt.begin_token, nt.end_token, CityItemToken.ItemType.CITY, nt.item, nt.morph)
                                if (nt.begin_token == nt.end_token and (isinstance(nt.begin_token, TextToken))): 
                                    ci.doubtful = CityItemToken.__check_doubtful(Utils.asObjectOrNull(nt.begin_token, TextToken))
                                    str0_ = nt.begin_token.term
                                    if (str0_ != nt.item.canonic_text): 
                                        if (LanguageHelper.ends_with_ex(str0_, "О", "А", None, None)): 
                                            ci.alt_value = str0_
                                return ci
            if (li is not None): 
                for nt in li: 
                    if (nt.item is None): 
                        ty = (CityItemToken.ItemType.NOUN if nt.termin.tag is None else Utils.valToEnum(nt.termin.tag, CityItemToken.ItemType))
                        ci = CityItemToken._new1537(nt.begin_token, nt.end_token, ty, nt.morph)
                        ci.value = nt.termin.canonic_text
                        if (ci.value == "СТАНЦИЯ" and t.previous is not None): 
                            if (t.previous.is_value("НЕФТЕПЕРЕКАЧИВАЮЩАЯ", None)): 
                                return None
                        if (ty == CityItemToken.ItemType.MISC and ci.value == "ЖИТЕЛЬ" and t.previous is not None): 
                            if (t.previous.is_value("МЕСТНЫЙ", "МІСЦЕВИЙ")): 
                                return None
                            if (t.previous.morph.class0_.is_pronoun): 
                                return None
                        if (ty == CityItemToken.ItemType.NOUN and t.is_value("СТ", None) and nt.end_token.next0_ is not None): 
                            if (nt.end_token.next0_.is_value("РАЗИН", None)): 
                                return None
                        if (ty == CityItemToken.ItemType.NOUN and not t.chars.is_all_lower): 
                            if (t.morph.class0_.is_proper_surname): 
                                ci.doubtful = True
                        if (t.is_value("ДЕР", None)): 
                            if (t.previous is not None and t.previous.is_value("ФОН", None)): 
                                return None
                        if ((prev is not None and prev.typ == CityItemToken.ItemType.NOUN and (isinstance(t, TextToken))) and t.is_value("СЕЛО", None) and not t.chars.is_all_lower): 
                            if (MiscLocationHelper.is_user_param_address(t)): 
                                return CityItemToken._new1520(t, t, CityItemToken.ItemType.PROPERNAME, t.term)
                        if (nt.begin_token == nt.end_token): 
                            if (t.is_value("СТ", None)): 
                                if (OrgItemToken.try_parse(t, None) is not None): 
                                    return None
                        if (nt.begin_token.kit.base_language.is_ua): 
                            if (nt.begin_token.is_value("М", None) or nt.begin_token.is_value("Г", None)): 
                                if (not nt.begin_token.chars.is_all_lower): 
                                    return None
                                ci.doubtful = True
                            elif (nt.begin_token.is_value("МІС", None)): 
                                if (t.term != "МІС"): 
                                    return None
                                ci.doubtful = True
                        if (nt.begin_token.kit.base_language.is_ru): 
                            if (nt.begin_token.is_value("Г", None)): 
                                ci.doubtful = True
                                if (NameToken.check_initial_and_surname("Г", nt.end_token.next0_)): 
                                    return None
                                if (nt.is_newline_before): 
                                    pass
                                elif (nt.begin_token.previous is not None and nt.begin_token.previous.morph.class0_.is_preposition): 
                                    pass
                                else: 
                                    ok = True
                                    if (not nt.begin_token.chars.is_all_lower and not MiscLocationHelper.is_user_param_address(nt)): 
                                        ok = False
                                        next0__ = CityItemToken.try_parse(nt.end_token.next0_, ci, False, None)
                                        if (next0__ is not None and next0__.typ == CityItemToken.ItemType.CITY): 
                                            if (nt.length_char == 1 and not nt.is_whitespace_before and (isinstance(t.previous, NumberToken))): 
                                                return None
                                            if (next0__.begin_token.get_morph_class_in_dictionary().is_proper_surname): 
                                                pass
                                            else: 
                                                ok = True
                                                ci.doubtful = False
                                    elif ((nt.end_token == nt.begin_token and nt.end_token.next0_ is not None and not nt.end_token.is_whitespace_after) and ((nt.end_token.next0_.is_char_of("\\/") or nt.end_token.next0_.is_hiphen))): 
                                        ok = False
                                    elif (not t.is_whitespace_before and t.previous is not None and ((t.previous.is_char_of("\\/") or t.previous.is_hiphen))): 
                                        return None
                                    elif (t.previous is not None and StreetItemToken.check_keyword(t.previous)): 
                                        if (AddressItemToken.check_street_after(t.previous, False)): 
                                            return None
                                    if (not ok): 
                                        nex = CityItemToken.try_parse(nt.end_token.next0_, None, False, None)
                                        if (nex is not None and nex.typ == CityItemToken.ItemType.CITY and (nt.end_token.whitespaces_after_count < 4)): 
                                            pass
                                        elif (nt.end_token.next0_ is not None and AddressItemToken.check_street_after(nt.end_token.next0_.next0_, False)): 
                                            pass
                                        else: 
                                            if (nex is None or nex.typ != CityItemToken.ItemType.PROPERNAME): 
                                                return None
                                            if (AddressItemToken.check_street_after(nex.end_token.next0_, False)): 
                                                pass
                                            elif (MiscLocationHelper.check_geo_object_after(nex.end_token, False, True)): 
                                                pass
                                            else: 
                                                return None
                            elif (nt.begin_token.is_value("ГОР", None)): 
                                if (t.term != "ГОР"): 
                                    if (t.chars.is_capital_upper): 
                                        ci = (None)
                                        break
                                    return None
                                ci.doubtful = True
                            elif (nt.begin_token.is_value("ПОС", None)): 
                                if (t.term != "ПОС"): 
                                    return None
                                ci.doubtful = True
                                ci.alt_value = "ПОСЕЛЕНИЕ"
                        npt1 = MiscLocationHelper._try_parse_npt(t.previous)
                        if (npt1 is not None and len(npt1.adjectives) > 0): 
                            s = npt1.adjectives[0].get_normal_case_text(None, MorphNumber.UNDEFINED, MorphGender.UNDEFINED, False)
                            if ((s == "РОДНОЙ" or s == "ЛЮБИМЫЙ" or s == "РІДНИЙ") or s == "КОХАНИЙ"): 
                                return None
                        if (t.is_value("ПОСЕЛЕНИЕ", None)): 
                            if (t.next0_ is not None and t.next0_.is_value("СТАНЦИЯ", None)): 
                                ci1 = CityItemToken.try_parse(t.next0_.next0_, None, False, None)
                                if (ci1 is not None and ((ci1.typ == CityItemToken.ItemType.PROPERNAME or ci1.typ == CityItemToken.ItemType.CITY))): 
                                    ci.end_token = t.next0_
                                    ci.alt_value = "СТАНЦИЯ"
                        if (ci.end_token.next0_ is not None and ci.end_token.next0_.is_char('.')): 
                            if (ci.length_char < 3): 
                                ci.end_token = ci.end_token.next0_
                            elif (t.previous is not None and t.previous.is_comma and MiscLocationHelper.is_user_param_address(t)): 
                                ci.end_token = ci.end_token.next0_
                        return ci
        if (not (isinstance(t, TextToken))): 
            return None
        if (t.term == "СПБ" and not t.chars.is_all_lower and CityItemToken.M_ST_PETERBURG is not None): 
            return CityItemToken._new1539(t, t, CityItemToken.ItemType.CITY, CityItemToken.M_ST_PETERBURG, CityItemToken.M_ST_PETERBURG.canonic_text)
        if (t.term == "НЕТ"): 
            return None
        if (t.is_value("МУНИЦИПАЛЬНЫЙ", None)): 
            return None
        if (t.chars.is_all_lower): 
            if (t.length_char < 4): 
                return None
            if (not MiscLocationHelper.is_user_param_address(t)): 
                return None
            if (StreetItemToken.check_keyword(t) or t.is_value("УЧАСТОК", None) or t.is_value("ДОМ", None)): 
                return None
            if (t.is_newline_before or t.is_newline_after): 
                return None
            if (t.previous is not None and t.previous.is_comma): 
                pass
            elif (prev is not None and prev.typ == CityItemToken.ItemType.NOUN): 
                pass
            ait = AddressItemToken.try_parse_pure_item(t, None, None)
            if (ait is not None): 
                if (ait.typ == AddressItemType.DETAIL): 
                    return None
        if (MiscLocationHelper.check_territory(t) is not None): 
            return None
        stds = CityItemToken.M_STD_ADJECTIVES.try_attach(t, None, False)
        if (stds is not None): 
            cit = CityItemToken.try_parse(stds[0].end_token.next0_, None, False, ad)
            if (cit is not None and ((((cit.typ == CityItemToken.ItemType.PROPERNAME and cit.value is not None)) or cit.typ == CityItemToken.ItemType.CITY))): 
                adj = stds[0].termin.canonic_text
                if (stds[0].end_token.is_value(adj, None) or MiscLocationHelper.is_user_param_address(t)): 
                    adj = MiscHelper.get_text_value_of_meta_token(stds[0], GetTextAttr.NO)
                cit.value = "{0} {1}".format(adj, Utils.ifNotNull(cit.value, (cit.onto_item.canonic_text if cit is not None and cit.onto_item is not None else None)))
                if (cit.alt_value is not None): 
                    cit.alt_value = "{0} {1}".format(adj, cit.alt_value)
                cit.begin_token = t
                cit.onto_item = (None)
                npt0 = MiscLocationHelper._try_parse_npt(t)
                if (npt0 is not None and npt0.end_token == cit.end_token): 
                    if (npt0.end_token.morph.contains_attr("кач.прил.", None) or MiscLocationHelper.is_user_param_address(t)): 
                        pass
                    else: 
                        cit.morph = npt0.morph
                        cit.alt_value = cit.value
                        cit.value = npt0.get_normal_case_text(None, MorphNumber.UNDEFINED, MorphGender.UNDEFINED, False)
                cit.typ = CityItemToken.ItemType.PROPERNAME
                cit.doubtful = False
                return cit
        t1 = t
        doubt = False
        if (t.morph.contains_attr("к.ф.", None)): 
            ptok = NameToken.M_PREF_ONTO.try_parse(t, TerminParseAttr.NO)
            if (ptok is not None): 
                tt = ptok.end_token.next0_
                if (tt is not None and tt.is_hiphen): 
                    tt = tt.next0_
                next0__ = CityItemToken.try_parse(tt, prev, dont_normalize, ad)
                if (next0__ is not None and ((next0__.typ == CityItemToken.ItemType.CITY or next0__.typ == CityItemToken.ItemType.PROPERNAME)) and next0__.begin_token == next0__.end_token): 
                    if (next0__.value is None): 
                        next0__.value = MiscHelper.get_text_value_of_meta_token(next0__, GetTextAttr.NO)
                    next0__.value = "{0}{1}".format(ptok.termin.canonic_text, next0__.value)
                    next0__.onto_item = (None)
                    next0__.begin_token = t
                    return next0__
        name = io.StringIO()
        altname = None
        k = 0
        is_prep = False
        tt = t
        while tt is not None: 
            if (not (isinstance(tt, TextToken))): 
                break
            if (not tt.chars.is_letter or ((tt.chars.is_cyrillic_letter != t.chars.is_cyrillic_letter and not tt.is_value("НА", None)))): 
                break
            if (tt != t): 
                si = StreetItemToken.try_parse(tt, None, False, None)
                if (si is not None and si.typ == StreetItemType.NOUN): 
                    if (si.end_token.next0_ is None or si.end_token.next0_.is_char_of(",.")): 
                        pass
                    else: 
                        break
                if (tt.length_char < 2): 
                    break
                if ((tt.length_char < 3) and not tt.is_value("НА", None)): 
                    if (tt.is_whitespace_before): 
                        break
            if (name.tell() > 0): 
                print('-', end="", file=name)
                if (altname is not None): 
                    print('-', end="", file=altname)
            if ((isinstance(tt, TextToken)) and ((is_prep or ((k > 0 and not tt.get_morph_class_in_dictionary().is_proper_geo))))): 
                print(tt.term, end="", file=name)
                if (altname is not None): 
                    print(tt.term, end="", file=altname)
            else: 
                ss = (tt.term if dont_normalize else CityItemToken.__get_normal_geo(tt))
                if (ss == "ПОЛ" and tt.is_value("ПОЛЕ", None)): 
                    ss = "ПОЛЕ"
                if (ss != tt.term): 
                    if (altname is None): 
                        altname = io.StringIO()
                    print(Utils.toStringStringIO(name), end="", file=altname)
                    print(tt.term, end="", file=altname)
                elif (altname is not None): 
                    print(ss, end="", file=altname)
                print(ss, end="", file=name)
            t1 = tt
            is_prep = tt.morph.class0_.is_preposition
            if (tt.next0_ is None or tt.next0_.next0_ is None): 
                break
            if (not tt.next0_.is_hiphen): 
                if (tt.next0_.is_value("ИМ", None) or tt.next0_.is_value("ИМЕНИ", None)): 
                    nam0 = NameToken.try_parse(tt.next0_, GeoTokenType.CITY, 0, False)
                    if (nam0 is not None and nam0.name is not None): 
                        print(" {0}".format(nam0.name), end="", file=name, flush=True)
                        tt = nam0.end_token
                        t1 = tt
                        break
                break
            if (dont_normalize): 
                break
            if (tt.is_whitespace_after or tt.next0_.is_whitespace_after): 
                if (tt.whitespaces_after_count > 1 or tt.next0_.whitespaces_after_count > 1): 
                    break
                if (not tt.next0_.next0_.chars.equals(tt.chars)): 
                    break
                ttt = tt.next0_.next0_.next0_
                if (ttt is not None and not ttt.is_newline_after): 
                    if (ttt.chars.is_letter): 
                        break
            kw = CityItemToken.check_keyword(tt.next0_.next0_)
            if (kw is not None): 
                if (kw.is_newline_after or kw.end_token.next0_ is None or kw.end_token.next0_.is_comma): 
                    pass
                else: 
                    break
            tt = tt.next0_
            k += 1
            tt = tt.next0_
        if (k > 0): 
            if (k > 2): 
                return None
            if (name.tell() < 2): 
                return None
            ww = 0
            nw = 0
            ii = 0
            while ii < name.tell(): 
                if (LanguageHelper.is_cyrillic_vowel(Utils.getCharAtStringIO(name, ii)) or LanguageHelper.is_latin_vowel(Utils.getCharAtStringIO(name, ii))): 
                    ww += 1
                else: 
                    nw += 1
                ii += 1
            if (nw == 0 or ww == 0): 
                return None
            reee = CityItemToken._new1519(t, t1, CityItemToken.ItemType.PROPERNAME, Utils.toStringStringIO(name), doubt)
            if (altname is not None): 
                reee.alt_value = Utils.toStringStringIO(altname)
            return reee
        if (t is None): 
            return None
        npt = (None if t.chars.is_latin_letter else NounPhraseHelper.try_parse(t, NounPhraseParseAttr.REFERENTCANBENOUN, 0, None))
        if (npt is not None and (isinstance(npt.end_token, ReferentToken)) and npt.end_token.begin_token != npt.end_token.end_token): 
            npt = (None)
        if (npt is not None and len(npt.adjectives) > 1): 
            npt = (None)
        if (npt is not None and npt.begin_token == npt.end_token): 
            npt = (None)
        if (npt is not None): 
            mc = npt.end_token.get_morph_class_in_dictionary()
            if (MiscLocationHelper.is_user_param_gar_address(npt)): 
                pass
            elif (mc.is_noun): 
                if (CityItemToken.check_keyword(npt.end_token) is not None): 
                    npt = (None)
            elif (not mc.is_undefined): 
                npt = (None)
            elif (npt.end_token.morph.class0_.is_proper_surname): 
                npt = (None)
            elif (AddressItemToken.check_street_after(npt.end_token, False)): 
                npt = (None)
        if (npt is not None): 
            ttt = npt.begin_token
            while ttt.end_char < npt.end_char: 
                if (ttt.is_newline_after): 
                    npt = (None)
                    break
                ttt = ttt.next0_
        if ((npt is not None and npt.end_token != t and len(npt.adjectives) > 0) and not npt.adjectives[0].end_token.next0_.is_comma): 
            cit = CityItemToken.try_parse(t.next0_, None, False, None)
            if (cit is not None and cit.typ == CityItemToken.ItemType.NOUN and ((LanguageHelper.ends_with_ex(cit.value, "ПУНКТ", "ПОСЕЛЕНИЕ", "ПОСЕЛЕННЯ", "ПОСЕЛОК") or t.next0_.is_value("ГОРОДОК", None) or t.next0_.is_value("СЕЛО", None)))): 
                ok2 = False
                mc = t.get_morph_class_in_dictionary()
                if (not mc.is_adjective): 
                    ok2 = True
                elif (not MiscHelper.can_be_start_of_sentence(t)): 
                    ok2 = True
                elif (MiscLocationHelper.check_geo_object_before(t, False)): 
                    ok2 = True
                if (ok2): 
                    return CityItemToken._new1541(t, t, CityItemToken.ItemType.CITY, t.get_normal_case_text(None, MorphNumber.UNDEFINED, MorphGender.UNDEFINED, False), npt.morph)
            check_ = True
            if (not npt.end_token.chars.equals(t.chars)): 
                if (npt.end_token.is_value("КИЛОМЕТР", None)): 
                    npt = (None)
                elif (OrgItemToken.try_parse(t.next0_, None) is not None): 
                    npt = (None)
                elif (npt.end_token.chars.is_all_lower and ((npt.end_token.next0_ is None or npt.end_token.next0_.is_comma or AddressItemToken.check_street_after(npt.end_token.next0_, False)))): 
                    pass
                else: 
                    aid = AddressItemToken.try_parse(t.next0_, False, None, None)
                    if (aid is not None): 
                        npt = (None)
                    elif (prev is not None and prev.typ == CityItemToken.ItemType.NOUN and CityAttachHelper.check_city_after(t.next0_)): 
                        check_ = False
                    else: 
                        rt1 = t.kit.process_referent("NAMEDENTITY", t, None)
                        if (rt1 is not None and rt1.end_token == npt.end_token): 
                            pass
                        else: 
                            ttt2 = npt.end_token.next0_
                            if (ttt2 is not None and ttt2.is_comma): 
                                ttt2 = ttt2.next0_
                            tli = TerrItemToken.try_parse_list(ttt2, 3, None)
                            if (tli is not None and len(tli) >= 2 and ((tli[0].termin_item is not None or tli[1].termin_item is not None))): 
                                pass
                            else: 
                                npt = (None)
            if (check_ and not dont_normalize and npt is not None): 
                org1 = OrgItemToken.try_parse(t.next0_, None)
                if (org1 is not None and not org1.is_doubt): 
                    org0 = OrgItemToken.try_parse(t, None)
                    if (org0 is not None and org0.is_doubt): 
                        npt = (None)
            if (check_ and not dont_normalize and npt is not None): 
                if (len(npt.adjectives) != 1): 
                    return None
                ter = TerrItemToken.check_onto_item(npt.noun.begin_token)
                if (ter is not None): 
                    npt = (None)
                elif (MiscLocationHelper.check_territory(npt.end_token) is not None): 
                    npt = (None)
                if (npt is not None): 
                    npt1 = MiscLocationHelper._try_parse_npt(npt.end_token)
                    if (npt1 is None or len(npt1.adjectives) == 0): 
                        si = StreetItemToken.try_parse(npt.end_token, None, False, None)
                        if ((si is None or si.typ != StreetItemType.NOUN or si.termin.canonic_text == "МОСТ") or si.termin.canonic_text == "ПАРК" or si.termin.canonic_text == "САД"): 
                            t1 = npt.end_token
                            doubt = CityItemToken.__check_doubtful(Utils.asObjectOrNull(t1, TextToken))
                            return CityItemToken._new1542(t, t1, CityItemToken.ItemType.PROPERNAME, npt.get_normal_case_text(None, MorphNumber.UNDEFINED, MorphGender.UNDEFINED, False), doubt, npt.morph)
        if (t.next0_ is not None and t.next0_.chars.equals(t.chars) and not t.is_newline_after): 
            ok = False
            if (TerrItemToken.check_onto_item(t.next0_) is not None): 
                pass
            elif (CityItemToken.check_keyword(t.next0_) is not None): 
                pass
            elif (t.next0_.next0_ is None or not t.next0_.next0_.chars.equals(t.chars)): 
                ok = True
            elif (isinstance(t.next0_.next0_.get_referent(), GeoReferent)): 
                ok = True
            else: 
                tis = TerrItemToken.try_parse_list(t.next0_.next0_, 2, None)
                if (tis is not None and len(tis) > 1): 
                    if (tis[0].is_adjective and tis[1].termin_item is not None): 
                        ok = True
            if (ok and (((isinstance(t.next0_, TextToken)) or (((isinstance(t.next0_, ReferentToken)) and t.next0_.begin_token == t.next0_.end_token))))): 
                if (isinstance(t.next0_, TextToken)): 
                    doubt = CityItemToken.__check_doubtful(Utils.asObjectOrNull(t.next0_, TextToken))
                stat = t.kit.statistics.get_bigramm_info(t, t.next0_)
                ok1 = False
                if ((stat is not None and stat.pair_count >= 2 and stat.pair_count == stat.second_count) and not stat.second_has_other_first): 
                    if (stat.pair_count > 2): 
                        doubt = False
                    ok1 = True
                elif (CityItemToken.M_STD_ADJECTIVES.try_attach(t, None, False) is not None and (isinstance(t.next0_, TextToken))): 
                    ok1 = True
                elif ((t.next0_.next0_ is not None and t.next0_.next0_.is_comma and t.morph.class0_.is_noun) and ((t.next0_.morph.class0_.is_adjective or t.next0_.morph.class0_.is_noun))): 
                    ok1 = True
                if (not ok1 and t.next0_.chars.value == t.chars.value): 
                    if (t.next0_.morph.case_.is_genitive or (((((LanguageHelper.ends_with(Utils.toStringStringIO(name), "ОВ") or LanguageHelper.ends_with(Utils.toStringStringIO(name), "ВО"))) and (isinstance(t.next0_, TextToken)) and not t.next0_.chars.is_all_lower) and t.next0_.length_char > 1 and not t.next0_.get_morph_class_in_dictionary().is_undefined))): 
                        if (MiscLocationHelper.check_geo_object_after(t.next0_, False, False)): 
                            ok1 = True
                        else: 
                            aid = AddressItemToken.try_parse(t.next0_.next0_, False, None, None)
                            if (aid is not None and not aid.is_doubt): 
                                if (aid.typ == AddressItemType.STREET or aid.typ == AddressItemType.PLOT or aid.typ == AddressItemType.HOUSE): 
                                    ok1 = True
                if (not ok1): 
                    if (AddressItemToken.check_street_after(t.next0_.next0_, False)): 
                        if (not AddressItemToken.check_street_after(t.next0_, False)): 
                            ok1 = True
                if (not ok1 and t.get_morph_class_in_dictionary().is_proper_name and MiscLocationHelper.is_user_param_address(t)): 
                    pp = t.kit.process_referent("PERSON", t, None)
                    if (pp is not None and pp.end_token != t and (isinstance(pp.end_token, TextToken))): 
                        if (TerrItemToken.check_keyword(pp.end_token.next0_) is None): 
                            return CityItemToken._new1543(t, pp.end_token, CityItemToken.ItemType.PROPERNAME, pp.end_token.term, MiscHelper.get_text_value_of_meta_token(pp, GetTextAttr.NO), pp.morph)
                if (ok1): 
                    tne = CityItemToken.__try_parse_int(t.next0_, None, False, ad)
                    if (tne is not None and tne.typ == CityItemToken.ItemType.NOUN): 
                        pass
                    else: 
                        if (isinstance(t.next0_, TextToken)): 
                            print(" {0}".format(t.next0_.term), end="", file=name, flush=True)
                            if (altname is not None): 
                                print(" {0}".format(t.next0_.term), end="", file=altname, flush=True)
                        else: 
                            print(" {0}".format(MiscHelper.get_text_value_of_meta_token(Utils.asObjectOrNull(t.next0_, ReferentToken), GetTextAttr.NO)), end="", file=name, flush=True)
                            if (altname is not None): 
                                print(" {0}".format(MiscHelper.get_text_value_of_meta_token(Utils.asObjectOrNull(t.next0_, ReferentToken), GetTextAttr.NO)), end="", file=altname, flush=True)
                        t1 = t.next0_
                        return CityItemToken._new1544(t, t1, CityItemToken.ItemType.PROPERNAME, Utils.toStringStringIO(name), (None if altname is None else Utils.toStringStringIO(altname)), doubt, t.next0_.morph)
        if (t.length_char < 2): 
            return None
        if (t1 is not None and t1.end_char > t.end_char): 
            t = t1
        else: 
            t1 = t
        doubt = CityItemToken.__check_doubtful(Utils.asObjectOrNull(t, TextToken))
        if (((t.next0_ is not None and prev is not None and prev.typ == CityItemToken.ItemType.NOUN) and t.next0_.chars.is_cyrillic_letter and t.next0_.chars.is_all_lower) and t.whitespaces_after_count == 1): 
            tt = t.next0_
            ok = False
            if (tt.next0_ is None or tt.next0_.is_char_of(",;")): 
                ok = True
                next0__ = CityItemToken.try_parse(tt, None, False, None)
                if (next0__ is not None and next0__.typ == CityItemToken.ItemType.NOUN): 
                    ok = False
            if (ok and AddressItemToken.try_parse(tt.next0_, False, None, None) is None): 
                t1 = tt
                print(" {0}".format(t1.get_source_text().upper()), end="", file=name, flush=True)
        if (MiscHelper.is_eng_article(t)): 
            return None
        if (StreetItemToken.check_keyword(t)): 
            if (AddressItemToken.check_street_after(t, False)): 
                if (prev is not None and prev.typ == CityItemToken.ItemType.NOUN and t.chars.is_capital_upper): 
                    pass
                else: 
                    return None
        res = CityItemToken._new1544(t, t1, CityItemToken.ItemType.PROPERNAME, Utils.toStringStringIO(name), (None if altname is None else Utils.toStringStringIO(altname)), doubt, t.morph)
        if (t1 == t and (isinstance(t1, TextToken)) and t1.term0 is not None): 
            res.alt_value = t1.term0
        sog = False
        glas = False
        for ch in res.value: 
            if (LanguageHelper.is_cyrillic_vowel(ch) or LanguageHelper.is_latin_vowel(ch)): 
                glas = True
            else: 
                sog = True
        if (t.chars.is_all_upper and t.length_char > 2): 
            if (not glas or not sog): 
                res.doubtful = True
        elif (not glas or not sog): 
            return None
        if (t == t1 and (isinstance(t, TextToken))): 
            if (t.term != res.value): 
                res.alt_value = t.term
        if ((res.whitespaces_after_count < 2) and (isinstance(res.end_token.next0_, TextToken))): 
            abbr = CityItemToken.M_SPEC_ABBRS.try_parse(res.end_token.next0_, TerminParseAttr.NO)
            if (abbr is not None): 
                res.end_token = abbr.end_token
                res.doubtful = False
                res.misc = abbr.termin.canonic_text
                abbr = CityItemToken.M_SPEC_ABBRS.try_parse(res.end_token.next0_, TerminParseAttr.NO)
                if (abbr is not None): 
                    res.misc2 = abbr.termin.canonic_text
                    res.end_token = abbr.end_token
            elif (not res.end_token.next0_.chars.is_all_lower): 
                abbr = CityItemToken.M_SPEC_ABBRS.try_parse(res.begin_token, TerminParseAttr.NO)
                if (abbr is not None and abbr.end_token == res.end_token): 
                    next0__ = CityItemToken.__try_parse_int(res.end_token.next0_, None, dont_normalize, ad)
                    if (next0__ is not None and ((next0__.typ == CityItemToken.ItemType.PROPERNAME or next0__.typ == CityItemToken.ItemType.CITY))): 
                        res.end_token = next0__.end_token
                        res.doubtful = False
                        res.value = next0__.value
                        res.alt_value = "{0} {1}".format(res.value, next0__.value)
        return res
    
    @staticmethod
    def __try_parse_spec(t : 'Token') -> 'CityItemToken':
        from pullenti.ner.geo.internal.OrgItemToken import OrgItemToken
        if (t is None): 
            return None
        org0_ = OrgItemToken.try_parse(t, None)
        if (org0_ is not None): 
            return CityItemToken._new1546(t, org0_.end_token, CityItemToken.ItemType.PROPERNAME, org0_)
        tok1 = CityItemToken.M_SPEC_NAMES.try_parse(t, TerminParseAttr.NO)
        if (tok1 is not None): 
            res = CityItemToken._new1520(t, tok1.end_token, CityItemToken.ItemType.PROPERNAME, tok1.termin.canonic_text)
            if ((t.length_char < len(res.value)) and (isinstance(t, TextToken)) and t == res.end_token): 
                res.alt_value = t.term
            return res
        tok1 = CityItemToken.M_SPEC_ABBRS.try_parse(t, TerminParseAttr.NO)
        if (tok1 is not None): 
            tt = tok1.end_token.next0_
            tok2 = CityItemToken.M_SPEC_ABBRS.try_parse(tt, TerminParseAttr.NO)
            if (tok2 is not None): 
                tt = tok2.end_token.next0_
            res = None
            if (BracketHelper.can_be_start_of_sequence(tt, True, False)): 
                br = BracketHelper.try_parse(tt, BracketParseAttr.NO, 100)
                if (br is not None): 
                    res = CityItemToken._new1501(t, br.end_token, CityItemToken.ItemType.PROPERNAME)
                    res.value = MiscHelper.get_text_value_of_meta_token(br, GetTextAttr.NO)
            elif (tt is not None): 
                tmp = CityItemToken._new1520(tt.previous, tt.previous, CityItemToken.ItemType.NOUN, "ГОРОД")
                cit = CityItemToken.try_parse(tt, tmp, False, None)
                if (cit is not None and ((cit.typ == CityItemToken.ItemType.PROPERNAME or cit.typ == CityItemToken.ItemType.CITY))): 
                    res = cit
            if (res is not None): 
                res.typ = CityItemToken.ItemType.PROPERNAME
                res.doubtful = False
                res.begin_token = t
                if (res.misc is None): 
                    res.misc = tok1.termin.canonic_text
                else: 
                    res.misc2 = tok1.termin.canonic_text
                if (tok2 is not None): 
                    res.misc2 = tok2.termin.canonic_text
                tok2 = CityItemToken.M_SPEC_NAMES.try_parse(res.end_token.next0_, TerminParseAttr.NO)
                if (tok2 is not None): 
                    res.misc2 = tok2.termin.canonic_text
                    res.end_token = tok2.end_token
                return res
        return None
    
    @staticmethod
    def try_parse_back(t : 'Token', only_noun : bool=False) -> 'CityItemToken':
        while t is not None and ((t.is_char_of("(,") or t.is_and)):
            t = t.previous
        if (not (isinstance(t, TextToken))): 
            return None
        cou = 0
        tt = t
        first_pass4130 = True
        while True:
            if first_pass4130: first_pass4130 = False
            else: tt = tt.previous
            if (not (tt is not None)): break
            if (not (isinstance(tt, TextToken))): 
                return None
            if (not tt.chars.is_letter): 
                continue
            if (only_noun): 
                vv = CityItemToken.check_keyword(tt)
                if (vv is not None and vv.end_token == t): 
                    return CityItemToken._new1520(tt, t, CityItemToken.ItemType.NOUN, vv.termin.canonic_text)
            else: 
                res = CityItemToken.try_parse(tt, None, False, None)
                if (res is not None and res.end_token == t): 
                    return res
            cou += 1
            if (cou > 2): 
                break
        return None
    
    @staticmethod
    def __get_normal_geo(t : 'Token') -> str:
        tt = Utils.asObjectOrNull(t, TextToken)
        if (tt is None): 
            return None
        ch = tt.term[len(tt.term) - 1]
        if (((ch == 'О' or ch == 'В' or ch == 'Ы') or ch == 'И' or ch == 'Х') or ch == 'Ь' or ch == 'Й'): 
            return tt.term
        for wf in tt.morph.items: 
            if (wf.class0_.is_proper_geo and wf.is_in_dictionary): 
                return wf.normal_case
        geo_eq_term = False
        for wf in tt.morph.items: 
            if (wf.class0_.is_proper_geo): 
                ggg = wf.normal_case
                if (ggg == tt.term): 
                    geo_eq_term = True
                elif (not wf.case_.is_nominative): 
                    return ggg
        if (geo_eq_term): 
            return tt.term
        if (tt.morph.items_count > 0): 
            return tt.morph.get_indexer_item(0).normal_case
        else: 
            return tt.term
    
    @staticmethod
    def __check_doubtful(tt : 'TextToken') -> bool:
        if (tt is None): 
            return True
        if (tt.chars.is_all_lower): 
            return True
        if (tt.length_char < 3): 
            return True
        if (((tt.term == "СОЧИ" or tt.is_value("КИЕВ", None) or tt.is_value("ПСКОВ", None)) or tt.is_value("БОСТОН", None) or tt.is_value("РИГА", None)) or tt.is_value("АСТАНА", None) or tt.is_value("АЛМАТЫ", None)): 
            return False
        if (LanguageHelper.ends_with(tt.term, "ВО")): 
            return False
        if (tt.is_value("ИВАНОВ", None)): 
            return True
        if ((isinstance(tt.next0_, TextToken)) and (tt.whitespaces_after_count < 2) and not tt.next0_.chars.is_all_lower): 
            if (tt.chars.equals(tt.next0_.chars) and not tt.chars.is_latin_letter and ((not tt.morph.case_.is_genitive and not tt.morph.case_.is_accusative))): 
                mc = tt.next0_.get_morph_class_in_dictionary()
                if (mc.is_proper_surname or mc.is_proper_secname): 
                    return True
        if ((isinstance(tt.previous, TextToken)) and (tt.whitespaces_before_count < 2) and not tt.previous.chars.is_all_lower): 
            mc = tt.previous.get_morph_class_in_dictionary()
            if (mc.is_proper_surname): 
                return True
        ok = False
        for wff in tt.morph.items: 
            wf = Utils.asObjectOrNull(wff, MorphWordForm)
            if (wf.is_in_dictionary): 
                if (not wf.class0_.is_proper): 
                    ok = True
                if (wf.class0_.is_proper_surname or wf.class0_.is_proper_name or wf.class0_.is_proper_secname): 
                    if (wf.normal_case != "ЛОНДОН" and wf.normal_case != "ЛОНДОНЕ"): 
                        ok = True
            elif (wf.class0_.is_proper_surname): 
                val = Utils.ifNotNull(wf.normal_full, Utils.ifNotNull(wf.normal_case, ""))
                if (LanguageHelper.ends_with_ex(val, "ОВ", "ЕВ", "ИН", None)): 
                    if (val != "БЕРЛИН"): 
                        if (tt.previous is not None and tt.previous.is_value("В", None)): 
                            pass
                        else: 
                            return True
        if (not ok): 
            return False
        t0 = tt.previous
        if (t0 is not None and ((t0.is_char(',') or t0.morph.class0_.is_conjunction))): 
            t0 = t0.previous
        if (t0 is not None and (isinstance(t0.get_referent(), GeoReferent))): 
            return False
        if (MiscLocationHelper.check_geo_object_after_brief(tt, None)): 
            return False
        return True
    
    @staticmethod
    def _new1501(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType') -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        return res
    
    @staticmethod
    def _new1519(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : str, _arg5 : bool) -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.value = _arg4
        res.doubtful = _arg5
        return res
    
    @staticmethod
    def _new1520(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : str) -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.value = _arg4
        return res
    
    @staticmethod
    def _new1528(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : bool, _arg5 : 'Condition', _arg6 : str) -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.doubtful = _arg4
        res._cond = _arg5
        res.value = _arg6
        return res
    
    @staticmethod
    def _new1535(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : 'IntOntologyItem', _arg5 : 'MorphCollection') -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.onto_item = _arg4
        res.morph = _arg5
        return res
    
    @staticmethod
    def _new1537(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : 'MorphCollection') -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.morph = _arg4
        return res
    
    @staticmethod
    def _new1539(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : 'IntOntologyItem', _arg5 : str) -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.onto_item = _arg4
        res.value = _arg5
        return res
    
    @staticmethod
    def _new1541(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : str, _arg5 : 'MorphCollection') -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.value = _arg4
        res.morph = _arg5
        return res
    
    @staticmethod
    def _new1542(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : str, _arg5 : bool, _arg6 : 'MorphCollection') -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.value = _arg4
        res.doubtful = _arg5
        res.morph = _arg6
        return res
    
    @staticmethod
    def _new1543(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : str, _arg5 : str, _arg6 : 'MorphCollection') -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.value = _arg4
        res.alt_value = _arg5
        res.morph = _arg6
        return res
    
    @staticmethod
    def _new1544(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : str, _arg5 : str, _arg6 : bool, _arg7 : 'MorphCollection') -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.value = _arg4
        res.alt_value = _arg5
        res.doubtful = _arg6
        res.morph = _arg7
        return res
    
    @staticmethod
    def _new1546(_arg1 : 'Token', _arg2 : 'Token', _arg3 : 'ItemType', _arg4 : 'ReferentToken') -> 'CityItemToken':
        res = CityItemToken(_arg1, _arg2)
        res.typ = _arg3
        res.org_ref = _arg4
        return res