_generateInstances(nodeArrays) {
    return nodeArrays.map((nodes) => {
      var filename = nodes[0].loc.filename;

      var start = nodes.reduce((res, curr) => {
        return NodeUtils.isBefore(curr, res) ? curr : res;
      }).loc.start;

      // The end line requires more careful approximation so as not to
      // accidentally include a large number of irrelevant src lines
      // from a large node
      var base = nodes.map(node => node.loc.start)
        .reduce((res, curr) => (res.line > curr.line) ? res : curr);

      var last = nodes[nodes.length - 1];
      var lastEnd = last.loc.end;
      if (lastEnd.line > base.line && !NodeUtils.getChildren(last).length) {
        base = lastEnd;
      }

      var maxEnd = nodes.map(node => node.loc.end)
        .reduce((res, curr) => (res.line > curr.line) ? res : curr);
      var end = maxEnd.line - base.line <= 2 ? maxEnd : base;

      return {filename, start, end};
    });
  }
Returns an array of objects containing the filename, start, end, and
lines associated with all instances of a match. Due to sibling traversal,
the end line must be searched for among the nodes, and isn't always
defined by the last node in the array.

@private

@param   {Node[][]} nodeArrays   Multi-dimensional array of nodes
@returns {object}