trantree.pas

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

{
    Этот исходный текст является частью Продвинутого векторного транслятора.

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

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

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

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

unit TranTree;

{$MODE DELPHI,EXTENDEDSYNTAX ON}

interface

uses
    Lang, Utils, TranIntf;

{$ASMMODE INTEL,CALLING REGISTER,INLINE ON,GOTO ON}
{$H+,I-,J-,M-,Q-,R-,T-}

type
    SyntaxNode = interface;
    SyntaxTree = interface;
    TranslatorSyntaxNode = class;
    TranslatorSyntaxTree = class;

    TranslatorSyntaxNode_Class = class of TranslatorSyntaxNode;

    SyntaxNode = interface(Node) ['{2187DBA7-8D82-42DE-95E7-6B43015BBA93}']
        procedure clearData();
        procedure setPosition(position: int);
        procedure setValue(value: int);
        procedure setAssociate(associate: _Interface);
        procedure setDataType(dataType: TypeDescriptor);
        procedure setDataAssociate(position, value: int;
                dataType: TypeDescriptor; associate: _Interface);
        procedure setGoAlwaysToNode(goAlwaysToNode: SyntaxNode);
        procedure setGoIfTrueToNode(goIfTrueToNode: SyntaxNode);
        procedure setGoIfFalseToNode(goIfFalseToNode: SyntaxNode);
        procedure setDataGoToNode(ifTrue, ifFalse: SyntaxNode);
        function getLabelNumber(): int;
        function getPosition(): int;
        function getValue(): int;
        function getDataType(): TypeDescriptor;
        function getAssociate(): _Interface;
        function getGoAlwaysToNode(): SyntaxNode;
        function getGoIfTrueToNode(): SyntaxNode;
        function getGoIfFalseToNode(): SyntaxNode;
        function getChildWithMaxLabelNumber(): SyntaxNode;
        function getChildWithMinLabelNumber(): SyntaxNode;
        property labelNumber: int read getLabelNumber;
        property position: int read getPosition write setPosition;
        property value: int read getValue write setValue;
        property dataType: TypeDescriptor read getDataType write setDataType;
        property associate: _Interface read getAssociate write setAssociate;
        property goAlwaysToNode: SyntaxNode read getGoAlwaysToNode write setGoAlwaysToNode;
        property goIfTrueToNode: SyntaxNode read getGoIfTrueToNode write setGoIfTrueToNode;
        property goIfFalseToNode: SyntaxNode read getGoIfFalseToNode write setGoIfFalseToNode;
    end;

    SyntaxTree = interface(Tree) ['{2187DBA7-8D82-42DE-95E7-6B43015BBA94}']
        procedure deleteLabelNumber(labelNumber: int);
        function assignLabelNumberTo(node: SyntaxNode): int;
        function setLabelNumber(node: SyntaxNode; labelNumber: int): int;
        function getNodesWithLabelNumberCount(): int;
        function getNodeWithLabelNumber(labelNumber: int): SyntaxNode;
        function getLexemes(): Lexer;
        property lexemes: Lexer read getLexemes;
    end;

    TranslatorSyntaxNode = class(RefCountInterfacedObject, Node, SyntaxNode)
    public
        constructor create(); virtual;
        procedure setIndex(index: int); virtual;
        procedure setParent(parent: Node; index: int); virtual;
        function isParent(parentForTest: Node): boolean; virtual;
        function getIndex(): int; virtual;
        function getChildrensCount(): int; virtual;
        function getChild(index: int): Node; virtual;
        function getParent(): Node; virtual;
        function getOwner(): Tree; virtual;
        function enumerateChildrens(): NodeEnumerator; virtual;
        procedure clearData(); virtual;
        procedure setPosition(position: int); virtual;
        procedure setValue(value: int); virtual;
        procedure setAssociate(associate: _Interface); virtual;
        procedure setDataType(dataType: TypeDescriptor); virtual;
        procedure setDataAssociate(position, value: int;
                dataType: TypeDescriptor; associate: _Interface); virtual;
        procedure setGoAlwaysToNode(goAlwaysToNode: SyntaxNode); virtual;
        procedure setGoIfTrueToNode(goIfTrueToNode: SyntaxNode); virtual;
        procedure setGoIfFalseToNode(goIfFalseToNode: SyntaxNode); virtual;
        procedure setDataGoToNode(ifTrue, ifFalse: SyntaxNode); virtual;
        function getLabelNumber(): int; virtual;
        function getPosition(): int; virtual;
        function getValue(): int; virtual;
        function getDataType(): TypeDescriptor; virtual;
        function getAssociate(): _Interface; virtual;
        function getGoAlwaysToNode(): SyntaxNode; virtual;
        function getGoIfTrueToNode(): SyntaxNode; virtual;
        function getGoIfFalseToNode(): SyntaxNode; virtual;
        function getChildWithMaxLabelNumber(): SyntaxNode; virtual;
        function getChildWithMinLabelNumber(): SyntaxNode; virtual;
    private
        labelNumber: int;
        index: int;
        count: int;
        childrens: Node_Array1d;
        parent: TranslatorSyntaxNode;
        owner: TranslatorSyntaxTree;
        procedure addChild(child: Node);
        procedure insertChild(index: int; child: Node);
        procedure deleteChild(index: int);
        function isSubNodeFor(parentForTest: TranslatorSyntaxNode): boolean;
    private
        position: int;
        value: int;
        dataType: TypeDescriptor;
        associate: _Interface;
        goAlwaysToNode: SyntaxNode;
        goIfTrueToNode: SyntaxNode;
        goIfFalseToNode: SyntaxNode;
    end;

    TranslatorSyntaxTree = class(RefCountInterfacedObject, Tree, SyntaxTree)
    public
        constructor create(); overload;
        constructor create(lexemes: Lexer); overload;
        constructor create(lexemes: Lexer; nodesClass: TranslatorSyntaxNode_Class); overload;
        procedure deleteChildrens(parent: Node); virtual;
        procedure deleteNode(sibling: Node); virtual;
        function addChildLast(parent: Node): Node; virtual;
        function addChildFirst(parent: Node): Node; virtual;
        function addNodeAfter(sibling: Node): Node; virtual;
        function addNodeBefore(sibling: Node): Node; virtual;
        function getRoot(): Node; virtual;
        procedure deleteLabelNumber(labelNumber: int); virtual;
        function assignLabelNumberTo(node: SyntaxNode): int; virtual;
        function setLabelNumber(node: SyntaxNode; labelNumber: int): int; virtual;
        function getNodesWithLabelNumberCount(): int; virtual;
        function getNodeWithLabelNumber(labelNumber: int): SyntaxNode; virtual;
        function getLexemes(): Lexer; virtual;
    private
        count: int;
        countWithLabelNumber: int;
        nodes: Node_Array1d;
        root: SyntaxNode;
        lexemes: Lexer;
        nodesClass: TranslatorSyntaxNode_Class;
        procedure add(node: Node);
        procedure delete(index: int);
        procedure move(oldIndex, newIndex: int);
        function indexOf(node: Node): int;
    end;

resourcestring
    msgCannotChangeParentOnDeleted = 'Нельзя сменить родительский узел у удалённого узла.';
    msgCannotChangeParentOnRootNode = 'Нельзя сменить родительский узел у корневого узла.';
    msgCannotSetSubNodeAsParent = 'Нельзя установить подчинённый узел в качестве родительского.';

implementation

type
    TranslatorNodeEnumerator = class;

    TranslatorNodeEnumerator = class(RefCountInterfacedObject, NodeEnumerator)
    public
        constructor create(node: TranslatorSyntaxNode);
        destructor destroy; override;
        function nextChild(): Node; virtual;
        function nextSibling(): Node; virtual;
    strict private
        index: int;
        istack: Stack;
        node: TranslatorSyntaxNode;
    end;

function ifThen(condition: boolean; valueIfTrue, valueIfFalse: int): int; inline;
begin
    if condition = true then begin
        result := valueIfTrue;
    end else begin
        result := valueIfFalse;
    end;
end;

{ TranslatorSyntaxNode }

constructor TranslatorSyntaxNode.create();
begin
    inherited create();
end;

procedure TranslatorSyntaxNode.setIndex(index: int);
begin
    setParent(parent, index);
end;

procedure TranslatorSyntaxNode.setParent(parent: Node; index: int);
var
    oldIndex: int;
    newIndex: int;
    oldParent: TranslatorSyntaxNode;
    newParent: TranslatorSyntaxNode;
    ownedTree: TranslatorSyntaxTree;
begin
    ownedTree := self.owner;
    if ownedTree = nil then begin
        raise IllegalStateException.create(msgCannotChangeParentOnDeleted);
    end;
    if parent = nil then begin
        parent := ownedTree.root;
    end;
    if not (parent is TranslatorSyntaxNode) or
            (ownedTree <> (parent as TranslatorSyntaxNode).owner) then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'parent');
    end;
    oldParent := self.parent;
    if oldParent = nil then begin
        raise IllegalStateException.create(msgCannotChangeParentOnRootNode);
    end;
    newParent := parent as TranslatorSyntaxNode;
    if (newParent = self) or newParent.isSubNodeFor(self) then begin
        raise IllegalArgumentException.create(msgCannotSetSubNodeAsParent);
    end;
    oldIndex := self.index;
    newIndex := Math.max(Math.min(newParent.count, index), 0);
    if (newParent = oldParent) and (newIndex > oldIndex) then begin
        dec(newIndex);
    end;
    oldParent.deleteChild(oldIndex);
    newParent.insertChild(newIndex, self);
    self.parent := newParent;
