// Split the input into chunks. module.exports = function (input, fail) { var len = input.length, level = 0, parenLevel = 0, lastOpening, lastOpeningParen, lastMultiComment, lastMultiCommentEndBrace, chunks = [], emitFrom = 0, chunkerCurrentIndex, currentChunkStartIndex, cc, cc2, matched; function emitChunk(force) { var len = chunkerCurrentIndex - emitFrom; if (((len < 512) && !force) || !len) { return; } chunks.push(input.slice(emitFrom, chunkerCurrentIndex + 1)); emitFrom = chunkerCurrentIndex + 1; } for (chunkerCurrentIndex = 0; chunkerCurrentIndex < len; chunkerCurrentIndex++) { cc = input.charCodeAt(chunkerCurrentIndex); if (((cc >= 97) && (cc <= 122)) || (cc < 34)) { // a-z or whitespace continue; } switch (cc) { case 40: // ( parenLevel++; lastOpeningParen = chunkerCurrentIndex; continue; case 41: // ) if (--parenLevel < 0) { return fail("missing opening `(`", chunkerCurrentIndex); } continue; case 59: // ; if (!parenLevel) { emitChunk(); } continue; case 123: // { level++; lastOpening = chunkerCurrentIndex; continue; case 125: // } if (--level < 0) { return fail("missing opening `{`", chunkerCurrentIndex); } if (!level && !parenLevel) { emitChunk(); } continue; case 92: // \ if (chunkerCurrentIndex < len - 1) { chunkerCurrentIndex++; continue; } return fail("unescaped `\\`", chunkerCurrentIndex); case 34: case 39: case 96: // ", ' and ` matched = 0; currentChunkStartIndex = chunkerCurrentIndex; for (chunkerCurrentIndex = chunkerCurrentIndex + 1; chunkerCurrentIndex < len; chunkerCurrentIndex++) { cc2 = input.charCodeAt(chunkerCurrentIndex); if (cc2 > 96) { continue; } if (cc2 == cc) { matched = 1; break; } if (cc2 == 92) { // \ if (chunkerCurrentIndex == len - 1) { return fail("unescaped `\\`", chunkerCurrentIndex); } chunkerCurrentIndex++; } } if (matched) { continue; } return fail("unmatched `" + String.fromCharCode(cc) + "`", currentChunkStartIndex); case 47: // /, check for comment if (parenLevel || (chunkerCurrentIndex == len - 1)) { continue; } cc2 = input.charCodeAt(chunkerCurrentIndex + 1); if (cc2 == 47) { // //, find lnfeed for (chunkerCurrentIndex = chunkerCurrentIndex + 2; chunkerCurrentIndex < len; chunkerCurrentIndex++) { cc2 = input.charCodeAt(chunkerCurrentIndex); if ((cc2 <= 13) && ((cc2 == 10) || (cc2 == 13))) { break; } } } else if (cc2 == 42) { // /*, find */ lastMultiComment = currentChunkStartIndex = chunkerCurrentIndex; for (chunkerCurrentIndex = chunkerCurrentIndex + 2; chunkerCurrentIndex < len - 1; chunkerCurrentIndex++) { cc2 = input.charCodeAt(chunkerCurrentIndex); if (cc2 == 125) { lastMultiCommentEndBrace = chunkerCurrentIndex; } if (cc2 != 42) { continue; } if (input.charCodeAt(chunkerCurrentIndex + 1) == 47) { break; } } if (chunkerCurrentIndex == len - 1) { return fail("missing closing `*/`", currentChunkStartIndex); } chunkerCurrentIndex++; } continue; case 42: // *, check for unmatched */ if ((chunkerCurrentIndex < len - 1) && (input.charCodeAt(chunkerCurrentIndex + 1) == 47)) { return fail("unmatched `/*`", chunkerCurrentIndex); } continue; } } if (level !== 0) { if ((lastMultiComment > lastOpening) && (lastMultiCommentEndBrace > lastMultiComment)) { return fail("missing closing `}` or `*/`", lastOpening); } else { return fail("missing closing `}`", lastOpening); } } else if (parenLevel !== 0) { return fail("missing closing `)`", lastOpeningParen); } emitChunk(true); return chunks; };