docs: function parseTag(str, line) {
      var tokens, parser, chunks, tagName, tag, args, last;
  
      if (utils.startsWith(str, 'end')) {
        last = stack[stack.length - 1];
        if (last && last.name === str.split(/\s+/)[0].replace(/^end/, '') && last.ends) {
          switch (last.name) {
          case 'autoescape':
            escape = opts.autoescape;
            break;
          case 'raw':
            inRaw = false;
            break;
          }
          stack.pop();
          return;
        }
  
        if (!inRaw) {
          utils.throwError('Unexpected end of tag "' + str.replace(/^end/, '') + '"', line, opts.filename);
        }
      }
  
      if (inRaw) {
        return;
      }
  
      chunks = str.split(/\s+(.+)?/);
      tagName = chunks.shift();
  
      if (!tags.hasOwnProperty(tagName)) {
        utils.throwError('Unexpected tag "' + str + '"', line, opts.filename);
      }
  
      tokens = lexer.read(utils.strip(chunks.join(' ')));
      parser = new TokenParser(tokens, filters, false, line, opts.filename);
      tag = tags[tagName];
  
      /**
       * Define custom parsing methods for your tag.
       * @callback parse
       *
       * @example
       * exports.parse = function (str, line, parser, types, options, swig) {
       *   parser.on('start', function () {
       *     // ...
       *   });
       *   parser.on(types.STRING, function (token) {
       *     // ...
       *   });
       * };
       *
       * @param {string} str The full token string of the tag.
       * @param {number} line The line number that this tag appears on.
       * @param {TokenParser} parser A TokenParser instance.
       * @param {TYPES} types Lexer token type enum.
       * @param {TagToken[]} stack The current stack of open tags.
       * @param {SwigOpts} options Swig Options Object.
       * @param {object} swig The Swig instance (gives acces to loaders, parsers, etc)
       */
      if (!tag.parse(chunks[1], line, parser, _t, stack, opts, swig)) {
        utils.throwError('Unexpected tag "' + tagName + '"', line, opts.filename);
      }
  
      parser.parse();
      args = parser.out;
  
      switch (tagName) {
      case 'autoescape':
        escape = (args[0] !== 'false') ? args[0] : false;
        break;
      case 'raw':
        inRaw = true;
        break;
      }
  
      /**
       * A parsed tag token.
       * @typedef {Object} TagToken
       * @property {compile} [compile] Method for compiling this token.
       * @property {array} [args] Array of arguments for the tag.
       * @property {Token[]} [content=[]] An array of tokens that are children of this Token.
       * @property {boolean} [ends] Whether or not this tag requires an end tag.
       * @property {string} name The name of this tag.
       */
      return {
        block: !!tags[tagName].block,
        compile: tag.compile,
        args: args,
        content: [],
        ends: tag.ends,
        name: tagName
      };
    }