end;

function TranslatorSyntaxNode.isParent(parentForTest: Node): boolean;
var
    current: TranslatorSyntaxNode;
    parentAsObject: TObject;
begin
    current := self;
    parentAsObject := parentForTest as TObject;
    while (current <> nil) and (current <> parentAsObject) do begin
        current := current.parent;
    end;
    result := current = parentAsObject;
end;

function TranslatorSyntaxNode.getIndex(): int;
begin
    result := index;
end;

function TranslatorSyntaxNode.getChildrensCount(): int;
begin
    result := count;
end;

function TranslatorSyntaxNode.getChild(index: int): Node;
begin
    if (index < 0) or (index >= count) then begin
        raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
    end;
    result := childrens[index];
end;

function TranslatorSyntaxNode.getParent(): Node;
begin
    result := parent;
end;

function TranslatorSyntaxNode.getOwner(): Tree;
begin
    result := owner;
end;

function TranslatorSyntaxNode.enumerateChildrens(): NodeEnumerator;
begin
    result := TranslatorNodeEnumerator.create(self);
end;

procedure TranslatorSyntaxNode.clearData();
begin
    position := -1;
    value := 0;
    dataType := nil;
    associate := nil;
    goAlwaysToNode := nil;
    goIfTrueToNode := nil;
    goIfFalseToNode := nil;
