// See the dependencies parsejavascript.js and parseregex.js (optionally with parseregex-unicode.js) for options var JSAndRegexParser = Editor.Parser = (function() { // Parser var run = function () {}, regexParser, jsParser, lastRegexSrc, regexPG = {}, jsPG = {}; function simpleStream (s) { var str = s, pos = 0; return { next : function () { if (pos >= str.length) { throw StopIteration; } return str.charAt(pos++); } }; } function regex () { var token; try { token = regexParser.next(); } catch(e) { _setState(js); return js(); } _setState(regex); return token; } function js () { var token = jsParser.next(); if (token.type === 'regexp') { lastRegexSrc = stringStream(simpleStream(token.content)); regexParser = RegexParser.make(lastRegexSrc); return regex(); } return token; } function _setState (func) { run = func; } function parseJSAndRegex (stream, basecolumn) { JSParser.configure(jsPG); RegexParser.configure(regexPG); jsParser = JSParser.make(stream, basecolumn); _setState(js); var iter = { next: function() { return run(stream); }, copy: function() { var _run = run, _lastRegexSrc = lastRegexSrc, _jsParser = jsParser.copy(), _regexParser = regexParser && regexParser.copy(); return function (_stream) { stream = _stream; jsParser = _jsParser(_stream); regexParser = _regexParser && _regexParser(_lastRegexSrc); run = _run; return iter; }; } }; return iter; } // Parser object return { make: parseJSAndRegex, configure: function (parserConfig) { for (var opt in parserConfig) { if ((/^regex_/).test(opt)) { regexPG[opt.replace(/^regex_/, '')] = parserConfig[opt]; } else { // Doesn't need a js- prefix, but we'll strip if it does jsPG[opt.replace(/^js_/, '')] = parserConfig[opt]; } } regexPG.flavor = regexPG.flavor || 'ecma-262-ed3'; // Allow ed5, etc. if specified regexPG.literal = true; // This is only for literals, since can't easily detect whether will be used for RegExp regexPG.literal_initial = '/'; // Ensure it's always this for JavaScript regex literals } }; })();