docs: function buildTree(tokens, options) {
    var first;
    var last;
    var isReflected = false;
  
    tokens = _.filter(tokens, function(token) {
      return !token.isWarpStart && !token.isWeftStart;
    });
  
    // Strip parenthesis at beginning and end
    if (tokens.length >= 2) {
      first = _.first(tokens);
      last = _.last(tokens);
      if (first.isBlockBodyStart && last.isBlockBodyEnd) {
        tokens.splice(0, 1);
        tokens.splice(-1, 1);
      } else {
        if (first.isBlockBodyStart) {
          options.errorHandler(
            new Error(utils.error.message.unexpectedToken),
            {token: first},
            utils.error.severity.error
          );
          tokens.splice(0, 1);
        }
        if (last.isBlockBodyStart) {
          options.errorHandler(
            new Error(utils.error.message.unexpectedToken),
            {token: last},
            utils.error.severity.error
          );
          tokens.splice(-1, 1);
        }
      }
    }
  
    // Check if sequence is reflected
    if (tokens.length >= 4) {
      first = _.first(tokens);
      last = _.last(tokens);
      if (first.isStripe && last.isStripe) {
        first = tokens[1];
        last = tokens[tokens.length - 2];
        if (first.isBlockBodyStart && last.isBlockBodyEnd) {
          isReflected = true;
          tokens.splice(1, 1);
          tokens.splice(-2, 1);
        }
      }
    }
  
    // Convert all tokens to items
    var items = _.chain(tokens)
      .map(function(token) {
        if (token.isStripe) {
          return utils.node.newStripe(token);
        }
        options.errorHandler(
          new Error(utils.error.message.unexpectedToken),
          {token: token},
          utils.error.severity.error
        );
        return null;
      })
      .filter()
      .value();
  
    // Check for <stripe> '(' ')' <stripe>
    if (items.length <= 2) {
      isReflected = false;
    }
  
    return utils.node.newRootBlock(items, isReflected);
  }