function parse( str ) {
	var conf;
	var out;
	var key;
	var FLG;
	var ch;
	var kv;
	var v;
	var i;

	out = {};

	// Split the string into key-value pairs, taking care to account for values having array literal syntax...
	conf = [];
	kv = '';
	for ( i = 0; i < str.length; i++ ) {
		ch = str[ i ];
		if ( !FLG && ch === ',' ) {
			conf.push( kv );
			kv = '';
		} else if ( ch === '[' ) {
			kv += ch;
			FLG = true;
		} else if ( ch === ']' ) {
			kv += ch;
			FLG = false;
		} else {
			kv += ch;
		}
	}
	// Push remaining key-value pair:
	conf.push( kv );

	// Process each key-value pair...
	for ( i = 0; i < conf.length; i++ ) {
		// Split into "key" and "value" (NOTE: we assume that a `value` is not object literal syntax; e.g., `foo:{"a":"b"}`. We further assume that a `value` is not a string containing a `:` character; e.g. `foo:"a:b"`.):
		conf[ i ] = conf[ i ].split( ':' );

		// Validate that a key-value pair has been provided:
		if ( conf[ i ].length !== 2 ) {
			return new Error( format( 'unexpected error. Code block configuration settings should be provided as comma-separated `key:value` pairs (e.g., `foo:true, bar:"string", baz:["error",2]`). Value: `%s`.', conf[ i ].join( ':' ) ) );
		}
		// Trim any excess leading or trailing whitespace from the key and value:
		key = trim( conf[ i ][ 0 ] );
		v = trim( conf[ i ][ 1 ] );

		// Attempt to parse the value as JSON:
		v = parseJSON( v );
		if ( v instanceof Error ) {
			return new Error( format( 'unexpected error. Code block configuration values should be parseable as JSON. Value: `%s`.', trim( conf[i][1] ) ) );
		}
		// Update output object:
		out[ key ] = v;
	}
	return out;
}
Parses a code block configuration.

@private
@param {string} str - configuration string
@returns {(Error|Object)} configuration object or an error