end;

procedure TranslatorSyntaxNode.setPosition(position: int);
begin
    self.position := position;
end;

procedure TranslatorSyntaxNode.setValue(value: int);
begin
    self.value := value;
end;

procedure TranslatorSyntaxNode.setAssociate(associate: _Interface);
begin
    self.associate := associate;
end;

procedure TranslatorSyntaxNode.setDataType(dataType: TypeDescriptor);
begin
    self.dataType := dataType;
end;

procedure TranslatorSyntaxNode.setDataAssociate(position, value: int;
        dataType: TypeDescriptor; associate: _Interface);
begin
    self.position := position;
    self.value := value;
    self.dataType := dataType;
    self.associate := associate;
end;

procedure TranslatorSyntaxNode.setGoAlwaysToNode(goAlwaysToNode: SyntaxNode);
begin
    self.goAlwaysToNode := goAlwaysToNode;
    self.goIfTrueToNode := nil;
    self.goIfFalseToNode := nil;
end;

procedure TranslatorSyntaxNode.setGoIfTrueToNode(goIfTrueToNode: SyntaxNode);
begin
    self.goAlwaysToNode := nil;
    self.goIfTrueToNode := goIfTrueToNode;
end;

procedure TranslatorSyntaxNode.setGoIfFalseToNode(goIfFalseToNode: SyntaxNode);
begin
    self.goAlwaysToNode := nil;
    self.goIfFalseToNode := goIfFalseToNode;
