matchBrackets method

String matchBrackets(
  1. String open,
  2. String close, [
  3. bool canEscape = true,
  4. bool mustClose = true,
])

Get all characters between open and close, assuming open occurs at position in document. This function allows nesting unless open and close match. If canEscape is true (default) backslashes can escape open or close, otherwise they are just parsed as text. If mustClose is true, an exception will be thrown if a matching close to the top-level open is not found. Either way, this function will throw an exception if document ends with \ or if open doesn't occur at position. This function's result is exclusive, meaning it will not contain the top-level open or close (but will include any nested ones. Did you get all that?

Implementation

String matchBrackets(String open, String close, [bool canEscape = true, bool mustClose = true]) {
	var result = "", level = 0;

	// make sure the opener occurs at the current position
	if (!matches(open)) {
		throw "opener $open does not occur at position";
	}
	// automatically seek past and increment if opener == closer
	else if (open == close) {
		level ++;
		seek(open.length);
	}

	// find open/closers
	while (inBounds) {
		// escape (backslash)
		if (canEscape && matches("\\")) {
			// skip character and next backslash
			if (seek(2)) {
				// append previous character
				result += peek(-1);
			} else {
				// do not allow backslash at eof
				throw "backslash at eof";
			}
		}
		// closer
		else if (matches(close)) {
			// skip past closer and decrement level
			seek(close.length);
			level --;
			// if we've reached the top again, break
			if (level == 0) {
				break;
			}
			// otherwise, append to result
			result += close;
		}
		// opener
		else if (matches(open)) {
			// skip past opener
			seek(open.length);
			// don't append first opener to result
			if (level != 0) {
				result += open;
			}
			// increment level
			level ++;
		}
		// everything else
		else {
			// append to result
			result += peek();
			// advance
			seek();
		}
	}

	// throw an error if we aren't closed and we should be
	if (mustClose && level != 0) {
		throw "no closer found for opener $open";
	}

	return result;
}