ru.malik.elaborarer.avt.table.pas

Переключить прокрутку окна
Загрузить этот исходный код

{
    Этот исходный код является частью проекта ПВТ-ОО.

    Copyright © 2021 Малик Разработчик

    Это свободная программа: вы можете перераспространять её и/или
    изменять её на условиях Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она может быть полезна,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <http://www.gnu.org/licenses/>.
}

unit ru.malik.elaborarer.avt.table;

{$MODE DELPHI}

interface

uses
    pascalx.lang,
    pascalx.utils,
    ru.malik.elaborarer.avt.programme,
    ru.malik.elaborarer.avt.lexer,
    ru.malik.elaborarer.avt.constant;

{$ASMMODE INTEL,CALLING REGISTER,TYPEINFO ON}

{%region pulic }
type
    AVTTableBuilder = class;

    AVTTableBuilder = class(AVTConstantExpression)
    private
        class function skipParenthesis(source: AVTSource; pos: int): int; static;
        class function skipCurly(source: AVTSource; pos: int): int; static;
        class function skipValue(source: AVTSource; pos: int): int; static;
    protected
        class function parseOperator(source: AVTSource; pos: int): int; static;
    private
        fldTypeObjectRef: AVTTypeStructured;
        fldTypeStructRef: AVTTypeStructured;
        fldTypeThrowableRef: AVTTypeStructured;
        function parseArguments(source: AVTSource; typeRef: AVTTypeStructured; pos: int; arguments: Vector): int;
        function parseThrows(source: AVTSource; typeRef: AVTTypeStructured; methodRef: AVTMethod; pos: int): int;
        function parseStructuredTypeName(source: AVTSource; typeRef: AVTTypeStructured; pos: int): AVTTypeStructured;
    public
        procedure parsePackage(source: AVTSource);
        procedure parseTypes(source: AVTSource);
        procedure parseImport(source: AVTSource);
        procedure parseSupertypes(source: AVTSource);
        procedure parseMembers(typeRef: AVTTypeStructured);
        procedure parseFields(typeRef: AVTTypeStructured);
        procedure parseProperties(typeRef: AVTTypeStructured);
    end;
{%endregion}

implementation