end;

procedure TranslatorSyntaxNode.setDataGoToNode(ifTrue, ifFalse: SyntaxNode);
begin
    self.goAlwaysToNode := nil;
    self.goIfTrueToNode := ifTrue;
    self.goIfFalseToNode := ifFalse;
end;

function TranslatorSyntaxNode.getLabelNumber(): int;
begin
    result := labelNumber;
end;

function TranslatorSyntaxNode.getPosition(): int;
begin
    result := position;
end;

function TranslatorSyntaxNode.getValue(): int;
begin
    result := value;
end;

function TranslatorSyntaxNode.getDataType(): TypeDescriptor;
begin
    result := dataType;
end;

function TranslatorSyntaxNode.getAssociate(): _Interface;
begin
    result := associate;
end;

function TranslatorSyntaxNode.getGoAlwaysToNode(): SyntaxNode;
begin
    result := goAlwaysToNode;
end;

function TranslatorSyntaxNode.getGoIfTrueToNode(): SyntaxNode;
begin
    result := goIfTrueToNode;
end;

function TranslatorSyntaxNode.getGoIfFalseToNode(): SyntaxNode;
begin
    result := goIfFalseToNode;
end;

function TranslatorSyntaxNode.getChildWithMaxLabelNumber(): SyntaxNode;
var
    nodeLabelNumber: int;
    resultLabelNumber: int;
    node: TranslatorSyntaxNode;
    enum: NodeEnumerator;
begin
    resultLabelNumber := self.labelNumber;
    if resultLabelNumber < 0 then begin
        result := nil;
    end else begin
        result := self;
    end;
    enum := TranslatorNodeEnumerator.create(self);
    repeat
        node := enum.nextChild() as TranslatorSyntaxNode;
        if node = nil then begin
            break;
        end;
        nodeLabelNumber := node.labelNumber;
        if (nodeLabelNumber >= 0) and ((resultLabelNumber < 0) or
                (nodeLabelNumber > resultLabelNumber)) then begin
            resultLabelNumber := nodeLabelNumber;
            result := node;
        end;
    until false;
end;

function TranslatorSyntaxNode.getChildWithMinLabelNumber(): SyntaxNode;
var
    nodeLabelNumber: int;
    resultLabelNumber: int;
    node: TranslatorSyntaxNode;
    enum: NodeEnumerator;
begin
    resultLabelNumber := self.labelNumber;
    if resultLabelNumber < 0 then begin
        result := nil;
    end else begin
        result := self;
    end;
    enum := TranslatorNodeEnumerator.create(self);
    repeat
        node := enum.nextChild() as TranslatorSyntaxNode;
        if node = nil then begin
            break;
        end;
        nodeLabelNumber := node.labelNumber;
        if (nodeLabelNumber >= 0) and ((resultLabelNumber < 0) or
                (nodeLabelNumber < resultLabelNumber)) then begin
            resultLabelNumber := nodeLabelNumber;
            result := node;
        end;
    until false;
end;

procedure TranslatorSyntaxNode.addChild(child: Node);
var
    c: int;
    childrens: Node_Array1d;
    newchildrens: Node_Array1d;
begin
    c := self.count;
    childrens := self.childrens;
    if length(childrens) = c then begin
        newchildrens := Node_Array1d(Interface_Array1d_create((c shl 1) + 1));
        arraycopyInterfaces(childrens, 0, newchildrens, 0, c);
        self.childrens := newchildrens;
        childrens := newchildrens;
    end;
    childrens[c] := child;
    self.count := c + 1;
end;

procedure TranslatorSyntaxNode.insertChild(index: int; child: Node);
var
    i: int;
    c: int;
    e: int;
    childrens: Node_Array1d;
    newchildrens: Node_Array1d;
