import { Node, Parent } from './nodes';
import { Test } from './test';
/**
 * Continue traversing as normal.
 */
export declare const CONTINUE = true;
/**
 * Do not traverse this node’s children
 */
export declare const SKIP = "skip";
/**
 * Stop traversing immediately
 */
export declare const EXIT = false;
/**
 * Union of the action types
 */
export type Action = true | false | 'skip';
/**
 * Move to the sibling at index next (after node itself is completely traversed).
 * Useful if mutating the tree, such as removing the node the visitor is currently on,
 * or any of its previous siblings (or next siblings, in case of reverse)
 * Results less than 0 or greater than or equal to children.length stop traversing the parent
 */
export type Index = number;
/**
 * List with one or two values, the first an action, the second an index.
 */
export type ActionTuple = [Action, Index];
export type VisitorResult = void | Action | Index | ActionTuple;
/**
 * Invoked when a node (matching test, if given) is found.
 * Visitors are free to transform node. They can also transform the parent of node (the last of ancestors).
 * Replacing node itself, if visit.SKIP is not returned, still causes its descendants to be visited.
 * If adding or removing previous siblings (or next siblings, in case of reverse) of node, visitor should return a new index (number) to specify the sibling to traverse after node is traversed.
 * Adding or removing next siblings of node (or previous siblings, in case of reverse) is handled as expected without needing to return a new index.
 * Removing the children property of an ancestor still results in them being traversed.
 *
 * @param node  The active Node
 * @param index Index of Node within it's Parent's list of children.
 * @param parents   Ancestors of node (parent of node will be parents[parents.length-1])
 * @param ctx   Whatever was originally provided to @see VisitOptions.context
 * @returns The return value can have the following forms:
 *          index (number) — Treated as a tuple of [CONTINUE, index]
 *               Move to the sibling at index next (after node itself is completely traversed).
 *               Useful if mutating the tree, such as removing the node the visitor is currently on, or any of its previous siblings (or next siblings, in case of reverse)
 *               Results less than 0 or greater than or equal to children.length stop traversing the parent
 *          action (*) — Treated as a tuple of [action]
 *              CONTINUE:   Continue traversing as normal (same behaviour as not returning anything)
 *              SKIP:   Do not traverse this node’s children (continue with the specified index)
 *              EXIT:   Stop traversing immediately
 *          tuple (Array.<*>) — List with one or two values, the first an action, the second and index.
 *              Note that passing a tuple only makes sense if the action is SKIP. If the action is EXIT, that action can be returned. If the action is CONTINUE, index can be returned.
 */
export type Visitor<T extends Node, P extends Parent, C extends any = never> = (node: T, index: number, parents: P[], ctx: C) => VisitorResult;
/**
 * Options for more control over visitation.
 */
export interface VisitOptions<C extends any = never> {
    /**
     * When false, the tree is traversed in preorder (NLR), visiting the node itself, then its head, etc.
     * When true, the tree is traversed in reverse preorder (NRL): the node itself is visited, then its tail, etc.
     * (default: false)
     */
    reverse?: boolean;
    /**
     *  When true, the Visitor will be called once for every Node which has children, before those children are visited.
     *  The Visitor will be invoked as:
     *      Visitor(undefined, PreTraversalIndex (aka Number.MIN_SAFE_INTEGER), parents);
     *          NOTE: parents[parents.length-1] will be the Node whose children are about to be visited.
     * (default: false)
     */
    preTraverse?: boolean;
    /**
     *  When true, the Visitor will be called once for every Node which has children, after those children have been visited.
     *  The Visitor will be invoked as:
     *      Visitor(undefined, PostTraversalIndex (aka Number.MAX_SAFE_INTEGER), parents);
     *          NOTE: parents[parents.length-1] will be the Node whose children have just been visited
     * (default: false)
     */
    postTraverse?: boolean;
    /**
     * Caller defined context that will be passed to every invocation of the @see Visitor.
     */
    context?: C;
}
export declare const PreTraversalIndex: number;
export declare const PostTraversalIndex: number;
export declare function visitorResultToTuple(value: any): any;
export declare const vistorResultToTuple: typeof visitorResultToTuple;
export declare function visit<T extends Node<any>, P extends Parent<T>, C extends any = never>(tree: T | T[], visitor: Visitor<T, P, C>): any;
export declare function visit<T extends Node<any>, P extends Parent<T>, C extends any = never>(tree: T | T[], visitor: Visitor<T, P, C>, options: boolean | VisitOptions<C>): any;
export declare function visit<T extends Node<any>, P extends Parent<T>, C extends any = never>(tree: T | T[], tst: Test<T>, visitor: Visitor<T, P, C>): any;
export declare function visit<T extends Node<any>, P extends Parent<T>, C extends any = never>(tree: T | T[], tst: Test<T>, visitor: Visitor<T, P, C>, options: boolean | VisitOptions<C>): any;
