docs: function buildTree(tokens, options) {
    var stack = [{
      isRegularBlock: true,
      items: []
    }];
    var current;
    var parent;
  
    _.each(tokens, function(token) {
      if (token.isStripe) {
        current = _.last(stack);
        current.items.push(utils.node.newStripe(token));
        return;
      }
      if (token.isPivot) {
        current = _.last(stack);
        if (current.isPivotBlock) {
          current.items.push(utils.node.newStripe(token));
          stack.pop();
          parent = _.last(stack);
          parent.items.push(utils.node.newBlock(current.items, true));
        } else {
          stack.push({
            isPivotBlock: true,
            token: token,
            items: [utils.node.newStripe(token)]
          });
        }
        return;
      }
      if (token.isBlockStart || token.isBlockEnd) {
        current = _.last(stack);
        if (current.isPivotBlock) {
          options.errorHandler(
            new Error(utils.error.message.orphanedPivot),
            {token: current.token},
            utils.error.severity.warning
          );
          stack.pop();
          parent = _.last(stack);
          [].push.apply(parent.items, current.items);
        }
      }
      if (token.isBlockStart) {
        stack.push({
          isRegularBlock: true,
          token: token,
          items: []
        });
        return;
      }
      if (token.isBlockEnd) {
        if (stack.length > 1) {
          current = stack.pop();
          if (isMatchingToken(current.token, token)) {
            if (current.items.length > 0) {
              parent = _.last(stack);
              parent.items.push(utils.node.newBlock(
                current.items, // items
                utils.token.isClosingSquareBracket(token), // reflect
                current.token.repeat * token.repeat // repeat
              ));
            }
            return;
          }
          // Put block back onto stack and proceed to showing an error
          stack.push(current);
        }
        options.errorHandler(
          new Error(utils.error.message.unmatchedBlockEnd),
          {token: token},
          utils.error.severity.error
        );
        return;
      }
      options.errorHandler(
        new Error(utils.error.message.unexpectedToken),
        {token: token},
        utils.error.severity.error
      );
    });
  
    while (stack.length > 1) {
      current = stack.pop();
      parent = _.last(stack);
      if (current.items.length > 0) {
        [].push.apply(parent.items, current.items);
      }
      if (current.isPivotBlock) {
        options.errorHandler(
          new Error(utils.error.message.orphanedPivot),
          {token: current.token},
          utils.error.severity.warning
        );
      } else {
        options.errorHandler(
          new Error(utils.error.message.unmatchedBlockStart),
          {token: current.token},
          utils.error.severity.error
        );
      }
    }
  
    current = _.first(stack).items;
    var isReflected = false;
    if ((current.length == 1) && current[0].isBlock && current[0].reflect) {
      isReflected = true;
      current = current[0].items;
    }
    return utils.node.newRootBlock(current, isReflected);
  }