begin
    c := self.count;
    childrens := self.childrens;
    if length(childrens) = c then begin
        newchildrens := Node_Array1d(Interface_Array1d_create((c shl 1) + 1));
        arraycopyInterfaces(childrens, 0, newchildrens, 0, c);
        self.childrens := newchildrens;
        childrens := newchildrens;
    end;
    e := c - index;
    if e > 0 then begin
        arraycopyInterfaces(childrens, index, childrens, index + 1, e);
    end;
    childrens[index] := child;
    self.count := c + 1;
    for i := index to c do begin
        (childrens[i] as TranslatorSyntaxNode).index := i;
    end;
end;

procedure TranslatorSyntaxNode.deleteChild(index: int);
var
    i: int;
    c: int;
    e: int;
    childrens: Node_Array1d;
begin
    c := self.count - 1;
    e := c - index;
    childrens := self.childrens;
    if e > 0 then begin
        arraycopyInterfaces(childrens, index + 1, childrens, index, e);
    end;
    childrens[c] := nil;
    self.count := c;
    for i := c - 1 downto index do begin
        (childrens[i] as TranslatorSyntaxNode).index := i;
    end;
end;

function TranslatorSyntaxNode.isSubNodeFor(parentForTest: TranslatorSyntaxNode): boolean;
var
    current: TranslatorSyntaxNode;
begin
    current := self.parent;
    while (current <> nil) and (current <> parentForTest) do begin
        current := current.parent;
    end;
    result := current = parentForTest;
end;

{ TranslatorSyntaxTree }

constructor TranslatorSyntaxTree.create();
begin
    create(nil, TranslatorSyntaxNode);
end;

constructor TranslatorSyntaxTree.create(lexemes: Lexer);
begin
    create(lexemes, TranslatorSyntaxNode);
end;

constructor TranslatorSyntaxTree.create(lexemes: Lexer; nodesClass: TranslatorSyntaxNode_Class);
var
    root: TranslatorSyntaxNode;
begin
    inherited create();
    if nodesClass = nil then begin
        nodesClass := TranslatorSyntaxNode;
    end;
    root := nodesClass.create();
    root.labelNumber := -1;
    root.index := -1;
    root.owner := self;
    root.position := -1;
    self.count := 1;
    self.countWithLabelNumber := 0;
    self.nodes := Node_Array1d(Interface_Array1d_create([
        root as SyntaxNode
    ]));
    self.root := root;
    self.lexemes := lexemes;
    self.nodesClass := nodesClass;
end;

procedure TranslatorSyntaxTree.deleteChildrens(parent: Node);
var
    i: int;
    c: int;
    nodes: Node_Array1d;
    current: TranslatorSyntaxNode;
    parentAsSyntaxNode: TranslatorSyntaxNode;
begin
    if parent = nil then begin
        parent := root;
    end;
    if not (parent is TranslatorSyntaxNode) or
            (self <> (parent as TranslatorSyntaxNode).owner) then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'parent');
    end;
    c := self.count - 1;
    nodes := self.nodes;
    parentAsSyntaxNode := parent as TranslatorSyntaxNode;
    for i := c downto 0 do begin
        current := nodes[i] as TranslatorSyntaxNode;
        if current.isSubNodeFor(parentAsSyntaxNode) then begin
            current.owner := nil;
        end;
    end;
    for i := c downto 0 do begin
        current := nodes[i] as TranslatorSyntaxNode;
        if current.owner <> nil then begin
            continue;
        end;
        if current.parent = parentAsSyntaxNode then begin
            current.index := -1;
            current.parent := nil;
        end;
        current.clearData();
        delete(i);
    end;
    parentAsSyntaxNode.count := 0;
    parentAsSyntaxNode.childrens := nil;
end;

procedure TranslatorSyntaxTree.deleteNode(sibling: Node);
var
    i: int;
    c: int;
    index: int;
    nodes: Node_Array1d;
    current: TranslatorSyntaxNode;
    parentAsSyntaxNode: TranslatorSyntaxNode;
    siblingAsSyntaxNode: TranslatorSyntaxNode;
