| 
						 | 
						- /*
 -   Copyright (C) 2012-2013 Yusuke Suzuki <utatane.tea@gmail.com>
 -   Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
 - 
 -   Redistribution and use in source and binary forms, with or without
 -   modification, are permitted provided that the following conditions are met:
 - 
 -     * Redistributions of source code must retain the above copyright
 -       notice, this list of conditions and the following disclaimer.
 -     * Redistributions in binary form must reproduce the above copyright
 -       notice, this list of conditions and the following disclaimer in the
 -       documentation and/or other materials provided with the distribution.
 - 
 -   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 -   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 -   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 -   ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 -   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 -   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 -   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 -   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 -   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 -   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 - */
 - /*jslint vars:false, bitwise:true*/
 - /*jshint indent:4*/
 - /*global exports:true*/
 - (function clone(exports) {
 -     'use strict';
 - 
 -     var Syntax,
 -         VisitorOption,
 -         VisitorKeys,
 -         BREAK,
 -         SKIP,
 -         REMOVE;
 - 
 -     function deepCopy(obj) {
 -         var ret = {}, key, val;
 -         for (key in obj) {
 -             if (obj.hasOwnProperty(key)) {
 -                 val = obj[key];
 -                 if (typeof val === 'object' && val !== null) {
 -                     ret[key] = deepCopy(val);
 -                 } else {
 -                     ret[key] = val;
 -                 }
 -             }
 -         }
 -         return ret;
 -     }
 - 
 -     // based on LLVM libc++ upper_bound / lower_bound
 -     // MIT License
 - 
 -     function upperBound(array, func) {
 -         var diff, len, i, current;
 - 
 -         len = array.length;
 -         i = 0;
 - 
 -         while (len) {
 -             diff = len >>> 1;
 -             current = i + diff;
 -             if (func(array[current])) {
 -                 len = diff;
 -             } else {
 -                 i = current + 1;
 -                 len -= diff + 1;
 -             }
 -         }
 -         return i;
 -     }
 - 
 -     Syntax = {
 -         AssignmentExpression: 'AssignmentExpression',
 -         AssignmentPattern: 'AssignmentPattern',
 -         ArrayExpression: 'ArrayExpression',
 -         ArrayPattern: 'ArrayPattern',
 -         ArrowFunctionExpression: 'ArrowFunctionExpression',
 -         AwaitExpression: 'AwaitExpression', // CAUTION: It's deferred to ES7.
 -         BlockStatement: 'BlockStatement',
 -         BinaryExpression: 'BinaryExpression',
 -         BreakStatement: 'BreakStatement',
 -         CallExpression: 'CallExpression',
 -         CatchClause: 'CatchClause',
 -         ChainExpression: 'ChainExpression',
 -         ClassBody: 'ClassBody',
 -         ClassDeclaration: 'ClassDeclaration',
 -         ClassExpression: 'ClassExpression',
 -         ComprehensionBlock: 'ComprehensionBlock',  // CAUTION: It's deferred to ES7.
 -         ComprehensionExpression: 'ComprehensionExpression',  // CAUTION: It's deferred to ES7.
 -         ConditionalExpression: 'ConditionalExpression',
 -         ContinueStatement: 'ContinueStatement',
 -         DebuggerStatement: 'DebuggerStatement',
 -         DirectiveStatement: 'DirectiveStatement',
 -         DoWhileStatement: 'DoWhileStatement',
 -         EmptyStatement: 'EmptyStatement',
 -         ExportAllDeclaration: 'ExportAllDeclaration',
 -         ExportDefaultDeclaration: 'ExportDefaultDeclaration',
 -         ExportNamedDeclaration: 'ExportNamedDeclaration',
 -         ExportSpecifier: 'ExportSpecifier',
 -         ExpressionStatement: 'ExpressionStatement',
 -         ForStatement: 'ForStatement',
 -         ForInStatement: 'ForInStatement',
 -         ForOfStatement: 'ForOfStatement',
 -         FunctionDeclaration: 'FunctionDeclaration',
 -         FunctionExpression: 'FunctionExpression',
 -         GeneratorExpression: 'GeneratorExpression',  // CAUTION: It's deferred to ES7.
 -         Identifier: 'Identifier',
 -         IfStatement: 'IfStatement',
 -         ImportExpression: 'ImportExpression',
 -         ImportDeclaration: 'ImportDeclaration',
 -         ImportDefaultSpecifier: 'ImportDefaultSpecifier',
 -         ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
 -         ImportSpecifier: 'ImportSpecifier',
 -         Literal: 'Literal',
 -         LabeledStatement: 'LabeledStatement',
 -         LogicalExpression: 'LogicalExpression',
 -         MemberExpression: 'MemberExpression',
 -         MetaProperty: 'MetaProperty',
 -         MethodDefinition: 'MethodDefinition',
 -         ModuleSpecifier: 'ModuleSpecifier',
 -         NewExpression: 'NewExpression',
 -         ObjectExpression: 'ObjectExpression',
 -         ObjectPattern: 'ObjectPattern',
 -         PrivateIdentifier: 'PrivateIdentifier',
 -         Program: 'Program',
 -         Property: 'Property',
 -         PropertyDefinition: 'PropertyDefinition',
 -         RestElement: 'RestElement',
 -         ReturnStatement: 'ReturnStatement',
 -         SequenceExpression: 'SequenceExpression',
 -         SpreadElement: 'SpreadElement',
 -         Super: 'Super',
 -         SwitchStatement: 'SwitchStatement',
 -         SwitchCase: 'SwitchCase',
 -         TaggedTemplateExpression: 'TaggedTemplateExpression',
 -         TemplateElement: 'TemplateElement',
 -         TemplateLiteral: 'TemplateLiteral',
 -         ThisExpression: 'ThisExpression',
 -         ThrowStatement: 'ThrowStatement',
 -         TryStatement: 'TryStatement',
 -         UnaryExpression: 'UnaryExpression',
 -         UpdateExpression: 'UpdateExpression',
 -         VariableDeclaration: 'VariableDeclaration',
 -         VariableDeclarator: 'VariableDeclarator',
 -         WhileStatement: 'WhileStatement',
 -         WithStatement: 'WithStatement',
 -         YieldExpression: 'YieldExpression'
 -     };
 - 
 -     VisitorKeys = {
 -         AssignmentExpression: ['left', 'right'],
 -         AssignmentPattern: ['left', 'right'],
 -         ArrayExpression: ['elements'],
 -         ArrayPattern: ['elements'],
 -         ArrowFunctionExpression: ['params', 'body'],
 -         AwaitExpression: ['argument'], // CAUTION: It's deferred to ES7.
 -         BlockStatement: ['body'],
 -         BinaryExpression: ['left', 'right'],
 -         BreakStatement: ['label'],
 -         CallExpression: ['callee', 'arguments'],
 -         CatchClause: ['param', 'body'],
 -         ChainExpression: ['expression'],
 -         ClassBody: ['body'],
 -         ClassDeclaration: ['id', 'superClass', 'body'],
 -         ClassExpression: ['id', 'superClass', 'body'],
 -         ComprehensionBlock: ['left', 'right'],  // CAUTION: It's deferred to ES7.
 -         ComprehensionExpression: ['blocks', 'filter', 'body'],  // CAUTION: It's deferred to ES7.
 -         ConditionalExpression: ['test', 'consequent', 'alternate'],
 -         ContinueStatement: ['label'],
 -         DebuggerStatement: [],
 -         DirectiveStatement: [],
 -         DoWhileStatement: ['body', 'test'],
 -         EmptyStatement: [],
 -         ExportAllDeclaration: ['source'],
 -         ExportDefaultDeclaration: ['declaration'],
 -         ExportNamedDeclaration: ['declaration', 'specifiers', 'source'],
 -         ExportSpecifier: ['exported', 'local'],
 -         ExpressionStatement: ['expression'],
 -         ForStatement: ['init', 'test', 'update', 'body'],
 -         ForInStatement: ['left', 'right', 'body'],
 -         ForOfStatement: ['left', 'right', 'body'],
 -         FunctionDeclaration: ['id', 'params', 'body'],
 -         FunctionExpression: ['id', 'params', 'body'],
 -         GeneratorExpression: ['blocks', 'filter', 'body'],  // CAUTION: It's deferred to ES7.
 -         Identifier: [],
 -         IfStatement: ['test', 'consequent', 'alternate'],
 -         ImportExpression: ['source'],
 -         ImportDeclaration: ['specifiers', 'source'],
 -         ImportDefaultSpecifier: ['local'],
 -         ImportNamespaceSpecifier: ['local'],
 -         ImportSpecifier: ['imported', 'local'],
 -         Literal: [],
 -         LabeledStatement: ['label', 'body'],
 -         LogicalExpression: ['left', 'right'],
 -         MemberExpression: ['object', 'property'],
 -         MetaProperty: ['meta', 'property'],
 -         MethodDefinition: ['key', 'value'],
 -         ModuleSpecifier: [],
 -         NewExpression: ['callee', 'arguments'],
 -         ObjectExpression: ['properties'],
 -         ObjectPattern: ['properties'],
 -         PrivateIdentifier: [],
 -         Program: ['body'],
 -         Property: ['key', 'value'],
 -         PropertyDefinition: ['key', 'value'],
 -         RestElement: [ 'argument' ],
 -         ReturnStatement: ['argument'],
 -         SequenceExpression: ['expressions'],
 -         SpreadElement: ['argument'],
 -         Super: [],
 -         SwitchStatement: ['discriminant', 'cases'],
 -         SwitchCase: ['test', 'consequent'],
 -         TaggedTemplateExpression: ['tag', 'quasi'],
 -         TemplateElement: [],
 -         TemplateLiteral: ['quasis', 'expressions'],
 -         ThisExpression: [],
 -         ThrowStatement: ['argument'],
 -         TryStatement: ['block', 'handler', 'finalizer'],
 -         UnaryExpression: ['argument'],
 -         UpdateExpression: ['argument'],
 -         VariableDeclaration: ['declarations'],
 -         VariableDeclarator: ['id', 'init'],
 -         WhileStatement: ['test', 'body'],
 -         WithStatement: ['object', 'body'],
 -         YieldExpression: ['argument']
 -     };
 - 
 -     // unique id
 -     BREAK = {};
 -     SKIP = {};
 -     REMOVE = {};
 - 
 -     VisitorOption = {
 -         Break: BREAK,
 -         Skip: SKIP,
 -         Remove: REMOVE
 -     };
 - 
 -     function Reference(parent, key) {
 -         this.parent = parent;
 -         this.key = key;
 -     }
 - 
 -     Reference.prototype.replace = function replace(node) {
 -         this.parent[this.key] = node;
 -     };
 - 
 -     Reference.prototype.remove = function remove() {
 -         if (Array.isArray(this.parent)) {
 -             this.parent.splice(this.key, 1);
 -             return true;
 -         } else {
 -             this.replace(null);
 -             return false;
 -         }
 -     };
 - 
 -     function Element(node, path, wrap, ref) {
 -         this.node = node;
 -         this.path = path;
 -         this.wrap = wrap;
 -         this.ref = ref;
 -     }
 - 
 -     function Controller() { }
 - 
 -     // API:
 -     // return property path array from root to current node
 -     Controller.prototype.path = function path() {
 -         var i, iz, j, jz, result, element;
 - 
 -         function addToPath(result, path) {
 -             if (Array.isArray(path)) {
 -                 for (j = 0, jz = path.length; j < jz; ++j) {
 -                     result.push(path[j]);
 -                 }
 -             } else {
 -                 result.push(path);
 -             }
 -         }
 - 
 -         // root node
 -         if (!this.__current.path) {
 -             return null;
 -         }
 - 
 -         // first node is sentinel, second node is root element
 -         result = [];
 -         for (i = 2, iz = this.__leavelist.length; i < iz; ++i) {
 -             element = this.__leavelist[i];
 -             addToPath(result, element.path);
 -         }
 -         addToPath(result, this.__current.path);
 -         return result;
 -     };
 - 
 -     // API:
 -     // return type of current node
 -     Controller.prototype.type = function () {
 -         var node = this.current();
 -         return node.type || this.__current.wrap;
 -     };
 - 
 -     // API:
 -     // return array of parent elements
 -     Controller.prototype.parents = function parents() {
 -         var i, iz, result;
 - 
 -         // first node is sentinel
 -         result = [];
 -         for (i = 1, iz = this.__leavelist.length; i < iz; ++i) {
 -             result.push(this.__leavelist[i].node);
 -         }
 - 
 -         return result;
 -     };
 - 
 -     // API:
 -     // return current node
 -     Controller.prototype.current = function current() {
 -         return this.__current.node;
 -     };
 - 
 -     Controller.prototype.__execute = function __execute(callback, element) {
 -         var previous, result;
 - 
 -         result = undefined;
 - 
 -         previous  = this.__current;
 -         this.__current = element;
 -         this.__state = null;
 -         if (callback) {
 -             result = callback.call(this, element.node, this.__leavelist[this.__leavelist.length - 1].node);
 -         }
 -         this.__current = previous;
 - 
 -         return result;
 -     };
 - 
 -     // API:
 -     // notify control skip / break
 -     Controller.prototype.notify = function notify(flag) {
 -         this.__state = flag;
 -     };
 - 
 -     // API:
 -     // skip child nodes of current node
 -     Controller.prototype.skip = function () {
 -         this.notify(SKIP);
 -     };
 - 
 -     // API:
 -     // break traversals
 -     Controller.prototype['break'] = function () {
 -         this.notify(BREAK);
 -     };
 - 
 -     // API:
 -     // remove node
 -     Controller.prototype.remove = function () {
 -         this.notify(REMOVE);
 -     };
 - 
 -     Controller.prototype.__initialize = function(root, visitor) {
 -         this.visitor = visitor;
 -         this.root = root;
 -         this.__worklist = [];
 -         this.__leavelist = [];
 -         this.__current = null;
 -         this.__state = null;
 -         this.__fallback = null;
 -         if (visitor.fallback === 'iteration') {
 -             this.__fallback = Object.keys;
 -         } else if (typeof visitor.fallback === 'function') {
 -             this.__fallback = visitor.fallback;
 -         }
 - 
 -         this.__keys = VisitorKeys;
 -         if (visitor.keys) {
 -             this.__keys = Object.assign(Object.create(this.__keys), visitor.keys);
 -         }
 -     };
 - 
 -     function isNode(node) {
 -         if (node == null) {
 -             return false;
 -         }
 -         return typeof node === 'object' && typeof node.type === 'string';
 -     }
 - 
 -     function isProperty(nodeType, key) {
 -         return (nodeType === Syntax.ObjectExpression || nodeType === Syntax.ObjectPattern) && 'properties' === key;
 -     }
 -   
 -     function candidateExistsInLeaveList(leavelist, candidate) {
 -         for (var i = leavelist.length - 1; i >= 0; --i) {
 -             if (leavelist[i].node === candidate) {
 -                 return true;
 -             }
 -         }
 -         return false;
 -     }
 - 
 -     Controller.prototype.traverse = function traverse(root, visitor) {
 -         var worklist,
 -             leavelist,
 -             element,
 -             node,
 -             nodeType,
 -             ret,
 -             key,
 -             current,
 -             current2,
 -             candidates,
 -             candidate,
 -             sentinel;
 - 
 -         this.__initialize(root, visitor);
 - 
 -         sentinel = {};
 - 
 -         // reference
 -         worklist = this.__worklist;
 -         leavelist = this.__leavelist;
 - 
 -         // initialize
 -         worklist.push(new Element(root, null, null, null));
 -         leavelist.push(new Element(null, null, null, null));
 - 
 -         while (worklist.length) {
 -             element = worklist.pop();
 - 
 -             if (element === sentinel) {
 -                 element = leavelist.pop();
 - 
 -                 ret = this.__execute(visitor.leave, element);
 - 
 -                 if (this.__state === BREAK || ret === BREAK) {
 -                     return;
 -                 }
 -                 continue;
 -             }
 - 
 -             if (element.node) {
 - 
 -                 ret = this.__execute(visitor.enter, element);
 - 
 -                 if (this.__state === BREAK || ret === BREAK) {
 -                     return;
 -                 }
 - 
 -                 worklist.push(sentinel);
 -                 leavelist.push(element);
 - 
 -                 if (this.__state === SKIP || ret === SKIP) {
 -                     continue;
 -                 }
 - 
 -                 node = element.node;
 -                 nodeType = node.type || element.wrap;
 -                 candidates = this.__keys[nodeType];
 -                 if (!candidates) {
 -                     if (this.__fallback) {
 -                         candidates = this.__fallback(node);
 -                     } else {
 -                         throw new Error('Unknown node type ' + nodeType + '.');
 -                     }
 -                 }
 - 
 -                 current = candidates.length;
 -                 while ((current -= 1) >= 0) {
 -                     key = candidates[current];
 -                     candidate = node[key];
 -                     if (!candidate) {
 -                         continue;
 -                     }
 - 
 -                     if (Array.isArray(candidate)) {
 -                         current2 = candidate.length;
 -                         while ((current2 -= 1) >= 0) {
 -                             if (!candidate[current2]) {
 -                                 continue;
 -                             }
 - 
 -                             if (candidateExistsInLeaveList(leavelist, candidate[current2])) {
 -                               continue;
 -                             }
 - 
 -                             if (isProperty(nodeType, candidates[current])) {
 -                                 element = new Element(candidate[current2], [key, current2], 'Property', null);
 -                             } else if (isNode(candidate[current2])) {
 -                                 element = new Element(candidate[current2], [key, current2], null, null);
 -                             } else {
 -                                 continue;
 -                             }
 -                             worklist.push(element);
 -                         }
 -                     } else if (isNode(candidate)) {
 -                         if (candidateExistsInLeaveList(leavelist, candidate)) {
 -                           continue;
 -                         }
 - 
 -                         worklist.push(new Element(candidate, key, null, null));
 -                     }
 -                 }
 -             }
 -         }
 -     };
 - 
 -     Controller.prototype.replace = function replace(root, visitor) {
 -         var worklist,
 -             leavelist,
 -             node,
 -             nodeType,
 -             target,
 -             element,
 -             current,
 -             current2,
 -             candidates,
 -             candidate,
 -             sentinel,
 -             outer,
 -             key;
 - 
 -         function removeElem(element) {
 -             var i,
 -                 key,
 -                 nextElem,
 -                 parent;
 - 
 -             if (element.ref.remove()) {
 -                 // When the reference is an element of an array.
 -                 key = element.ref.key;
 -                 parent = element.ref.parent;
 - 
 -                 // If removed from array, then decrease following items' keys.
 -                 i = worklist.length;
 -                 while (i--) {
 -                     nextElem = worklist[i];
 -                     if (nextElem.ref && nextElem.ref.parent === parent) {
 -                         if  (nextElem.ref.key < key) {
 -                             break;
 -                         }
 -                         --nextElem.ref.key;
 -                     }
 -                 }
 -             }
 -         }
 - 
 -         this.__initialize(root, visitor);
 - 
 -         sentinel = {};
 - 
 -         // reference
 -         worklist = this.__worklist;
 -         leavelist = this.__leavelist;
 - 
 -         // initialize
 -         outer = {
 -             root: root
 -         };
 -         element = new Element(root, null, null, new Reference(outer, 'root'));
 -         worklist.push(element);
 -         leavelist.push(element);
 - 
 -         while (worklist.length) {
 -             element = worklist.pop();
 - 
 -             if (element === sentinel) {
 -                 element = leavelist.pop();
 - 
 -                 target = this.__execute(visitor.leave, element);
 - 
 -                 // node may be replaced with null,
 -                 // so distinguish between undefined and null in this place
 -                 if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) {
 -                     // replace
 -                     element.ref.replace(target);
 -                 }
 - 
 -                 if (this.__state === REMOVE || target === REMOVE) {
 -                     removeElem(element);
 -                 }
 - 
 -                 if (this.__state === BREAK || target === BREAK) {
 -                     return outer.root;
 -                 }
 -                 continue;
 -             }
 - 
 -             target = this.__execute(visitor.enter, element);
 - 
 -             // node may be replaced with null,
 -             // so distinguish between undefined and null in this place
 -             if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) {
 -                 // replace
 -                 element.ref.replace(target);
 -                 element.node = target;
 -             }
 - 
 -             if (this.__state === REMOVE || target === REMOVE) {
 -                 removeElem(element);
 -                 element.node = null;
 -             }
 - 
 -             if (this.__state === BREAK || target === BREAK) {
 -                 return outer.root;
 -             }
 - 
 -             // node may be null
 -             node = element.node;
 -             if (!node) {
 -                 continue;
 -             }
 - 
 -             worklist.push(sentinel);
 -             leavelist.push(element);
 - 
 -             if (this.__state === SKIP || target === SKIP) {
 -                 continue;
 -             }
 - 
 -             nodeType = node.type || element.wrap;
 -             candidates = this.__keys[nodeType];
 -             if (!candidates) {
 -                 if (this.__fallback) {
 -                     candidates = this.__fallback(node);
 -                 } else {
 -                     throw new Error('Unknown node type ' + nodeType + '.');
 -                 }
 -             }
 - 
 -             current = candidates.length;
 -             while ((current -= 1) >= 0) {
 -                 key = candidates[current];
 -                 candidate = node[key];
 -                 if (!candidate) {
 -                     continue;
 -                 }
 - 
 -                 if (Array.isArray(candidate)) {
 -                     current2 = candidate.length;
 -                     while ((current2 -= 1) >= 0) {
 -                         if (!candidate[current2]) {
 -                             continue;
 -                         }
 -                         if (isProperty(nodeType, candidates[current])) {
 -                             element = new Element(candidate[current2], [key, current2], 'Property', new Reference(candidate, current2));
 -                         } else if (isNode(candidate[current2])) {
 -                             element = new Element(candidate[current2], [key, current2], null, new Reference(candidate, current2));
 -                         } else {
 -                             continue;
 -                         }
 -                         worklist.push(element);
 -                     }
 -                 } else if (isNode(candidate)) {
 -                     worklist.push(new Element(candidate, key, null, new Reference(node, key)));
 -                 }
 -             }
 -         }
 - 
 -         return outer.root;
 -     };
 - 
 -     function traverse(root, visitor) {
 -         var controller = new Controller();
 -         return controller.traverse(root, visitor);
 -     }
 - 
 -     function replace(root, visitor) {
 -         var controller = new Controller();
 -         return controller.replace(root, visitor);
 -     }
 - 
 -     function extendCommentRange(comment, tokens) {
 -         var target;
 - 
 -         target = upperBound(tokens, function search(token) {
 -             return token.range[0] > comment.range[0];
 -         });
 - 
 -         comment.extendedRange = [comment.range[0], comment.range[1]];
 - 
 -         if (target !== tokens.length) {
 -             comment.extendedRange[1] = tokens[target].range[0];
 -         }
 - 
 -         target -= 1;
 -         if (target >= 0) {
 -             comment.extendedRange[0] = tokens[target].range[1];
 -         }
 - 
 -         return comment;
 -     }
 - 
 -     function attachComments(tree, providedComments, tokens) {
 -         // At first, we should calculate extended comment ranges.
 -         var comments = [], comment, len, i, cursor;
 - 
 -         if (!tree.range) {
 -             throw new Error('attachComments needs range information');
 -         }
 - 
 -         // tokens array is empty, we attach comments to tree as 'leadingComments'
 -         if (!tokens.length) {
 -             if (providedComments.length) {
 -                 for (i = 0, len = providedComments.length; i < len; i += 1) {
 -                     comment = deepCopy(providedComments[i]);
 -                     comment.extendedRange = [0, tree.range[0]];
 -                     comments.push(comment);
 -                 }
 -                 tree.leadingComments = comments;
 -             }
 -             return tree;
 -         }
 - 
 -         for (i = 0, len = providedComments.length; i < len; i += 1) {
 -             comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
 -         }
 - 
 -         // This is based on John Freeman's implementation.
 -         cursor = 0;
 -         traverse(tree, {
 -             enter: function (node) {
 -                 var comment;
 - 
 -                 while (cursor < comments.length) {
 -                     comment = comments[cursor];
 -                     if (comment.extendedRange[1] > node.range[0]) {
 -                         break;
 -                     }
 - 
 -                     if (comment.extendedRange[1] === node.range[0]) {
 -                         if (!node.leadingComments) {
 -                             node.leadingComments = [];
 -                         }
 -                         node.leadingComments.push(comment);
 -                         comments.splice(cursor, 1);
 -                     } else {
 -                         cursor += 1;
 -                     }
 -                 }
 - 
 -                 // already out of owned node
 -                 if (cursor === comments.length) {
 -                     return VisitorOption.Break;
 -                 }
 - 
 -                 if (comments[cursor].extendedRange[0] > node.range[1]) {
 -                     return VisitorOption.Skip;
 -                 }
 -             }
 -         });
 - 
 -         cursor = 0;
 -         traverse(tree, {
 -             leave: function (node) {
 -                 var comment;
 - 
 -                 while (cursor < comments.length) {
 -                     comment = comments[cursor];
 -                     if (node.range[1] < comment.extendedRange[0]) {
 -                         break;
 -                     }
 - 
 -                     if (node.range[1] === comment.extendedRange[0]) {
 -                         if (!node.trailingComments) {
 -                             node.trailingComments = [];
 -                         }
 -                         node.trailingComments.push(comment);
 -                         comments.splice(cursor, 1);
 -                     } else {
 -                         cursor += 1;
 -                     }
 -                 }
 - 
 -                 // already out of owned node
 -                 if (cursor === comments.length) {
 -                     return VisitorOption.Break;
 -                 }
 - 
 -                 if (comments[cursor].extendedRange[0] > node.range[1]) {
 -                     return VisitorOption.Skip;
 -                 }
 -             }
 -         });
 - 
 -         return tree;
 -     }
 - 
 -     exports.Syntax = Syntax;
 -     exports.traverse = traverse;
 -     exports.replace = replace;
 -     exports.attachComments = attachComments;
 -     exports.VisitorKeys = VisitorKeys;
 -     exports.VisitorOption = VisitorOption;
 -     exports.Controller = Controller;
 -     exports.cloneEnvironment = function () { return clone({}); };
 - 
 -     return exports;
 - }(exports));
 - /* vim: set sw=4 ts=4 et tw=80 : */
 
 
  |