/*
 * 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#.NET project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

const Utils = require("./../../../unisharp/Utils");
const StringBuilder = require("./../../../unisharp/StringBuilder");

const Referent = require("./../../Referent");
const ILTypes = require("./ILTypes");
const MetaToken = require("./../../MetaToken");
const LanguageHelper = require("./../../../morph/LanguageHelper");
const MiscHelper = require("./../../core/MiscHelper");
const Termin = require("./../../core/Termin");
const GeoReferent = require("./../../geo/GeoReferent");
const DecreeToken = require("./../../decree/internal/DecreeToken");
const InstrToken = require("./InstrToken");
const UriReferent = require("./../../uri/UriReferent");
const DecreeTokenItemType = require("./../../decree/internal/DecreeTokenItemType");
const DecreeReferent = require("./../../decree/DecreeReferent");
const TerminCollection = require("./../../core/TerminCollection");
const PersonPropertyReferent = require("./../../person/PersonPropertyReferent");
const PhoneReferent = require("./../../phone/PhoneReferent");
const BankDataReferent = require("./../../bank/BankDataReferent");
const InstrumentParticipantReferent = require("./../InstrumentParticipantReferent");
const InstrumentAnalyzer = require("./../InstrumentAnalyzer");
const MorphNumber = require("./../../../morph/MorphNumber");
const TerminParseAttr = require("./../../core/TerminParseAttr");
const NounPhraseParseAttr = require("./../../core/NounPhraseParseAttr");
const OrganizationReferent = require("./../../org/OrganizationReferent");
const ParticipantTokenKinds = require("./ParticipantTokenKinds");
const ReferentToken = require("./../../ReferentToken");
const NounPhraseHelper = require("./../../core/NounPhraseHelper");
const MorphGender = require("./../../../morph/MorphGender");
const MorphClass = require("./../../../morph/MorphClass");
const BracketParseAttr = require("./../../core/BracketParseAttr");
const TextToken = require("./../../TextToken");
const AddressReferent = require("./../../address/AddressReferent");
const PersonIdentityReferent = require("./../../person/PersonIdentityReferent");
const NumberToken = require("./../../NumberToken");
const PersonReferent = require("./../../person/PersonReferent");
const BracketHelper = require("./../../core/BracketHelper");

class ParticipantToken extends MetaToken {
    
    constructor(begin, end) {
        super(begin, end, null);
        this.typ = null;
        this.kind = ParticipantTokenKinds.UNDEFINED;
        this.parts = null;
    }
    
    toString() {
        let res = new StringBuilder();
        res.append(String(this.kind)).append(": ").append(((this.typ != null ? this.typ : "?")));
        if (this.parts !== null) {
            for (const p of this.parts) {
                res.append("; ").append(p.toStringEx(true, null, 0));
            }
        }
        return res.toString();
    }
    
    static tryAttach(t, p1 = null, p2 = null, isContract = false) {
        if (t === null) 
            return null;
        let tt = t;
        let br = false;
        if (p1 === null && p2 === null && isContract) {
            let r1 = t.getReferent();
            if ((r1 !== null && t.next !== null && t.next.isCommaAnd) && (t.next.next instanceof ReferentToken)) {
                let r2 = t.next.next.getReferent();
                if (r1.typeName === r2.typeName) {
                    let ttt = t.next.next.next;
                    let refs = new Array();
                    refs.push(r1);
                    refs.push(r2);
                    for (; ttt !== null; ttt = ttt.next) {
                        if ((ttt.isCommaAnd && ttt.next !== null && ttt.next.getReferent() !== null) && ttt.next.getReferent().typeName === r1.typeName) {
                            ttt = ttt.next;
                            if (!refs.includes(ttt.getReferent())) 
                                refs.push(ttt.getReferent());
                            continue;
                        }
                        break;
                    }
                    for (; ttt !== null; ttt = ttt.next) {
                        if (ttt.isComma || ttt.morph._class.isPreposition) 
                            continue;
                        if ((ttt.isValue("ИМЕНОВАТЬ", null) || ttt.isValue("ДАЛЬНЕЙШИЙ", null) || ttt.isValue("ДАЛЕЕ", null)) || ttt.isValue("ТЕКСТ", null)) 
                            continue;
                        if (ttt.isValue("ДОГОВАРИВАТЬСЯ", null)) 
                            continue;
                        let npt = NounPhraseHelper.tryParse(ttt, NounPhraseParseAttr.NO, 0, null);
                        if (npt !== null && npt.noun.isValue("СТОРОНА", null) && npt.morph.number !== MorphNumber.SINGULAR) {
                            let re = ParticipantToken._new2264(t, npt.endToken, ParticipantTokenKinds.NAMEDASPARTS);
                            re.parts = refs;
                            return re;
                        }
                        break;
                    }
                }
            }
            if ((r1 instanceof OrganizationReferent) || (r1 instanceof PersonReferent)) {
                let hasBr = false;
                let hasNamed = false;
                if (r1 instanceof PersonReferent) {
                    if (t.previous !== null && t.previous.isValue("ЛИЦО", null)) 
                        return null;
                }
                else if (t.previous !== null && ((t.previous.isValue("ВЫДАВАТЬ", null) || t.previous.isValue("ВЫДАТЬ", null)))) 
                    return null;
                for (let ttt = t.beginToken; ttt !== null && (ttt.endChar < t.endChar); ttt = ttt.next) {
                    if (ttt.isChar('(')) 
                        hasBr = true;
                    else if ((ttt.isValue("ИМЕНОВАТЬ", null) || ttt.isValue("ДАЛЬНЕЙШИЙ", null) || ttt.isValue("ДАЛЕЕ", null)) || ttt.isValue("ТЕКСТ", null)) 
                        hasNamed = true;
                    else if ((ttt.isComma || ttt.morph._class.isPreposition || ttt.isHiphen) || ttt.isChar(':')) {
                    }
                    else if (ttt instanceof ReferentToken) {
                    }
                    else if (hasBr || hasNamed) {
                        let npt = NounPhraseHelper.tryParse(ttt, NounPhraseParseAttr.REFERENTCANBENOUN, 0, null);
                        if (npt === null) 
                            break;
                        if (hasBr) {
                            if (npt.endToken.next === null || !npt.endToken.next.isChar(')')) 
                                break;
                        }
                        if (!hasNamed) {
                            if (ParticipantToken.m_Ontology.tryParse(ttt, TerminParseAttr.NO) === null) 
                                break;
                        }
                        let re = ParticipantToken._new2264(t, t, ParticipantTokenKinds.NAMEDAS);
                        re.typ = npt.getNormalCaseText(null, MorphNumber.SINGULAR, MorphGender.UNDEFINED, false);
                        re.parts = new Array();
                        re.parts.push(r1);
                        return re;
                    }
                }
                hasBr = false;
                hasNamed = false;
                let endSide = null;
                let brr = null;
                let addRefs = null;
                for (let ttt = t.next; ttt !== null; ttt = ttt.next) {
                    if ((ttt instanceof NumberToken) && (ttt.next instanceof TextToken) && ttt.next.term === "СТОРОНЫ") {
                        endSide = (ttt = ttt.next);
                        if (ttt.next !== null && ttt.next.isComma) 
                            ttt = ttt.next;
                        if (ttt.next !== null && ttt.next.isAnd) 
                            break;
                    }
                    if (brr !== null && ttt.beginChar > brr.endChar) 
                        brr = null;
                    if (BracketHelper.canBeStartOfSequence(ttt, false, false)) {
                        brr = BracketHelper.tryParse(ttt, BracketParseAttr.NO, 100);
                        if (brr !== null && (brr.lengthChar < 7) && ttt.isChar('(')) {
                            ttt = brr.endToken;
                            brr = null;
                            continue;
                        }
                    }
                    else if ((ttt.isValue("ИМЕНОВАТЬ", null) || ttt.isValue("ДАЛЬНЕЙШИЙ", null) || ttt.isValue("ДАЛЕЕ", null)) || ttt.isValue("ТЕКСТ", null)) 
                        hasNamed = true;
                    else if ((ttt.isComma || ttt.morph._class.isPreposition || ttt.isHiphen) || ttt.isChar(':')) {
                    }
                    else if (brr !== null || hasNamed) {
                        if (BracketHelper.canBeStartOfSequence(ttt, true, false)) 
                            ttt = ttt.next;
                        let npt = NounPhraseHelper.tryParse(ttt, NounPhraseParseAttr.REFERENTCANBENOUN, 0, null);
                        let typ22 = null;
                        if (npt !== null) {
                            ttt = npt.endToken;
                            if (npt.endToken.isValue("ДОГОВОР", null)) 
                                continue;
                        }
                        else {
                            let ttok = null;
                            if (ttt instanceof MetaToken) 
                                ttok = ParticipantToken.m_Ontology.tryParse(ttt.beginToken, TerminParseAttr.NO);
                            if (ttok !== null) 
                                typ22 = ttok.termin.canonicText;
                            else if (hasNamed && ttt.morph._class.isAdjective) 
                                typ22 = ttt.getNormalCaseText(MorphClass.ADJECTIVE, MorphNumber.UNDEFINED, MorphGender.UNDEFINED, false);
                            else if (brr !== null) 
                                continue;
                            else 
                                break;
                        }
                        if (BracketHelper.canBeEndOfSequence(ttt.next, true, null, false)) 
                            ttt = ttt.next;
                        if (brr !== null) {
                            if (ttt.next === null) {
                                ttt = brr.endToken;
                                continue;
                            }
                            ttt = ttt.next;
                        }
                        if (!hasNamed && typ22 === null) {
                            if (ParticipantToken.m_Ontology.tryParse(npt.beginToken, TerminParseAttr.NO) === null) 
                                break;
                        }
                        let re = ParticipantToken._new2264(t, ttt, ParticipantTokenKinds.NAMEDAS);
                        re.typ = (typ22 != null ? typ22 : npt.getNormalCaseText(null, MorphNumber.SINGULAR, MorphGender.UNDEFINED, false));
                        re.parts = new Array();
                        re.parts.push(r1);
                        return re;
                    }
                    else if ((ttt.isValue("ЗАРЕГИСТРИРОВАННЫЙ", null) || ttt.isValue("КАЧЕСТВО", null) || ttt.isValue("ПРОЖИВАЮЩИЙ", null)) || ttt.isValue("ЗАРЕГ", null)) {
                    }
                    else if (ttt.getReferent() === r1) {
                    }
                    else if ((ttt.getReferent() instanceof PersonIdentityReferent) || (ttt.getReferent() instanceof AddressReferent)) {
                        if (addRefs === null) 
                            addRefs = new Array();
                        addRefs.push(ttt.getReferent());
                    }
                    else {
                        let prr = ttt.kit.processReferent("PERSONPROPERTY", ttt, null);
                        if (prr !== null) {
                            ttt = prr.endToken;
                            continue;
                        }
                        if (ttt.getReferent() instanceof GeoReferent) 
                            continue;
                        let npt = NounPhraseHelper.tryParse(ttt, NounPhraseParseAttr.NO, 0, null);
                        if (npt !== null) {
                            if ((npt.noun.isValue("МЕСТО", null) || npt.noun.isValue("ЖИТЕЛЬСТВО", null) || npt.noun.isValue("ПРЕДПРИНИМАТЕЛЬ", null)) || npt.noun.isValue("ПОЛ", null) || npt.noun.isValue("РОЖДЕНИЕ", null)) {
                                ttt = npt.endToken;
                                continue;
                            }
                        }
                        if (ttt.isNewlineBefore) 
                            break;
                        if (ttt.lengthChar < 3) 
                            continue;
                        let mc = ttt.getMorphClassInDictionary();
                        if (mc.isAdverb || mc.isAdjective) 
                            continue;
                        if (ttt.chars.isAllUpper) 
                            continue;
                        break;
                    }
                }
                if (endSide !== null || ((addRefs !== null && t.previous !== null && t.previous.isAnd))) {
                    let re = ParticipantToken._new2264(t, (endSide != null ? endSide : t), ParticipantTokenKinds.NAMEDAS);
                    re.typ = null;
                    re.parts = new Array();
                    re.parts.push(r1);
                    if (addRefs !== null) 
                        re.parts.splice(re.parts.length, 0, ...addRefs);
                    return re;
                }
            }
            let too = ParticipantToken.m_Ontology.tryParse(t, TerminParseAttr.NO);
            if (too !== null) {
                if ((t.previous instanceof TextToken) && t.previous.isValue("ЛИЦО", null)) 
                    too = null;
            }
            if (too !== null && too.termin.tag !== null && too.termin.canonicText !== "СТОРОНА") {
                let tt1 = too.endToken.next;
                if (tt1 !== null) {
                    if (tt1.isHiphen || tt1.isChar(':')) 
                        tt1 = tt1.next;
                }
                if (tt1 instanceof ReferentToken) {
                    r1 = tt1.getReferent();
                    if ((r1 instanceof PersonReferent) || (r1 instanceof OrganizationReferent)) {
                        let re = ParticipantToken._new2264(t, tt1, ParticipantTokenKinds.NAMEDAS);
                        re.typ = too.termin.canonicText;
                        re.parts = new Array();
                        re.parts.push(r1);
                        return re;
                    }
                }
            }
        }
        let addTyp1 = (p1 === null ? null : p1.typ);
        let addTyp2 = (p2 === null ? null : p2.typ);
        if (BracketHelper.canBeStartOfSequence(tt, false, false) && tt.next !== null) {
            br = true;
            tt = tt.next;
        }
        let term1 = null;
        let term2 = null;
        if (addTyp1 !== null && addTyp1.indexOf(' ') > 0 && !addTyp1.startsWith("СТОРОНА")) 
            term1 = new Termin(addTyp1);
        if (addTyp2 !== null && addTyp2.indexOf(' ') > 0 && !addTyp2.startsWith("СТОРОНА")) 
            term2 = new Termin(addTyp2);
        let named = false;
        let _typ = null;
        let t1 = null;
        let t0 = tt;
        for (; tt !== null; tt = tt.next) {
            if (tt.morph._class.isPreposition && _typ !== null) 
                continue;
            if (tt.isCharOf("(:)") || tt.isHiphen) 
                continue;
            if (tt.isTableControlChar) 
                break;
            if (tt.isNewlineBefore && tt !== t0) {
                if (tt instanceof NumberToken) 
                    break;
                if ((tt instanceof TextToken) && (tt.previous instanceof TextToken)) {
                    if (tt.previous.isValue(tt.term, null)) 
                        break;
                }
            }
            if (BracketHelper.isBracket(tt, false)) 
                continue;
            let tok = (ParticipantToken.m_Ontology !== null ? ParticipantToken.m_Ontology.tryParse(tt, TerminParseAttr.NO) : null);
            if (tok !== null && (tt.previous instanceof TextToken)) {
                if (tt.previous.isValue("ЛИЦО", null)) 
                    return null;
            }
            if (tok === null) {
                if (addTyp1 !== null && ((MiscHelper.isNotMoreThanOneError(addTyp1, tt) || (((tt instanceof MetaToken) && tt.beginToken.isValue(addTyp1, null)))))) {
                    if (_typ !== null) {
                        if (!ParticipantToken._isTypesEqual(addTyp1, _typ)) 
                            break;
                    }
                    _typ = addTyp1;
                    t1 = tt;
                    continue;
                }
                if (addTyp2 !== null && ((MiscHelper.isNotMoreThanOneError(addTyp2, tt) || (((tt instanceof MetaToken) && tt.beginToken.isValue(addTyp2, null)))))) {
                    if (_typ !== null) {
                        if (!ParticipantToken._isTypesEqual(addTyp2, _typ)) 
                            break;
                    }
                    _typ = addTyp2;
                    t1 = tt;
                    continue;
                }
                if (tt.chars.isLetter) {
                    if (term1 !== null) {
                        let tok1 = term1.tryParse(tt, TerminParseAttr.NO);
                        if (tok1 !== null) {
                            if (_typ !== null) {
                                if (!ParticipantToken._isTypesEqual(addTyp1, _typ)) 
                                    break;
                            }
                            _typ = addTyp1;
                            t1 = (tt = tok1.endToken);
                            continue;
                        }
                    }
                    if (term2 !== null) {
                        let tok2 = term2.tryParse(tt, TerminParseAttr.NO);
                        if (tok2 !== null) {
                            if (_typ !== null) {
                                if (!ParticipantToken._isTypesEqual(addTyp2, _typ)) 
                                    break;
                            }
                            _typ = addTyp2;
                            t1 = (tt = tok2.endToken);
                            continue;
                        }
                    }
                    if (named && tt.getMorphClassInDictionary().isNoun) {
                        if (!tt.chars.isAllLower || BracketHelper.isBracket(tt.previous, true)) {
                            if (DecreeToken.isKeyword(tt, false) === null) {
                                let val = tt.getNormalCaseText(MorphClass.NOUN, MorphNumber.SINGULAR, MorphGender.UNDEFINED, false);
                                if (_typ !== null) {
                                    if (!ParticipantToken._isTypesEqual(_typ, val)) 
                                        break;
                                }
                                _typ = val;
                                t1 = tt;
                                continue;
                            }
                        }
                    }
                }
                if (named && _typ === null && isContract) {
                    if ((tt instanceof TextToken) && tt.chars.isCyrillicLetter && tt.chars.isCapitalUpper) {
                        let dc = tt.getMorphClassInDictionary();
                        if (dc.isUndefined || dc.isNoun) {
                            let dt = DecreeToken.tryAttach(tt, null, false);
                            let ok = true;
                            if (dt !== null) 
                                ok = false;
                            else if (tt.isValue("СТОРОНА", null)) 
                                ok = false;
                            if (ok) {
                                _typ = tt.lemma;
                                t1 = tt;
                                continue;
                            }
                        }
                        if (dc.isAdjective) {
                            let npt = NounPhraseHelper.tryParse(tt, NounPhraseParseAttr.NO, 0, null);
                            if (npt !== null && npt.adjectives.length > 0 && npt.noun.getMorphClassInDictionary().isNoun) {
                                _typ = npt.getNormalCaseText(null, MorphNumber.SINGULAR, MorphGender.UNDEFINED, false);
                                t1 = npt.endToken;
                                continue;
                            }
                        }
                    }
                }
                if (tt === t) 
                    break;
                if ((tt instanceof NumberToken) || tt.isChar('.')) 
                    break;
                if (tt.lengthChar < 4) {
                    if (_typ !== null) 
                        continue;
                }
                break;
            }
            if (tok.termin.tag === null) 
                named = true;
            else {
                if (_typ !== null) 
                    break;
                if (tok.termin.canonicText === "СТОРОНА") {
                    let tt1 = tt.next;
                    if (tt1 !== null && tt1.isHiphen) 
                        tt1 = tt1.next;
                    if (!(tt1 instanceof NumberToken)) 
                        break;
                    if (tt1.isNewlineBefore) 
                        break;
                    _typ = (tok.termin.canonicText + " " + tt1.value);
                    t1 = tt1;
                }
                else {
                    _typ = tok.termin.canonicText;
                    t1 = tok.endToken;
                }
                break;
            }
            tt = tok.endToken;
        }
        if (_typ === null) 
            return null;
        if (!named && t1 !== t && !_typ.startsWith("СТОРОНА")) {
            if (!ParticipantToken._isTypesEqual(_typ, addTyp1) && !ParticipantToken._isTypesEqual(_typ, addTyp2)) 
                return null;
        }
        if (BracketHelper.canBeEndOfSequence(t1.next, false, null, false)) {
            t1 = t1.next;
            if (!t.isWhitespaceBefore && BracketHelper.canBeStartOfSequence(t.previous, false, false)) 
                t = t.previous;
        }
        else if (BracketHelper.canBeStartOfSequence(t, false, false) && BracketHelper.canBeEndOfSequence(t1.next, true, t, true)) 
            t1 = t1.next;
        if (br && t1.next !== null && BracketHelper.canBeEndOfSequence(t1.next, false, null, false)) 
            t1 = t1.next;
        let res = ParticipantToken._new2269(t, t1, (named ? ParticipantTokenKinds.NAMEDAS : ParticipantTokenKinds.PURE), _typ);
        if (t.isChar(':')) 
            res.beginToken = t.next;
        return res;
    }
    
    static _isTypesEqual(t1, t2) {
        if (t1 === t2) 
            return true;
        if (t1 === "ЗАЙМОДАВЕЦ" || t1 === "ЗАИМОДАВЕЦ") 
            t1 = "ЗАИМОДАТЕЛЬ";
        if (t2 === "ЗАЙМОДАВЕЦ" || t2 === "ЗАИМОДАВЕЦ") 
            t2 = "ЗАИМОДАТЕЛЬ";
        if (t1 === "ПРОДАВЕЦ") 
            t1 = "ПОСТАВЩИК";
        if (t2 === "ПРОДАВЕЦ") 
            t2 = "ПОСТАВЩИК";
        if (t1 === "ПОКУПАТЕЛЬ") 
            t1 = "ЗАКАЗЧИК";
        if (t2 === "ПОКУПАТЕЛЬ") 
            t2 = "ЗАКАЗЧИК";
        return t1 === t2;
    }
    
    static tryAttachToExist(t, p1, p2) {
        if (t === null) 
            return null;
        if (t.beginChar >= 7674 && (t.beginChar < 7680)) {
        }
        let pp = ParticipantToken.tryAttach(t, p1, p2, false);
        let p = null;
        let rt = null;
        if (pp === null || pp.kind !== ParticipantTokenKinds.PURE) {
            let pers = t.getReferent();
            if ((pers instanceof PersonReferent) || (pers instanceof GeoReferent) || (pers instanceof OrganizationReferent)) {
                if (p1 !== null && p1.containsRef(pers)) 
                    p = p1;
                else if (p2 !== null && p2.containsRef(pers)) 
                    p = p2;
                if (p !== null) 
                    rt = new ReferentToken(p, t, t);
            }
        }
        else {
            if (p1 !== null && ParticipantToken._isTypesEqual(pp.typ, p1.typ)) 
                p = p1;
            else if (p2 !== null && ParticipantToken._isTypesEqual(pp.typ, p2.typ)) 
                p = p2;
            if (p !== null) {
                rt = new ReferentToken(p, pp.beginToken, pp.endToken);
                if (rt.beginToken.previous !== null && rt.beginToken.previous.isValue("ОТ", null)) 
                    rt.beginToken = rt.beginToken.previous;
            }
        }
        if (rt === null) 
            return null;
        if (rt.endToken.next !== null && rt.endToken.next.isChar(':')) {
            let rt1 = ParticipantToken.tryAttachRequisites(rt.endToken.next.next, p, (p === p1 ? p2 : p1), false);
            if (rt1 !== null) {
                rt1.beginToken = rt.beginToken;
                return rt1;
            }
            rt.endToken = rt.endToken.next;
        }
        while (rt.endToken.next !== null && (rt.endToken.next.getReferent() instanceof OrganizationReferent)) {
            let org = Utils.as(rt.endToken.next.getReferent(), OrganizationReferent);
            if (rt.referent.findSlot(null, org, true) !== null) {
                rt.endToken = rt.endToken.next;
                continue;
            }
            break;
        }
        return rt;
    }
    
    static tryAttachRequisites(t, cur, other, cantBeEmpty = false) {
        if (t === null || cur === null) 
            return null;
        if (t.isTableControlChar) 
            return null;
        let err = 0;
        let specChars = 0;
        let rt = null;
        let t0 = t;
        let isInTabCell = false;
        let cou = 0;
        for (let tt = t.next; tt !== null && (cou < 300); tt = tt.next,cou++) {
            if (tt.isTableControlChar) {
                isInTabCell = true;
                break;
            }
        }
        for (; t !== null; t = t.next) {
            if (t.beginChar === 8923) {
            }
            if (t.isTableControlChar) {
                if (t !== t0) {
                    if (rt !== null) 
                        rt.endToken = t.previous;
                    else if (!cantBeEmpty) 
                        rt = new ReferentToken(cur, t0, t.previous);
                    break;
                }
                else 
                    continue;
            }
            if ((t.isCharOf(":.") || t.isValue("М", null) || t.isValue("M", null)) || t.isValue("П", null)) {
                if (rt !== null) 
                    rt.endToken = t;
                continue;
            }
            let pp = ParticipantToken.tryAttachToExist(t, cur, other);
            if (pp !== null) {
                if (pp.referent !== cur) 
                    break;
                if (rt === null) 
                    rt = new ReferentToken(cur, t, t);
                rt.endToken = pp.endToken;
                err = 0;
                continue;
            }
            if (t.isNewlineBefore) {
                let iii = InstrToken.parse(t, 0, null);
                if (iii !== null) {
                    if (iii.typ === ILTypes.APPENDIX) 
                        break;
                }
            }
            if (t.whitespacesBeforeCount > 25 && !isInTabCell) {
                if (t !== t0) {
                    if (t.previous !== null && t.previous.isCharOf(",;")) {
                    }
                    else if (t.newlinesBeforeCount > 1) 
                        break;
                }
                if ((t.getReferent() instanceof PersonReferent) || (t.getReferent() instanceof OrganizationReferent)) {
                    if (!cur.containsRef(t.getReferent())) 
                        break;
                }
            }
            if ((t.isCharOf(";:,.") || t.isHiphen || t.morph._class.isPreposition) || t.morph._class.isConjunction) 
                continue;
            if (t.isCharOf("_/\\")) {
                if ((++specChars) > 10 && rt === null) 
                    rt = new ReferentToken(cur, t0, t);
                if (rt !== null) 
                    rt.endToken = t;
                continue;
            }
            if (t.isNewlineBefore && (t instanceof NumberToken)) 
                break;
            if (t.isValue("ОФИС", null)) {
                if (BracketHelper.canBeStartOfSequence(t.next, true, false)) {
                    let br = BracketHelper.tryParse(t.next, BracketParseAttr.NO, 100);
                    if (br !== null) {
                        t = br.endToken;
                        continue;
                    }
                }
                if ((t.next instanceof TextToken) && !t.next.chars.isAllLower) 
                    t = t.next;
                continue;
            }
            let r = t.getReferent();
            if ((((r instanceof PersonReferent) || (r instanceof AddressReferent) || (r instanceof UriReferent)) || (r instanceof OrganizationReferent) || (r instanceof PhoneReferent)) || (r instanceof PersonIdentityReferent) || (r instanceof BankDataReferent)) {
                if (other !== null && other.findSlot(null, r, true) !== null) {
                    if (!(r instanceof UriReferent)) 
                        break;
                }
                if (rt === null) 
                    rt = new ReferentToken(cur, t, t);
                if (cur.findSlot(InstrumentParticipantReferent.ATTR_DELEGATE, r, true) !== null) {
                }
                else 
                    cur.addSlot(InstrumentParticipantReferent.ATTR_REF, r, false, 0);
                rt.endToken = t;
                err = 0;
            }
            else {
                if ((t instanceof TextToken) && t.lengthChar > 1) 
                    ++err;
                if (isInTabCell && rt !== null) {
                    if (err > 300) 
                        break;
                }
                else if (err > 4) 
                    break;
            }
        }
        return rt;
    }
    
    attachFirst(p, minChar, maxChar) {
        let t = null;
        let tt0 = this.beginToken;
        let refs = new Array();
        for (t = tt0.previous; t !== null && t.beginChar >= minChar; t = t.previous) {
            if (t.isNewlineAfter) {
                if (t.newlinesAfterCount > 1) 
                    break;
                if (t.next instanceof NumberToken) 
                    break;
            }
            let tt = ParticipantToken._tryAttachContractGround(t, p, false);
            if (tt !== null) 
                continue;
            let r = t.getReferent();
            if (((((r instanceof OrganizationReferent) || (r instanceof PhoneReferent) || (r instanceof PersonReferent)) || (r instanceof PersonPropertyReferent) || (r instanceof AddressReferent)) || (r instanceof UriReferent) || (r instanceof PersonIdentityReferent)) || (r instanceof BankDataReferent)) {
                if (!refs.includes(r)) 
                    refs.splice(0, 0, r);
                tt0 = t;
            }
        }
        if (refs.length > 0) {
            for (const r of refs) {
                if (r !== refs[0] && (refs[0] instanceof OrganizationReferent) && (((r instanceof PersonReferent) || (r instanceof PersonPropertyReferent)))) 
                    p.addSlot(InstrumentParticipantReferent.ATTR_DELEGATE, r, false, 0);
                else 
                    p.addSlot(InstrumentParticipantReferent.ATTR_REF, r, false, 0);
            }
        }
        let rt = new ReferentToken(p, tt0, this.endToken);
        t = this.endToken.next;
        if (BracketHelper.isBracket(t, false)) 
            t = t.next;
        if (t !== null && t.isChar(',')) 
            t = t.next;
        for (; t !== null && ((maxChar === 0 || t.beginChar <= maxChar)); t = t.next) {
            if (t.isValue("СТОРОНА", null)) 
                break;
            let r = t.getReferent();
            if (((((r instanceof OrganizationReferent) || (r instanceof PhoneReferent) || (r instanceof PersonReferent)) || (r instanceof PersonPropertyReferent) || (r instanceof AddressReferent)) || (r instanceof UriReferent) || (r instanceof PersonIdentityReferent)) || (r instanceof BankDataReferent)) {
                if ((((r instanceof PersonPropertyReferent) && t.next !== null && t.next.isComma) && (t.next.next instanceof ReferentToken) && (t.next.next.getReferent() instanceof PersonReferent)) && !t.next.isNewlineAfter) {
                    let pe = Utils.as(t.next.next.getReferent(), PersonReferent);
                    pe.addSlot(PersonReferent.ATTR_ATTR, r, false, 0);
                    r = pe;
                    t = t.next.next;
                }
                let isDelegate = false;
                if (t.previous.isValue("ЛИЦО", null) || t.previous.isValue("ИМЯ", null)) 
                    isDelegate = true;
                if (t.previous.isValue("КОТОРЫЙ", null) && t.previous.previous !== null && ((t.previous.previous.isValue("ИМЯ", null) || t.previous.previous.isValue("ЛИЦО", null)))) 
                    isDelegate = true;
                p.addSlot(((((r instanceof PersonReferent) || (r instanceof PersonPropertyReferent))) && isDelegate ? InstrumentParticipantReferent.ATTR_DELEGATE : InstrumentParticipantReferent.ATTR_REF), r, false, 0);
                rt.endToken = t;
                continue;
            }
            let tt = ParticipantToken._tryAttachContractGround(t, p, false);
            if (tt !== null) {
                t = rt.endToken = tt;
                if (rt.beginChar === tt.beginChar) 
                    rt.beginToken = tt;
                continue;
            }
            if (t.isValue("В", null) && t.next !== null && t.next.isValue("ЛИЦО", null)) {
                t = t.next;
                continue;
            }
            if (t.isValue("ОТ", null) && t.next !== null && t.next.isValue("ИМЯ", null)) {
                t = t.next;
                continue;
            }
            if (t.isValue("ПО", null) && t.next !== null && t.next.isValue("ПОРУЧЕНИЕ", null)) {
                t = t.next;
                continue;
            }
            if (t.isNewlineBefore) 
                break;
            if (t.getMorphClassInDictionary().equals(MorphClass.VERB)) {
                if ((!t.isValue("УДОСТОВЕРЯТЬ", null) && !t.isValue("ПРОЖИВАТЬ", null) && !t.isValue("ЗАРЕГИСТРИРОВАТЬ", null)) && !t.isValue("ДЕЙСТВОВАТЬ", null)) 
                    break;
            }
            if (t.isAnd && t.previous !== null && t.previous.isComma) 
                break;
            if (t.isAnd && t.next.getReferent() !== null) {
                if (t.next.getReferent() instanceof OrganizationReferent) 
                    break;
                let pe = Utils.as(t.next.getReferent(), PersonReferent);
                if (pe !== null) {
                    let hasIp = false;
                    for (const s of pe.slots) {
                        if (s.typeName === PersonReferent.ATTR_ATTR) {
                            if (s.value.toString().startsWith("индивидуальный предприниматель")) {
                                hasIp = true;
                                break;
                            }
                        }
                    }
                    if (hasIp) 
                        break;
                }
            }
        }
        for (t = rt.beginToken; t !== null && t.endChar <= rt.endChar; t = t.next) {
            let tt = ParticipantToken._tryAttachContractGround(t, p, true);
            if (tt !== null) {
                if (tt.endChar > rt.endChar) 
                    rt.endToken = tt;
                t = tt;
            }
        }
        return rt;
    }
    
    static _tryAttachContractGround(t, ip, canBePassport = false) {
        let ok = false;
        for (; t !== null; t = t.next) {
            if (t.isChar(',') || t.morph._class.isPreposition) 
                continue;
            if (t.isChar('(')) {
                let br = BracketHelper.tryParse(t, BracketParseAttr.NO, 100);
                if (br !== null) {
                    t = br.endToken;
                    continue;
                }
            }
            if (t.isValue("ОСНОВАНИЕ", null) || t.isValue("ДЕЙСТВОВАТЬ", null) || t.isValue("ДЕЙСТВУЮЩИЙ", null)) {
                ok = true;
                if (t.next !== null && t.next.isChar('(')) {
                    let br = BracketHelper.tryParse(t.next, BracketParseAttr.NO, 100);
                    if (br !== null && (br.lengthChar < 10)) 
                        t = br.endToken;
                }
                continue;
            }
            let dr = Utils.as(t.getReferent(), DecreeReferent);
            if (dr !== null) {
                ip.ground = dr;
                return t;
            }
            let pir = Utils.as(t.getReferent(), PersonIdentityReferent);
            if (pir !== null && canBePassport) {
                if (pir.typ !== null && !pir.typ.includes("паспорт")) {
                    ip.ground = pir;
                    return t;
                }
            }
            if (t.isValue("УСТАВ", null)) {
                ip.ground = t.getNormalCaseText(MorphClass.NOUN, MorphNumber.SINGULAR, MorphGender.UNDEFINED, false);
                return t;
            }
            if (t.isValue("ДОВЕРЕННОСТЬ", null)) {
                let dts = DecreeToken.tryAttachList(t.next, null, 10, false);
                if (dts === null) {
                    let hasSpec = false;
                    for (let ttt = t.next; ttt !== null && ((ttt.endChar - t.endChar) < 200); ttt = ttt.next) {
                        if (ttt.isComma) 
                            continue;
                        if (ttt.isValue("УДОСТОВЕРИТЬ", null) || ttt.isValue("УДОСТОВЕРЯТЬ", null)) {
                            hasSpec = true;
                            continue;
                        }
                        let dt = DecreeToken.tryAttach(ttt, null, false);
                        if (dt !== null) {
                            if (dt.typ === DecreeTokenItemType.DATE || dt.typ === DecreeTokenItemType.NUMBER) {
                                dts = DecreeToken.tryAttachList(ttt, null, 10, false);
                                break;
                            }
                        }
                        let npt = NounPhraseHelper.tryParse(ttt, NounPhraseParseAttr.NO, 0, null);
                        if (npt !== null) {
                            if (npt.endToken.isValue("НОТАРИУС", null)) {
                                ttt = npt.endToken;
                                hasSpec = true;
                                continue;
                            }
                        }
                        if (ttt.getReferent() !== null) {
                            if (hasSpec) 
                                continue;
                        }
                        break;
                    }
                }
                if (dts !== null && dts.length > 0) {
                    let t0 = t;
                    dr = new DecreeReferent();
                    dr.typ = "ДОВЕРЕННОСТЬ";
                    for (const d of dts) {
                        if (d.typ === DecreeTokenItemType.DATE) {
                            dr.addDate(d);
                            t = d.endToken;
                        }
                        else if (d.typ === DecreeTokenItemType.NUMBER) {
                            dr.addNumber(d);
                            t = d.endToken;
                        }
                        else 
                            break;
                    }
                    let ad = t.kit.getAnalyzerDataByAnalyzerName(InstrumentAnalyzer.ANALYZER_NAME);
                    ip.ground = ad.registerReferent(dr);
                    let rt = new ReferentToken(Utils.as(ip.ground, Referent), t0, t);
                    t.kit.embedToken(rt);
                    return rt;
                }
                ip.ground = "ДОВЕРЕННОСТЬ";
                return t;
            }
            break;
        }
        return null;
    }
    
    static getDocTypes(name, name2) {
        let res = new Array();
        if (name === null) 
            return res;
        if (name === "АРЕНДОДАТЕЛЬ") {
            res.push("ДОГОВОР АРЕНДЫ");
            res.push("ДОГОВОР СУБАРЕНДЫ");
        }
        else if (name === "АРЕНДАТОР") 
            res.push("ДОГОВОР АРЕНДЫ");
        else if (name === "СУБАРЕНДАТОР") 
            res.push("ДОГОВОР СУБАРЕНДЫ");
        else if (name === "НАЙМОДАТЕЛЬ" || name === "НАНИМАТЕЛЬ") 
            res.push("ДОГОВОР НАЙМА");
        else if (name === "АГЕНТ" || name === "ПРИНЦИПАЛ") 
            res.push("АГЕНТСКИЙ ДОГОВОР");
        else if (name === "ПРОДАВЕЦ" || name === "ПОКУПАТЕЛЬ") 
            res.push("ДОГОВОР КУПЛИ-ПРОДАЖИ");
        else if (name === "ЗАКАЗЧИК" || name === "ИСПОЛНИТЕЛЬ" || LanguageHelper.endsWith(name, "ПОДРЯДЧИК")) 
            res.push("ДОГОВОР УСЛУГ");
        else if (name === "ПОСТАВЩИК") 
            res.push("ДОГОВОР ПОСТАВКИ");
        else if (name === "ЛИЦЕНЗИАР" || name === "ЛИЦЕНЗИАТ") 
            res.push("ЛИЦЕНЗИОННЫЙ ДОГОВОР");
        else if (name === "СТРАХОВЩИК" || name === "СТРАХОВАТЕЛЬ") 
            res.push("ДОГОВОР СТРАХОВАНИЯ");
        if (name2 === null) 
            return res;
        let tmp = ParticipantToken.getDocTypes(name2, null);
        for (let i = res.length - 1; i >= 0; i--) {
            if (!tmp.includes(res[i])) 
                res.splice(i, 1);
        }
        return res;
    }
    
    static initialize() {
        if (ParticipantToken.m_Ontology !== null) 
            return;
        ParticipantToken.m_Ontology = new TerminCollection();
        let t = null;
        for (const s of ["АРЕНДОДАТЕЛЬ", "АРЕНДАТОР", "СУБАРЕНДАТОР", "НАЙМОДАТЕЛЬ", "НАНИМАТЕЛЬ", "АГЕНТ", "ПРИНЦИПАЛ", "ПРОДАВЕЦ", "ПОКУПАТЕЛЬ", "ЗАКАЗЧИК", "ИСПОЛНИТЕЛЬ", "ПОСТАВЩИК", "ПОДРЯДЧИК", "СУБПОДРЯДЧИК", "СТОРОНА", "ЛИЦЕНЗИАР", "ЛИЦЕНЗИАТ", "СТРАХОВЩИК", "СТРАХОВАТЕЛЬ", "ПРОВАЙДЕР", "АБОНЕНТ", "ЗАСТРОЙЩИК", "УЧАСТНИК ДОЛЕВОГО СТРОИТЕЛЬСТВА", "КЛИЕНТ", "ЗАЕМЩИК", "УПРАВЛЯЮЩИЙ"]) {
            ParticipantToken.m_Ontology.add(Termin._new96(s, ParticipantToken.m_Ontology));
        }
        t = Termin._new96("ГЕНПОДРЯДЧИК", ParticipantToken.m_Ontology);
        t.addVariant("ГЕНЕРАЛЬНЫЙ ПОДРЯДЧИК", false);
        ParticipantToken.m_Ontology.add(t);
        t = Termin._new96("ЗАИМОДАТЕЛЬ", ParticipantToken.m_Ontology);
        t.addVariant("ЗАЙМОДАТЕЛЬ", false);
        t.addVariant("ЗАЙМОДАВЕЦ", false);
        t.addVariant("ЗАИМОДАВЕЦ", false);
        ParticipantToken.m_Ontology.add(t);
        t = new Termin("ИМЕНУЕМЫЙ");
        t.addVariant("ИМЕНОВАТЬСЯ", false);
        t.addVariant("ИМЕНУЕМ", false);
        t.addVariant("ДАЛЬНЕЙШИЙ", false);
        t.addVariant("ДАЛЕЕ", false);
        t.addVariant("ДАЛЕЕ ПО ТЕКСТУ", false);
        ParticipantToken.m_Ontology.add(t);
    }
    
    static _new2174(_arg1, _arg2, _arg3) {
        let res = new ParticipantToken(_arg1, _arg2);
        res.typ = _arg3;
        return res;
    }
    
    static _new2264(_arg1, _arg2, _arg3) {
        let res = new ParticipantToken(_arg1, _arg2);
        res.kind = _arg3;
        return res;
    }
    
    static _new2269(_arg1, _arg2, _arg3, _arg4) {
        let res = new ParticipantToken(_arg1, _arg2);
        res.kind = _arg3;
        res.typ = _arg4;
        return res;
    }
    
    static static_constructor() {
        ParticipantToken.m_Ontology = null;
    }
}


ParticipantToken.static_constructor();

module.exports = ParticipantToken