begin
    if not (sibling is TranslatorSyntaxNode) or
            (self <> (sibling as TranslatorSyntaxNode).owner) or (root = sibling) then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'sibling');
    end;
    c := self.count - 1;
    nodes := self.nodes;
    siblingAsSyntaxNode := sibling as TranslatorSyntaxNode;
    parentAsSyntaxNode := siblingAsSyntaxNode.parent;
    index := siblingAsSyntaxNode.index;
    for i := c downto 0 do begin
        current := nodes[i] as TranslatorSyntaxNode;
        if (current = siblingAsSyntaxNode) or current.isSubNodeFor(siblingAsSyntaxNode) then begin
            current.owner := nil;
        end;
    end;
    for i := c downto 0 do begin
        current := nodes[i] as TranslatorSyntaxNode;
        if current.owner <> nil then begin
            continue;
        end;
        if current = siblingAsSyntaxNode then begin
            current.index := -1;
            current.parent := nil;
        end;
        current.clearData();
        delete(i);
    end;
    parentAsSyntaxNode.deleteChild(index);
end;

function TranslatorSyntaxTree.addChildLast(parent: Node): Node;
var
    resultAsSyntaxNode: TranslatorSyntaxNode;
    parentAsSyntaxNode: TranslatorSyntaxNode;
begin
    if parent = nil then begin
        parent := root;
    end;
    if not (parent is TranslatorSyntaxNode) or
            (self <> (parent as TranslatorSyntaxNode).owner) then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'parent');
    end;
    parentAsSyntaxNode := parent as TranslatorSyntaxNode;
    resultAsSyntaxNode := nodesClass.create();
    resultAsSyntaxNode.labelNumber := -1;
    resultAsSyntaxNode.index := parentAsSyntaxNode.count;
    resultAsSyntaxNode.parent := parentAsSyntaxNode;
    resultAsSyntaxNode.owner := self;
    resultAsSyntaxNode.position := -1;
    result := resultAsSyntaxNode;
    parentAsSyntaxNode.addChild(result);
    add(result);
end;

function TranslatorSyntaxTree.addChildFirst(parent: Node): Node;
var
    resultAsSyntaxNode: TranslatorSyntaxNode;
    parentAsSyntaxNode: TranslatorSyntaxNode;
begin
    if parent = nil then begin
        parent := root;
    end;
    if not (parent is TranslatorSyntaxNode) or
            (self <> (parent as TranslatorSyntaxNode).owner) then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'parent');
    end;
    parentAsSyntaxNode := parent as TranslatorSyntaxNode;
    resultAsSyntaxNode := nodesClass.create();
    resultAsSyntaxNode.labelNumber := -1;
    resultAsSyntaxNode.index := 0;
    resultAsSyntaxNode.parent := parentAsSyntaxNode;
    resultAsSyntaxNode.owner := self;
    resultAsSyntaxNode.position := -1;
    result := resultAsSyntaxNode;
    parentAsSyntaxNode.insertChild(0, result);
    add(result);
end;

function TranslatorSyntaxTree.addNodeAfter(sibling: Node): Node;
var
    index: int;
    resultAsSyntaxNode: TranslatorSyntaxNode;
    parentAsSyntaxNode: TranslatorSyntaxNode;
    siblingAsSyntaxNode: TranslatorSyntaxNode;
begin
    if not (sibling is TranslatorSyntaxNode) or
            (self <> (sibling as TranslatorSyntaxNode).owner) or (root = sibling) then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'sibling');
    end;
    siblingAsSyntaxNode := sibling as TranslatorSyntaxNode;
    parentAsSyntaxNode := siblingAsSyntaxNode.parent;
    resultAsSyntaxNode := nodesClass.create();
    index := siblingAsSyntaxNode.index + 1;
    resultAsSyntaxNode.labelNumber := -1;
    resultAsSyntaxNode.index := index;
    resultAsSyntaxNode.parent := parentAsSyntaxNode;
    resultAsSyntaxNode.owner := self;
    resultAsSyntaxNode.position := -1;
    result := resultAsSyntaxNode;
    parentAsSyntaxNode.insertChild(index, result);
    add(result);
end;

function TranslatorSyntaxTree.addNodeBefore(sibling: Node): Node;
var
    index: int;
    resultAsSyntaxNode: TranslatorSyntaxNode;
    parentAsSyntaxNode: TranslatorSyntaxNode;
    siblingAsSyntaxNode: TranslatorSyntaxNode;
