| 
						 | 
						- /*
 -  * @fileoverview Main Doctrine object
 -  * @author Yusuke Suzuki <utatane.tea@gmail.com>
 -  * @author Dan Tao <daniel.tao@gmail.com>
 -  * @author Andrew Eisenberg <andrew@eisenberg.as>
 -  */
 - 
 - (function () {
 -     'use strict';
 - 
 -     var typed,
 -         utility,
 -         jsdoc,
 -         esutils,
 -         hasOwnProperty;
 - 
 -     esutils = require('esutils');
 -     typed = require('./typed');
 -     utility = require('./utility');
 - 
 -     function sliceSource(source, index, last) {
 -         return source.slice(index, last);
 -     }
 - 
 -     hasOwnProperty = (function () {
 -         var func = Object.prototype.hasOwnProperty;
 -         return function hasOwnProperty(obj, name) {
 -             return func.call(obj, name);
 -         };
 -     }());
 -     function shallowCopy(obj) {
 -         var ret = {}, key;
 -         for (key in obj) {
 -             if (obj.hasOwnProperty(key)) {
 -                 ret[key] = obj[key];
 -             }
 -         }
 -         return ret;
 -     }
 - 
 -     function isASCIIAlphanumeric(ch) {
 -         return (ch >= 0x61  /* 'a' */ && ch <= 0x7A  /* 'z' */) ||
 -             (ch >= 0x41  /* 'A' */ && ch <= 0x5A  /* 'Z' */) ||
 -             (ch >= 0x30  /* '0' */ && ch <= 0x39  /* '9' */);
 -     }
 - 
 -     function isParamTitle(title) {
 -         return title === 'param' || title === 'argument' || title === 'arg';
 -     }
 - 
 -     function isReturnTitle(title) {
 -         return title === 'return' || title === 'returns';
 -     }
 - 
 -     function isProperty(title) {
 -         return title === 'property' || title === 'prop';
 -     }
 - 
 -     function isNameParameterRequired(title) {
 -         return isParamTitle(title) || isProperty(title) ||
 -             title === 'alias' || title === 'this' || title === 'mixes' || title === 'requires';
 -     }
 - 
 -     function isAllowedName(title) {
 -         return isNameParameterRequired(title) || title === 'const' || title === 'constant';
 -     }
 - 
 -     function isAllowedNested(title) {
 -         return isProperty(title) || isParamTitle(title);
 -     }
 - 
 -     function isAllowedOptional(title) {
 -         return isProperty(title) || isParamTitle(title);
 -     }
 - 
 -     function isTypeParameterRequired(title) {
 -         return isParamTitle(title) || isReturnTitle(title) ||
 -             title === 'define' || title === 'enum' ||
 -             title === 'implements' || title === 'this' ||
 -             title === 'type' || title === 'typedef' || isProperty(title);
 -     }
 - 
 -     // Consider deprecation instead using 'isTypeParameterRequired' and 'Rules' declaration to pick when a type is optional/required
 -     // This would require changes to 'parseType'
 -     function isAllowedType(title) {
 -         return isTypeParameterRequired(title) || title === 'throws' || title === 'const' || title === 'constant' ||
 -             title === 'namespace' || title === 'member' || title === 'var' || title === 'module' ||
 -             title === 'constructor' || title === 'class' || title === 'extends' || title === 'augments' ||
 -             title === 'public' || title === 'private' || title === 'protected';
 -     }
 - 
 -     // A regex character class that contains all whitespace except linebreak characters (\r, \n, \u2028, \u2029)
 -     var WHITESPACE = '[ \\f\\t\\v\\u00a0\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]';
 - 
 -     var STAR_MATCHER = '(' + WHITESPACE + '*(?:\\*' + WHITESPACE + '?)?)(.+|[\r\n\u2028\u2029])';
 - 
 -     function unwrapComment(doc) {
 -         // JSDoc comment is following form
 -         //   /**
 -         //    * .......
 -         //    */
 - 
 -         return doc.
 -             // remove /**
 -             replace(/^\/\*\*?/, '').
 -             // remove */
 -             replace(/\*\/$/, '').
 -             // remove ' * ' at the beginning of a line
 -             replace(new RegExp(STAR_MATCHER, 'g'), '$2').
 -             // remove trailing whitespace
 -             replace(/\s*$/, '');
 -     }
 - 
 -     /**
 -      * Converts an index in an "unwrapped" JSDoc comment to the corresponding index in the original "wrapped" version
 -      * @param {string} originalSource The original wrapped comment
 -      * @param {number} unwrappedIndex The index of a character in the unwrapped string
 -      * @returns {number} The index of the corresponding character in the original wrapped string
 -      */
 -     function convertUnwrappedCommentIndex(originalSource, unwrappedIndex) {
 -         var replacedSource = originalSource.replace(/^\/\*\*?/, '');
 -         var numSkippedChars = 0;
 -         var matcher = new RegExp(STAR_MATCHER, 'g');
 -         var match;
 - 
 -         while ((match = matcher.exec(replacedSource))) {
 -             numSkippedChars += match[1].length;
 - 
 -             if (match.index + match[0].length > unwrappedIndex + numSkippedChars) {
 -                 return unwrappedIndex + numSkippedChars + originalSource.length - replacedSource.length;
 -             }
 -         }
 - 
 -         return originalSource.replace(/\*\/$/, '').replace(/\s*$/, '').length;
 -     }
 - 
 -     // JSDoc Tag Parser
 - 
 -     (function (exports) {
 -         var Rules,
 -             index,
 -             lineNumber,
 -             length,
 -             source,
 -             originalSource,
 -             recoverable,
 -             sloppy,
 -             strict;
 - 
 -         function advance() {
 -             var ch = source.charCodeAt(index);
 -             index += 1;
 -             if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D  /* '\r' */ && source.charCodeAt(index) === 0x0A  /* '\n' */)) {
 -                 lineNumber += 1;
 -             }
 -             return String.fromCharCode(ch);
 -         }
 - 
 -         function scanTitle() {
 -             var title = '';
 -             // waste '@'
 -             advance();
 - 
 -             while (index < length && isASCIIAlphanumeric(source.charCodeAt(index))) {
 -                 title += advance();
 -             }
 - 
 -             return title;
 -         }
 - 
 -         function seekContent() {
 -             var ch, waiting, last = index;
 - 
 -             waiting = false;
 -             while (last < length) {
 -                 ch = source.charCodeAt(last);
 -                 if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D  /* '\r' */ && source.charCodeAt(last + 1) === 0x0A  /* '\n' */)) {
 -                     waiting = true;
 -                 } else if (waiting) {
 -                     if (ch === 0x40  /* '@' */) {
 -                         break;
 -                     }
 -                     if (!esutils.code.isWhiteSpace(ch)) {
 -                         waiting = false;
 -                     }
 -                 }
 -                 last += 1;
 -             }
 -             return last;
 -         }
 - 
 -         // type expression may have nest brace, such as,
 -         // { { ok: string } }
 -         //
 -         // therefore, scanning type expression with balancing braces.
 -         function parseType(title, last, addRange) {
 -             var ch, brace, type, startIndex, direct = false;
 - 
 - 
 -             // search '{'
 -             while (index < last) {
 -                 ch = source.charCodeAt(index);
 -                 if (esutils.code.isWhiteSpace(ch)) {
 -                     advance();
 -                 } else if (ch === 0x7B  /* '{' */) {
 -                     advance();
 -                     break;
 -                 } else {
 -                     // this is direct pattern
 -                     direct = true;
 -                     break;
 -                 }
 -             }
 - 
 - 
 -             if (direct) {
 -                 return null;
 -             }
 - 
 -             // type expression { is found
 -             brace = 1;
 -             type = '';
 -             while (index < last) {
 -                 ch = source.charCodeAt(index);
 -                 if (esutils.code.isLineTerminator(ch)) {
 -                     advance();
 -                 } else {
 -                     if (ch === 0x7D  /* '}' */) {
 -                         brace -= 1;
 -                         if (brace === 0) {
 -                             advance();
 -                             break;
 -                         }
 -                     } else if (ch === 0x7B  /* '{' */) {
 -                         brace += 1;
 -                     }
 -                     if (type === '') {
 -                         startIndex = index;
 -                     }
 -                     type += advance();
 -                 }
 -             }
 - 
 -             if (brace !== 0) {
 -                 // braces is not balanced
 -                 return utility.throwError('Braces are not balanced');
 -             }
 - 
 -             if (isAllowedOptional(title)) {
 -                 return typed.parseParamType(type, {startIndex: convertIndex(startIndex), range: addRange});
 -             }
 - 
 -             return typed.parseType(type, {startIndex: convertIndex(startIndex), range: addRange});
 -         }
 - 
 -         function scanIdentifier(last) {
 -             var identifier;
 -             if (!esutils.code.isIdentifierStartES5(source.charCodeAt(index)) && !source[index].match(/[0-9]/)) {
 -                 return null;
 -             }
 -             identifier = advance();
 -             while (index < last && esutils.code.isIdentifierPartES5(source.charCodeAt(index))) {
 -                 identifier += advance();
 -             }
 -             return identifier;
 -         }
 - 
 -         function skipWhiteSpace(last) {
 -             while (index < last && (esutils.code.isWhiteSpace(source.charCodeAt(index)) || esutils.code.isLineTerminator(source.charCodeAt(index)))) {
 -                 advance();
 -             }
 -         }
 - 
 -         function parseName(last, allowBrackets, allowNestedParams) {
 -             var name = '',
 -                 useBrackets,
 -                 insideString;
 - 
 - 
 -             skipWhiteSpace(last);
 - 
 -             if (index >= last) {
 -                 return null;
 -             }
 - 
 -             if (source.charCodeAt(index) === 0x5B  /* '[' */) {
 -                 if (allowBrackets) {
 -                     useBrackets = true;
 -                     name = advance();
 -                 } else {
 -                     return null;
 -                 }
 -             }
 - 
 -             name += scanIdentifier(last);
 - 
 -             if (allowNestedParams) {
 -                 if (source.charCodeAt(index) === 0x3A /* ':' */ && (
 -                         name === 'module' ||
 -                         name === 'external' ||
 -                         name === 'event')) {
 -                     name += advance();
 -                     name += scanIdentifier(last);
 - 
 -                 }
 -                 if(source.charCodeAt(index) === 0x5B  /* '[' */ && source.charCodeAt(index + 1) === 0x5D  /* ']' */){
 -                     name += advance();
 -                     name += advance();
 -                 }
 -                 while (source.charCodeAt(index) === 0x2E  /* '.' */ ||
 -                         source.charCodeAt(index) === 0x2F  /* '/' */ ||
 -                         source.charCodeAt(index) === 0x23  /* '#' */ ||
 -                         source.charCodeAt(index) === 0x2D  /* '-' */ ||
 -                         source.charCodeAt(index) === 0x7E  /* '~' */) {
 -                     name += advance();
 -                     name += scanIdentifier(last);
 -                 }
 -             }
 - 
 -             if (useBrackets) {
 -                 skipWhiteSpace(last);
 -                 // do we have a default value for this?
 -                 if (source.charCodeAt(index) === 0x3D  /* '=' */) {
 -                     // consume the '='' symbol
 -                     name += advance();
 -                     skipWhiteSpace(last);
 - 
 -                     var ch;
 -                     var bracketDepth = 1;
 - 
 -                     // scan in the default value
 -                     while (index < last) {
 -                         ch = source.charCodeAt(index);
 - 
 -                         if (esutils.code.isWhiteSpace(ch)) {
 -                             if (!insideString) {
 -                                 skipWhiteSpace(last);
 -                                 ch = source.charCodeAt(index);
 -                             }
 -                         }
 - 
 -                         if (ch === 0x27 /* ''' */) {
 -                             if (!insideString) {
 -                                 insideString = '\'';
 -                             } else {
 -                                 if (insideString === '\'') {
 -                                     insideString = '';
 -                                 }
 -                             }
 -                         }
 - 
 -                         if (ch === 0x22 /* '"' */) {
 -                             if (!insideString) {
 -                                 insideString = '"';
 -                             } else {
 -                                 if (insideString === '"') {
 -                                     insideString = '';
 -                                 }
 -                             }
 -                         }
 - 
 -                         if (ch === 0x5B /* '[' */) {
 -                             bracketDepth++;
 -                         } else if (ch === 0x5D  /* ']' */ &&
 -                             --bracketDepth === 0) {
 -                             break;
 -                         }
 - 
 -                         name += advance();
 -                     }
 -                 }
 - 
 -                 skipWhiteSpace(last);
 - 
 -                 if (index >= last || source.charCodeAt(index) !== 0x5D  /* ']' */) {
 -                     // we never found a closing ']'
 -                     return null;
 -                 }
 - 
 -                 // collect the last ']'
 -                 name += advance();
 -             }
 - 
 -             return name;
 -         }
 - 
 -         function skipToTag() {
 -             while (index < length && source.charCodeAt(index) !== 0x40  /* '@' */) {
 -                 advance();
 -             }
 -             if (index >= length) {
 -                 return false;
 -             }
 -             utility.assert(source.charCodeAt(index) === 0x40  /* '@' */);
 -             return true;
 -         }
 - 
 -         function convertIndex(rangeIndex) {
 -             if (source === originalSource) {
 -                 return rangeIndex;
 -             }
 -             return convertUnwrappedCommentIndex(originalSource, rangeIndex);
 -         }
 - 
 -         function TagParser(options, title) {
 -             this._options = options;
 -             this._title = title.toLowerCase();
 -             this._tag = {
 -                 title: title,
 -                 description: null
 -             };
 -             if (this._options.lineNumbers) {
 -                 this._tag.lineNumber = lineNumber;
 -             }
 -             this._first = index - title.length - 1;
 -             this._last = 0;
 -             // space to save special information for title parsers.
 -             this._extra = { };
 -         }
 - 
 -         // addError(err, ...)
 -         TagParser.prototype.addError = function addError(errorText) {
 -             var args = Array.prototype.slice.call(arguments, 1),
 -                 msg = errorText.replace(
 -                     /%(\d)/g,
 -                     function (whole, index) {
 -                         utility.assert(index < args.length, 'Message reference must be in range');
 -                         return args[index];
 -                     }
 -                 );
 - 
 -             if (!this._tag.errors) {
 -                 this._tag.errors = [];
 -             }
 -             if (strict) {
 -                 utility.throwError(msg);
 -             }
 -             this._tag.errors.push(msg);
 -             return recoverable;
 -         };
 - 
 -         TagParser.prototype.parseType = function () {
 -             // type required titles
 -             if (isTypeParameterRequired(this._title)) {
 -                 try {
 -                     this._tag.type = parseType(this._title, this._last, this._options.range);
 -                     if (!this._tag.type) {
 -                         if (!isParamTitle(this._title) && !isReturnTitle(this._title)) {
 -                             if (!this.addError('Missing or invalid tag type')) {
 -                                 return false;
 -                             }
 -                         }
 -                     }
 -                 } catch (error) {
 -                     this._tag.type = null;
 -                     if (!this.addError(error.message)) {
 -                         return false;
 -                     }
 -                 }
 -             } else if (isAllowedType(this._title)) {
 -                 // optional types
 -                 try {
 -                     this._tag.type = parseType(this._title, this._last, this._options.range);
 -                 } catch (e) {
 -                     //For optional types, lets drop the thrown error when we hit the end of the file
 -                 }
 -             }
 -             return true;
 -         };
 - 
 -         TagParser.prototype._parseNamePath = function (optional) {
 -             var name;
 -             name = parseName(this._last, sloppy && isAllowedOptional(this._title), true);
 -             if (!name) {
 -                 if (!optional) {
 -                     if (!this.addError('Missing or invalid tag name')) {
 -                         return false;
 -                     }
 -                 }
 -             }
 -             this._tag.name = name;
 -             return true;
 -         };
 - 
 -         TagParser.prototype.parseNamePath = function () {
 -             return this._parseNamePath(false);
 -         };
 - 
 -         TagParser.prototype.parseNamePathOptional = function () {
 -             return this._parseNamePath(true);
 -         };
 - 
 - 
 -         TagParser.prototype.parseName = function () {
 -             var assign, name;
 - 
 -             // param, property requires name
 -             if (isAllowedName(this._title)) {
 -                 this._tag.name = parseName(this._last, sloppy && isAllowedOptional(this._title), isAllowedNested(this._title));
 -                 if (!this._tag.name) {
 -                     if (!isNameParameterRequired(this._title)) {
 -                         return true;
 -                     }
 - 
 -                     // it's possible the name has already been parsed but interpreted as a type
 -                     // it's also possible this is a sloppy declaration, in which case it will be
 -                     // fixed at the end
 -                     if (isParamTitle(this._title) && this._tag.type && this._tag.type.name) {
 -                         this._extra.name = this._tag.type;
 -                         this._tag.name = this._tag.type.name;
 -                         this._tag.type = null;
 -                     } else {
 -                         if (!this.addError('Missing or invalid tag name')) {
 -                             return false;
 -                         }
 -                     }
 -                 } else {
 -                     name = this._tag.name;
 -                     if (name.charAt(0) === '[' && name.charAt(name.length - 1) === ']') {
 -                         // extract the default value if there is one
 -                         // example: @param {string} [somebody=John Doe] description
 -                         assign = name.substring(1, name.length - 1).split('=');
 -                         if (assign.length > 1) {
 -                             this._tag['default'] = assign.slice(1).join('=');
 -                         }
 -                         this._tag.name = assign[0];
 - 
 -                         // convert to an optional type
 -                         if (this._tag.type && this._tag.type.type !== 'OptionalType') {
 -                             this._tag.type = {
 -                                 type: 'OptionalType',
 -                                 expression: this._tag.type
 -                             };
 -                         }
 -                     }
 -                 }
 -             }
 - 
 - 
 -             return true;
 -         };
 - 
 -         TagParser.prototype.parseDescription = function parseDescription() {
 -             var description = sliceSource(source, index, this._last).trim();
 -             if (description) {
 -                 if ((/^-\s+/).test(description)) {
 -                     description = description.substring(2);
 -                 }
 -                 this._tag.description = description;
 -             }
 -             return true;
 -         };
 - 
 -         TagParser.prototype.parseCaption = function parseDescription() {
 -             var description = sliceSource(source, index, this._last).trim();
 -             var captionStartTag = '<caption>';
 -             var captionEndTag = '</caption>';
 -             var captionStart = description.indexOf(captionStartTag);
 -             var captionEnd = description.indexOf(captionEndTag);
 -             if (captionStart >= 0 && captionEnd >= 0) {
 -                 this._tag.caption = description.substring(
 -                     captionStart + captionStartTag.length, captionEnd).trim();
 -                 this._tag.description = description.substring(captionEnd + captionEndTag.length).trim();
 -             } else {
 -                 this._tag.description = description;
 -             }
 -             return true;
 -         };
 - 
 -         TagParser.prototype.parseKind = function parseKind() {
 -             var kind, kinds;
 -             kinds = {
 -                 'class': true,
 -                 'constant': true,
 -                 'event': true,
 -                 'external': true,
 -                 'file': true,
 -                 'function': true,
 -                 'member': true,
 -                 'mixin': true,
 -                 'module': true,
 -                 'namespace': true,
 -                 'typedef': true
 -             };
 -             kind = sliceSource(source, index, this._last).trim();
 -             this._tag.kind = kind;
 -             if (!hasOwnProperty(kinds, kind)) {
 -                 if (!this.addError('Invalid kind name \'%0\'', kind)) {
 -                     return false;
 -                 }
 -             }
 -             return true;
 -         };
 - 
 -         TagParser.prototype.parseAccess = function parseAccess() {
 -             var access;
 -             access = sliceSource(source, index, this._last).trim();
 -             this._tag.access = access;
 -             if (access !== 'private' && access !== 'protected' && access !== 'public') {
 -                 if (!this.addError('Invalid access name \'%0\'', access)) {
 -                     return false;
 -                 }
 -             }
 -             return true;
 -         };
 - 
 -         TagParser.prototype.parseThis = function parseThis() {
 -             // this name may be a name expression (e.g. {foo.bar}),
 -             // an union (e.g. {foo.bar|foo.baz}) or a name path (e.g. foo.bar)
 -             var value = sliceSource(source, index, this._last).trim();
 -             if (value && value.charAt(0) === '{') {
 -                 var gotType = this.parseType();
 -                 if (gotType && this._tag.type.type === 'NameExpression' || this._tag.type.type === 'UnionType') {
 -                     this._tag.name = this._tag.type.name;
 -                     return true;
 -                 } else {
 -                     return this.addError('Invalid name for this');
 -                 }
 -             } else {
 -                 return this.parseNamePath();
 -             }
 -         };
 - 
 -         TagParser.prototype.parseVariation = function parseVariation() {
 -             var variation, text;
 -             text = sliceSource(source, index, this._last).trim();
 -             variation = parseFloat(text, 10);
 -             this._tag.variation = variation;
 -             if (isNaN(variation)) {
 -                 if (!this.addError('Invalid variation \'%0\'', text)) {
 -                     return false;
 -                 }
 -             }
 -             return true;
 -         };
 - 
 -         TagParser.prototype.ensureEnd = function () {
 -             var shouldBeEmpty = sliceSource(source, index, this._last).trim();
 -             if (shouldBeEmpty) {
 -                 if (!this.addError('Unknown content \'%0\'', shouldBeEmpty)) {
 -                     return false;
 -                 }
 -             }
 -             return true;
 -         };
 - 
 -         TagParser.prototype.epilogue = function epilogue() {
 -             var description;
 - 
 -             description = this._tag.description;
 -             // un-fix potentially sloppy declaration
 -             if (isAllowedOptional(this._title) && !this._tag.type && description && description.charAt(0) === '[') {
 -                 this._tag.type = this._extra.name;
 -                 if (!this._tag.name) {
 -                     this._tag.name = undefined;
 -                 }
 - 
 -                 if (!sloppy) {
 -                     if (!this.addError('Missing or invalid tag name')) {
 -                         return false;
 -                     }
 -                 }
 -             }
 - 
 -             return true;
 -         };
 - 
 -         Rules = {
 -             // http://usejsdoc.org/tags-access.html
 -             'access': ['parseAccess'],
 -             // http://usejsdoc.org/tags-alias.html
 -             'alias': ['parseNamePath', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-augments.html
 -             'augments': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-constructor.html
 -             'constructor': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
 -             // Synonym: http://usejsdoc.org/tags-constructor.html
 -             'class': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
 -             // Synonym: http://usejsdoc.org/tags-extends.html
 -             'extends': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-example.html
 -             'example': ['parseCaption'],
 -             // http://usejsdoc.org/tags-deprecated.html
 -             'deprecated': ['parseDescription'],
 -             // http://usejsdoc.org/tags-global.html
 -             'global': ['ensureEnd'],
 -             // http://usejsdoc.org/tags-inner.html
 -             'inner': ['ensureEnd'],
 -             // http://usejsdoc.org/tags-instance.html
 -             'instance': ['ensureEnd'],
 -             // http://usejsdoc.org/tags-kind.html
 -             'kind': ['parseKind'],
 -             // http://usejsdoc.org/tags-mixes.html
 -             'mixes': ['parseNamePath', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-mixin.html
 -             'mixin': ['parseNamePathOptional', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-member.html
 -             'member': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-method.html
 -             'method': ['parseNamePathOptional', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-module.html
 -             'module': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
 -             // Synonym: http://usejsdoc.org/tags-method.html
 -             'func': ['parseNamePathOptional', 'ensureEnd'],
 -             // Synonym: http://usejsdoc.org/tags-method.html
 -             'function': ['parseNamePathOptional', 'ensureEnd'],
 -             // Synonym: http://usejsdoc.org/tags-member.html
 -             'var': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-name.html
 -             'name': ['parseNamePath', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-namespace.html
 -             'namespace': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-private.html
 -             'private': ['parseType', 'parseDescription'],
 -             // http://usejsdoc.org/tags-protected.html
 -             'protected': ['parseType', 'parseDescription'],
 -             // http://usejsdoc.org/tags-public.html
 -             'public': ['parseType', 'parseDescription'],
 -             // http://usejsdoc.org/tags-readonly.html
 -             'readonly': ['ensureEnd'],
 -             // http://usejsdoc.org/tags-requires.html
 -             'requires': ['parseNamePath', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-since.html
 -             'since': ['parseDescription'],
 -             // http://usejsdoc.org/tags-static.html
 -             'static': ['ensureEnd'],
 -             // http://usejsdoc.org/tags-summary.html
 -             'summary': ['parseDescription'],
 -             // http://usejsdoc.org/tags-this.html
 -             'this': ['parseThis', 'ensureEnd'],
 -             // http://usejsdoc.org/tags-todo.html
 -             'todo': ['parseDescription'],
 -             // http://usejsdoc.org/tags-typedef.html
 -             'typedef': ['parseType', 'parseNamePathOptional'],
 -             // http://usejsdoc.org/tags-variation.html
 -             'variation': ['parseVariation'],
 -             // http://usejsdoc.org/tags-version.html
 -             'version': ['parseDescription']
 -         };
 - 
 -         TagParser.prototype.parse = function parse() {
 -             var i, iz, sequences, method;
 - 
 - 
 -             // empty title
 -             if (!this._title) {
 -                 if (!this.addError('Missing or invalid title')) {
 -                     return null;
 -                 }
 -             }
 - 
 -             // Seek to content last index.
 -             this._last = seekContent(this._title);
 - 
 -             if (this._options.range) {
 -                 this._tag.range = [this._first, source.slice(0, this._last).replace(/\s*$/, '').length].map(convertIndex);
 -             }
 - 
 -             if (hasOwnProperty(Rules, this._title)) {
 -                 sequences = Rules[this._title];
 -             } else {
 -                 // default sequences
 -                 sequences = ['parseType', 'parseName', 'parseDescription', 'epilogue'];
 -             }
 - 
 -             for (i = 0, iz = sequences.length; i < iz; ++i) {
 -                 method = sequences[i];
 -                 if (!this[method]()) {
 -                     return null;
 -                 }
 -             }
 - 
 -             return this._tag;
 -         };
 - 
 -         function parseTag(options) {
 -             var title, parser, tag;
 - 
 -             // skip to tag
 -             if (!skipToTag()) {
 -                 return null;
 -             }
 - 
 -             // scan title
 -             title = scanTitle();
 - 
 -             // construct tag parser
 -             parser = new TagParser(options, title);
 -             tag = parser.parse();
 - 
 -             // Seek global index to end of this tag.
 -             while (index < parser._last) {
 -                 advance();
 -             }
 - 
 -             return tag;
 -         }
 - 
 -         //
 -         // Parse JSDoc
 -         //
 - 
 -         function scanJSDocDescription(preserveWhitespace) {
 -             var description = '', ch, atAllowed;
 - 
 -             atAllowed = true;
 -             while (index < length) {
 -                 ch = source.charCodeAt(index);
 - 
 -                 if (atAllowed && ch === 0x40  /* '@' */) {
 -                     break;
 -                 }
 - 
 -                 if (esutils.code.isLineTerminator(ch)) {
 -                     atAllowed = true;
 -                 } else if (atAllowed && !esutils.code.isWhiteSpace(ch)) {
 -                     atAllowed = false;
 -                 }
 - 
 -                 description += advance();
 -             }
 - 
 -             return preserveWhitespace ? description : description.trim();
 -         }
 - 
 -         function parse(comment, options) {
 -             var tags = [], tag, description, interestingTags, i, iz;
 - 
 -             if (options === undefined) {
 -                 options = {};
 -             }
 - 
 -             if (typeof options.unwrap === 'boolean' && options.unwrap) {
 -                 source = unwrapComment(comment);
 -             } else {
 -                 source = comment;
 -             }
 - 
 -             originalSource = comment;
 - 
 -             // array of relevant tags
 -             if (options.tags) {
 -                 if (Array.isArray(options.tags)) {
 -                     interestingTags = { };
 -                     for (i = 0, iz = options.tags.length; i < iz; i++) {
 -                         if (typeof options.tags[i] === 'string') {
 -                             interestingTags[options.tags[i]] = true;
 -                         } else {
 -                             utility.throwError('Invalid "tags" parameter: ' + options.tags);
 -                         }
 -                     }
 -                 } else {
 -                     utility.throwError('Invalid "tags" parameter: ' + options.tags);
 -                 }
 -             }
 - 
 -             length = source.length;
 -             index = 0;
 -             lineNumber = 0;
 -             recoverable = options.recoverable;
 -             sloppy = options.sloppy;
 -             strict = options.strict;
 - 
 -             description = scanJSDocDescription(options.preserveWhitespace);
 - 
 -             while (true) {
 -                 tag = parseTag(options);
 -                 if (!tag) {
 -                     break;
 -                 }
 -                 if (!interestingTags || interestingTags.hasOwnProperty(tag.title)) {
 -                     tags.push(tag);
 -                 }
 -             }
 - 
 -             return {
 -                 description: description,
 -                 tags: tags
 -             };
 -         }
 -         exports.parse = parse;
 -     }(jsdoc = {}));
 - 
 -     exports.version = utility.VERSION;
 -     exports.parse = jsdoc.parse;
 -     exports.parseType = typed.parseType;
 -     exports.parseParamType = typed.parseParamType;
 -     exports.unwrapComment = unwrapComment;
 -     exports.Syntax = shallowCopy(typed.Syntax);
 -     exports.Error = utility.DoctrineError;
 -     exports.type = {
 -         Syntax: exports.Syntax,
 -         parseType: typed.parseType,
 -         parseParamType: typed.parseParamType,
 -         stringify: typed.stringify
 -     };
 - }());
 - /* vim: set sw=4 ts=4 et tw=80 : */
 
 
  |