static parseFromString(stringRepresentation, setString, unsetString) {
			if (stringRepresentation === null) {
				throw new IllegalArgumentException('stringRepresentation cannot be null');
			}
			const bits = new Array(stringRepresentation.length);
			let bitsPos = 0;
			let rowStartPos = 0;
			let rowLength = -1;
			let nRows = 0;
			let pos = 0;
			while (pos < stringRepresentation.length) {
				if (stringRepresentation.charAt(pos) === '\n' ||
					stringRepresentation.charAt(pos) === '\r') {
					if (bitsPos > rowStartPos) {
						if (rowLength === -1) {
							rowLength = bitsPos - rowStartPos;
						}
						else if (bitsPos - rowStartPos !== rowLength) {
							throw new IllegalArgumentException('row lengths do not match');
						}
						rowStartPos = bitsPos;
						nRows++;
					}
					pos++;
				}
				else if (stringRepresentation.substring(pos, pos + setString.length) === setString) {
					pos += setString.length;
					bits[bitsPos] = true;
					bitsPos++;
				}
				else if (stringRepresentation.substring(pos, pos + unsetString.length) === unsetString) {
					pos += unsetString.length;
					bits[bitsPos] = false;
					bitsPos++;
				}
				else {
					throw new IllegalArgumentException('illegal character encountered: ' + stringRepresentation.substring(pos));
				}
			}
			// no EOL at end?
			if (bitsPos > rowStartPos) {
				if (rowLength === -1) {
					rowLength = bitsPos - rowStartPos;
				}
				else if (bitsPos - rowStartPos !== rowLength) {
					throw new IllegalArgumentException('row lengths do not match');
				}
				nRows++;
			}
			const matrix = new BitMatrix(rowLength, nRows);
			for (let i = 0; i < bitsPos; i++) {
				if (bits[i]) {
					matrix.set(Math.floor(i % rowLength), Math.floor(i / rowLength));
				}
			}
			return matrix;
		}
@function parse
@param stringRepresentation
@param setString
@param unsetString