begin
    if not (sibling is TranslatorSyntaxNode) or
            (self <> (sibling as TranslatorSyntaxNode).owner) or (root = sibling) then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'sibling');
    end;
    siblingAsSyntaxNode := sibling as TranslatorSyntaxNode;
    parentAsSyntaxNode := siblingAsSyntaxNode.parent;
    resultAsSyntaxNode := nodesClass.create();
    index := siblingAsSyntaxNode.index;
    resultAsSyntaxNode.labelNumber := -1;
    resultAsSyntaxNode.index := index;
    resultAsSyntaxNode.parent := parentAsSyntaxNode;
    resultAsSyntaxNode.owner := self;
    resultAsSyntaxNode.position := -1;
    result := resultAsSyntaxNode;
    parentAsSyntaxNode.insertChild(index, result);
    add(result);
end;

function TranslatorSyntaxTree.getRoot(): Node;
begin
    result := root;
end;

procedure TranslatorSyntaxTree.deleteLabelNumber(labelNumber: int);
var
    w: int;
begin
    w := countWithLabelNumber - 1;
    if (labelNumber < 0) or (labelNumber > w) then begin
        raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
    end;
    countWithLabelNumber := w;
    move(labelNumber, w);
end;

function TranslatorSyntaxTree.assignLabelNumberTo(node: SyntaxNode): int;
var
    nodeAsSyntaxNode: TranslatorSyntaxNode;
begin
    if node = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    if not (node is TranslatorSyntaxNode) or
            (self <> (node as TranslatorSyntaxNode).owner) then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'node');
    end;
    nodeAsSyntaxNode := node as TranslatorSyntaxNode;
    result := nodeAsSyntaxNode.labelNumber;
    if result >= 0 then begin
        exit;
    end;
    result := countWithLabelNumber;
    countWithLabelNumber := result + 1;
    move(indexOf(node), result);
end;

function TranslatorSyntaxTree.setLabelNumber(node: SyntaxNode; labelNumber: int): int;
var
    w: int;
    currentNumber: int;
    nodeAsSyntaxNode: TranslatorSyntaxNode;
begin
    if node = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    if not (node is TranslatorSyntaxNode) or
            (self <> (node as TranslatorSyntaxNode).owner) then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'node');
    end;
    nodeAsSyntaxNode := node as TranslatorSyntaxNode;
    currentNumber := nodeAsSyntaxNode.labelNumber;
    w := countWithLabelNumber;
    if labelNumber < -1 then begin
        labelNumber := -1;
    end;
    if currentNumber >= 0 then begin
        if labelNumber >= 0 then begin
            if labelNumber >= w then begin
                labelNumber := w - 1;
            end;
            move(currentNumber, labelNumber);
        end else begin
            dec(w);
            countWithLabelNumber := w;
            move(currentNumber, w);
        end;
    end else
    if labelNumber >= 0 then begin
        if labelNumber > w then begin
            labelNumber := w;
        end;
        countWithLabelNumber := w + 1;
        move(indexOf(node), labelNumber);
    end;
    result := labelNumber;
end;

function TranslatorSyntaxTree.getNodesWithLabelNumberCount(): int;
begin
    result := countWithLabelNumber;
end;

function TranslatorSyntaxTree.getNodeWithLabelNumber(labelNumber: int): SyntaxNode;
begin
    if (labelNumber < 0) or (labelNumber >= countWithLabelNumber) then begin
        raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
    end;
    result := nodes[labelNumber] as SyntaxNode;
end;

function TranslatorSyntaxTree.getLexemes(): Lexer;
begin
    result := lexemes;
end;

procedure TranslatorSyntaxTree.add(node: Node);
var
    c: int;
    nodes: Node_Array1d;
    newnodes: Node_Array1d;
begin
    c := self.count;
    nodes := self.nodes;
    if length(nodes) = c then begin
        newnodes := Node_Array1d(Interface_Array1d_create((c shl 1) + 1));
        arraycopyInterfaces(nodes, 0, newnodes, 0, c);
        self.nodes := newnodes;
        nodes := newnodes;
    end;
    nodes[c] := node;
    self.count := c + 1;
end;

