function analyze( files, options, clbk ) {
	var results;
	var nfiles;
	var opts;
	var err;
	var idx;
	var acc;
	var dir;
	var cb;
	if ( !isStringArray( files ) ) {
		throw new TypeError( format( 'invalid argument. First argument must be a list of file paths. Value: `%s`.', files ) );
	}
	nfiles = files.length;
	debug( 'Files: %s', files.join( ', ' ) );

	dir = cwd();
	debug( 'Current working directory: %s', dir );

	opts = {};
	opts.cumulative = defaults.cumulative;
	if ( arguments.length > 2 ) {
		err = validate( opts, options );
		if ( err ) {
			throw err;
		}
		cb = clbk;
	} else {
		cb = options;
	}
	if ( !isFunction( cb ) ) {
		throw new TypeError( format( 'invalid argument. Callback argument must be a function. Value: `%s`.', cb ) );
	}
	debug( 'Options: %s', JSON.stringify( opts ) );

	if ( opts.cumulative ) {
		acc = incrsummary();
	} else {
		results = [];
	}
	idx = -1;

	debug( 'Starting analysis of %d files...', nfiles );
	return next();

	/**
	* Processes the next file.
	*
	* @private
	*/
	function next() {
		var f;

		idx += 1;
		debug( 'Reading file: %s (%d of %d)', files[ idx ], idx+1, nfiles );

		f = resolve( dir, files[ idx ] );
		readFile( f, fopts, onFile );
	}

	/**
	* Callback invoked upon reading a file.
	*
	* @private
	* @param {(Error|null)} error - error object
	* @param {(string|Buffer)} file - file contents
	* @returns {void}
	*/
	function onFile( error, file ) {
		if ( error ) {
			debug( 'Encountered an error when reading file: %s (%d of %d). Error: %s', files[ idx ], idx+1, nfiles, error.message );
			return done( error );
		}
		debug( 'Successfully read file: %s (%d of %d).', files[ idx ], idx+1, nfiles );
		if ( opts.cumulative ) {
			debug( 'Updating cumulative summary...' );
			acc( file );
		} else {
			debug( 'Generating program summary...' );
			results.push( summary( file ) );
		}
		done();
	}

	/**
	* Callback invoked upon analyzing a file.
	*
	* @private
	* @param {(Error|null)} [error] - error object
	* @returns {void}
	*/
	function done( error ) {
		if ( error ) {
			return cb( error );
		}
		debug( 'Finished analyzing file %d of %d.', idx+1, nfiles );
		if ( idx === nfiles-1 ) {
			if ( opts.cumulative ) {
				debug( 'Finished analysis. Returning cumulative results...' );
				return cb( null, acc() );
			}
			debug( 'Finished analysis. Returning results...' );
			return cb( null, results );
		}
		next();
	}
}
Asynchronously performs a static summary analysis for a list of JavaScript files.

@param {StringArray} files - list of files
@param {Options} [options] - function options
@param {boolean} [options.cumulative=true] - boolean indicating whether to perform a cumulative analysis
@param {Callback} clbk - callback to invoke upon completing analysis
@throws {TypeError} first argument must be a list of file paths
@throws {TypeError} options argument must be an object
@throws {TypeError} must provide valid options
@throws {TypeError} last argument must be a function
@returns {void}

@example
var files = [ __filename ];

analyze( files, clbk );

function clbk( error, results ) {
    if ( error ) {
        throw error;
    }
    console.log( JSON.stringify( results ) );
}