{%region AVTTableBuilder }
    class function AVTTableBuilder.skipParenthesis(source: AVTSource; pos: int): int;
    var
        counter: int;
    begin
        if source.getLexemeType(pos) = CHAR_PARENTH_OPENED then begin
            counter := 1;
            repeat
                inc(pos);
                case source.getLexemeType(pos) of
                CHAR_PARENTH_OPENED: begin
                    inc(counter);
                end;
                CHAR_PARENTH_CLOSED: begin
                    dec(counter);
                    if counter = 0 then begin
                        inc(pos);
                        break;
                    end;
                end;
                AVT_END:
                    raise AVTCompilerException.create('")" expected', source, pos);
                end;
            until false;
        end;
        result := pos;
    end;

    class function AVTTableBuilder.skipCurly(source: AVTSource; pos: int): int;
    var
        counter: int;
    begin
        if source.getLexemeType(pos) = CHAR_CURLY_OPENED then begin
            counter := 1;
            repeat
                inc(pos);
                case source.getLexemeType(pos) of
                CHAR_CURLY_OPENED: begin
                    inc(counter);
                end;
                CHAR_CURLY_CLOSED: begin
                    dec(counter);
                    if counter = 0 then begin
                        inc(pos);
                        break;
                    end;
                end;
                AVT_END:
                    raise AVTCompilerException.create('"}" expected', source, pos);
                end;
            until false;
        end;
        result := pos;
    end;

    class function AVTTableBuilder.skipValue(source: AVTSource; pos: int): int;
    var
        counterCurly: int;
        counterBracket: int;
        counterParenth: int;
    begin
        counterCurly := 0;
        counterBracket := 0;
        counterParenth := 0;
        repeat
            case source.getLexemeType(pos) of
            CHAR_CURLY_OPENED: begin
                inc(counterCurly);
            end;
            CHAR_CURLY_CLOSED: begin
                dec(counterCurly);
            end;
            CHAR_BRACKET_OPENED: begin
                inc(counterBracket);
            end;
            CHAR_BRACKET_CLOSED: begin
                dec(counterBracket);
            end;
            CHAR_PARENTH_OPENED: begin
                inc(counterParenth);
            end;
            CHAR_PARENTH_CLOSED: begin
                dec(counterParenth);
            end;
            CHAR_SEMICOLON: begin
                if (counterCurly or counterBracket or counterParenth) = 0 then break;
            end;
            AVT_END: begin
                raise AVTCompilerException.create('";" expected', source, pos);
            end;
            end;
            inc(pos);
        until false;
        result := pos;
    end;

    class function AVTTableBuilder.parseOperator(source: AVTSource; pos: int): int;
    var
        lexemeType: int;
        operatorKind: int;
    begin
        lexemeType := source.getLexemeType(pos);
        case lexemeType of
        CHAR_BRACKET_OPENED: begin
            inc(pos);
            if source.getLexemeType(pos) <> CHAR_BRACKET_CLOSED then begin
                raise AVTCompilerException.create('"]" expected', source, pos);
            end;
            inc(pos);
            if source.getLexemeType(pos) = CHAR_EQUALS then begin
                inc(pos);
                operatorKind := SET_ARRAY_ELEMENT;
            end else begin
                operatorKind := GET_ARRAY_ELEMENT;
            end;
        end;
        CHAR_PARENTH_OPENED: begin
            inc(pos);
            if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
                raise AVTCompilerException.create('")" expected', source, pos);
            end;
            inc(pos);
            operatorKind := INVOKE_VIRTUAL;
        end;
        OPER_BIT_NOT, OPER_BIT_AND, OPER_BIT_OR, OPER_BIT_XOR, OPER_SCAL_PLUS, OPER_SCAL_MINUS,
        OPER_SCAL_MUL, OPER_SCAL_DIV, OPER_SCAL_DIVU, OPER_SCAL_REM, OPER_SCAL_REMU, OPER_SCAL_ADD, OPER_SCAL_SUB,
        OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR, OPER_SCAL_G, OPER_SCAL_GE, OPER_SCAL_L, OPER_SCAL_LE,
        OPER_VECT_UNPCKL, OPER_VECT_UNPCKU, OPER_VECT_PACK, OPER_VECT_PLUS, OPER_VECT_MINUS,
        OPER_VECT_MUL, OPER_VECT_DIV, OPER_VECT_ADD, OPER_VECT_SUB, OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR,
        OPER_VECT_G, OPER_VECT_GE, OPER_VECT_L, OPER_VECT_LE, OPER_VECT_E, OPER_VECT_NE,
        OPER_VECT_MULS, OPER_VECT_ADDS, OPER_VECT_SUBS, OPER_VECT_MULU, OPER_VECT_ADDU, OPER_VECT_SUBU: begin
            inc(pos);
            operatorKind := lexemeType;
        end
        else
            raise AVTCompilerException.create('Valid operator symbol expected', source, pos);
        end;
        source.position := pos;
        result := operatorKind;
    end;

    function AVTTableBuilder.parseArguments(source: AVTSource; typeRef: AVTTypeStructured; pos: int; arguments: Vector): int;
    var
        names: Vector;
        nameAsValue: Value;
        typeParsedRef: AVTType;
        argumentName: AnsiString;
    begin
        names := Vector.create();
        try
            if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
                typeParsedRef := parseType(typeRef, pos);
                if typeParsedRef.isVoid() then begin
                    raise AVTCompilerException.create('The type void is an invalid type for parameter', source, pos);
                end;
                pos := source.position;
                if source.getLexemeType(pos) <> LITR_NAME then begin
                    raise AVTCompilerException.create('Parameter name expected', source, pos);
                end;
                argumentName := source.getLexemeAnsiString(pos);
                nameAsValue := ValueOfAnsiString.create(argumentName);
                if names.contains(nameAsValue) then begin
                    raise AVTCompilerException.create('Duplicate parameter ' + argumentName, source, pos);
                end;
                names.append(nameAsValue);
                arguments.append(ValueOfObject.create(AVTVariable.create(typeParsedRef, argumentName, source, pos)));
                inc(pos);
                case source.getLexemeType(pos) of
                CHAR_COMMA: begin
                    inc(pos);
                end;
                CHAR_PARENTH_CLOSED: begin
                    break;
                end
                else
                    raise AVTCompilerException.create('")" expected', source, pos);
                end;
            until false;
        finally
            names.free();
        end;
        result := pos + 1;
    end;

    function AVTTableBuilder.parseThrows(source: AVTSource; typeRef: AVTTypeStructured; methodRef: AVTMethod; pos: int): int;
    var
        typeParsedRef: AVTTypeStructured;
        typeThrowableRef: AVTTypeStructured;
    begin
        typeThrowableRef := fldTypeThrowableRef;
        repeat
            typeParsedRef := parseStructuredTypeName(source, typeRef, pos);
            if not typeParsedRef.isImplements(typeThrowableRef) then begin
                raise AVTCompilerException.create('No exception of type ' + typeParsedRef.fullName + ' can be thrown; an exception type must be subtype of ' + typeThrowableRef.fullName, source, pos);
            end;
            if methodRef.isThrows(typeParsedRef) then begin
                raise AVTCompilerException.create('Duplicate exception ' + typeParsedRef.fullName, source, pos);
            end;
            methodRef.addThrows(typeParsedRef);
            pos := source.position;
            if source.getLexemeType(pos) <> CHAR_COMMA then break;
            inc(pos);
        until false;
        result := pos;
    end;

    function AVTTableBuilder.parseStructuredTypeName(source: AVTSource; typeRef: AVTTypeStructured; pos: int): AVTTypeStructured;
    var
        itemParsedRef: AVTItem;
    begin
        if source.getLexemeType(pos) <> LITR_NAME then begin
            raise AVTCompilerException.create('Type or package name expected', source, pos);
        end;
        itemParsedRef := resolveName(source.getLexemeAnsiString(pos), typeRef, pos);
        if itemParsedRef is AVTPackage then begin
            result := parseFullyQualifiedTypeName(AVTPackage(itemParsedRef), typeRef, pos + 1);
            exit;
        end;
        if itemParsedRef is AVTTypeStructured then begin
            source.position := pos + 1;
            result := AVTTypeStructured(itemParsedRef);
            exit;
        end;
        raise AVTCompilerException.create('Type or package name expected', source, pos);
    end;

    procedure AVTTableBuilder.parsePackage(source: AVTSource);
    var
        pos: int;
        lxt: int;
        packageName: AnsiString;
        packageRef0: AVTPackage;
        packageRef1: AVTPackage;
        programme: AVTProgramme;
    begin
        packageRef0 := nil;
        programme := self.programme;
        if source.getLexemeType(0) <> AVT_PACKAGE then begin
            raise AVTCompilerException.create('"package" expected', source, 0);
        end;
        pos := 1;
        repeat
            if source.getLexemeType(pos) <> LITR_NAME then begin
                raise AVTCompilerException.create('Package name expected', source, pos);
            end;
            packageName := source.getLexemeAnsiString(pos);
            if packageRef0 = nil then begin
                packageRef1 := programme.getPackage(packageName);
            end else begin
                packageRef1 := packageRef0.getSubpackage(packageName);
            end;
            if packageRef1 = nil then begin
                packageRef1 := AVTPackage.create(programme, packageRef0, packageName);
            end;
            packageRef0 := packageRef1;
            inc(pos);
            lxt := source.getLexemeType(pos);
            if lxt <> CHAR_PERIOD then break;
            inc(pos);
        until false;
        if lxt <> CHAR_SEMICOLON then begin
            raise AVTCompilerException.create('";" expected', source, pos);
        end;
        source.position := pos + 1;
        source.package := packageRef0;
    end;

    procedure AVTTableBuilder.parseTypes(source: AVTSource);
    var
        pos: int;
        lxt: int;
        flags: int;
        typeName: AnsiString;
        typeDoc: UnicodeString;
        packageRef: AVTPackage;
    begin
        pos := source.position;
        packageRef := source.package;
        repeat
            { раздел импортов }
            lxt := source.getLexemeType(pos);
            if (lxt <> AVT_IMPORT) and (lxt <> LITR_NAME) and (lxt <> CHAR_PERIOD) and (lxt <> OPER_SCAL_MUL) and (lxt <> CHAR_SEMICOLON) then break;
            inc(pos);
        until false;
        repeat
            { документация }
            typeDoc := '';
            if lxt = LITR_DOCUMENTATION then begin
                typeDoc := source.getLexemeUnicodeString(pos);
                inc(pos);
            end;
            { видимость }
            case source.getLexemeType(pos) of
            AVT_PUBLISHED, AVT_PROTECTED, AVT_PRIVATE: begin
                raise AVTCompilerException.create('Type can not have published, protected or private visibility', source, pos);
            end;
            AVT_PUBLIC: begin
                flags := FLAG_PUBLIC;
                inc(pos);
            end;
            AVT_PACKAGE: begin
                flags := FLAG_PACKAGE;
                inc(pos);
            end
            else
                flags := FLAG_SOURCE;
            end;
            { абстрактность }
            case source.getLexemeType(pos) of
            AVT_ABSTRACT: begin
                flags := flags or FLAG_ABSTRACT;
                inc(pos);
            end;
            AVT_FINAL: begin
                flags := flags or FLAG_FINAL;
                inc(pos);
            end;
            end;
            { разновидность }
            case source.getLexemeType(pos) of
            AVT_CLASS: begin
                inc(pos);
            end;
            AVT_STRUCT: begin
                if (flags and FLAG_ABSTRACT) <> 0 then begin
                    raise AVTCompilerException.create('Structure can not be abstract', source, pos);
                end;
                flags := flags or FLAG_STRUCT;
                inc(pos);
            end;
            AVT_SERVICE: begin
                if (flags and FLAG_FINAL) <> 0 then begin
                    raise AVTCompilerException.create('Service can not be final', source, pos);
                end;
                flags := flags or FLAG_SERVICE;
                inc(pos);
            end;
            AVT_INTERFACE: begin
                if (flags and FLAG_FINAL) <> 0 then begin
                    raise AVTCompilerException.create('Interface can not be final', source, pos);
                end;
                flags := flags or (FLAG_INTERFACE or FLAG_ABSTRACT);
                inc(pos);
            end
            else
                raise AVTCompilerException.create('"class", "service", "interface" or "struct" expected', source, pos);
            end;
            { название }
            if source.getLexemeType(pos) <> LITR_NAME then begin
                raise AVTCompilerException.create('Type name expected', source, pos);
            end;
            typeName := source.getLexemeAnsiString(pos);
            if packageRef.fullName = 'avt.lang' then begin
                if (typeName = 'Object') and (flags <> FLAG_PUBLIC) then begin
                    raise AVTCompilerException.create('This type must be a "public class" type', source, pos);
                end;
                if (typeName = 'Struct') and (flags <> FLAG_PUBLIC) then begin
                    raise AVTCompilerException.create('This type must be a "public class" type', source, pos);
                end;
            end;
            if packageRef.getSubpackage(typeName) <> nil then begin
                raise AVTCompilerException.create('Type name conflicts with same package name ' + typeName, source, pos);
            end;
            if packageRef.getType(typeName, false) <> nil then begin
                raise AVTCompilerException.create('Duplicate declaration of type ' + typeName, source, pos);
            end;
            AVTTypeStructured.create(packageRef, false, flags, typeName, source, pos, typeDoc);
            pos := skipCurly(source, skipParenthesis(source, pos + 1));
            lxt := source.getLexemeType(pos);
        until lxt = AVT_END;
    end;

    procedure AVTTableBuilder.parseImport(source: AVTSource);
    var
        isType: boolean;
        pos: int;
        lxt: int;
        vis: int;
        periodPos: int;
        fullName: AnsiString;
        typeName: AnsiString;
        packageName: AnsiString;
        packageRef: AVTPackage;
        typeRef: AVTTypeStructured;
        programme: AVTProgramme;
    begin
        pos := source.position;
        programme := self.programme;
        packageRef := programme.getPackage('avt.lang');
        if packageRef <> nil then source.addImportedPackage(packageRef);
        while source.getLexemeType(pos) = AVT_IMPORT do begin
            inc(pos);
            if source.getLexemeType(pos) <> LITR_NAME then begin
                raise AVTCompilerException.create('Package name expected', source, pos);
            end;
            fullName := source.getLexemeAnsiString(pos);
            isType := true;
            inc(pos);
            repeat
                case source.getLexemeType(pos) of
                CHAR_PERIOD: begin
                    if not isType then begin
                        raise AVTCompilerException.create('";" expected', source, pos);
                    end;
                    inc(pos);
                    case source.getLexemeType(pos) of
                    LITR_NAME: begin
                        fullName := fullName + '.' + source.getLexemeAnsiString(pos);
                        inc(pos);
                    end;
                    OPER_SCAL_MUL: begin
                        isType := false;
                        inc(pos);
                    end
                    else
                        raise AVTCompilerException.create('Name or "*" expected', source, pos);
                    end;
                end;
                CHAR_SEMICOLON: begin
                    if isType then begin
                        periodPos := stringLastIndexOf('.', fullName);
                        if periodPos <= 0 then begin
                            raise AVTCompilerException.create('Type not found: ' + fullName, source, pos);
                        end;
                        packageName := stringCopy(fullName, 1, periodPos);
                        typeName := stringCopy(fullName, periodPos + 1);
                        packageRef := programme.getPackage(packageName);
                        if packageRef = nil then begin
                            raise AVTCompilerException.create('Package not found: ' + packageName, source, pos);
                        end;
                        typeRef := packageRef.getType(typeName) as AVTTypeStructured;
                        if typeRef = nil then begin
                            raise AVTCompilerException.create('Type not found: ' + fullName, source, pos);
                        end;
                        if source.getImportedType(typeName) <> nil then begin
                            raise AVTCompilerException.create('Type already imported: ' + typeName, source, pos);
                        end;
                        if source.getDeclaredType(typeName) <> nil then begin
                            raise AVTCompilerException.create('Type already declared: ' + typeName, source, pos);
                        end;
                        vis := typeRef.visibility;
                        if (vis <> AVT_PUBLIC) and ((vis <> AVT_PACKAGE) or (typeRef.package <> source.package)) and ((vis <> AVT_SOURCE) or (typeRef.source <> source)) then begin
                            raise AVTCompilerException.create('The type ' + typeRef.fullName + ' is not visible', source, pos);
                        end;
                        source.addImportedType(typeRef);
                    end else begin
                        packageRef := programme.getPackage(fullName);
                        if packageRef = nil then begin
                            raise AVTCompilerException.create('Package not found: ' + fullName, source, pos);
                        end;
                        if source.isImportedPackage(packageRef) then begin
                            raise AVTCompilerException.create('Package already imported: ' + fullName, source, pos);
                        end;
                        source.addImportedPackage(packageRef);
                    end;
                    inc(pos);
                    break;
                end
                else
                    if isType then begin
                        raise AVTCompilerException.create('"." or ";" expected', source, pos);
                    end;
                    raise AVTCompilerException.create('";" expected', source, pos);
                end;
            until false;
        end;
        lxt := source.getLexemeType(pos);
        if (lxt = LITR_NAME) or (lxt = CHAR_PERIOD) or (lxt = OPER_SCAL_MUL) or (lxt = CHAR_SEMICOLON) then begin
            raise AVTCompilerException.create('"import" expected', source, pos);
        end;
    end;

    procedure AVTTableBuilder.parseSupertypes(source: AVTSource);
    var
        isExtends: boolean;
        pos: int;
        e: Enumeration;
        typeRef: AVTTypeStructured;
        typeClassRef: AVTTypeStructured;
        typeParsedRef: AVTTypeStructured;
        typeObjectRef: AVTTypeStructured;
        typeStructRef: AVTTypeStructured;
        typeStringRef: AVTTypeStructured;
        typeThrowableRef: AVTTypeStructured;
        packageAvtLangRef: AVTPackage;
    begin
        typeObjectRef := fldTypeObjectRef;
        typeStructRef := fldTypeStructRef;
        if (typeObjectRef = nil) or (typeStructRef = nil) then begin
            packageAvtLangRef := programme.getPackage('avt.lang');
            if packageAvtLangRef <> nil then begin
                typeClassRef := packageAvtLangRef.getType('Class') as AVTTypeStructured;
                typeObjectRef := packageAvtLangRef.getType('Object') as AVTTypeStructured;
                typeStructRef := packageAvtLangRef.getType('Struct') as AVTTypeStructured;
                typeStringRef := packageAvtLangRef.getType('String') as AVTTypeStructured;
                typeThrowableRef := packageAvtLangRef.getType('Throwable') as AVTTypeStructured;
                fldTypeObjectRef := typeObjectRef;
                fldTypeStructRef := typeStructRef;
                fldTypeThrowableRef := typeThrowableRef;
            end;
            if typeClassRef = nil then begin
                raise AVTGlobalException.create('Essential type not found: avt.lang.Class');
            end;
            if typeObjectRef = nil then begin
                raise AVTGlobalException.create('Essential type not found: avt.lang.Object');
            end;
            if typeStructRef = nil then begin
                raise AVTGlobalException.create('Essential type not found: avt.lang.Struct');
            end;
            if typeStringRef = nil then begin
                raise AVTGlobalException.create('Essential type not found: avt.lang.String');
            end;
            if typeThrowableRef = nil then begin
                raise AVTGlobalException.create('Essential type not found: avt.lang.Throwable');
            end;
        end;
        e := source.declaredTypes();
        while e.hasMoreElements() do begin
            typeRef := e.nextElement().objectValue() as AVTTypeStructured;
            pos := typeRef.declarationPosition + 1;
            if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
                if typeRef.isStruct() then begin
                    typeRef.setExtends(typeStructRef);
                end else
                if typeRef <> typeObjectRef then begin
                    typeRef.setExtends(typeObjectRef);
                end;
            end else begin
                isExtends := true;
                repeat
                    inc(pos);
                    typeParsedRef := parseStructuredTypeName(source, typeRef, pos);
                    if typeRef.isStruct() then begin
                        if typeRef.extends() <> nil then begin
                            raise AVTCompilerException.create('Structure can have only one supertype', source, pos);
                        end;
                        if not typeParsedRef.isStruct() and (typeParsedRef <> typeStructRef) then begin
                            raise AVTCompilerException.create('Structure supertype must be a structure or avt.lang.Struct type', source, pos);
                        end;
                        typeRef.setExtends(typeParsedRef, pos);
                    end else begin
                        if typeParsedRef.isStruct() then begin
                            raise AVTCompilerException.create('Structures not allowed here', source, pos);
                        end;
                        if not typeParsedRef.isClass() then begin
                            isExtends := false;
                        end else
                        if not isExtends then begin
                            raise AVTCompilerException.create('Type must be service or interface', source, pos);
                        end;
                        if isExtends then begin
                            typeRef.setExtends(typeParsedRef, pos);
                        end else begin
                            typeRef.addImplements(typeParsedRef, pos);
                        end;
                    end;
                    pos := source.position;
                    case source.getLexemeType(pos) of
                    CHAR_COMMA: ;
                    CHAR_PARENTH_CLOSED: begin
                        inc(pos);
                        break;
                    end;
                    else
                        raise AVTCompilerException.create('")" expected', source, pos);
                    end;
                    isExtends := false;
                until false;
                if not typeRef.isStruct() and (typeRef.extends() = nil) then begin
                    typeRef.setExtends(typeObjectRef);
                end;
            end;
            if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
                raise AVTCompilerException.create('"{" expected', source, pos);
            end;
            typeRef.implementationPosition := pos + 1;
        end;
    end;

    procedure AVTTableBuilder.parseMembers(typeRef: AVTTypeStructured);
    var
        lxt: int;
        pos: int;
        flags: int;
        bindingPos: int;
        implDetailsPos: int;
        typeReturnPos: int;
        namePos: int;
        argumentsPos: int;
        operatorKind: int;
        argumentsSize: int;
        fieldLength: int;
        memberName: AnsiString;
        memberDoc: UnicodeString;
        memberFoundRef: TObject;
        argumentsList: Vector;
        typeReturnRef: AVTType;
        overriddableRef: AVTOverriddable;
        fieldRef: AVTField;
        source: AVTSource;
    begin
        { разновидность структурированного типа: class, service, interface, struct }
        source := typeRef.source;
        pos := typeRef.implementationPosition;
        repeat
            lxt := source.getLexemeType(pos);
            if lxt = CHAR_CURLY_CLOSED then break;
            { документация }
            memberDoc := '';
            if lxt = LITR_DOCUMENTATION then begin
                memberDoc := source.getLexemeUnicodeString(pos);
                inc(pos);
            end;
            { видимость: published, public, protected, package, <default>, private }
            case source.getLexemeType(pos) of
            AVT_PUBLISHED: begin
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Structure fields can have only public visibility', source, pos);
                end;
                flags := FLAG_PUBLISHED;
                inc(pos);
            end;
            AVT_PUBLIC: begin
                flags := FLAG_PUBLIC;
                inc(pos);
            end;
            AVT_PROTECTED: begin
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Structure fields can have only public visibility', source, pos);
                end;
                flags := FLAG_PROTECTED;
                inc(pos);
            end;
            AVT_PACKAGE: begin
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Structure fields can have only public visibility', source, pos);
                end;
                if typeRef.isInterface() then begin
                    raise AVTCompilerException.create('Interface members can not be hidden', source, pos);
                end;
                flags := FLAG_PACKAGE;
                inc(pos);
            end;
            AVT_PRIVATE: begin
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Structure fields can have only public visibility', source, pos);
                end;
                if typeRef.isInterface() then begin
                    raise AVTCompilerException.create('Interface members can not be hidden', source, pos);
                end;
                flags := FLAG_PRIVATE;
                inc(pos);
            end
            else
                if typeRef.isStruct() or typeRef.isInterface() then begin
                    flags := FLAG_PUBLIC;
                end else begin
                    flags := FLAG_SOURCE;
                end;
            end;
            { связывание: static final, static, abstract, final }
            bindingPos := pos;
            case source.getLexemeType(pos) of
            AVT_STATIC: begin
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Structure fields can not be static', source, pos);
                end;
                flags := flags or FLAG_STATIC;
                inc(pos);
                if source.getLexemeType(pos) = AVT_FINAL then begin
                    flags := flags or FLAG_FINAL;
                    inc(pos);
                end else
                if typeRef.isInterface() then begin
                    flags := flags or FLAG_FINAL;
                end;
            end;
            AVT_FINAL: begin
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Structure fields can not be final', source, pos);
                end;
                flags := flags or FLAG_FINAL;
                inc(pos);
                if typeRef.isService() then begin
                    flags := flags or FLAG_STATIC;
                end;
            end;
            AVT_ABSTRACT: begin
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Structure fields can not be abstract', source, pos);
                end;
                if typeRef.isService() and (flags <= FLAG_PACKAGE) then begin
                    raise AVTCompilerException.create('Hidden service members can not be abstract', source, pos);
                end;
                if typeRef.isClass() and (flags = FLAG_PRIVATE) then begin
                    raise AVTCompilerException.create('Private class members can not be abstract', source, pos);
                end;
                flags := flags or FLAG_ABSTRACT;
                inc(pos);
            end;
            end;
            { детали реализации: native interrupt, native, interrupt native, interrupt, synchronized }
            implDetailsPos := pos;
            case source.getLexemeType(pos) of
            AVT_NATIVE: begin
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Implementation details can not be used in structures', source, pos);
                end;
                if typeRef.isInterface() then begin
                    raise AVTCompilerException.create('Implementation details can not be used in interfaces', source, pos);
                end;
                if (flags and FLAG_ABSTRACT) <> 0 then begin
                    raise AVTCompilerException.create('Abstract members can not have implementation details', source, pos);
                end;
                flags := flags or FLAG_NATIVE;
                inc(pos);
                if source.getLexemeType(pos) = AVT_INTERRUPT then begin
                    if (flags and FLAG_STATIC) = 0 then begin
                        raise AVTCompilerException.create('"static" expected. Interrupt method requires "static" modifier', source, bindingPos);
                    end;
                    flags := flags or FLAG_INTERRUPT;
                    inc(pos);
                end;
            end;
            AVT_INTERRUPT: begin
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Implementation details can not be used in structures', source, pos);
                end;
                if typeRef.isInterface() then begin
                    raise AVTCompilerException.create('Implementation details can not be used in interfaces', source, pos);
                end;
                if (flags and FLAG_ABSTRACT) <> 0 then begin
                    raise AVTCompilerException.create('Abstract members can not have implementation details', source, pos);
                end;
                if (flags and FLAG_STATIC) = 0 then begin
                    raise AVTCompilerException.create('"static" expected. Interrupt method requires "static" modifier', source, bindingPos);
                end;
                flags := flags or FLAG_INTERRUPT;
                inc(pos);
                if source.getLexemeType(pos) = AVT_NATIVE then begin
                    flags := flags or FLAG_NATIVE;
                    inc(pos);
                end;
            end;
            AVT_SYNCHRONIZED: begin
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Implementation details can not be used in structures', source, pos);
                end;
                if typeRef.isInterface() then begin
                    raise AVTCompilerException.create('Implementation details can not be used in interfaces', source, pos);
                end;
                if (flags and FLAG_ABSTRACT) <> 0 then begin
                    raise AVTCompilerException.create('Abstract members can not have implementation details', source, pos);
                end;
                flags := flags or FLAG_SYNCHRONIZED;
                inc(pos);
            end;
            end;
            { члены типов }
            case source.getLexemeType(pos) of
            CHAR_CURLY_OPENED: begin
                { метод инициализации типа (статичный блок) }
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Static block can not be used in structures', source, pos);
                end;
                if (flags and FLAG_STATIC) = 0 then begin
                    raise AVTCompilerException.create('"static" expected. Static block requires "static" modifier', source, bindingPos);
                end;
                if (flags and (FLAG_NATIVE or FLAG_INTERRUPT or FLAG_SYNCHRONIZED)) <> 0 then begin
                    raise AVTCompilerException.create('Implementation details not supported by static block', source, implDetailsPos);
                end;
                if typeRef.members(SPECNAME_CLASS_INIT).hasMoreElements() then begin
                    raise AVTCompilerException.create('Duplicate static block in ' + typeRef.simpleName, source, pos);
                end;
                with AVTClassInit.create(typeRef, pos) do begin
                    implementationPosition := pos;
                end;
                pos := skipCurly(source, pos);
                continue;
            end;
            CHAR_PARENTH_OPENED: begin
                { метод инициализации экземпляра типа (конструктор) }
                if not typeRef.isClass() then begin
                    raise AVTCompilerException.create('Constructors allowed in classes only', source, pos);
                end;
                if (flags and (FLAG_STATIC or FLAG_ABSTRACT or FLAG_FINAL)) <> 0 then begin
                    raise AVTCompilerException.create('Binding modifiers not supported by constructor', source, bindingPos);
                end;
                if (flags and (FLAG_NATIVE or FLAG_INTERRUPT or FLAG_SYNCHRONIZED)) <> 0 then begin
                    raise AVTCompilerException.create('Implementation details not supported by constructor', source, implDetailsPos);
                end;
                argumentsPos := pos;
                argumentsList := Vector.create();
                try
                    pos := parseArguments(source, typeRef, pos + 1, argumentsList);
                    with typeRef.members(SPECNAME_INST_INIT) do while hasMoreElements() do if (nextElement().objectValue() as AVTMethod).isIdentityArguments(argumentsList) then begin
                        raise AVTCompilerException.create('Duplicate constructor with same arguments in ' + typeRef.simpleName, source, argumentsPos);
                    end;
                    overriddableRef := AVTInstInit.create(typeRef, flags, argumentsList, argumentsPos, pos, memberDoc);
                finally
                    argumentsList.free();
                end;
                if source.getLexemeType(pos) = AVT_THROWS then begin
                    pos := parseThrows(source, typeRef, overriddableRef as AVTMethod, pos + 1);
                end;
                overriddableRef.implementationPosition := pos;
                if source.getLexemeType(pos) = CHAR_COLON then begin
                    inc(pos);
                    lxt := source.getLexemeType(pos);
                    if (lxt <> AVT_SUPER) and (lxt <> AVT_THIS) then begin
                        raise AVTCompilerException.create('"super" or "this" expected', source, pos);
                    end;
                    inc(pos);
                    if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
                        raise AVTCompilerException.create('"(" expected', source, pos);
                    end;
                    pos := skipParenthesis(source, pos);
                end;
                if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
                    raise AVTCompilerException.create('"{" expected', source, pos);
                end;
                pos := skipCurly(source, pos);
                continue;
            end;
            end;
            overriddableRef := nil;
            typeReturnPos := pos;
            typeReturnRef := parseType(typeRef, pos);
            pos := source.position;
            namePos := pos;
            case source.getLexemeType(pos) of
            AVT_OPERATOR: begin
                { оператор }
                if typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Operators can not be declared in structures', source, pos);
                end;
                if (flags and FLAG_STATIC) <> 0 then begin
                    raise AVTCompilerException.create('Operators can not be static', source, bindingPos);
                end;
                if typeRef.isInterface() then begin
                    flags := flags or FLAG_ABSTRACT;
                end;
                operatorKind := parseOperator(source, pos + 1);
                pos := source.position;
                if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
                    raise AVTCompilerException.create('"(" expected', source, pos);
                end;
                argumentsPos := pos;
                argumentsList := Vector.create();
                try
                    pos := parseArguments(source, typeRef, pos + 1, argumentsList);
                    argumentsSize := argumentsList.size();
                    if argumentsSize = 0 then begin
                        case operatorKind of
                        OPER_SCAL_ADD: operatorKind := OPER_SCAL_PLUS;
                        OPER_SCAL_SUB: operatorKind := OPER_SCAL_MINUS;
                        OPER_VECT_ADD: operatorKind := OPER_VECT_PLUS;
                        OPER_VECT_SUB: operatorKind := OPER_VECT_MINUS;
                        end;
                    end;
                    case operatorKind of
                    SET_ARRAY_ELEMENT: begin
                        if not typeReturnRef.isVoid() then begin
                            raise AVTCompilerException.create('"void" expected. The operator []= can return the type void only', source, typeReturnPos);
                        end;
                        if argumentsSize <> 2 then begin
                            raise AVTCompilerException.create('The operator []= requires 2 parameters', source, argumentsPos);
                        end;
                    end;
                    GET_ARRAY_ELEMENT, OPER_BIT_AND, OPER_BIT_OR, OPER_BIT_XOR, OPER_SCAL_MUL, OPER_SCAL_DIV, OPER_SCAL_DIVU,
                    OPER_SCAL_REM, OPER_SCAL_REMU, OPER_SCAL_ADD, OPER_SCAL_SUB, OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR,
                    OPER_VECT_MUL, OPER_VECT_DIV, OPER_VECT_ADD, OPER_VECT_SUB, OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR,
                    OPER_VECT_G, OPER_VECT_GE, OPER_VECT_L, OPER_VECT_LE, OPER_VECT_E, OPER_VECT_NE,
                    OPER_VECT_MULS, OPER_VECT_ADDS, OPER_VECT_SUBS, OPER_VECT_MULU, OPER_VECT_ADDU, OPER_VECT_SUBU: begin
                        if typeReturnRef.isVoid() then begin
                            raise AVTCompilerException.create('The type void is an invalid return type for the operator ' + AVTOperator.operatorToChar(operatorKind), source, typeReturnPos);
                        end;
                        if argumentsSize <> 1 then begin
                            raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + ' requires 1 parameter', source, argumentsPos);
                        end;
                    end;
                    OPER_SCAL_G, OPER_SCAL_GE, OPER_SCAL_L, OPER_SCAL_LE: begin
                        if not typeReturnRef.isBoolean() then begin
                            raise AVTCompilerException.create('"boolean" expected. The operator ' + AVTOperator.operatorToChar(operatorKind) + ' can return value of the type boolean only', source, typeReturnPos);
                        end;
                        if argumentsSize <> 1 then begin
                            raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + ' requires 1 parameter', source, argumentsPos);
                        end;
                    end;
                    OPER_BIT_NOT, OPER_SCAL_PLUS, OPER_SCAL_MINUS, OPER_VECT_UNPCKL, OPER_VECT_UNPCKU, OPER_VECT_PACK, OPER_VECT_PLUS, OPER_VECT_MINUS: begin
                        if typeReturnRef.isVoid() then begin
                            raise AVTCompilerException.create('The type void is an invalid return type for the operator ' + AVTOperator.operatorToChar(operatorKind), source, typeReturnPos);
                        end;
                        if argumentsSize <> 0 then begin
                            raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + ' requires no parameters', source, argumentsPos);
                        end;
                    end;
                    end;
                    with typeRef.members(AVTOperator.operatorToSpecName(operatorKind)) do while hasMoreElements() do if (nextElement().objectValue() as AVTMethod).isIdentityArguments(argumentsList) then begin
                        raise AVTCompilerException.create('Duplicate operator ' + AVTOperator.operatorToChar(operatorKind) +' with same arguments in ' + typeRef.simpleName, source, namePos);
                    end;
                    overriddableRef := AVTOperator.create(typeRef, flags, typeReturnRef, operatorKind, argumentsList, namePos, memberDoc);
                finally
                    argumentsList.free();
                end;
                if (flags and (FLAG_ABSTRACT or FLAG_NATIVE)) = 0 then begin
                    overriddableRef.implementationPosition := pos;
                    if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
                        raise AVTCompilerException.create('"{" expected', source, pos);
                    end;
                    pos := skipCurly(source, pos);
                end else begin
                    if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
                        raise AVTCompilerException.create('";" expected', source, pos);
                    end;
                    inc(pos);
                end;
            end;
            LITR_NAME: begin
                memberName := source.getLexemeAnsiString(pos);
                inc(pos);
                case source.getLexemeType(pos) of
                CHAR_PARENTH_OPENED: begin
                    { метод }
                    if typeRef.isStruct() then begin
                        raise AVTCompilerException.create('Methods can not be declared in structures', source, pos);
                    end;
                    if typeRef.isInterface() then begin
                        if (flags and (FLAG_STATIC or FLAG_FINAL)) <> 0 then begin
                            raise AVTCompilerException.create('Interface methods can not be static final', source, bindingPos);
                        end;
                        flags := flags or FLAG_ABSTRACT;
                    end;
                    argumentsPos := pos;
                    argumentsList := Vector.create();
                    try
                        pos := parseArguments(source, typeRef, pos + 1, argumentsList);
                        if (flags and FLAG_INTERRUPT) <> 0 then begin
                            if not typeReturnRef.isVoid() then begin
                                raise AVTCompilerException.create('"void" expected. The interrupt method can return the type void only', source, typeReturnPos);
                            end;
                        end;
                        with typeRef.members(memberName) do while hasMoreElements() do begin
                            memberFoundRef := nextElement().objectValue();
                            if (memberFoundRef is AVTField) or (memberFoundRef is AVTProperty) then begin
                                raise AVTCompilerException.create('Duplicate member ' + memberName + '. Field or property with same name already declared in ' + typeRef.simpleName, source, namePos);
                            end;
                            if (memberFoundRef is AVTMethod) and AVTMethod(memberFoundRef).isIdentityArguments(argumentsList) then begin
                                raise AVTCompilerException.create('Duplicate method ' + memberName + ' with same argument types in ' + typeRef.simpleName, source, argumentsPos);
                            end;
                        end;
                        overriddableRef := AVTMethod.create(typeRef, flags, typeReturnRef, memberName, argumentsList, namePos, pos, memberDoc);
                    finally
                        argumentsList.free();
                    end;
                    if source.getLexemeType(pos) = AVT_THROWS then begin
                        pos := parseThrows(source, typeRef, overriddableRef as AVTMethod, pos + 1);
                    end;
                    if (flags and (FLAG_ABSTRACT or FLAG_NATIVE)) = 0 then begin
                        overriddableRef.implementationPosition := pos;
                        if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
                            raise AVTCompilerException.create('"{" expected', source, pos);
                        end;
                        pos := skipCurly(source, pos);
                    end else begin
                        if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
                            raise AVTCompilerException.create('";" expected', source, pos);
                        end;
                        inc(pos);
                    end;
                end;
                CHAR_CURLY_OPENED: begin
                    { свойство }
                    if typeRef.isStruct() then begin
                        raise AVTCompilerException.create('Properties can not be declared in structures', source, pos);
                    end;
                    if (flags and FLAG_STATIC) <> 0 then begin
                        raise AVTCompilerException.create('Properties can not be static', source, bindingPos);
                    end;
                    if (flags and (FLAG_NATIVE or FLAG_INTERRUPT or FLAG_SYNCHRONIZED)) <> 0 then begin
                        raise AVTCompilerException.create('Implementation details not supported by properties', source, implDetailsPos);
                    end;
                    if typeRef.isInterface() then begin
                        flags := flags or FLAG_ABSTRACT;
                    end;
                    if typeReturnRef.isVoid() then begin
                        raise AVTCompilerException.create('The type void is an invalid type for properties', source, typeReturnPos);
                    end;
                    if typeRef.members(memberName).hasMoreElements() then begin
                        raise AVTCompilerException.create('Duplicate property ' + memberName + '. Another member with same name already declared in ' + typeRef.simpleName, source, namePos);
                    end;
                    overriddableRef := AVTProperty.create(typeRef, flags, typeReturnRef, memberName, namePos, memberDoc);
                    overriddableRef.implementationPosition := pos + 1;
                    pos := skipCurly(source, pos);
                end
                else
                    { поле }
                    if (flags and FLAG_ABSTRACT) <> 0 then begin
                        raise AVTCompilerException.create('Fields can not be abstract', source, bindingPos);
                    end;
                    if (flags and (FLAG_NATIVE or FLAG_INTERRUPT or FLAG_SYNCHRONIZED)) <> 0 then begin
                        raise AVTCompilerException.create('Implementation details not supported by fields', source, implDetailsPos);
                    end;
                    if typeRef.isStruct() and not typeReturnRef.isPrimitive() then begin
                        raise AVTCompilerException.create('Type of structure field must be primitive', source, typeReturnPos);
                    end;
                    if typeRef.isService() then begin
                        if typeRef.isInterface() then begin
                            flags := flags or (FLAG_STATIC or FLAG_FINAL);
                        end else begin
                            flags := flags or FLAG_STATIC;
                        end;
                    end;
                    if typeReturnRef.isVoid() then begin
                        raise AVTCompilerException.create('The type void is an invalid type for fields', source, typeReturnPos);
                    end;
                    if typeRef.members(memberName).hasMoreElements() then begin
                        raise AVTCompilerException.create('Duplicate field ' + memberName + '. Another member with same name already declared in ' + typeRef.simpleName, source, namePos);
                    end;
                    fieldRef := AVTField.create(typeRef, flags, typeReturnRef, 0, memberName, namePos, memberDoc);
                    if source.getLexemeType(pos) = CHAR_EQUALS then begin
                        if (flags and FLAG_STATIC) = 0 then begin
                            raise AVTCompilerException.create('"static" expected. Field with initial value requires static modifier', source, bindingPos);
                        end;
                        inc(pos);
                        fieldRef.implementationPosition := pos;
                        pos := skipValue(source, pos);
                    end;
                    if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
                        raise AVTCompilerException.create('";" expected', source, pos);
                    end;
                    inc(pos);
                end;
            end;
            CHAR_BRACKET_OPENED: begin
                { поле структуры, имеющее длину }
                if not typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Fields with length specified can be declared in structures only', source, pos);
                end;
                if not typeReturnRef.isPrimitive() then begin
                    raise AVTCompilerException.create('Type of structure field must be primitive', source, typeReturnPos);
                end;
                if typeReturnRef.isVoid() then begin
                    raise AVTCompilerException.create('The type void is an invalid type for fields', source, typeReturnPos);
                end;
                inc(namePos, 3);
                inc(pos);
                lxt := source.getLexemeType(pos);
                if (lxt <> LITR_BYTE) and (lxt <> LITR_SHORT) and (lxt <> LITR_INT) then begin
                    raise AVTCompilerException.create('Integer literal between 1 and 65536 expected', source, pos);
                end;
                fieldLength := source.getLexemeInt(pos);
                if (fieldLength < 1) or (fieldLength > $00010000) then begin
                    raise AVTCompilerException.create('Integer literal between 1 and 65536 expected', source, pos);
                end;
                inc(pos);
                if source.getLexemeType(pos) <> CHAR_BRACKET_CLOSED then begin
                    raise AVTCompilerException.create('"]" expected', source, pos);
                end;
                inc(pos);
                typeReturnRef := programme.systemPackage.getType(typeReturnRef.simpleName + '[]');
                if source.getLexemeType(pos) <> LITR_NAME then begin
                    AVTField.create(typeRef, flags, typeReturnRef, fieldLength, '');
                end else begin
                    memberName := source.getLexemeAnsiString(pos);
                    inc(pos);
                    if typeRef.members(memberName).hasMoreElements() then begin
                        raise AVTCompilerException.create('Duplicate field ' + memberName + '. Another member with same name already declared in ' + typeRef.simpleName, source, namePos);
                    end;
                    AVTField.create(typeRef, flags, typeReturnRef, fieldLength, memberName, namePos, memberDoc);
                end;
                if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
                    raise AVTCompilerException.create('";" expected', source, pos);
                end;
                inc(pos);
            end;
            CHAR_SEMICOLON: begin
                { поле структуры, безымянное }
                if not typeRef.isStruct() then begin
                    raise AVTCompilerException.create('Unnamed fields can be declared in structures only', source, pos);
                end;
                if not typeReturnRef.isPrimitive() then begin
                    raise AVTCompilerException.create('Type of structure field must be primitive', source, typeReturnPos);
                end;
                if typeReturnRef.isVoid() then begin
                    raise AVTCompilerException.create('The type void is an invalid type for fields', source, typeReturnPos);
                end;
                AVTField.create(typeRef, flags, typeReturnRef, 0, '');
                inc(pos);
            end
            else
                raise AVTCompilerException.create('Member name or "operator" expected', source, pos);
            end;
        until false;
    end;

    procedure AVTTableBuilder.parseFields(typeRef: AVTTypeStructured);
    var
        mem: TObject;
    begin
        with typeRef.members() do while hasMoreElements() do begin
            mem := nextElement().objectValue();
            if (mem is AVTField) and AVTItem(mem).isStatic() then begin
                parseFieldInitialValue(AVTField(mem));
            end;
        end;
    end;

    procedure AVTTableBuilder.parseProperties(typeRef: AVTTypeStructured);
    var
        mem: TObject;
    begin
        with typeRef.members() do while hasMoreElements() do begin
            mem := nextElement().objectValue();
            if mem is AVTProperty then begin
                parsePropertyImplementation(AVTProperty(mem));
            end;
        end;
    end;
{%endregion}

end.