procedure TranslatorSyntaxTree.delete(index: int);
var
    i: int;
    c: int;
    w: int;
    e: int;
    nodes: Node_Array1d;
begin
    c := self.count - 1;
    w := self.countWithLabelNumber - 1;
    e := c - index;
    nodes := self.nodes;
    if e > 0 then begin
        arraycopyInterfaces(nodes, index + 1, nodes, index, e);
    end;
    if index <= w then begin
        self.countWithLabelNumber := w;
        for i := w downto index do begin
            (nodes[i] as TranslatorSyntaxNode).labelNumber := ifThen(i < w, i, -1);
        end;
    end;
    nodes[c] := nil;
    self.count := c;
end;

procedure TranslatorSyntaxTree.move(oldIndex, newIndex: int);
var
    i: int;
    w: int;
    nodes: Node_Array1d;
    n: Node;
begin
    w := self.countWithLabelNumber;
    nodes := self.nodes;
    n := nodes[oldIndex];
    if oldIndex < newIndex then begin
        { перемещение вперёд }
        arraycopyInterfaces(nodes, oldIndex + 1, nodes, oldIndex, newIndex - oldIndex);
        nodes[newIndex] := n;
        for i := oldIndex to newIndex do begin
            (nodes[i] as TranslatorSyntaxNode).labelNumber := ifThen(i < w, i, -1);
        end;
    end else
    if newIndex < oldIndex then begin
        { перемещение назад }
        arraycopyInterfaces(nodes, newIndex, nodes, newIndex + 1, oldIndex - newIndex);
        nodes[newIndex] := n;
        for i := newIndex to oldIndex do begin
            (nodes[i] as TranslatorSyntaxNode).labelNumber := ifThen(i < w, i, -1);
        end;
    end else begin
        { остаться на месте }
        i := oldIndex;
        (nodes[i] as TranslatorSyntaxNode).labelNumber := ifThen(i < w, i, -1);
    end;
end;

function TranslatorSyntaxTree.indexOf(node: Node): int;
var
    i: int;
    nodes: Node_Array1d;
    nobj: TObject;
begin
    nodes := self.nodes;
    nobj := node as TObject;
    for i := count - 1 downto 0 do begin
        if (nodes[i] as TObject) = nobj then begin
            result := i;
            exit;
        end;
    end;
    result := -1;
end;

{ TranslatorNodeEnumerator }

constructor TranslatorNodeEnumerator.create(node: TranslatorSyntaxNode);
begin
    inherited create();
    self.index := 0;
    self.istack := Stack.create();
    self.node := node;
end;

destructor TranslatorNodeEnumerator.destroy;
begin
    istack.free();
    inherited destroy;
end;

function TranslatorNodeEnumerator.nextChild(): Node;
var
    index: int;
    istack: Stack;
    node: TranslatorSyntaxNode;
    resultAsSyntaxNode: TranslatorSyntaxNode;
begin
    istack := self.istack;
    index := self.index;
    node := self.node;
    try
        repeat
            if index < node.count then begin
                result := node.childrens[index];
                resultAsSyntaxNode := result as TranslatorSyntaxNode;
                inc(index);
                if resultAsSyntaxNode.count > 0 then begin
                    istack.push(index);
                    index := 0;
                    node := resultAsSyntaxNode;
                end;
                break;
            end else
            if istack.isEmpty() then begin
                result := nil;
                break;
            end else begin
                index := (istack.pop() as IntegerAsObject).intValue();
                node := node.parent;
            end;
        until false;
    finally
        self.index := index;
        self.node := node;
    end;
end;

function TranslatorNodeEnumerator.nextSibling(): Node;
var
    index: int;
    istack: Stack;
    node: TranslatorSyntaxNode;
begin
    istack := self.istack;
    index := self.index;
    node := self.node;
    try
        repeat
            if index < node.count then begin
                result := node.childrens[index];
                inc(index);
                break;
            end else
            if istack.isEmpty() then begin
                result := nil;
                break;
            end else begin
                index := (istack.pop() as IntegerAsObject).intValue();
                node := node.parent;
            end;
        until false;
    finally
        self.index := index;
        self.node := node;
    end;
end;

end.