diff --git a/README.md b/README.md index 9b2a403..034ae93 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ __Transform a JSON grammar into an ACE syntax-highlight parser__ -A simple and light-weight (~ 30kB minified, ~ 11kB zipped) [ACE](https://github.com/ajaxorg/ace) add-on +A simple and light-weight (~ 40kB minified, ~ 15kB zipped) [ACE](https://github.com/ajaxorg/ace) add-on to generate syntax-highlight parsers (ace modes) from a grammar specification in JSON format. @@ -31,15 +31,9 @@ See also: [codemirror-grammar](https://github.com/foo123/codemirror-grammar) , ###Todo -Code Indentation, Behaviours, Matching (ACE default), Code Folding is not handled +Code Indentation, Behaviours, Matching are ACE defaults, see [Modularity and Future Directions](https://github.com/foo123/editor-grammar/blob/master/grammar-reference.md#modularity-and-future-directions) -*generic code-folders implementations have been added, specified in grammar.Extra.fold option* - - -see [Modularity and Future Directions](https://github.com/foo123/editor-grammar/blob/master/grammar-reference.md#modularity-and-future-directions) - -* handle arbitrary, user-defined, code `folding` in the `grammar` specification (e.g via `fold action` tokens) * handle arbitrary, user-defined, code `(de-)indentation` in the `grammar` specification (e.g via `indent action` tokens) * handle arbitrary, user-defined, code `matching` (e.g `brackets`, `tags`, etc..) in the `grammar` specification (e.g via `match action` tokens) * handle arbitrary, user-defined, `(operator) precedence` relations in the `grammar` specification (e.g via `precedence action` tokens) @@ -48,6 +42,7 @@ see [Modularity and Future Directions](https://github.com/foo123/editor-grammar/ * enable grammar add-on to pre-compile a grammar specification directly into mode source code, so it can be used without the add-on as standalone mode [TODO, maybe] + ###Features * A [`Grammar`](https://github.com/foo123/editor-grammar/blob/master/grammar-reference.md) can **extend other `Grammars`** (so arbitrary `variations` and `dialects` can be handled more easily) @@ -59,6 +54,7 @@ see [Modularity and Future Directions](https://github.com/foo123/editor-grammar/ * `Grammar` can define [*action* tokens](https://github.com/foo123/editor-grammar/blob/master/grammar-reference.md#action-tokens) to perform *complex context-specific* parsing functionality, including **associated tag matching** and **duplicate identifiers** (see for example `xml.grammar` example) (**NEW feature**) * Generated highlight modes can support **toggle comments** and **keyword autocompletion** functionality if defined in the grammar * Generated highlight modes can support **lint-like syntax-annotation** functionality generated from the grammar +* Generated highlight modes can support custom, user-defined, **code folding** functionality from the [grammar `fold` model](https://github.com/foo123/editor-grammar/blob/master/grammar-reference.md#code-folding) (**NEW feature**) * Generated parsers are **optimized for speed and size** * Can generate a syntax-highlight parser from a grammar **interactively and on-the-fly** ( see example, http://foo123.github.io/examples/ace-grammar ) * see also [Modularity and Future Directions](https://github.com/foo123/editor-grammar/blob/master/grammar-reference.md#modularity-and-future-directions) @@ -155,6 +151,7 @@ xml_mode.supportGrammarAnnotations = true; // enable user-defined autocompletion (if defined) xml_mode.supportAutoCompletion = true; +xml_mode.autocompleter.options = {prefixMatch:true, caseInsensitiveMatch:false}; // 3. use it with ACE var editor = ace.edit("editor"); diff --git a/build/ace_grammar.js b/build/ace_grammar.js index 4f2472a..45686f0 100644 --- a/build/ace_grammar.js +++ b/build/ace_grammar.js @@ -3175,8 +3175,8 @@ function Type( TYPE, positive ) if ( T_STR_OR_ARRAY & get_type( TYPE ) ) TYPE = new_re( '\\b(' + map( make_array( TYPE ).sort( by_length ), esc_re ).join( '|' ) + ')\\b' ); return false === positive - ? function( type ) { return !TYPE.test( type ); } - : function( type ) { return TYPE.test( type ); }; + ? function( type ) { return !type || !TYPE.test( type ); } + : function( type ) { return !!type && TYPE.test( type ); }; } function next_tag( iter, T, M, L, R, S ) @@ -3194,7 +3194,7 @@ function next_tag( iter, T, M, L, R, S ) } else return; } - if ( !(type=iter.token(iter.row, found.index+1)) || !T( type ) ) + if ( !T( iter.token(iter.row, found.index+1) ) ) { iter.col = found.index + 1; continue; @@ -3210,7 +3210,7 @@ function end_tag( iter, T, M, L, R, S ) for (;;) { gt = iter.text.indexOf( R, iter.col ); - if ( -1 == gt ) + if ( -1 === gt ) { if ( iter.next( ) ) { @@ -3219,7 +3219,7 @@ function end_tag( iter, T, M, L, R, S ) } else return; } - if ( !(type=iter.token(iter.row, gt+1)) || !T( type ) ) + if ( !T( iter.token(iter.row, gt+1) ) ) { iter.col = gt + 1; continue; @@ -3237,13 +3237,13 @@ var Folder = { Pattern: function( S, E, T ) { // TODO - return function( ){ }; + return function fold_pattern( ){ }; } ,Indented: function( NOTEMPTY ) { NOTEMPTY = NOTEMPTY || Stream.$NOTEMPTY$; - return function( iter ) { + return function fold_indentation( iter ) { var first_line, first_indentation, cur_line, cur_indentation, start_line = iter.row, start_pos, last_line_in_fold, end_pos, i, end; @@ -3280,24 +3280,24 @@ var Folder = { if ( !S || !E ) return function( ){ }; T = T || TRUE; - return function( iter ) { + return function fold_delimiter( iter ) { var line = iter.row, col = iter.col, - lineText, startCh, at, pass, found, + lineText, startCh, at, pass, found, tokenType, depth, lastLine, end, endCh, i, text, pos, nextOpen, nextClose; lineText = iter.line( line ); for (at=col,pass=0 ;;) { var found = at<=0 ? -1 : lineText.lastIndexOf( S, at-1 ); - if ( -1 == found ) + if ( -1 === found ) { - if ( 1 == pass ) return; + if ( 1 === pass ) return; pass = 1; at = lineText.length; continue; } - if ( 1 == pass && found < col ) return; - if ( T( iter.token( line, found+1 ) ) ) + if ( 1 === pass && found < col ) return; + if ( T( tokenType = iter.token( line, found+1 ) ) ) { startCh = found + S.length; break; @@ -3307,7 +3307,7 @@ var Folder = { depth = 1; lastLine = iter.last(); outer: for (i=line; i<=lastLine; ++i) { - text = iter.line( i ); pos = i==line ? startCh : 0; + text = iter.line( i ); pos = i===line ? startCh : 0; for (;;) { nextOpen = text.indexOf( S, pos ); @@ -3315,9 +3315,12 @@ var Folder = { if ( nextOpen < 0 ) nextOpen = text.length; if ( nextClose < 0 ) nextClose = text.length; pos = MIN( nextOpen, nextClose ); - if ( pos == text.length ) break; - if ( pos == nextOpen ) ++depth; - else if ( !--depth ) { end = i; endCh = pos; break outer; } + if ( pos >= text.length ) break; + if ( iter.token(i, pos+1) == tokenType ) + { + if ( pos === nextOpen ) ++depth; + else if ( !--depth ) { end = i; endCh = pos; break outer; } + } ++pos; } } @@ -3331,43 +3334,45 @@ var Folder = { L = L || "<"; R = R || ">"; S = S || "/"; M = M || new_re( esc_re(L) + "(" + esc_re(S) + "?)([a-zA-Z_\\-][a-zA-Z0-9_\\-:]*)", "g" ); - return function( iter ) { + return function fold_markup( iter ) { iter.col = 0; iter.min = iter.first( ); iter.max = iter.last( ); iter.text = iter.line( iter.row ); - var openTag, end, start, close, tagName, startLine = iter.row; + var openTag, end, start, close, tagName, startLine = iter.row, + stack, next, startCh, i; for (;;) { openTag = next_tag(iter, T, M, L, R, S); - if ( !openTag || iter.row != startLine || !(end = end_tag(iter, T, M, L, R, S)) ) return; - if ( !openTag[1] && end != "autoclosed" ) + if ( !openTag || iter.row !== startLine || !(end = end_tag(iter, T, M, L, R, S)) ) return; + if ( !openTag[1] && "autoclosed" !== end ) { start = [iter.row, iter.col]; tagName = openTag[2]; close = null; // start find_matching_close - var stack = [], next, startCh, i; + stack = []; for (;;) { next = next_tag(iter, T, M, L, R, S); startLine = iter.row; startCh = iter.col - (next ? next[0].length : 0); if ( !next || !(end = end_tag(iter, T, M, L, R, S)) ) return; - if ( end == "autoclosed" ) continue; + if ( "autoclosed" === end ) continue; if ( next[1] ) { // closing tag for (i=stack.length-1; i>=0; --i) { - if ( stack[i] == next[2] ) + if ( stack[i] === next[2] ) { stack.length = i; break; } } - if ( i < 0 && (!tagName || tagName == next[2]) ) + if ( i < 0 && (!tagName || tagName === next[2]) ) { - close = { + /*close = { tag: next[2], pos: [startLine, startCh, iter.row, iter.col] }; - break; + break;*/ + return [start[0], start[1], startLine, startCh]; } } else @@ -3377,10 +3382,10 @@ var Folder = { } } // end find_matching_close - if ( close ) + /*if ( close ) { return [start[0], start[1], close.pos[0], close.pos[1]]; - } + }*/ } } }; @@ -3432,6 +3437,9 @@ this_path = (function(isNode, isBrowser, isWorker) { return { path: path, file: file, base: base }; })(isNode, isBrowser, isWorker), +// browser caches worker source file, even with reset/reload, try to not cache +NOCACHE = '?nocache=' + uuid('nonce') + '_' + (~~(1000*Math.random( ))), + // ace supposed to be available $ace$ = (typeof ace !== 'undefined') ? ace : { require: function() { return { }; }, config: {} } ; @@ -3440,8 +3448,8 @@ $ace$ = (typeof ace !== 'undefined') ? ace : { require: function() { return { }; // // parser factories var AceParser = Class(Parser, { - constructor: function AceParser( grammar, DEFAULT ) { - var self = this, rxLine, FOLD = null, TYPE; + constructor: function AceParser( grammar, DEFAULT, withFolders ) { + var self = this, FOLD = null, TYPE; Parser.call(self, grammar, "text", "invalid"); self.$v$ = 'value'; @@ -3451,22 +3459,9 @@ var AceParser = Class(Parser, { // support comments toggle self.LC = grammar.$comments.line || null; self.BC = grammar.$comments.block ? { start: grammar.$comments.block[0][0], end: grammar.$comments.block[0][1] } : null; - if ( self.LC ) - { - if ( T_ARRAY & get_type(self.LC) ) - rxLine = map( self.LC, esc_re ).join( "|" ); - - else - rxLine = esc_re( self.LC ); - - self.rxLine = new_re("^(\\s*)(?:" + rxLine + ")?"); - } - if ( self.BC ) - { - self.rxStart = new_re("^(\\s*)(?:" + esc_re(self.BC.start) + ")"); - self.rxEnd = new_re("(?:" + esc_re(self.BC.end) + ")\\s*$"); - } + if ( false !== withFolders ) + { // comment-block folding if ( grammar.$comments.block && grammar.$comments.block.length ) { @@ -3506,17 +3501,15 @@ var AceParser = Class(Parser, { } }, 0, FOLD.length-1, FOLD); } + } } ,LC: null ,BC: null - ,rxLine: null - ,rxStart: null - ,rxEnd: null ,dispose: function( ) { var self = this; - self.LC = self.BC = self.rxLine = self.rxStart = self.rxEnd = null; + self.LC = self.BC = null; return Parser[PROTO].dispose.call( self ); } @@ -3527,21 +3520,6 @@ var AceParser = Class(Parser, { return {tokens:self.tokenize( Stream( line ), state, row ), state:state}; } - ,keywords: function( append, ace ) { - var self = this; - if ( self.$grammar.$autocomplete ) - { - return map(self.$grammar.$autocomplete, function( word ){ - return { - name: word.word, - value: word.word, - meta: word.meta, - score: 1 - }; - }); - } - return []; - } ,autocomplete: function( state, session, position, prefix, options, ace ) { var self = this; if ( self.$grammar.$autocomplete && prefix.length ) @@ -3578,10 +3556,6 @@ var AceParser = Class(Parser, { return []; } - ,indent: function( state, line, tab, ace ) { - return line.match(Stream.$SPACE$)[0]; - } - ,iterator: function( session, ace ) { var tabSize = session.getTabSize(); return { @@ -3618,193 +3592,6 @@ var AceParser = Class(Parser, { return fold; } } - - // toggle comment lines - ,tCL: function( state, session, startRow, endRow ) { - var parser = self, doc = session.doc, - ignoreBlankLines = true, - shouldRemove = true, - minIndent = Infinity, - tabSize = session.getTabSize(), - insertAtTabStop = false, - comment, uncomment, testRemove, shouldInsertSpace, - lineCommentStart, lineCommentEnd, regexpStart, regexpEnd, - minEmptyLength, regexpLine, commentWithSpace - ; - - if ( !parser.LC ) - { - if ( !parser.BC ) return false; - - lineCommentStart = parser.BC.start; - lineCommentEnd = parser.BC.end; - regexpStart = parser.rxStart; - regexpEnd = parser.rxEnd; - - comment = function( i ) { - var line = doc.getLine(i); - if (testRemove(line, i)) return; - if (!ignoreBlankLines || /\S/.test(line)) - { - doc.insertInLine({row: i, column: line.length}, lineCommentEnd); - doc.insertInLine({row: i, column: minIndent}, lineCommentStart); - } - }; - - uncomment = function( i ) { - var line = doc.getLine(i), m; - if (m = line.match(regexpEnd)) - doc.removeInLine(i, line.length - m[0].length, line.length); - if (m = line.match(regexpStart)) - doc.removeInLine(i, m[1].length, m[0].length); - }; - - testRemove = function( line, row ) { - if (regexpStart.test(line)) return true; - var tokens = session.getTokens(row); - for (var i = 0; i < tokens.length; i++) - { - if (tokens[i].type === 'comment') return true; - } - }; - } - else - { - lineCommentStart = (T_ARRAY === get_type(parser.LC)) ? parser.LC[0] : parser.LC; - regexpLine = parser.rxLine; - commentWithSpace = lineCommentStart + " "; - - insertAtTabStop = session.getUseSoftTabs(); - - uncomment = function( i ) { - var line = doc.getLine(i), m = line.match(regexpLine), start, end; - if (!m) return; - start = m[1].length; end = m[0].length; - if (!shouldInsertSpace(line, start, end) && m[0][end - 1] == " ") end--; - doc.removeInLine(i, start, end); - }; - - comment = function( i ) { - var line = doc.getLine(i); - if (!ignoreBlankLines || /\S/.test(line)) - { - if (shouldInsertSpace(line, minIndent, minIndent)) - doc.insertInLine({row: i, column: minIndent}, commentWithSpace); - else - doc.insertInLine({row: i, column: minIndent}, lineCommentStart); - } - }; - - testRemove = function( line, i ) { - return regexpLine.test(line); - }; - - shouldInsertSpace = function(line, before, after) { - var spaces = 0; - while (before-- && line[CHAR](before) == " ") spaces++; - if (spaces % tabSize != 0) return false; - spaces = 0; - while (line[CHAR](after++) == " ") spaces++; - if (tabSize > 2) return spaces % tabSize != tabSize - 1; - else return spaces % tabSize == 0; - return true; - }; - } - - minEmptyLength = Infinity; - - iterate(function( i ) { - var line = doc.getLine(i), indent = line.search(/\S/); - if (indent !== -1) - { - if (indent < minIndent) minIndent = indent; - if (shouldRemove && !testRemove(line, i)) shouldRemove = false; - } - else if (minEmptyLength > line.length) - { - minEmptyLength = line.length; - } - }, startRow, endRow); - - if (Infinity == minIndent) - { - minIndent = minEmptyLength; - ignoreBlankLines = false; - shouldRemove = false; - } - - if (insertAtTabStop && minIndent % tabSize != 0) - minIndent = Math.floor(minIndent / tabSize) * tabSize; - - iterate(shouldRemove ? uncomment : comment, startRow, endRow); - } - - // toggle block comment - ,tCB: function( state, session, range, cursor, TokenIterator, Range ) { - var parser = self, comment = parser.BC, iterator, token, sel, - initialRange, startRow, colDiff, - startRange, endRange, i, row, column, - comment_re = /comment/ - ; - if (!comment) return; - - iterator = new TokenIterator( session, cursor.row, cursor.column ); - token = iterator.getCurrentToken(); - - sel = session.selection; - initialRange = sel.toOrientedRange(); - - if (token && comment_re.test(token.type)) - { - while (token && comment_re.test(token.type)) - { - i = token.value.indexOf(comment.start); - if (i != -1) - { - row = iterator.getCurrentTokenRow(); - column = iterator.getCurrentTokenColumn() + i; - startRange = new Range(row, column, row, column + comment.start.length); - break; - } - token = iterator.stepBackward(); - }; - - iterator = new TokenIterator(session, cursor.row, cursor.column); - token = iterator.getCurrentToken(); - while (token && comment_re.test(token.type)) - { - i = token.value.indexOf(comment.end); - if (i != -1) - { - row = iterator.getCurrentTokenRow(); - column = iterator.getCurrentTokenColumn() + i; - endRange = new Range(row, column, row, column + comment.end.length); - break; - } - token = iterator.stepForward(); - } - if (endRange) - session.remove(endRange); - if (startRange) - { - session.remove(startRange); - startRow = startRange.start.row; - colDiff = -comment.start.length; - } - } - else - { - colDiff = comment.start.length; - startRow = range.start.row; - session.insert(range.end, comment.end); - session.insert(range.start, comment.start); - } - if (initialRange.start.row == startRow) - initialRange.start.column += colDiff; - if (initialRange.end.row == startRow) - initialRange.end.column += colDiff; - session.selection.fromOrientedRange(initialRange); - } }); AceParser.Type = Type; AceParser.Fold = Folder; @@ -3823,10 +3610,10 @@ function grammar_worker_init( e ) ace.define('ace/grammar_worker', ['require', 'exports', 'module' , 'ace/worker/mirror'], function( require, exports, module ) { - var WorkerMirror = require("./worker/mirror").Mirror, AceGrammarWorker; + var WorkerMirror = require("./worker/mirror").Mirror; // extends require("./worker/mirror").Mirror - exports.AceGrammarWorker = AceGrammarWorker = Class(WorkerMirror, { + exports.AceGrammarWorker = Class(WorkerMirror, { constructor: function AceGrammarWorker( sender ) { var self = this; WorkerMirror.call( self, sender ); @@ -3837,7 +3624,7 @@ function grammar_worker_init( e ) ,init_parser: function( grammar, id ) { var self = this; - self.$parser = new AceParser( parse_grammar( grammar ) ); + self.$parser = new AceParser( parse_grammar( grammar ), null, false ); self.sender.callback( 1, id ); } @@ -3876,9 +3663,11 @@ function grammar_worker_init( e ) } } +/* // adapted from ace Marker renderer +// https://github.com/ajaxorg/ace/issues/2720 // renderer(html, range, left, top, config); -/*function getBorderClass(tl, tr, br, bl) +function getBorderClass(tl, tr, br, bl) { return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0); } @@ -3912,8 +3701,8 @@ function custom_text_marker( clazz, popup, session, Range ) ); } }; -}*/ - +} +*/ function clear_markers( session, $markers ) { if ( !session[$markers] ) session[$markers] = []; @@ -3960,49 +3749,63 @@ function update_annotations( session, errors, $markers, Range ) session.setAnnotations( errors ); } - function get_mode( grammar, DEFAULT, ace ) { - // ace required helpers ace = ace || $ace$; /* pass ace reference if not already available */ - var ace_mode, grammar_copy = clone( grammar ) + var grammar_copy = clone( grammar ) + // ace required helpers ,Range = ace.require('ace/range').Range - ,TokenIterator = ace.require('ace/token_iterator').TokenIterator - // adapted from ace directly - ,WorkerClient = ace.require("ace/worker/worker_client").WorkerClient + ,WorkerClient = ace.require('ace/worker/worker_client').WorkerClient ,AceWorker = Class(WorkerClient, { - constructor: function AceWorker( topLevelNamespaces, mod, classname ) { + constructor: function AceWorker( topLevelNamespaces, mod, classname, workerUrl ) { var self = this, require = ace.require, config = ace.config; self.$sendDeltaQueue = self.$sendDeltaQueue.bind(self); self.changeListener = self.changeListener.bind(self); self.onMessage = self.onMessage.bind(self); if (require.nameToUrl && !require.toUrl) require.toUrl = require.nameToUrl; - - var workerUrl; + + if ( !workerUrl ) + { if (config.get("packaged") || !require.toUrl) { - workerUrl = config.moduleUrl(mod, "worker"); + workerUrl = workerUrl || config.moduleUrl(mod, "worker"); } else { var normalizePath = self.$normalizePath; - workerUrl = normalizePath(require.toUrl("ace/worker/worker.js", null, "_")); + workerUrl = workerUrl || normalizePath(require.toUrl("ace/worker/worker.js", null, "_")); var tlns = {}; topLevelNamespaces.forEach(function(ns) { tlns[ns] = normalizePath(require.toUrl(ns, null, "_").replace(/(\.js)?(\?.*)?$/, "")); }); } - - self.$worker = new Worker( workerUrl ); - + } + + try { + self.$worker = new Worker(workerUrl); + } catch(e) { + if (e instanceof window.DOMException) { + var blob = self.$workerBlob(workerUrl); + var URL = window.URL || window.webkitURL; + var blobURL = URL.createObjectURL(blob); + + self.$worker = new Worker(blobURL); + URL.revokeObjectURL(blobURL); + } else { + throw e; + } + } + self.$worker.postMessage({ load: true, - ace_worker_base: this_path.base + '/' + config.moduleUrl("ace/worker/json") + // browser caches worker source file, even with reset/reload, try to not cache + // https://github.com/ajaxorg/ace/issues/2730 + ace_worker_base: this_path.base + '/' + config.moduleUrl("ace/worker/json") + NOCACHE }); self.$worker.postMessage({ init : true, - tlns: tlns, - module: mod, - classname: classname + tlns : tlns, + module : mod, + classname : classname }); self.callbackId = 1; @@ -4011,145 +3814,129 @@ function get_mode( grammar, DEFAULT, ace ) self.$worker.onmessage = self.onMessage; } }) - // adapted from ace directly - ,FoldMode = ace.require("ace/mode/folding/fold_mode").FoldMode + ,FoldMode = ace.require('ace/mode/folding/fold_mode').FoldMode ,AceFold = Class(FoldMode, { constructor: function( $folder ) { var self = this; FoldMode.call( self ); self.$findFold = $folder; + self.$lastFold = null; } ,getFoldWidget: function( session, foldStyle, row ) { - var self = this, fold = self.$findFold( session, foldStyle, row ); - if ( fold ) - { - if ( "markbeginend" === foldStyle && fold.end ) return "end"; - else return "start"; - } - return ""; + var fold = this.$lastFold = this.$findFold( session, foldStyle, row ); + // cache the fold to be re-used in getFoldWidgetRange + // it is supposed that getFoldWidgetRange is called after getFoldWidget succeeds + // on same row and with same style, so same fold should be re-used for efficiency + return fold + ? ("markbeginend" === foldStyle && fold.end ? "end" : "start") + : ""; } ,getFoldWidgetRange: function( session, foldStyle, row, forceMultiline ) { - var fold = this.$findFold( session, foldStyle, row ); + // cache the fold to be re-used in getFoldWidgetRange + // it is supposed that getFoldWidgetRange is called after getFoldWidget succeeds + // on same row and with same style, so same fold should be re-used for efficiency + var fold = this.$lastFold;// this.$findFold( session, foldStyle, row ); if ( fold ) return new Range(fold[0], fold[1], fold[2], fold[3]); } }) - ; - - // ACE-compatible Mode - ace_mode = { - $id: uuid("ace_grammar_mode") - ,$parser: new AceGrammar.Parser( parse_grammar( grammar ), DEFAULT ) - - /* - // maybe needed in later versions..? - ,createModeDelegates: function (mapping) { } - ,$delegator: function(method, args, defaultHandler) { } - ,HighlightRules: null - ,$behaviour: parser.$behaviour || null - ,lineCommentStart: parser.LC - ,blockComment: parser.BC - ,$getIndent: function(line) { return parser.indent(line); } - ,$createKeywordList: function() { return parser.$createKeywordList(); } - */ - - ,getTokenizer: function( ) { - return ace_mode.$parser; - } - - ,toggleCommentLines: function( state, session, startRow, endRow ) { - return ace_mode.$parser.tCL( state, session, startRow, endRow ); - } - ,toggleBlockComment: function( state, session, range, cursor ) { - return ace_mode.$parser.tCB( state, session, range, cursor, TokenIterator, Range ); + ,Mode = ace.require('ace/mode/text').Mode + ,AceMode = Class(Mode, { + constructor: function AceMode( ) { + var self = this; + Mode.call( self ); + self.$id = AceMode.$id; + self.$tokenizer = AceMode.$parser; + // comment-toggle functionality + self.lineCommentStart = AceMode.$parser.LC; + self.blockComment = AceMode.$parser.BC; + // custom, user-defined, code folding generated from grammar + self.foldingRules = new AceFold( self.folder.bind( self ) ); } - ,transformAction: function( state, action, editor, session, param ) { } - - ,getNextLineIndent: function( state, line, tab ) { - return ace_mode.$parser.indent( state, line, tab ); - } - ,checkOutdent: function( state, line, input ) { - return false; - } - ,autoOutdent: function( state, doc, row ) { } - - // custom, user-defined, code folding generated from grammar - ,supportCodeFolding: true - ,$folder: function folder( session, foldStyle, row ) { - var fold, min_row, current_row, folder; - if ( ace_mode.supportCodeFolding && ace_mode.$parser ) - { - folder = ace_mode.$parser; - - if ( "markbeginend" === foldStyle ) - { - current_row = row; min_row = MAX(0, row-500); // check up to 500 rows up - fold = folder.fold( session, row, ace ); - if ( fold ) - { - fold.start = true; fold.end = false; - return fold; - } - // try to find if any block ends on this row, backwards - // TODO, maybe a bit slower, than direct backwards search - while ( row > min_row && (!fold || current_row !== fold[2]) ) fold = folder.fold( session, --row, ace ); - if ( fold && current_row === fold[2] ) - { - fold.start = false; fold.end = true; - return fold; // found end of fold, return end marker - } - } - - else if ( fold = folder.fold( session, row, ace ) ) - { - fold.start = true; fold.end = false; - return fold; - } - } - } - ,foldingRules: null /* added below */ // custom, user-defined, syntax lint-like validation/annotations generated from grammar ,supportGrammarAnnotations: false ,createWorker: function( session ) { - if ( !ace_mode.supportGrammarAnnotations ) + if ( !this.supportGrammarAnnotations ) { - clear_annotations( session, ace_mode.$id+'$markers' ); + clear_annotations( session, AceMode.$markers ); return null; } // add this worker as an ace custom module - ace.config.setModuleUrl("ace/grammar_worker", this_path.file); - var worker = new AceWorker(['ace'], "ace/grammar_worker", 'AceGrammarWorker'); + //ace.config.setModuleUrl("ace/grammar_worker", this_path.file + NOCACHE); + var worker = new AceWorker(['ace'], "ace/grammar_worker", 'AceGrammarWorker', this_path.file + NOCACHE); worker.attachToDocument( session.getDocument( ) ); // create a worker for this grammar worker.call('init_parser', [grammar_copy], function( ){ // hook worker to enable error annotations worker.on("ace_grammar_worker_error", function( e ) { var errors = e.data; - update_annotations( session, errors, ace_mode.$id+'$markers', Range ) + update_annotations( session, errors, AceMode.$markers, Range ) }); worker.on("ace_grammar_worker_ok", function() { - clear_annotations( session, ace_mode.$id+'$markers' ); + clear_annotations( session, AceMode.$markers ); }); }); + worker.on("terminate", function() { + clear_annotations( session, AceMode.$markers ); + }); return worker; } + + // custom, user-defined, code folding generated from grammar + ,supportCodeFolding: true + ,folder: function folder( session, foldStyle, row ) { + return !this.supportCodeFolding + ? null + : AceMode.$folder( session, foldStyle, row, folder.options||{} ); + } + // custom, user-defined, autocompletions generated from grammar ,supportAutoCompletion: true + ,autocompleter: function autocompleter( state, session, position, prefix ) { + return !this.supportAutoCompletion + ? [] + : AceMode.$autocompleter( state, session, position, prefix, autocompleter.options||{} ); + } + ,getKeywords: function( append ) { + return []; // use getCompletions + } ,getCompletions: function( state, session, position, prefix ) { - return ace_mode.supportAutoCompletion && ace_mode.$parser - ? ace_mode.$parser.autocomplete( state, session, position, prefix, options, ace ) - : []; + return this.autocompleter( state, session, position, prefix ); } ,dispose: function( ) { - if ( ace_mode.$parser ) ace_mode.$parser.dispose( ); - ace_mode.$parser = null; - ace_mode.foldingRules = ace_mode.$folder = null; + var self = this; + self.$tokenizer = self.foldingRules = self.autocompleter = null; + AceMode.dispose( ); } + }); + AceMode.$id = uuid("ace_grammar_mode"); + AceMode.$markers = AceMode.$id+'$markers'; + AceMode.$parser = new AceGrammar.Parser( parse_grammar( grammar ), DEFAULT ); + AceMode.$folder = function folder( session, foldStyle, row, options ) { + var min_row, current_row, folder = AceMode.$parser, + fold = folder.fold( session, row, ace ); + if ( "markbeginend" === foldStyle ) + { + if ( fold ) { fold.start = true; fold.end = false; return fold; } + current_row = row; min_row = MAX(0, row-200); // check up to 200 rows up for efficiency + // try to find if any block ends on this row, backwards + // TODO, maybe a bit slower, than direct backwards search + while ( row > min_row && (!fold || current_row !== fold[2]) ) fold = folder.fold( session, --row, ace ); + // found end of fold, return end marker + if ( fold && current_row === fold[2] ) { fold.start = false; fold.end = true; return fold; } + } + else if ( fold ) { fold.start = true; fold.end = false; return fold; } + }; + AceMode.$autocompleter = function autocompleter( state, session, position, prefix, options ) { + return AceMode.$parser.autocomplete( state, session, position, prefix, options, ace ); + }; + AceMode.dispose = function( ) { + if ( AceMode.$parser ) AceMode.$parser.dispose( ); + AceMode.$parser = AceMode.$folder = AceMode.$autocompleter = AceMode.autocompleter = null; }; - ace_mode.foldingRules = new AceFold( ace_mode.$folder ); - return ace_mode; + return new AceMode( ); // object } diff --git a/build/ace_grammar.min.js b/build/ace_grammar.min.js index ddf1ff4..407f5f8 100644 --- a/build/ace_grammar.min.js +++ b/build/ace_grammar.min.js @@ -7,5 +7,5 @@ * https://github.com/foo123/ace-grammar * https://github.com/foo123/editor-grammar * -**/!function(e,n,t){"use strict";var r,o="object"==typeof module&&module.exports,i="function"==typeof define&&define.amd;o?module.exports=(module.$deps=module.$deps||{})[n]=module.$deps[n]||t.call(e,{NODE:module})||1:i&&"function"==typeof require&&"function"==typeof require.specified&&require.specified(n)?define(n,["require","exports","module"],function(n,r,o){return t.call(e,{AMD:o})}):n in e||(e[n]=r=t.call(e,{})||1)&&i&&define(n,[],function(){return r})}(this,"AceGrammar",function(e){"use strict";function n(e){var n=0;return null===e?n=$t:!0===e||!1===e||e instanceof Boolean?n=xt:ot===e?n=kt:(n=jt[ut.call(e)]||dt,n=bt===n||e instanceof Number?isNaN(e)?vt:isFinite(e)?bt:yt:wt===n||e instanceof String?1===e.length?_t:wt:Ot===n||e instanceof Array?Ot:St===n||e instanceof RegExp?St:qt===n||e instanceof Date?qt:Et===n||e instanceof Function?Et:Ct===n?Ct:dt),n}function t(e,n,t,r){var o,i,l,s,a,u,c=e.length;if(arguments.length<4&&(r=c-1),0>r&&(r+=c),arguments.length<3&&(t=0),t>r)return[];if(t===r)return[n(e[t],t,t,r)];for(l=r-t+1,s=15&l,a=1&s,u=new Array(l),a&&(u[0]=n(e[t],t,t,r)),o=a;s>o;o+=2)i=t+o,u[o]=n(e[i],i,t,r),u[o+1]=n(e[i+1],i+1,t,r);for(o=s;l>o;o+=16)i=t+o,u[o]=n(e[i],i,t,r),u[o+1]=n(e[i+1],i+1,t,r),u[o+2]=n(e[i+2],i+2,t,r),u[o+3]=n(e[i+3],i+3,t,r),u[o+4]=n(e[i+4],i+4,t,r),u[o+5]=n(e[i+5],i+5,t,r),u[o+6]=n(e[i+6],i+6,t,r),u[o+7]=n(e[i+7],i+7,t,r),u[o+8]=n(e[i+8],i+8,t,r),u[o+9]=n(e[i+9],i+9,t,r),u[o+10]=n(e[i+10],i+10,t,r),u[o+11]=n(e[i+11],i+11,t,r),u[o+12]=n(e[i+12],i+12,t,r),u[o+13]=n(e[i+13],i+13,t,r),u[o+14]=n(e[i+14],i+14,t,r),u[o+15]=n(e[i+15],i+15,t,r);return u}function r(e,n,t,r,o){var i,l,s,a,u,c=e.length,f=t;if(arguments.length<5&&(o=c-1),0>o&&(o+=c),arguments.length<4&&(r=0),r>o)return f;if(r===o)return n(f,e[r],r);for(s=o-r+1,a=15&s,u=1&a,u&&(f=n(f,e[r],r)),i=u;a>i;i+=2)l=r+i,f=n(n(f,e[l],l),e[l+1],l+1);for(i=a;s>i;i+=16)l=r+i,f=n(n(n(n(n(n(n(n(n(n(n(n(n(n(n(n(f,e[l],l),e[l+1],l+1),e[l+2],l+2),e[l+3],l+3),e[l+4],l+4),e[l+5],l+5),e[l+6],l+6),e[l+7],l+7),e[l+8],l+8),e[l+9],l+9),e[l+10],l+10),e[l+11],l+11),e[l+12],l+12),e[l+13],l+13),e[l+14],l+14),e[l+15],l+15);return f}function o(e,n,t,r){if(n>t)return r;if(n===t)return e(n,r,n,t),r;var o,i,l=t-n+1,s=15&l,a=1&s;for(a&&e(n,r,n,t),o=a;s>o;o+=2)i=n+o,e(i,r,n,t),e(++i,r,n,t);for(o=s;l>o;o+=16)i=n+o,e(i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t),e(++i,r,n,t);return r}function i(e,t){var r,o,l,s,a=n(e),u=0;if(bt===n(t)?t>0?(u=t,t=!0):t=!1:t=!1!==t,Ct===a){o={};for(l in e)e[lt](l)&&e[st](l)&&(r=n(e[l]),o[l]=Ct===r?t?i(e[l],u>0?u-1:t):e[l]:Ot===r?t?i(e[l],u>0?u-1:t):e[l].slice():qt===r?new Date(e[l]):wt&r?e[l].slice():bt&r?0+e[l]:e[l])}else if(Ot===a)for(s=e.length,o=new Array(s),l=0;s>l;l++)r=n(e[l]),o[l]=Ct===r?t?i(e[l],u>0?u-1:t):e[l]:Ot===r?t?i(e[l],u>0?u-1:t):e[l].slice():qt===r?new Date(e[l]):wt&r?e[l].slice():bt&r?0+e[l]:e[l];else o=qt===a?new Date(e):wt&a?e.slice():bt&a?0+e:e;return o}function l(){var e,t,r,o,s,a,u,c,f,p,m=arguments,g=m.length;if(1>g)return null;for(t=i(m[0]),r=1;g>r;r++)if(e=m[r])for(o in e)if(e[lt](o)&&e[st](o))if(t[lt](o)&&t[st](o)){if(f=n(t[o]),p=n(e[o]),Ct===f&&Ct===p)t[o]=l(t[o],e[o]);else if(Ot===f&&Ot===p){if(u=t[o],c=e[o],a=c.length,!a)continue;if(u.length)for(s=0;a>s;s++)0>u.indexOf(c[s])&&u.push(c[s]);else t[o]=c.slice()}}else t[o]=i(e[o]);return t}function s(){return!0}function a(e,t){return t||Ot!==n(e)?[e]:e}function u(e,t){return e=a(e),(t||Ot!==n(e[0]))&&(e=[e]),e}function c(e,t){return wt&n(t)&&wt&n(e)&&t.length&&t.length<=e.length&&t===e.substr(0,t.length)}function f(e,n,t){return nt&&e[r-t-1].$id===n;)t++;t&&(e.length=r-t)}return e}function m(e,n,t){return t?e[n]=ot:delete e[n],e}function g(e){return(e||"id_")+ ++Pt}function h(e){return(e||"uuid")+"_"+ ++Pt+"_"+(new Date).getTime()}function d(){var e,t,r,o,i,l,s=arguments,a=s.length;for(e=s[0]||{},i=1;a>i;i++)if(t=s[i],Ct===n(t))for(o in t)t[lt](o)&&t[st](o)&&(r=t[o],l=n(r),e[o]=bt&l?0+r:qt&l?new Date(r):Mt&l?r.slice():r);return e}function k(e,n){var t,r=arguments.length,o="constructor";return 0===r?(e=Object,n={}):1===r?(n=e||{},e=Object):(e=e||Object,n=n||{}),n[lt](o)||(n[o]=function(){}),t=n[o],delete n[o],t[it]=d(ct(e[it]),n),t[it][o]=t,t}function $(e){return e.replace(Bt,"\\$1")}function b(e,n){return new RegExp(e,n||"")}function y(e,n,t,r){var o,i,l,s,a=e.pos,u=e.length,c="",f=!!t;if(f){for(r=!!r,i=!1,s=0;u>a&&(o=e[gt](a++),n!==o||i);)l=t===o,i=!i&&l,r?(l&&s++,(!l||2&s)&&(c+=o,s=0)):c+=o;2&s&&(c+=t)}else for(;u>a&&(o=e[gt](a++),n!==o);)c+=o;return e.pos=a,c}function v(e,t,r){var o,i,l,s,a,u=!0===r?0:1;for(wt&n(t)&&(t=[t,t,t],u=0),i=e.length,a="",o=0;i>o;)l=e[gt](o),i>o+1&&"$"===l?(s=e.charCodeAt(o+1),36===s?(a+="$",o+=2):s>=48&&57>=s?(a+=t[u+s-48]||"",o+=2):(a+=l,o+=1)):(a+=l,o+=1);return a}function x(e,t,r){if(!e||(bt|St)&n(e))return e;var o,i=t?t.length||0:0;if(i&&t===e.substr(0,i)){var l,s,a,o,u,c=e.substr(i),f=c[gt](0),p="";for(o=c.length;o--&&(u=c[gt](o),f!==u);)"i"===u.toLowerCase()&&(p="i");return l=c.substring(1,o),s="^("+l+")",r[s]||(a=b(s,p),r[s]=a),r[s]}return e}function w(e,r,o){var i,l="";return wt&n(r)?l=r:r&&(l=Gt),i=t(e.sort(It),$).join("|"),[b("^("+i+")"+l,o?"i":""),1]}function _(e,t,r,o){var i=n(t);if(bt===i)return t;if(o[e])return o[e];r=r||0;var l,s=0;return t&&t.isCharList&&(s=1,m(t,"isCharList")),l=$t===i?new D(Ln,e,t,$t,r):_t===i?new D(Ln,e,t,_t,r):Rt&i?new D(Ln,e,t,St,r):wt&i?new D(Ln,e,t,s?Lt:wt,r):t,o[e]=l}function L(e,t,r,o,i,l,s){if(s[e])return s[e];var u,f,p,m,g,h,d,k=0,$=0,b=1,y=wt&n(o)?!0:!!o;if(u=a(t),p=u.length,1===p)d=_(e,x(u[0],r,l),0,s);else if(p>1){for(m=(p>>>1)+1,f=0;m>=f;f++)g=n(u[f]),h=n(u[p-1-f]),(_t!==g||_t!==h)&&(b=0),Ot&g||Ot&h?k=1:(St&g||St&h||c(u[f],r)||c(u[p-1-f],r))&&($=1);if(b&&!y)u=u.slice().join(""),u.isCharList=1,d=_(e,u,0,s);else if(!y||k||$)if(k||$){for(f=0;p>f;f++)u[f]=Ot&n(u[f])?L(e+"_"+f,u[f],r,o,i,l,s):_(e+"_"+f,x(u[f],r,l),f,s);d=p>1?new D(On,e,u):u[0]}else{for(u=u.sort(It),f=0;p>f;f++)u[f]=_(e+"_"+f,x(u[f],r,l),f,s);d=p>1?new D(On,e,u):u[0]}else d=_(e,w(u,o,i),0,s)}return s[e]=d}function O(e,t,r,i,l){if(l[e])return l[e];var s=u(t),a=[],f=[];return o(function(t){var o,u;o=_(e+"_0_"+t,x(s[t][0],r,i),t,l),u=s[t].length>1?St!==o.ptype||wt!==n(s[t][1])||c(s[t][1],r)?_(e+"_1_"+t,x(s[t][1],r,i),t,l):s[t][1]:o,a.push(o),f.push(u)},0,s.length-1),l[e]=new D(Cn,e,[a,f])}function C(e,n){var t=u(e.tokens.slice());o(function(e){var r=t[e][0],o=t[e].length>1?t[e][1]:t[e][0],i=t[e].length>2?t[e][2]:"";null===o?(n.line=n.line||[],n.line.push(r)):(n.block=n.block||[],n.block.push([r,o,i]))},0,t.length-1)}function E(e,n,r){var o=e.meta||n,i=!(!e.caseInsesitive&&!e.ci),l=t(a(e.tokens),function(e){return{word:e,meta:o,ci:i}});r.autocomplete=(r.autocomplete||[]).concat(l)}function S(e){e.Lex||(e.Lex={}),e.Syntax||(e.Syntax={});var t,r,o,i,s,a,u,c,f,p,g,h=e.Lex,d=e.Syntax,k=[h,d],$=k.length;for(g=0;$>g;){p=k[g++];for(o in p)p[lt](o)&&(t=o.split(":"),r=t[1]&&At(t[1]).length?At(t[1]):null,t=At(t[0]),t.length||(t=o,r=null),t!==o&&(p[t]=p[o],m(p,o),r&&(r=r[mt](),i=p[t],s=n(i),Ct===s?p[t].type||(p[t].type=r):(p[t]={type:r},"error"===r?(p[t].type="action",p[t].error=i):"nop"===r?(p[t].type="action",p[t].nop=!0):"group"===r?(p[t].type="sequence",p[t].tokens=i):"action"===r&&wt===s?p[t][i]=!0:p[t].tokens=i))),h===p&&(Ft&n(p[t])&&(p[t]={type:"simple",tokens:p[t]}),i=p[t],i.type&&(c=i.type=i.type[mt](),"line-block"===c?(i.type="block",i.multiline=!1,i.escape=!1):"escaped-line-block"===c?(i.type="block",i.multiline=!1,i.escape="\\"):"escaped-block"===c&&(i.type="block",i.multiline=!0,i.escape="\\"))))}p=h;for(t in p)if(p[lt](t))for(i=p[t];i.extend;)a=i.extend,m(i,"extend"),u=h[a],u&&(Ft&n(u)&&(u=h[a]={type:"simple",tokens:u}),i=l(u,i));p=h;for(t in p)p[lt](t)&&(i=p[t],i.type?(c=i.type=i.type[mt](),"line-block"===c?(i.type="block",i.multiline=!1,i.escape=!1):"escaped-line-block"===c?(i.type="block",i.multiline=!1,i.escape="\\"):"escaped-block"===c&&(i.type="block",i.multiline=!0,i.escape="\\")):i["escaped-line-block"]?(i.type="block",i.multiline=!1,i.escape||(i.escape="\\"),i.tokens=i["escaped-line-block"],m(i,"escaped-line-block")):i["escaped-block"]?(i.type="block",i.multiline=!0,i.escape||(i.escape="\\"),i.tokens=i["escaped-block"],m(i,"escaped-block")):i["line-block"]?(i.type="block",i.multiline=!1,i.escape=!1,i.tokens=i["line-block"],m(i,"line-block")):i.comment?(i.type="comment",i.escape=!1,i.tokens=i.comment,m(i,"comment")):i.block?(i.type="block",i.tokens=i.block,m(i,"block")):i.simple?(i.type="simple",i.tokens=i.simple,m(i,"simple")):i.nop?(i.type="action",i.action=["nop",i.nop,!1],i.nop=!0):i.error?(i.type="action",i.action=["error",i.error,!!i["in-context"]],m(i,"error")):i[lt]("context")?(i.type="action",i.action=[i.context?"context-start":"context-end",i.context,!!i["in-context"]],m(i,"context")):i.indent?(i.type="action",i.action=["indent",i.indent,!!i["in-context"]],m(i,"indent")):i.outdent?(i.type="action",i.action=["outdent",i.outdent,!!i["in-context"]],m(i,"outdent")):i.unique?(i.type="action",i.action=["unique",wt&n(i.unique)?["_DEFAULT_",i.unique]:i.unique,!!i["in-context"]],m(i,"unique")):i.push?(i.type="action",i.action=["push",i.push,!!i["in-context"]],m(i,"push")):i[lt]("pop")?(i.type="action",i.action=["pop",i.pop,!!i["in-context"]],m(i,"pop")):i.type="simple","action"===i.type?i.ci=!(!i.caseInsesitive&&!i.ci):"block"===i.type||"comment"===i.type?(i.multiline=i[lt]("multiline")?!!i.multiline:!0,wt&n(i.escape)||(i.escape=!1)):"simple"===i.type&&(i.autocomplete=!!i.autocomplete,i.meta=i.autocomplete&&wt&n(i.meta)?i.meta:null,i.combine=i[lt]("combine")?i.combine:!0,i.ci=!(!i.caseInsesitive&&!i.ci)));p=d;for(t in p)p[lt](t)&&(i=p[t],Ct!==n(i)||i.type?i.type&&(c=i.type=i.type[mt](),"group"===c&&i.match?(s=n(i.match),wt&s?(f=i.match[mt](),"alternation"===f||"either"===f?(i.type="alternation",m(i,"match")):"sequence"===f||"all"===f?(i.type="sequence",m(i,"match")):"zeroorone"===f?(i.type="zeroOrOne",m(i,"match")):"zeroormore"===f?(i.type="zeroOrMore",m(i,"match")):"oneormore"===f?(i.type="oneOrMore",m(i,"match")):(i.type="sequence",m(i,"match"))):Ot&s&&(i.type="repeat",i.repeat=i.match,m(i,"match"))):"either"===c?i.type="alternation":"all"===c?i.type="sequence":"lookahead"===c&&(i.type="positiveLookahead")):i.ngram||i["n-gram"]?(i.type="ngram",i.tokens=i.ngram||i["n-gram"],i["n-gram"]?m(i,"n-gram"):m(i,"ngram")):i.sequence||i.all?(i.type="sequence",i.tokens=i.sequence||i.all,i.all?m(i,"all"):m(i,"sequence")):i.alternation||i.either?(i.type="alternation",i.tokens=i.alternation||i.either,i.either?m(i,"either"):m(i,"alternation")):i.zeroOrOne?(i.type="zeroOrOne",i.tokens=i.zeroOrOne,m(i,"zeroOrOne")):i.zeroOrMore?(i.type="zeroOrMore",i.tokens=i.zeroOrMore,m(i,"zeroOrMore")):i.oneOrMore?(i.type="oneOrMore",i.tokens=i.oneOrMore,m(i,"oneOrMore")):i.positiveLookahead||i.lookahead?(i.type="positiveLookahead",i.tokens=i.positiveLookahead||i.lookahead,i.lookahead?m(i,"lookahead"):m(i,"positiveLookahead")):i.negativeLookahead&&(i.type="negativeLookahead",i.tokens=i.negativeLookahead,m(i,"negativeLookahead")));return e}function q(e,t,r,o){for(var i;wt&n(i=t[e]||r[e]);)e=i;return o?e:t[e]||r[e]||e}function T(e,n){return e.length>1?o(n?function(n,t){var r=t[t.length-1],o=e[n];r===o||t.push(o)}:function(n,t){var r=t[t.length-1],o=e[n];Wt.test(o)&&Wt.test(r)&&r===o||t.push(o)},1,e.length-1,[e[0]]):e}function M(e,r,o){var l,s,a,u,c,f,p,m,g,h,d,k,v,x,w,_=!1;if(w=e.modifier?e.modifier:null,m=new String(At(e)),m.pos=0,1===m.length)k=""+e,r[k]||o[k]||(r[k]={type:"simple",tokens:e}),e=k;else{for(l=[],s=[],a="",v=[];m.posc[0]&&(c[0]=0),2>c.length?c.push(c[0]):c[1]=c[1].length?parseInt(c[1],10)||ht:ht,0>c[1]&&(c[1]=0),d=s[s.length-1],k=""+d+["{",c[0],",",isFinite(c[1])?c[1]:"","}"].join(""),o[k]||(o[k]={type:"repeat",repeat:[c[0],c[1]],tokens:[d]}),s[s.length-1]=k):a+=g;else{if("}"===g){a+=g;continue}"&"===g||"!"===g?a+=g:"|"===g?(_=!1,s=T(s),s.length>1?(k=""+s.join(" "),o[k]||(o[k]={type:"sequence",tokens:s}),l.push(k)):s.length?l.push(s[0]):a+=g,s=[]):"("===g?(v.push([s,l,a]),s=[],l=[],a=""):")"===g&&(s=T(s),s.length>1?(k=""+s.join(" "),o[k]||(o[k]={type:"sequence",tokens:s}),l.push(k)):s.length&&l.push(s[0]),s=[],l=T(l,1),l.length>1?(k=""+l.join(" | "),o[k]||(o[k]={type:"alternation",tokens:l})):l.length&&(k=l[0]),l=[],x=v.pop(),s=x[0],l=x[1],a=x[2],d=k,k="("+d+")",o[k]||(o[k]=i(q(d,r,o))),s.push(k))}}else a+=g;a.length&&(_?(s.length&&(d=s[s.length-1],k=d+"."+a,f=r[k]||o[k],f||(p=q(d,r,o),o[k]=wt&n(p)?new String(p):i(p),o[k].modifier=a),s[s.length-1]=k),_=!1):"0"===a?(r[tt]||(r[tt]={type:"simple",tokens:0}),s.push(tt)):"^^"===a?(r[Hn]||(r[Hn]={type:"simple",tokens:Sn}),s.push(Hn)):"^^1"===a?(r[Jn]||(r[Jn]={type:"simple",tokens:qn}),s.push(Jn)):"^"===a?(r[Xn]||(r[Xn]={type:"simple",tokens:Mn}),s.push(Xn)):"$"===a?(r[et]||(r[et]={type:"simple",tokens:Tn}),s.push(et)):(r[a]||o[a]||(r[a]={type:"simple",tokens:a}),s.push(a))),a="",s=T(s),s.length>1?(k=""+s.join(" "),o[k]||(o[k]={type:"sequence",tokens:s}),l.push(k)):s.length&&l.push(s[0]),s=[],l=T(l,1),l.length>1?(k=""+l.join(" | "),o[k]||(o[k]={type:"alternation",tokens:l}),e=k):l.length&&(e=l[0]),l=[]}return w&&(r[e]||o[e])&&((r[e]||o[e]).modifier=w),e}function R(e,i,l,s,c,f,p,m,g,h,d){var k,$,b,y,v,x,w=null,_=null,S=null;if(Sn===e||qn===e||Mn===e||Tn===e)return new I(e,Sn===e?Hn:qn===e?$T_FBNL$:Mn===e?Xn:et,e,_);if(!1===e||0===e)return new I(Rn,tt,0,_);if(""===e)return new I(Fn,rt,"",_);if(null===e)return new I(jn,nt,$t,_,S);if(Ot&n(e)&&(b=e,e="NGRAM_"+b.join("_"),s[e]||(s[e]={type:"ngram",tokens:b})),e=""+e,m[e])return m[e];if(v=q(e,l,s),wt&n(v)&&(v=M(v,l,s),v=l[v]||s[v]||null),!v)return null;if(k=v.type?Kn[v.type[mt]().replace(zt,"")]||jn:jn,_=v.msg||null,S=v.modifier||null,$=v.tokens,jn&k){if(Sn===$||qn===$||Mn===$||Tn===$||!1===$||0===$)return w=new I($||Rn,e,$||0,_),m[e]=w,w;if(""===$)return w=new I(Fn,e,"",_),m[e]=w,w;if(null===$)return w=new I(jn,e,$t,_,S),m[e]=w,w;if(!$)return null}return En&k?(v[lt]("action")?"nop"===v.action[0]?v.action[0]=dn:"error"===v.action[0]?v.action[0]=kn:"context-start"===v.action[0]?v.action[0]=bn:"context-end"===v.action[0]?v.action[0]=yn:"push"===v.action[0]?v.action[0]=vn:"pop"===v.action[0]?v.action[0]=xn:"unique"===v.action[0]?v.action[0]=$n:"indent"===v.action[0]?v.action[0]=wn:"outdent"===v.action[0]&&(v.action[0]=_n):v[lt]("nop")?v.action=[dn,v.nop,!!v["in-context"]]:v[lt]("error")?v.action=[kn,v.error,!!v["in-context"]]:v[lt]("context")?v.action=[v.context?bn:yn,v.context,!!v["in-context"]]:v[lt]("context-start")?v.action=[bn,v["context-start"],!!v["in-context"]]:v[lt]("context-end")?v.action=[yn,v["context-end"],!!v["in-context"]]:v[lt]("push")?v.action=[vn,v.push,!!v["in-context"]]:v[lt]("pop")?v.action=[xn,v.pop,!!v["in-context"]]:v[lt]("unique")?v.action=[$n,wt&n(v.unique)?["_DEFAULT_",v.unique]:v.unique,!!v["in-context"]]:v[lt]("indent")?v.action=[wn,v.indent,!!v["in-context"]]:v[lt]("outdent")&&(v.action=[_n,v.outdent,!!v["in-context"]]),v.nop&&(v.action[0]=dn),w=new I(En,e,v.action.slice(),_,S),w.ci=!!v.caseInsensitive||v.ci,m[e]=w):($=a($),jn&k?(v.autocomplete&&E(v,e,d),x=v[lt]("combine")?v.combine:!0,w=new I(jn,e,L(e,$.slice(),i,x,!(!v.caseInsensitive&&!v.ci),f,p),_,S),m[e]=w):Dn&k?(An===k&&C(v,h),w=new I(k,e,O(e,$.slice(),i,f,p),_),w.mline=v[lt]("multiline")?!!v.multiline:!0,w.esc=v[lt]("escape")?v.escape:!1,w.inter=!!c[e+".inside"],An===k&&v.interleave&&g.push(z(w)),S&&(w.modifier=S),m[e]=w):Zn&k&&(Qn===k?(y=u($),w=t(y,function(n,t){return new I(Qn,e+"_NGRAM_"+t,null,_,S)}),m[e]=w,o(function(e){w[e].token=a(r(y[e],function(e,n){return e.concat(R(n,i,l,s,c,f,p,m,g,h,d))},[]))},0,y.length-1)):(Wn===k||Yn===k?w=new I(k,e,null,_,S):zn&k&&Ot&n(v.repeat)?(w=new I(zn,e,null,_,S),w.min=v.repeat[0],w.max=v.repeat[1]):Pn===k?(w=new I(Pn,e,null,_,S),w.min=0,w.max=1):Bn===k?(w=new I(Bn,e,null,_,S),w.min=0,w.max=ht):Un===k?(w=new I(Un,e,null,_,S),w.min=1,w.max=ht):w=In===k?new I(In,e,null,_,S):new I(Nn,e,null,_,S),m[e]=w,w.token=a(r($,function(e,n){return e.concat(R(n,i,l,s,c,f,p,m,g,h,d))},[]))))),m[e]}function F(e,n){var t,r,o=e.Style,i=e.Lex,l=e.Syntax,s=[],a={};for(t in o)o[lt](t)&&(r=i[t]||l[t],!r||"block"!=r.type&&"comment"!==r.type||(n&&(o[t+".inside"]||o[t])?(t=o[t+".inside"]||o[t],a[lt](t)||(s.push(t),a[t]=1)):n||a[lt](t)||(s.push(t),a[t]=1)));return s}function j(e){var t,o,l,s,a,u,c,f,p,m,g,h,d;return e.__parsed?e:(t=e.RegExpID||null,l=e.Extra?i(e.Extra):{},s=e.Style?i(e.Style):{},a=null,u=e.Lex?i(e.Lex):{},c=e.Syntax?i(e.Syntax):{},f={},p={},m={},h={},d={},g=[],o=e.Parser?i(e.Parser):[],e=S({Style:s,Fold:a,Lex:u,Syntax:c,$parser:null,$interleaved:null,$comments:null,$autocomplete:null,$extra:l,__parsed:0}),e.$parser=r(o,function(e,r){var o=R(r,t,u,c,s,f,p,m,g,h,d)||null;return o&&(Ot&n(o)?e=e.concat(o):e.push(o)),e},[]),e.$interleaved=g&&g.length?g:null,e.$comments=h,e.$autocomplete=d&&d.autocomplete&&d.autocomplete.length?d.autocomplete:null,e.__parsed=1,e)}function D(e,t,r,o,i){var l,s,a=this;l=a.type=e,a.name=t,a.pattern=r,s=a.ptype=o||wt,a.key=i||0,On===l?a.key=!1!==i:Cn===l?a.pattern[0]=new D(On,t+"_Start",r[0],null,!1):$t===s?a.pattern=null:St===s&&(a.pattern=St&n(r)?[r,0]:[r[0],r[1]||0])}function A(e,t,r){var o,i,l,s,a,u,c,f,p,m,g,h=e,d=h.type,k=h.pattern,$=h.key;if(Cn===d){if(o=h.name,l=k[0],s=k[1],u=A(l,t,r))return a=s[u[0]],f=n(a),p=l.pattern[u[0]].ptype,St===p&&Tt&f&&(c=bt&f?u[1][a+1]:v(a,u[1]),a=new D(Ln,o+"_End",c,c.length>1?wt:_t)),a}else if(On===d){for(m=0,g=k.length;g>m;m++)if(c=A(k[m],t,r))return $?[m,c[1]]:c}else{if(i=h.ptype,$t===i)return!1!==r&&t.end(),[$,""];if(St===i){if(c=t.slice(t.pos).match(k[0]),c&&0===c.index)return!1!==r&&t.mov(c[k[1]||0].length),[$,k[1]>0?c[k[1]]:c]}else if(Lt===i){if(c=t[gt](t.pos)||null,c&&-1y&&y>x?($=R,n.bck(y),u=1):($=C,a=1),P=n.sel(y,n.pos);break}k=n.nxt(1),N+=k,d=j&&!d&&F===k,y=n.pos}return c=T||j&&d,I+=N,g[1]=[_,y],m=[_,n.pos],a||!c&&!u?t.block=null:(t.block.ip=g,t.block.ep=m,t.block.i=I,t.block.e=P,f(U,w,z(O,b,0,B))),r.T=E,r.id=C,r.type=S||$,r.str=n.sel(L,n.pos),r.match=null,r.pos=[_,L,m[0],m[1]],t.block||(h=D+I+P,r.block={str:h,match:[h,I,D,P],part:[h,D,I,P],pos:[[p[0],p[1],m[0],m[1]],[p[0],p[1],g[0][0],g[0][1]],[g[0][0],g[0][1],g[1][0],g[1][1]],[g[1][0],g[1][1],m[0],m[1]]]}),S||$}return O.status&&O.$msg&&(O.$msg=v(O.$msg,C,!0)),!1}function Q(e,n,t,r){var o,i,l,s,a,u,c,p,m,h,d,k,$,b,y,v=e,x=v.type,w=(v.name,v.token),_=w.length,L=v.modifier;if(v.status&=gn,v.$msg=v.msg||null,k=t.stack,p=n.pos,m=k.length,u=0,c=0,b=v.$id||g(),In===x){for(v.status|=fn,$=[],h=0;_>h;h++){if(o=z(w[h],1,L,b),i=U(o,n,t,r),o.status&fn&&(u++,$.push(P(o))),!1!==i)return i;o.status&pn&&(c++,n.pos>p&&n.bck(p),k.length>m&&(k.length=m))}return u>0?v.status|=fn:v.status&=mn,_===c&&u>0?v.status|=pn:v.status&=gn,v.status&&!v.$msg&&$.length&&(v.$msg=$.join(" | ")),!1}if(Vn&x){y=!!(x&Nn),y?v.status|=fn:v.status&=mn,d=0;do o=z(w[d++],y,L,b),i=U(o,n,t,r);while(_>d&&!1===i&&!(o.status&hn));if(!1!==i){if(!0!==i||Rn!==o.type)for(h=_-1;h>=d;h--)f(k,m+_-h-1,z(w[h],1,L,b));return i}return o.status&pn?(y?v.status|=pn:v.status&=gn,n.pos>p&&n.bck(p),k.length>m&&(k.length=m)):y&&o.status&fn&&(v.status|=pn),v.status&&!v.$msg&&(v.$msg=P(o)),!1}if(Wn===x)return v.status=0,!1;if(Yn===x)return v.status=0,!1;for(l=v.found,s=v.min,a=v.max,v.status&=mn,$=[],h=0;_>h;h++){if(o=z(w[h],1,L,b),i=U(o,n,t,r),!1!==i){if(++l,a>=l)return v.found=l,f(k,m,z(v,0,0,b)),v.found=0,i;break}o.status&fn&&(u++,$.push(P(o))),o.status&pn&&(n.pos>p&&n.bck(p),k.length>m&&(k.length=m))}return s>l?v.status|=fn:v.status&=mn,l>a||s>l&&u>0?v.status|=pn:v.status&=gn,v.status&&!v.$msg&&$.length&&(v.$msg=$.join(" | ")),!1}function V(e,n){var t=this;t.id=e?h("state"):"state",n instanceof V?(t.line=n.line,t.bline=n.bline,t.status=n.status,t.stack=n.stack.slice(),t.block=n.block,t.status&un?(t.queu=n.queu,t.symb=n.symb,t.ctx=n.ctx,t.err=n.err):(t.queu=null,t.symb=null,t.ctx=null,t.err=null),t.$eol$=n.$eol$,t.$blank$=n.$blank$):(t.line=-1,t.bline=-1,t.status=n||0,t.stack=[],t.block=null,t.status&un?(t.queu=[],t.symb={},t.ctx=[],t.err={}):(t.queu=null,t.symb=null,t.ctx=null,t.err=null),t.$eol$=!0,t.$blank$=!0),t.toString=function(){return t.id+"_"+t.line+"_"+t.bline+"_"+(t.block?t.block.name:"0")}}function Z(e){e.id=null,e.line=null,e.bline=null,e.status=null,e.stack=null,e.block=null,e.queu=null,e.symb=null,e.ctx=null,e.err=null}function K(e,n,t){var r=new String(e);return r.start=n||0,r.pos=t||0,r.sol=function(){return 0===r.pos},r.eol=function(){return r.pos>=r.length},r.end=function(){return r.pos=r.length,r},r.mov=function(e){return r.pos=0>e?ft(0,r.pos+e):pt(r.length,r.pos+e),r},r.bck=function(e){return r.pos=ft(0,e),r},r.sft=function(){return r.start=r.pos,r},r.nxt=function(e,n){var t,o,i="";if(!0===e){for(n=n||K.$NONSPC$;r.poss||s>=n)return l+(n-i);l+=s-i,l+=t-l%t,i=s+1}}function J(e,r){return Mt&n(e)&&(e=b("\\b("+t(a(e).sort(It),$).join("|")+")\\b")),!1===r?function(n){return!e.test(n)}:function(n){return e.test(n)}}function X(e,n,t){for(;;){t.lastIndex=e.col;var r,o=t.exec(e.text);if(!o){if(e.next()){e.text=e.line(e.row);continue}return}{if((r=e.token(e.row,o.index+1))&&n(r))return e.col=o.index+o[0].length,o;e.col=o.index+1}}}function en(e,n,t,r,o,i){for(var l,s,a,u;;){if(l=e.text.indexOf(o,e.col),-1==l){if(e.next()){e.text=e.line(e.row);continue}return}if((u=e.token(e.row,l+1))&&n(u))return s=e.text.lastIndexOf(i,l),a=s>-1&&!K.$NOTEMPTY$.test(e.text.slice(s+1,l)),e.col=l+1,a?"autoclosed":"regular";e.col=l+1}}function nn(e){var n=e?e.data:null;n&&n.load&&n.ace_worker_base&&(importScripts(n.ace_worker_base),ace.define("ace/grammar_worker",["require","exports","module","ace/worker/mirror"],function(e,n){var t,r=e("./worker/mirror").Mirror;n.AceGrammarWorker=t=k(r,{constructor:function(e){var n=this;r.call(n,e),n.setTimeout(300)},$parser:null,init_parser:function(e,n){var t=this;t.$parser=new Xt(j(e)),t.sender.callback(1,n)},onUpdate:function(){var e,n,t,r,o,i=this,l=i.sender,s=i.$parser;if(!s)return void l.emit("ace_grammar_worker_ok",null);if(e=i.doc.getValue(),!e||!e.length)return void l.emit("ace_grammar_worker_ok",null);if(n=s.parse(e,un),!n)return void l.emit("ace_grammar_worker_ok",null);o=[];for(t in n)n[lt](t)&&(r=n[t],o.push({row:r[0],column:r[1],text:r[4]||"Syntax Error",type:"error",raw:r[4]||"Syntax Error",range:[r[0],r[1],r[2],r[3]]}));o.length?l.emit("ace_grammar_worker_error",o):l.emit("ace_grammar_worker_ok",null)}})}))}function tn(e,n){e[n]||(e[n]=[]);var t,r=e[n];if(r&&r.length)for(t=0;to;o++)i=n[o],i.range&&(l.push(e.addMarker(new r(i.range[0],i.range[1],i.range[2],i.range[3]),"ace_error-marker","text",0)),m(i,"range"))}function on(e,n){tn(e,n),e.clearAnnotations()}function ln(e,n,t,r){rn(e,n,t,r),e.setAnnotations(n)}function sn(e,n,t){t=t||Jt;var r,o=i(e),l=t.require("ace/range").Range,s=t.require("ace/token_iterator").TokenIterator,a=t.require("ace/worker/worker_client").WorkerClient,u=k(a,{constructor:function(e,n,r){var o=this,i=t.require,l=t.config;o.$sendDeltaQueue=o.$sendDeltaQueue.bind(o),o.changeListener=o.changeListener.bind(o),o.onMessage=o.onMessage.bind(o),i.nameToUrl&&!i.toUrl&&(i.toUrl=i.nameToUrl);var s;if(l.get("packaged")||!i.toUrl)s=l.moduleUrl(n,"worker");else{var a=o.$normalizePath;s=a(i.toUrl("ace/worker/worker.js",null,"_"));var u={};e.forEach(function(e){u[e]=a(i.toUrl(e,null,"_").replace(/(\.js)?(\?.*)?$/,""))})}o.$worker=new Worker(s),o.$worker.postMessage({load:!0,ace_worker_base:Ht.base+"/"+l.moduleUrl("ace/worker/json")}),o.$worker.postMessage({init:!0,tlns:u,module:n,classname:r}),o.callbackId=1,o.callbacks={},o.$worker.onmessage=o.onMessage}}),c=t.require("ace/mode/folding/fold_mode").FoldMode,f=k(c,{constructor:function(e){var n=this;c.call(n),n.$findFold=e},getFoldWidget:function(e,n,t){var r=this,o=r.$findFold(e,n,t);return o?"markbeginend"===n&&o.end?"end":"start":""},getFoldWidgetRange:function(e,n,t){var r=this.$findFold(e,n,t);return r?new l(r[0],r[1],r[2],r[3]):void 0}});return r={$id:h("ace_grammar_mode"),$parser:new er.Parser(j(e),n),getTokenizer:function(){return r.$parser},toggleCommentLines:function(e,n,t,o){return r.$parser.tCL(e,n,t,o)},toggleBlockComment:function(e,n,t,o){return r.$parser.tCB(e,n,t,o,s,l)},transformAction:function(){},getNextLineIndent:function(e,n,t){return r.$parser.indent(e,n,t)},checkOutdent:function(){return!1},autoOutdent:function(){},supportCodeFolding:!0,$folder:function p(e,n,o){var i,l,s,p;if(r.supportCodeFolding&&r.$parser)if(p=r.$parser,"markbeginend"===n){if(s=o,l=ft(0,o-500),i=p.fold(e,o,t))return i.start=!0,i.end=!1,i;for(;o>l&&(!i||s!==i[2]);)i=p.fold(e,--o,t);if(i&&s===i[2])return i.start=!1,i.end=!0,i}else if(i=p.fold(e,o,t))return i.start=!0,i.end=!1,i},foldingRules:null,supportGrammarAnnotations:!1,createWorker:function(e){if(!r.supportGrammarAnnotations)return on(e,r.$id+"$markers"),null;t.config.setModuleUrl("ace/grammar_worker",Ht.file);var n=new u(["ace"],"ace/grammar_worker","AceGrammarWorker");return n.attachToDocument(e.getDocument()),n.call("init_parser",[o],function(){n.on("ace_grammar_worker_error",function(n){var t=n.data;ln(e,t,r.$id+"$markers",l)}),n.on("ace_grammar_worker_ok",function(){on(e,r.$id+"$markers")})}),n},supportAutoCompletion:!0,getCompletions:function(e,n,o,i){return r.supportAutoCompletion&&r.$parser?r.$parser.autocomplete(e,n,o,i,options,t):[]},dispose:function(){r.$parser&&r.$parser.dispose(),r.$parser=null,r.foldingRules=r.$folder=null}},r.foldingRules=new f(r.$folder),r}var an=1,un=2,cn=32,fn=4,pn=8,mn=~fn,gn=~pn,hn=fn|pn,dn=0,kn=4,$n=8,bn=16,yn=17,vn=32,xn=33,wn=128,_n=129,Ln=2,On=4,Cn=8,En=4,Sn=8,qn=9,Tn=16,Mn=32,Rn=128,Fn=256,jn=512,Dn=1024,An=1025,In=2048,Nn=4096,zn=8192,Pn=8193,Bn=8194,Un=8195,Gn=16384,Wn=Gn,Yn=16385,Qn=32768,Vn=Nn|Qn,Zn=In|Nn|zn|Gn|Qn,Kn={action:En,simple:jn,block:Dn,comment:An,alternation:In,sequence:Nn,repeat:zn,zeroorone:Pn,zeroormore:Bn,oneormore:Un,positivelookahead:Wn,negativelookahead:Yn,ngram:Qn},Hn="$|SOF|$",Jn="$|NONBLANK|$",Xn="$|SOL|$",et="$|EOL|$",nt="$|ENDLINE|$",tt="$|EMPTY|$",rt="$|NONSPACE|$",ot=void 0,it="prototype",lt="hasOwnProperty",st="propertyIsEnumerable",at=Object[it],ut=at.toString,ct=Object.create,ft=Math.max,pt=Math.min,mt="toLowerCase",gt="charAt",ht=1/0,dt=4,kt=8,$t=16,bt=32,yt=33,vt=34,xt=64,wt=128,_t=129,Lt=130,Ot=256,Ct=512,Et=1024,St=2048,qt=4096,Tt=wt|bt,Mt=wt|Ot,Rt=St|Ot,Ft=wt|Ot|St,jt={"[object Number]":bt,"[object String]":wt,"[object Array]":Ot,"[object RegExp]":St,"[object Date]":qt,"[object Function]":Et,"[object Object]":Ct},Dt=/^\s+|\s+$/g,At=String[it].trim?function(e){return e.trim() -}:function(e){return e.replace(Dt,"")},It=function(e,n){return n.length-e.length},Nt=/\r\n|\r|\n/g,zt=/[\-_]/g,Pt=0,Bt=/([.*+?^${}()|[\]\/\\\-])/g,Ut=/^([.!&\[\]{}()*+?\/|'"]|\s)/,Gt="(\\s|\\W|$)",Wt=/[*+]$/;K.$SPC$=/^[\s\u00a0]+/,K.$NONSPC$=/[^\s\u00a0]/,K.$NOTEMPTY$=/\S/,K.$SPACE$=/^\s*/;var Yt=k({constructor:function(e,n,t){var r=this;r.$grammar=e,r.$DEF=n||null,r.$ERR=t||null,r.DEF=r.$DEF,r.ERR=r.$ERR,r.$folders=[]},$grammar:null,$folders:null,$n$:"name",$t$:"type",$v$:"token",$DEF:null,$ERR:null,DEF:null,ERR:null,dispose:function(){var e=this;return e.$grammar=null,e.$folders=null,e.$n$=e.$t$=e.$v$=null,e.$DEF=e.$ERR=e.DEF=e.ERR=null,e},token:function(e,n){var t,r,o,i,l,s,a,u,c,f,m,g,h,d,k,$=this,b=$.$grammar,y=b.Style,v=$.DEF,x=$.ERR,w={},_=$.$n$,L=$.$t$,O=$.$v$,C=b.$interleaved,E=b.$parser,S=E.length,q=C?C.length:0;if(e.sol()&&(n.$eol$&&(n.$blank$&&(n.bline=n.line),n.$eol$=!1,n.line++),n.$blank$=n.bline+1===n.line),n.$actionerr$=!1,i=n.stack,l=n.line,s=e.pos,m=!1,h=!0,g=!1,d=!1,k=n.block?n.block.name:ot,i.length&&Tn===i[i.length-1].type&&e.sol()&&i.pop(),(!i.length||Fn!==i[i.length-1].type&&k!==i[i.length-1].name)&&e.spc()&&(h=!1,d=!0),w[_]=null,w[L]=v,w[O]=null,h)for(o=new N,a=0;h&&(i.length||S>a)&&!e.eol();){if(c=e.pos,f=i.length,q&&!n.block){for(u=0;q>u;u++)if(t=C[u],m=U(t,e,n,o),!1!==m){h=!1;break}if(!h)break}if(!i.length&&a>=S)break;if(t=i.length?i.pop():E[a++],m=U(t,e,n,o),!1===m){if(t.status&hn){p(i,t.$id),e.nxt(!0)||(e.spc(),d=!0),g=!0,h=!1;break}}else{if(i.length&&En===i[i.length-1].type)for(;i.length&&En===i[i.length-1].type;)r=i.pop(),G(r,e,n,o),r.status&pn&&(n.$actionerr$=!0);else if(i.length>1&&e.eol()&&Dn&i[i.length-1].type&&n.block&&n.block.name===i[i.length-1].name)for(u=i.length-2;u>=0&&En===i[u].type;)r=i[u--],G(r,e,n,o),r.status&pn&&(n.$actionerr$=!0);if(!0!==m){h=!1;break}}}return h&&e.nxt(1),w[O]=e.cur(1),!1!==m?(m=y[m]||v,w[_]=t.name):g?(m=x,n.status&un&&B(n,l,s,l,e.pos,t)):m=v,w[L]=m,n.$eol$=e.eol(),n.$blank$=n.$blank$&&(d||n.$eol$),w},tokenize:function(e,n){var t=this,r=[];if(e.eol())n.line++,n.$blank$&&n.bline++;else for(;!e.eol();)r.push(t.token(e,n));return r},parse:function(e,n){var t,r,i,l,s,a=this,u=(e||"").split(Nt),c=u.length,f=null;if(n=n||an,r=!!(n&un),i=!!(n&an),t=new V(0,n),t.$full_parse$=!0,o(function(e){u[e]+="\n"},0,c-2),i?f=o(n&cn?function(e,n){n._=n._.concat(a.tokenize(K(u[e]),t,e))}:function(e,n){n._.push(a.tokenize(K(u[e]),t,e))},0,c-1,{_:[]})._:o(function(e){var n=K(u[e]);if(n.eol())t.line++,t.$blank$&&t.bline++;else for(;!n.eol();)a.token(n,t)},0,c-1),r&&t.queu&&t.queu.length)for(;t.queu.length;)l=t.queu.shift(),B(t,l[1],l[2],l[3],l[4],null,l[5]);return s=i&&r?{tokens:f,errors:t.err}:i?f:t.err,Z(t),s},iterator:function(){},validate:function(){},autocomplete:function(){},indent:function(){},fold:function(){}}),Qt={Pattern:function(){return function(){}},Indented:function(e){return e=e||K.$NOTEMPTY$,function(n){var t,r,o,i,l,s,a,u,c,f=n.row;if(t=n.line(f),e.test(t)){for(r=n.indentation(t),s=null,l=t.length,u=f+1,c=n.last();c>=u;++u)if(o=n.line(u),i=n.indentation(o),i>r)s=u,a=o.length;else if(e.test(o))break;return s?[f,l,s,a]:void 0}}},Delimited:function(e,n,t){return e&&n?(t=t||s,function(r){var o,i,l,s,a,u,c,f,p,m,g,h,d,k,$=r.row,b=r.col;for(o=r.line($),l=b,s=0;;){var a=0>=l?-1:o.lastIndexOf(e,l-1);if(-1!=a){if(1==s&&b>a)return;if(t(r.token($,a+1))){i=a+e.length;break}l=a-1}else{if(1==s)return;s=1,l=o.length}}u=1,c=r.last();e:for(m=$;c>=m;++m)for(g=r.line(m),h=m==$?i:0;d=g.indexOf(e,h),k=g.indexOf(n,h),0>d&&(d=g.length),0>k&&(k=g.length),h=pt(d,k),h!=g.length;){if(h==d)++u;else if(!--u){f=m,p=h;break e}++h}return null==f||$===f&&p===i?void 0:[$,i,f,p]}):function(){}},MarkedUp:function(e,n,t,r,o){return e=e||s,n=n||"<",t=t||">",r=r||"/",o=o||b($(n)+"("+$(r)+"?)([a-zA-Z_\\-][a-zA-Z0-9_\\-:]*)","g"),function(i){i.col=0,i.min=i.first(),i.max=i.last(),i.text=i.line(i.row);for(var l,s,a,u,c,f=i.row;;){if(l=X(i,e,o,n,t,r),!l||i.row!=f||!(s=en(i,e,o,n,t,r)))return;if(!l[1]&&"autoclosed"!=s){a=[i.row,i.col],c=l[2],u=null;for(var p,m,g,h=[];;){if(p=X(i,e,o,n,t,r),f=i.row,m=i.col-(p?p[0].length:0),!p||!(s=en(i,e,o,n,t,r)))return;if("autoclosed"!=s)if(p[1]){for(g=h.length-1;g>=0;--g)if(h[g]==p[2]){h.length=g;break}if(0>g&&(!c||c==p[2])){u={tag:p[2],pos:[f,m,i.row,i.col]};break}}else h.push(p[2])}if(u)return[a[0],a[1],u.pos[0],u.pos[1]]}}}}},Vt=!("undefined"==typeof global||"[object global]"!==ut.call(global)),Zt=!(Vt||"undefined"==typeof navigator),Kt=!!(Zt&&"function"==typeof importScripts&&navigator instanceof WorkerNavigator),Ht=function(e,n,t){var r,o=null,i=null,l=null;return e?(o=__filename,i=__dirname,l=__dirname):t?(o=self.location.href,i=o.split("/").slice(0,-1).join("/")):n&&(l=document.location.href.split("#")[0].split("?")[0].split("/").slice(0,-1).join("/"),(r=document.getElementsByTagName("script"))&&r.length&&(o=r[r.length-1].src,i=o.split("/").slice(0,-1).join("/"))),{path:i,file:o,base:l}}(Vt,Zt,Kt),Jt="undefined"!=typeof ace?ace:{require:function(){return{}},config:{}},Xt=k(Yt,{constructor:function nr(e,r){var i,l,a=this,u=null;if(Yt.call(a,e,"text","invalid"),a.$v$="value",a.DEF=r||a.$DEF,a.ERR=e.Style.error||a.$ERR,a.LC=e.$comments.line||null,a.BC=e.$comments.block?{start:e.$comments.block[0][0],end:e.$comments.block[0][1]}:null,a.LC&&(i=Ot&n(a.LC)?t(a.LC,$).join("|"):$(a.LC),a.rxLine=b("^(\\s*)(?:"+i+")?")),a.BC&&(a.rxStart=b("^(\\s*)(?:"+$(a.BC.start)+")"),a.rxEnd=b("(?:"+$(a.BC.end)+")\\s*$")),e.$comments.block&&e.$comments.block.length){l=nr.Type("comment");for(var c=0,f=e.$comments.block.length;f>c;c++)a.$folders.push(nr.Fold.Delimited(e.$comments.block[c][0],e.$comments.block[c][1],l))}e.Fold&&wt&n(e.Fold)?u=e.Fold[mt]():e.$extra.fold&&(u=e.$extra.fold[mt]()),u&&(u=u.split("+"),o(function(n,t){var r=At(t[n]);if("brace"===r||"cstyle"===r){var o=F(e,1);l=o.length?nr.Type(o,!1):s,a.$folders.push(nr.Fold.Delimited("{","}",l)),a.$folders.push(nr.Fold.Delimited("[","]",l))}else"indent"===r||"indentation"===r?a.$folders.push(nr.Fold.Indented()):("markup"===r||"html"===r||"xml"===r)&&(a.$folders.push(nr.Fold.Delimited("",nr.Type(["comment","tag"],!1))),a.$folders.push(nr.Fold.MarkedUp(nr.Type("tag"),"<",">","/")))},0,u.length-1,u))},LC:null,BC:null,rxLine:null,rxStart:null,rxEnd:null,dispose:function(){var e=this;return e.LC=e.BC=e.rxLine=e.rxStart=e.rxEnd=null,Yt[it].dispose.call(e)},getLineTokens:function(e,n,t){var r=this;return n=new V(1,n),{tokens:r.tokenize(K(e),n,t),state:n}},keywords:function(){var e=this;return e.$grammar.$autocomplete?t(e.$grammar.$autocomplete,function(e){return{name:e.word,value:e.word,meta:e.meta,score:1}}):[]},autocomplete:function(e,n,t,o,i){var l=this;if(l.$grammar.$autocomplete&&o.length){i=i||{};var s=i[lt]("caseInsesitiveMatch")?!!i.caseInsesitiveMatch:!1,a=i[lt]("prefixMatch")?!!i.prefixMatch:!0,u=o,c=u[mt](),f=u.length;return r(l.$grammar.$autocomplete,function(e,n){var t,r,o,i,l,p,m,g=n.word,h=g.length;return h>=f&&(t=n.meta,r=!!g.ci,m=s||r,m?(l=g[mt](),p=c):(l=g,p=u),(i=l.indexOf(p))>=0&&(!a||0===i)&&(o=m?g.indexOf(u):i,e.push({name:g,value:g,meta:t,score:1e3-10*(h-f)-5*(0>o?i+3:o)}))),e},[])}return[]},indent:function(e,n){return n.match(K.$SPACE$)[0]},iterator:function(e){var n=e.getTabSize();return{row:0,col:0,min:0,max:0,line:function(n){return e.getLine(n)},first:function(){return 0},last:function(){return e.getLength()-1},next:function(){var e=this;if(!(e.row>=e.max))return e.col=0,e.row++,!0},prev:function(){var e=this;if(!(e.row<=e.min))return e.col=0,e.row--,!0},indentation:function(e){return H(e,null,n)},token:function(n,t){return e.getTokenAt(n,t).type}}},fold:function(e,n,t){var r,o,i,l=this,s=l.$folders,a=s.length;if(a)for(o=l.iterator(e,t),o.row=n,o.col=0,r=0;a>r;r++)if(i=s[r](o))return i},tCL:function(e,t,r,i){var l,s,a,u,c,f,p,m,g,h,d,k=self,$=t.doc,b=!0,y=!0,v=1/0,x=t.getTabSize(),w=!1;if(k.LC)c=Ot===n(k.LC)?k.LC[0]:k.LC,h=k.rxLine,d=c+" ",w=t.getUseSoftTabs(),s=function(e){var n,t,r=$.getLine(e),o=r.match(h);o&&(n=o[1].length,t=o[0].length,u(r,n,t)||" "!=o[0][t-1]||t--,$.removeInLine(e,n,t))},l=function(e){var n=$.getLine(e);(!b||/\S/.test(n))&&(u(n,v,v)?$.insertInLine({row:e,column:v},d):$.insertInLine({row:e,column:v},c))},a=function(e){return h.test(e)},u=function(e,n,t){for(var r=0;n--&&" "==e[gt](n);)r++;if(r%x!=0)return!1;for(r=0;" "==e[gt](t++);)r++;return x>2?r%x!=x-1:r%x==0};else{if(!k.BC)return!1;c=k.BC.start,f=k.BC.end,p=k.rxStart,m=k.rxEnd,l=function(e){var n=$.getLine(e);a(n,e)||(!b||/\S/.test(n))&&($.insertInLine({row:e,column:n.length},f),$.insertInLine({row:e,column:v},c))},s=function(e){var n,t=$.getLine(e);(n=t.match(m))&&$.removeInLine(e,t.length-n[0].length,t.length),(n=t.match(p))&&$.removeInLine(e,n[1].length,n[0].length)},a=function(e,n){if(p.test(e))return!0;for(var r=t.getTokens(n),o=0;ot&&(v=t),y&&!a(n,e)&&(y=!1)):g>n.length&&(g=n.length)},r,i),1/0==v&&(v=g,b=!1,y=!1),w&&v%x!=0&&(v=Math.floor(v/x)*x),o(y?s:l,r,i)},tCB:function(e,n,t,r,o,i){var l,s,a,u,c,f,p,m,g,h,d,k=self,$=k.BC,b=/comment/;if($){if(l=new o(n,r.row,r.column),s=l.getCurrentToken(),a=n.selection,u=a.toOrientedRange(),s&&b.test(s.type)){for(;s&&b.test(s.type);){if(g=s.value.indexOf($.start),-1!=g){h=l.getCurrentTokenRow(),d=l.getCurrentTokenColumn()+g,p=new i(h,d,h,d+$.start.length);break}s=l.stepBackward()}for(l=new o(n,r.row,r.column),s=l.getCurrentToken();s&&b.test(s.type);){if(g=s.value.indexOf($.end),-1!=g){h=l.getCurrentTokenRow(),d=l.getCurrentTokenColumn()+g,m=new i(h,d,h,d+$.end.length);break}s=l.stepForward()}m&&n.remove(m),p&&(n.remove(p),c=p.start.row,f=-$.start.length)}else f=$.start.length,c=t.start.row,n.insert(t.end,$.end),n.insert(t.start,$.start);u.start.row==c&&(u.start.column+=f),u.end.row==c&&(u.end.column+=f),n.selection.fromOrientedRange(u)}}});Xt.Type=J,Xt.Fold=Qt,Kt&&(onmessage=nn);var er=e.AceGrammar={VERSION:"2.6.0",clone:i,extend:l,pre_process:S,parse:j,getMode:sn,Parser:Xt};return e.AceGrammar}); \ No newline at end of file +**/!function(e,t,n){"use strict";var r,o="object"==typeof module&&module.exports,i="function"==typeof define&&define.amd;o?module.exports=(module.$deps=module.$deps||{})[t]=module.$deps[t]||n.call(e,{NODE:module})||1:i&&"function"==typeof require&&"function"==typeof require.specified&&require.specified(t)?define(t,["require","exports","module"],function(t,r,o){return n.call(e,{AMD:o})}):t in e||(e[t]=r=n.call(e,{})||1)&&i&&define(t,[],function(){return r})}(this,"AceGrammar",function(e){"use strict";function t(e){var t=0;return null===e?t=$n:!0===e||!1===e||e instanceof Boolean?t=xn:rn===e?t=kn:(t=Tn[un.call(e)]||dn,t=bn===t||e instanceof Number?isNaN(e)?vn:isFinite(e)?bn:yn:wn===t||e instanceof String?1===e.length?_n:wn:En===t||e instanceof Array?En:Sn===t||e instanceof RegExp?Sn:Mn===t||e instanceof Date?Mn:Ln===t||e instanceof Function?Ln:qn===t?qn:dn),t}function n(e,t,n,r){var o,i,l,s,a,u,c=e.length;if(arguments.length<4&&(r=c-1),0>r&&(r+=c),arguments.length<3&&(n=0),n>r)return[];if(n===r)return[t(e[n],n,n,r)];for(l=r-n+1,s=15&l,a=1&s,u=new Array(l),a&&(u[0]=t(e[n],n,n,r)),o=a;s>o;o+=2)i=n+o,u[o]=t(e[i],i,n,r),u[o+1]=t(e[i+1],i+1,n,r);for(o=s;l>o;o+=16)i=n+o,u[o]=t(e[i],i,n,r),u[o+1]=t(e[i+1],i+1,n,r),u[o+2]=t(e[i+2],i+2,n,r),u[o+3]=t(e[i+3],i+3,n,r),u[o+4]=t(e[i+4],i+4,n,r),u[o+5]=t(e[i+5],i+5,n,r),u[o+6]=t(e[i+6],i+6,n,r),u[o+7]=t(e[i+7],i+7,n,r),u[o+8]=t(e[i+8],i+8,n,r),u[o+9]=t(e[i+9],i+9,n,r),u[o+10]=t(e[i+10],i+10,n,r),u[o+11]=t(e[i+11],i+11,n,r),u[o+12]=t(e[i+12],i+12,n,r),u[o+13]=t(e[i+13],i+13,n,r),u[o+14]=t(e[i+14],i+14,n,r),u[o+15]=t(e[i+15],i+15,n,r);return u}function r(e,t,n,r,o){var i,l,s,a,u,c=e.length,p=n;if(arguments.length<5&&(o=c-1),0>o&&(o+=c),arguments.length<4&&(r=0),r>o)return p;if(r===o)return t(p,e[r],r);for(s=o-r+1,a=15&s,u=1&a,u&&(p=t(p,e[r],r)),i=u;a>i;i+=2)l=r+i,p=t(t(p,e[l],l),e[l+1],l+1);for(i=a;s>i;i+=16)l=r+i,p=t(t(t(t(t(t(t(t(t(t(t(t(t(t(t(t(p,e[l],l),e[l+1],l+1),e[l+2],l+2),e[l+3],l+3),e[l+4],l+4),e[l+5],l+5),e[l+6],l+6),e[l+7],l+7),e[l+8],l+8),e[l+9],l+9),e[l+10],l+10),e[l+11],l+11),e[l+12],l+12),e[l+13],l+13),e[l+14],l+14),e[l+15],l+15);return p}function o(e,t,n,r){if(t>n)return r;if(t===n)return e(t,r,t,n),r;var o,i,l=n-t+1,s=15&l,a=1&s;for(a&&e(t,r,t,n),o=a;s>o;o+=2)i=t+o,e(i,r,t,n),e(++i,r,t,n);for(o=s;l>o;o+=16)i=t+o,e(i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n),e(++i,r,t,n);return r}function i(e,n){var r,o,l,s,a=t(e),u=0;if(bn===t(n)?n>0?(u=n,n=!0):n=!1:n=!1!==n,qn===a){o={};for(l in e)e[ln](l)&&e[sn](l)&&(r=t(e[l]),o[l]=qn===r?n?i(e[l],u>0?u-1:n):e[l]:En===r?n?i(e[l],u>0?u-1:n):e[l].slice():Mn===r?new Date(e[l]):wn&r?e[l].slice():bn&r?0+e[l]:e[l])}else if(En===a)for(s=e.length,o=new Array(s),l=0;s>l;l++)r=t(e[l]),o[l]=qn===r?n?i(e[l],u>0?u-1:n):e[l]:En===r?n?i(e[l],u>0?u-1:n):e[l].slice():Mn===r?new Date(e[l]):wn&r?e[l].slice():bn&r?0+e[l]:e[l];else o=Mn===a?new Date(e):wn&a?e.slice():bn&a?0+e:e;return o}function l(){var e,n,r,o,s,a,u,c,p,f,m=arguments,h=m.length;if(1>h)return null;for(n=i(m[0]),r=1;h>r;r++)if(e=m[r])for(o in e)if(e[ln](o)&&e[sn](o))if(n[ln](o)&&n[sn](o)){if(p=t(n[o]),f=t(e[o]),qn===p&&qn===f)n[o]=l(n[o],e[o]);else if(En===p&&En===f){if(u=n[o],c=e[o],a=c.length,!a)continue;if(u.length)for(s=0;a>s;s++)0>u.indexOf(c[s])&&u.push(c[s]);else n[o]=c.slice()}}else n[o]=i(e[o]);return n}function s(){return!0}function a(e,n){return n||En!==t(e)?[e]:e}function u(e,n){return e=a(e),(n||En!==t(e[0]))&&(e=[e]),e}function c(e,n){return wn&t(n)&&wn&t(e)&&n.length&&n.length<=e.length&&n===e.substr(0,n.length)}function p(e,t,n){return tn&&e[r-n-1].$id===t;)n++;n&&(e.length=r-n)}return e}function m(e,t,n){return n?e[t]=rn:delete e[t],e}function h(e){return(e||"id_")+ ++Pn}function g(e){return(e||"uuid")+"_"+ ++Pn+"_"+(new Date).getTime()}function d(){var e,n,r,o,i,l,s=arguments,a=s.length;for(e=s[0]||{},i=1;a>i;i++)if(n=s[i],qn===t(n))for(o in n)n[ln](o)&&n[sn](o)&&(r=n[o],l=t(r),e[o]=bn&l?0+r:Mn&l?new Date(r):Rn&l?r.slice():r);return e}function k(e,t){var n,r=arguments.length,o="constructor";return 0===r?(e=Object,t={}):1===r?(t=e||{},e=Object):(e=e||Object,t=t||{}),t[ln](o)||(t[o]=function(){}),n=t[o],delete t[o],n[on]=d(cn(e[on]),t),n[on][o]=n,n}function $(e){return e.replace(Un,"\\$1")}function b(e,t){return new RegExp(e,t||"")}function y(e,t,n,r){var o,i,l,s,a=e.pos,u=e.length,c="",p=!!n;if(p){for(r=!!r,i=!1,s=0;u>a&&(o=e[hn](a++),t!==o||i);)l=n===o,i=!i&&l,r?(l&&s++,(!l||2&s)&&(c+=o,s=0)):c+=o;2&s&&(c+=n)}else for(;u>a&&(o=e[hn](a++),t!==o);)c+=o;return e.pos=a,c}function v(e,n,r){var o,i,l,s,a,u=!0===r?0:1;for(wn&t(n)&&(n=[n,n,n],u=0),i=e.length,a="",o=0;i>o;)l=e[hn](o),i>o+1&&"$"===l?(s=e.charCodeAt(o+1),36===s?(a+="$",o+=2):s>=48&&57>=s?(a+=n[u+s-48]||"",o+=2):(a+=l,o+=1)):(a+=l,o+=1);return a}function x(e,n,r){if(!e||(bn|Sn)&t(e))return e;var o,i=n?n.length||0:0;if(i&&n===e.substr(0,i)){var l,s,a,o,u,c=e.substr(i),p=c[hn](0),f="";for(o=c.length;o--&&(u=c[hn](o),p!==u);)"i"===u.toLowerCase()&&(f="i");return l=c.substring(1,o),s="^("+l+")",r[s]||(a=b(s,f),r[s]=a),r[s]}return e}function w(e,r,o){var i,l="";return wn&t(r)?l=r:r&&(l=Bn),i=n(e.sort(Nn),$).join("|"),[b("^("+i+")"+l,o?"i":""),1]}function _(e,n,r,o){var i=t(n);if(bn===i)return n;if(o[e])return o[e];r=r||0;var l,s=0;return n&&n.isCharList&&(s=1,m(n,"isCharList")),l=$n===i?new A(_t,e,n,$n,r):_n===i?new A(_t,e,n,_n,r):jn&i?new A(_t,e,n,Sn,r):wn&i?new A(_t,e,n,s?On:wn,r):n,o[e]=l}function O(e,n,r,o,i,l,s){if(s[e])return s[e];var u,p,f,m,h,g,d,k=0,$=0,b=1,y=wn&t(o)?!0:!!o;if(u=a(n),f=u.length,1===f)d=_(e,x(u[0],r,l),0,s);else if(f>1){for(m=(f>>>1)+1,p=0;m>=p;p++)h=t(u[p]),g=t(u[f-1-p]),(_n!==h||_n!==g)&&(b=0),En&h||En&g?k=1:(Sn&h||Sn&g||c(u[p],r)||c(u[f-1-p],r))&&($=1);if(b&&!y)u=u.slice().join(""),u.isCharList=1,d=_(e,u,0,s);else if(!y||k||$)if(k||$){for(p=0;f>p;p++)u[p]=En&t(u[p])?O(e+"_"+p,u[p],r,o,i,l,s):_(e+"_"+p,x(u[p],r,l),p,s);d=f>1?new A(Ot,e,u):u[0]}else{for(u=u.sort(Nn),p=0;f>p;p++)u[p]=_(e+"_"+p,x(u[p],r,l),p,s);d=f>1?new A(Ot,e,u):u[0]}else d=_(e,w(u,o,i),0,s)}return s[e]=d}function E(e,n,r,i,l){if(l[e])return l[e];var s=u(n),a=[],p=[];return o(function(n){var o,u;o=_(e+"_0_"+n,x(s[n][0],r,i),n,l),u=s[n].length>1?Sn!==o.ptype||wn!==t(s[n][1])||c(s[n][1],r)?_(e+"_1_"+n,x(s[n][1],r,i),n,l):s[n][1]:o,a.push(o),p.push(u)},0,s.length-1),l[e]=new A(Et,e,[a,p])}function q(e,t){var n=u(e.tokens.slice());o(function(e){var r=n[e][0],o=n[e].length>1?n[e][1]:n[e][0],i=n[e].length>2?n[e][2]:"";null===o?(t.line=t.line||[],t.line.push(r)):(t.block=t.block||[],t.block.push([r,o,i]))},0,n.length-1)}function L(e,t,r){var o=e.meta||t,i=!(!e.caseInsesitive&&!e.ci),l=n(a(e.tokens),function(e){return{word:e,meta:o,ci:i}});r.autocomplete=(r.autocomplete||[]).concat(l)}function S(e){e.Lex||(e.Lex={}),e.Syntax||(e.Syntax={});var n,r,o,i,s,a,u,c,p,f,h,g=e.Lex,d=e.Syntax,k=[g,d],$=k.length;for(h=0;$>h;){f=k[h++];for(o in f)f[ln](o)&&(n=o.split(":"),r=n[1]&&Cn(n[1]).length?Cn(n[1]):null,n=Cn(n[0]),n.length||(n=o,r=null),n!==o&&(f[n]=f[o],m(f,o),r&&(r=r[mn](),i=f[n],s=t(i),qn===s?f[n].type||(f[n].type=r):(f[n]={type:r},"error"===r?(f[n].type="action",f[n].error=i):"nop"===r?(f[n].type="action",f[n].nop=!0):"group"===r?(f[n].type="sequence",f[n].tokens=i):"action"===r&&wn===s?f[n][i]=!0:f[n].tokens=i))),g===f&&(Dn&t(f[n])&&(f[n]={type:"simple",tokens:f[n]}),i=f[n],i.type&&(c=i.type=i.type[mn](),"line-block"===c?(i.type="block",i.multiline=!1,i.escape=!1):"escaped-line-block"===c?(i.type="block",i.multiline=!1,i.escape="\\"):"escaped-block"===c&&(i.type="block",i.multiline=!0,i.escape="\\"))))}f=g;for(n in f)if(f[ln](n))for(i=f[n];i.extend;)a=i.extend,m(i,"extend"),u=g[a],u&&(Dn&t(u)&&(u=g[a]={type:"simple",tokens:u}),i=l(u,i));f=g;for(n in f)f[ln](n)&&(i=f[n],i.type?(c=i.type=i.type[mn](),"line-block"===c?(i.type="block",i.multiline=!1,i.escape=!1):"escaped-line-block"===c?(i.type="block",i.multiline=!1,i.escape="\\"):"escaped-block"===c&&(i.type="block",i.multiline=!0,i.escape="\\")):i["escaped-line-block"]?(i.type="block",i.multiline=!1,i.escape||(i.escape="\\"),i.tokens=i["escaped-line-block"],m(i,"escaped-line-block")):i["escaped-block"]?(i.type="block",i.multiline=!0,i.escape||(i.escape="\\"),i.tokens=i["escaped-block"],m(i,"escaped-block")):i["line-block"]?(i.type="block",i.multiline=!1,i.escape=!1,i.tokens=i["line-block"],m(i,"line-block")):i.comment?(i.type="comment",i.escape=!1,i.tokens=i.comment,m(i,"comment")):i.block?(i.type="block",i.tokens=i.block,m(i,"block")):i.simple?(i.type="simple",i.tokens=i.simple,m(i,"simple")):i.nop?(i.type="action",i.action=["nop",i.nop,!1],i.nop=!0):i.error?(i.type="action",i.action=["error",i.error,!!i["in-context"]],m(i,"error")):i[ln]("context")?(i.type="action",i.action=[i.context?"context-start":"context-end",i.context,!!i["in-context"]],m(i,"context")):i.indent?(i.type="action",i.action=["indent",i.indent,!!i["in-context"]],m(i,"indent")):i.outdent?(i.type="action",i.action=["outdent",i.outdent,!!i["in-context"]],m(i,"outdent")):i.unique?(i.type="action",i.action=["unique",wn&t(i.unique)?["_DEFAULT_",i.unique]:i.unique,!!i["in-context"]],m(i,"unique")):i.push?(i.type="action",i.action=["push",i.push,!!i["in-context"]],m(i,"push")):i[ln]("pop")?(i.type="action",i.action=["pop",i.pop,!!i["in-context"]],m(i,"pop")):i.type="simple","action"===i.type?i.ci=!(!i.caseInsesitive&&!i.ci):"block"===i.type||"comment"===i.type?(i.multiline=i[ln]("multiline")?!!i.multiline:!0,wn&t(i.escape)||(i.escape=!1)):"simple"===i.type&&(i.autocomplete=!!i.autocomplete,i.meta=i.autocomplete&&wn&t(i.meta)?i.meta:null,i.combine=i[ln]("combine")?i.combine:!0,i.ci=!(!i.caseInsesitive&&!i.ci)));f=d;for(n in f)f[ln](n)&&(i=f[n],qn!==t(i)||i.type?i.type&&(c=i.type=i.type[mn](),"group"===c&&i.match?(s=t(i.match),wn&s?(p=i.match[mn](),"alternation"===p||"either"===p?(i.type="alternation",m(i,"match")):"sequence"===p||"all"===p?(i.type="sequence",m(i,"match")):"zeroorone"===p?(i.type="zeroOrOne",m(i,"match")):"zeroormore"===p?(i.type="zeroOrMore",m(i,"match")):"oneormore"===p?(i.type="oneOrMore",m(i,"match")):(i.type="sequence",m(i,"match"))):En&s&&(i.type="repeat",i.repeat=i.match,m(i,"match"))):"either"===c?i.type="alternation":"all"===c?i.type="sequence":"lookahead"===c&&(i.type="positiveLookahead")):i.ngram||i["n-gram"]?(i.type="ngram",i.tokens=i.ngram||i["n-gram"],i["n-gram"]?m(i,"n-gram"):m(i,"ngram")):i.sequence||i.all?(i.type="sequence",i.tokens=i.sequence||i.all,i.all?m(i,"all"):m(i,"sequence")):i.alternation||i.either?(i.type="alternation",i.tokens=i.alternation||i.either,i.either?m(i,"either"):m(i,"alternation")):i.zeroOrOne?(i.type="zeroOrOne",i.tokens=i.zeroOrOne,m(i,"zeroOrOne")):i.zeroOrMore?(i.type="zeroOrMore",i.tokens=i.zeroOrMore,m(i,"zeroOrMore")):i.oneOrMore?(i.type="oneOrMore",i.tokens=i.oneOrMore,m(i,"oneOrMore")):i.positiveLookahead||i.lookahead?(i.type="positiveLookahead",i.tokens=i.positiveLookahead||i.lookahead,i.lookahead?m(i,"lookahead"):m(i,"positiveLookahead")):i.negativeLookahead&&(i.type="negativeLookahead",i.tokens=i.negativeLookahead,m(i,"negativeLookahead")));return e}function M(e,n,r,o){for(var i;wn&t(i=n[e]||r[e]);)e=i;return o?e:n[e]||r[e]||e}function F(e,t){return e.length>1?o(t?function(t,n){var r=n[n.length-1],o=e[t];r===o||n.push(o)}:function(t,n){var r=n[n.length-1],o=e[t];Gn.test(o)&&Gn.test(r)&&r===o||n.push(o)},1,e.length-1,[e[0]]):e}function R(e,r,o){var l,s,a,u,c,p,f,m,h,g,d,k,v,x,w,_=!1;if(w=e.modifier?e.modifier:null,m=new String(Cn(e)),m.pos=0,1===m.length)k=""+e,r[k]||o[k]||(r[k]={type:"simple",tokens:e}),e=k;else{for(l=[],s=[],a="",v=[];m.posc[0]&&(c[0]=0),2>c.length?c.push(c[0]):c[1]=c[1].length?parseInt(c[1],10)||gn:gn,0>c[1]&&(c[1]=0),d=s[s.length-1],k=""+d+["{",c[0],",",isFinite(c[1])?c[1]:"","}"].join(""),o[k]||(o[k]={type:"repeat",repeat:[c[0],c[1]],tokens:[d]}),s[s.length-1]=k):a+=h;else{if("}"===h){a+=h;continue}"&"===h||"!"===h?a+=h:"|"===h?(_=!1,s=F(s),s.length>1?(k=""+s.join(" "),o[k]||(o[k]={type:"sequence",tokens:s}),l.push(k)):s.length?l.push(s[0]):a+=h,s=[]):"("===h?(v.push([s,l,a]),s=[],l=[],a=""):")"===h&&(s=F(s),s.length>1?(k=""+s.join(" "),o[k]||(o[k]={type:"sequence",tokens:s}),l.push(k)):s.length&&l.push(s[0]),s=[],l=F(l,1),l.length>1?(k=""+l.join(" | "),o[k]||(o[k]={type:"alternation",tokens:l})):l.length&&(k=l[0]),l=[],x=v.pop(),s=x[0],l=x[1],a=x[2],d=k,k="("+d+")",o[k]||(o[k]=i(M(d,r,o))),s.push(k))}}else a+=h;a.length&&(_?(s.length&&(d=s[s.length-1],k=d+"."+a,p=r[k]||o[k],p||(f=M(d,r,o),o[k]=wn&t(f)?new String(f):i(f),o[k].modifier=a),s[s.length-1]=k),_=!1):"0"===a?(r[tn]||(r[tn]={type:"simple",tokens:0}),s.push(tn)):"^^"===a?(r[Zt]||(r[Zt]={type:"simple",tokens:Lt}),s.push(Zt)):"^^1"===a?(r[Ht]||(r[Ht]={type:"simple",tokens:St}),s.push(Ht)):"^"===a?(r[Jt]||(r[Jt]={type:"simple",tokens:Ft}),s.push(Jt)):"$"===a?(r[Xt]||(r[Xt]={type:"simple",tokens:Mt}),s.push(Xt)):(r[a]||o[a]||(r[a]={type:"simple",tokens:a}),s.push(a))),a="",s=F(s),s.length>1?(k=""+s.join(" "),o[k]||(o[k]={type:"sequence",tokens:s}),l.push(k)):s.length&&l.push(s[0]),s=[],l=F(l,1),l.length>1?(k=""+l.join(" | "),o[k]||(o[k]={type:"alternation",tokens:l}),e=k):l.length&&(e=l[0]),l=[]}return w&&(r[e]||o[e])&&((r[e]||o[e]).modifier=w),e}function j(e,i,l,s,c,p,f,m,h,g,d){var k,$,b,y,v,x,w=null,_=null,S=null;if(Lt===e||St===e||Ft===e||Mt===e)return new N(e,Lt===e?Zt:St===e?$T_FBNL$:Ft===e?Jt:Xt,e,_);if(!1===e||0===e)return new N(Rt,tn,0,_);if(""===e)return new N(jt,nn,"",_);if(null===e)return new N(Dt,en,$n,_,S);if(En&t(e)&&(b=e,e="NGRAM_"+b.join("_"),s[e]||(s[e]={type:"ngram",tokens:b})),e=""+e,m[e])return m[e];if(v=M(e,l,s),wn&t(v)&&(v=R(v,l,s),v=l[v]||s[v]||null),!v)return null;if(k=v.type?Vt[v.type[mn]().replace(In,"")]||Dt:Dt,_=v.msg||null,S=v.modifier||null,$=v.tokens,Dt&k){if(Lt===$||St===$||Ft===$||Mt===$||!1===$||0===$)return w=new N($||Rt,e,$||0,_),m[e]=w,w;if(""===$)return w=new N(jt,e,"",_),m[e]=w,w;if(null===$)return w=new N(Dt,e,$n,_,S),m[e]=w,w;if(!$)return null}return qt&k?(v[ln]("action")?"nop"===v.action[0]?v.action[0]=gt:"error"===v.action[0]?v.action[0]=dt:"context-start"===v.action[0]?v.action[0]=$t:"context-end"===v.action[0]?v.action[0]=bt:"push"===v.action[0]?v.action[0]=yt:"pop"===v.action[0]?v.action[0]=vt:"unique"===v.action[0]?v.action[0]=kt:"indent"===v.action[0]?v.action[0]=xt:"outdent"===v.action[0]&&(v.action[0]=wt):v[ln]("nop")?v.action=[gt,v.nop,!!v["in-context"]]:v[ln]("error")?v.action=[dt,v.error,!!v["in-context"]]:v[ln]("context")?v.action=[v.context?$t:bt,v.context,!!v["in-context"]]:v[ln]("context-start")?v.action=[$t,v["context-start"],!!v["in-context"]]:v[ln]("context-end")?v.action=[bt,v["context-end"],!!v["in-context"]]:v[ln]("push")?v.action=[yt,v.push,!!v["in-context"]]:v[ln]("pop")?v.action=[vt,v.pop,!!v["in-context"]]:v[ln]("unique")?v.action=[kt,wn&t(v.unique)?["_DEFAULT_",v.unique]:v.unique,!!v["in-context"]]:v[ln]("indent")?v.action=[xt,v.indent,!!v["in-context"]]:v[ln]("outdent")&&(v.action=[wt,v.outdent,!!v["in-context"]]),v.nop&&(v.action[0]=gt),w=new N(qt,e,v.action.slice(),_,S),w.ci=!!v.caseInsensitive||v.ci,m[e]=w):($=a($),Dt&k?(v.autocomplete&&L(v,e,d),x=v[ln]("combine")?v.combine:!0,w=new N(Dt,e,O(e,$.slice(),i,x,!(!v.caseInsensitive&&!v.ci),p,f),_,S),m[e]=w):Tt&k?(At===k&&q(v,g),w=new N(k,e,E(e,$.slice(),i,p,f),_),w.mline=v[ln]("multiline")?!!v.multiline:!0,w.esc=v[ln]("escape")?v.escape:!1,w.inter=!!c[e+".inside"],At===k&&v.interleave&&h.push(I(w)),S&&(w.modifier=S),m[e]=w):Qt&k&&(Yt===k?(y=u($),w=n(y,function(t,n){return new N(Yt,e+"_NGRAM_"+n,null,_,S)}),m[e]=w,o(function(e){w[e].token=a(r(y[e],function(e,t){return e.concat(j(t,i,l,s,c,p,f,m,h,g,d))},[]))},0,y.length-1)):(Bt===k||Gt===k?w=new N(k,e,null,_,S):zt&k&&En&t(v.repeat)?(w=new N(zt,e,null,_,S),w.min=v.repeat[0],w.max=v.repeat[1]):It===k?(w=new N(It,e,null,_,S),w.min=0,w.max=1):Pt===k?(w=new N(Pt,e,null,_,S),w.min=0,w.max=gn):Ut===k?(w=new N(Ut,e,null,_,S),w.min=1,w.max=gn):w=Ct===k?new N(Ct,e,null,_,S):new N(Nt,e,null,_,S),m[e]=w,w.token=a(r($,function(e,t){return e.concat(j(t,i,l,s,c,p,f,m,h,g,d))},[]))))),m[e]}function D(e,t){var n,r,o=e.Style,i=e.Lex,l=e.Syntax,s=[],a={};for(n in o)o[ln](n)&&(r=i[n]||l[n],!r||"block"!=r.type&&"comment"!==r.type||(t&&(o[n+".inside"]||o[n])?(n=o[n+".inside"]||o[n],a[ln](n)||(s.push(n),a[n]=1)):t||a[ln](n)||(s.push(n),a[n]=1)));return s}function T(e){var n,o,l,s,a,u,c,p,f,m,h,g,d;return e.__parsed?e:(n=e.RegExpID||null,l=e.Extra?i(e.Extra):{},s=e.Style?i(e.Style):{},a=null,u=e.Lex?i(e.Lex):{},c=e.Syntax?i(e.Syntax):{},p={},f={},m={},g={},d={},h=[],o=e.Parser?i(e.Parser):[],e=S({Style:s,Fold:a,Lex:u,Syntax:c,$parser:null,$interleaved:null,$comments:null,$autocomplete:null,$extra:l,__parsed:0}),e.$parser=r(o,function(e,r){var o=j(r,n,u,c,s,p,f,m,h,g,d)||null;return o&&(En&t(o)?e=e.concat(o):e.push(o)),e},[]),e.$interleaved=h&&h.length?h:null,e.$comments=g,e.$autocomplete=d&&d.autocomplete&&d.autocomplete.length?d.autocomplete:null,e.__parsed=1,e)}function A(e,n,r,o,i){var l,s,a=this;l=a.type=e,a.name=n,a.pattern=r,s=a.ptype=o||wn,a.key=i||0,Ot===l?a.key=!1!==i:Et===l?a.pattern[0]=new A(Ot,n+"_Start",r[0],null,!1):$n===s?a.pattern=null:Sn===s&&(a.pattern=Sn&t(r)?[r,0]:[r[0],r[1]||0])}function C(e,n,r){var o,i,l,s,a,u,c,p,f,m,h,g=e,d=g.type,k=g.pattern,$=g.key;if(Et===d){if(o=g.name,l=k[0],s=k[1],u=C(l,n,r))return a=s[u[0]],p=t(a),f=l.pattern[u[0]].ptype,Sn===f&&Fn&p&&(c=bn&p?u[1][a+1]:v(a,u[1]),a=new A(_t,o+"_End",c,c.length>1?wn:_n)),a}else if(Ot===d){for(m=0,h=k.length;h>m;m++)if(c=C(k[m],n,r))return $?[m,c[1]]:c}else{if(i=g.ptype,$n===i)return!1!==r&&n.end(),[$,""];if(Sn===i){if(c=n.slice(n.pos).match(k[0]),c&&0===c.index)return!1!==r&&n.mov(c[k[1]||0].length),[$,k[1]>0?c[k[1]]:c]}else if(On===i){if(c=n[hn](n.pos)||null,c&&-1y&&y>x?($=j,t.bck(y),u=1):($=q,a=1),P=t.sel(y,t.pos);break}k=t.nxt(1),z+=k,d=T&&!d&&D===k,y=t.pos}return c=F||T&&d,N+=z,h[1]=[_,y],m=[_,t.pos],a||!c&&!u?n.block=null:(n.block.ip=h,n.block.ep=m,n.block.i=N,n.block.e=P,p(W,w,I(E,b,0,U))),r.T=L,r.id=q,r.type=S||$,r.str=t.sel(O,t.pos),r.match=null,r.pos=[_,O,m[0],m[1]],n.block||(g=A+N+P,r.block={str:g,match:[g,N,A,P],part:[g,A,N,P],pos:[[f[0],f[1],m[0],m[1]],[f[0],f[1],h[0][0],h[0][1]],[h[0][0],h[0][1],h[1][0],h[1][1]],[h[1][0],h[1][1],m[0],m[1]]]}),S||$}return E.status&&E.$msg&&(E.$msg=v(E.$msg,q,!0)),!1}function K(e,t,n,r){var o,i,l,s,a,u,c,f,m,g,d,k,$,b,y,v=e,x=v.type,w=(v.name,v.token),_=w.length,O=v.modifier;if(v.status&=mt,v.$msg=v.msg||null,k=n.stack,f=t.pos,m=k.length,u=0,c=0,b=v.$id||h(),Ct===x){for(v.status|=ct,$=[],g=0;_>g;g++){if(o=I(w[g],1,O,b),i=W(o,t,n,r),o.status&ct&&(u++,$.push(P(o))),!1!==i)return i;o.status&pt&&(c++,t.pos>f&&t.bck(f),k.length>m&&(k.length=m))}return u>0?v.status|=ct:v.status&=ft,_===c&&u>0?v.status|=pt:v.status&=mt,v.status&&!v.$msg&&$.length&&(v.$msg=$.join(" | ")),!1}if(Kt&x){y=!!(x&Nt),y?v.status|=ct:v.status&=ft,d=0;do o=I(w[d++],y,O,b),i=W(o,t,n,r);while(_>d&&!1===i&&!(o.status&ht));if(!1!==i){if(!0!==i||Rt!==o.type)for(g=_-1;g>=d;g--)p(k,m+_-g-1,I(w[g],1,O,b));return i}return o.status&pt?(y?v.status|=pt:v.status&=mt,t.pos>f&&t.bck(f),k.length>m&&(k.length=m)):y&&o.status&ct&&(v.status|=pt),v.status&&!v.$msg&&(v.$msg=P(o)),!1}if(Bt===x)return v.status=0,!1;if(Gt===x)return v.status=0,!1;for(l=v.found,s=v.min,a=v.max,v.status&=ft,$=[],g=0;_>g;g++){if(o=I(w[g],1,O,b),i=W(o,t,n,r),!1!==i){if(++l,a>=l)return v.found=l,p(k,m,I(v,0,0,b)),v.found=0,i;break}o.status&ct&&(u++,$.push(P(o))),o.status&pt&&(t.pos>f&&t.bck(f),k.length>m&&(k.length=m))}return s>l?v.status|=ct:v.status&=ft,l>a||s>l&&u>0?v.status|=pt:v.status&=mt,v.status&&!v.$msg&&$.length&&(v.$msg=$.join(" | ")),!1}function Q(e,t){var n=this;n.id=e?g("state"):"state",t instanceof Q?(n.line=t.line,n.bline=t.bline,n.status=t.status,n.stack=t.stack.slice(),n.block=t.block,n.status&at?(n.queu=t.queu,n.symb=t.symb,n.ctx=t.ctx,n.err=t.err):(n.queu=null,n.symb=null,n.ctx=null,n.err=null),n.$eol$=t.$eol$,n.$blank$=t.$blank$):(n.line=-1,n.bline=-1,n.status=t||0,n.stack=[],n.block=null,n.status&at?(n.queu=[],n.symb={},n.ctx=[],n.err={}):(n.queu=null,n.symb=null,n.ctx=null,n.err=null),n.$eol$=!0,n.$blank$=!0),n.toString=function(){return n.id+"_"+n.line+"_"+n.bline+"_"+(n.block?n.block.name:"0")}}function V(e){e.id=null,e.line=null,e.bline=null,e.status=null,e.stack=null,e.block=null,e.queu=null,e.symb=null,e.ctx=null,e.err=null}function Z(e,t,n){var r=new String(e);return r.start=t||0,r.pos=n||0,r.sol=function(){return 0===r.pos},r.eol=function(){return r.pos>=r.length},r.end=function(){return r.pos=r.length,r},r.mov=function(e){return r.pos=0>e?pn(0,r.pos+e):fn(r.length,r.pos+e),r},r.bck=function(e){return r.pos=pn(0,e),r},r.sft=function(){return r.start=r.pos,r},r.nxt=function(e,t){var n,o,i="";if(!0===e){for(t=t||Z.$NONSPC$;r.poss||s>=t)return l+(t-i);l+=s-i,l+=n-l%n,i=s+1}}function J(e,r){return Rn&t(e)&&(e=b("\\b("+n(a(e).sort(Nn),$).join("|")+")\\b")),!1===r?function(t){return!t||!e.test(t)}:function(t){return!!t&&e.test(t)}}function X(e,t,n){for(;;){n.lastIndex=e.col;var r=n.exec(e.text);if(!r){if(e.next()){e.text=e.line(e.row);continue}return}{if(t(e.token(e.row,r.index+1)))return e.col=r.index+r[0].length,r;e.col=r.index+1}}}function et(e,t,n,r,o,i){for(var l,s,a;;){if(l=e.text.indexOf(o,e.col),-1===l){if(e.next()){e.text=e.line(e.row);continue}return}if(t(e.token(e.row,l+1)))return s=e.text.lastIndexOf(i,l),a=s>-1&&!Z.$NOTEMPTY$.test(e.text.slice(s+1,l)),e.col=l+1,a?"autoclosed":"regular";e.col=l+1}}function tt(e){var t=e?e.data:null;t&&t.load&&t.ace_worker_base&&(importScripts(t.ace_worker_base),ace.define("ace/grammar_worker",["require","exports","module","ace/worker/mirror"],function(e,t){var n=e("./worker/mirror").Mirror;t.AceGrammarWorker=k(n,{constructor:function(e){var t=this;n.call(t,e),t.setTimeout(300)},$parser:null,init_parser:function(e,t){var n=this;n.$parser=new er(T(e),null,!1),n.sender.callback(1,t)},onUpdate:function(){var e,t,n,r,o,i=this,l=i.sender,s=i.$parser;if(!s)return void l.emit("ace_grammar_worker_ok",null);if(e=i.doc.getValue(),!e||!e.length)return void l.emit("ace_grammar_worker_ok",null);if(t=s.parse(e,at),!t)return void l.emit("ace_grammar_worker_ok",null);o=[];for(n in t)t[ln](n)&&(r=t[n],o.push({row:r[0],column:r[1],text:r[4]||"Syntax Error",type:"error",raw:r[4]||"Syntax Error",range:[r[0],r[1],r[2],r[3]]}));o.length?l.emit("ace_grammar_worker_error",o):l.emit("ace_grammar_worker_ok",null)}})}))}function nt(e,t){e[t]||(e[t]=[]);var n,r=e[t];if(r&&r.length)for(n=0;no;o++)i=t[o],i.range&&(l.push(e.addMarker(new r(i.range[0],i.range[1],i.range[2],i.range[3]),"ace_error-marker","text",0)),m(i,"range"))}function ot(e,t){nt(e,t),e.clearAnnotations()}function it(e,t,n,r){rt(e,t,n,r),e.setAnnotations(t)}function lt(e,t,n){n=n||Xn;var r=i(e),o=n.require("ace/range").Range,l=n.require("ace/worker/worker_client").WorkerClient,s=k(l,{constructor:function(e,t,r,o){var i=this,l=n.require,s=n.config;if(i.$sendDeltaQueue=i.$sendDeltaQueue.bind(i),i.changeListener=i.changeListener.bind(i),i.onMessage=i.onMessage.bind(i),l.nameToUrl&&!l.toUrl&&(l.toUrl=l.nameToUrl),!o)if(s.get("packaged")||!l.toUrl)o=o||s.moduleUrl(t,"worker");else{var a=i.$normalizePath;o=o||a(l.toUrl("ace/worker/worker.js",null,"_"));var u={};e.forEach(function(e){u[e]=a(l.toUrl(e,null,"_").replace(/(\.js)?(\?.*)?$/,""))})}try{i.$worker=new Worker(o)}catch(c){if(!(c instanceof window.DOMException))throw c;var p=i.$workerBlob(o),f=window.URL||window.webkitURL,m=f.createObjectURL(p);i.$worker=new Worker(m),f.revokeObjectURL(m)}i.$worker.postMessage({load:!0,ace_worker_base:Hn.base+"/"+s.moduleUrl("ace/worker/json")+Jn}),i.$worker.postMessage({init:!0,tlns:u,module:t,classname:r}),i.callbackId=1,i.callbacks={},i.$worker.onmessage=i.onMessage}}),a=n.require("ace/mode/folding/fold_mode").FoldMode,u=k(a,{constructor:function(e){var t=this;a.call(t),t.$findFold=e,t.$lastFold=null},getFoldWidget:function(e,t,n){var r=this.$lastFold=this.$findFold(e,t,n);return r?"markbeginend"===t&&r.end?"end":"start":""},getFoldWidgetRange:function(){var e=this.$lastFold;return e?new o(e[0],e[1],e[2],e[3]):void 0}}),c=n.require("ace/mode/text").Mode,p=k(c,{constructor:function f(){var e=this;c.call(e),e.$id=f.$id,e.$tokenizer=f.$parser,e.lineCommentStart=f.$parser.LC,e.blockComment=f.$parser.BC,e.foldingRules=new u(e.folder.bind(e))},supportGrammarAnnotations:!1,createWorker:function(e){if(!this.supportGrammarAnnotations)return ot(e,p.$markers),null;var t=new s(["ace"],"ace/grammar_worker","AceGrammarWorker",Hn.file+Jn);return t.attachToDocument(e.getDocument()),t.call("init_parser",[r],function(){t.on("ace_grammar_worker_error",function(t){var n=t.data;it(e,n,p.$markers,o)}),t.on("ace_grammar_worker_ok",function(){ot(e,p.$markers)})}),t.on("terminate",function(){ot(e,p.$markers)}),t},supportCodeFolding:!0,folder:function m(e,t,n){return this.supportCodeFolding?p.$folder(e,t,n,m.options||{}):null},supportAutoCompletion:!0,autocompleter:function h(e,t,n,r){return this.supportAutoCompletion?p.$autocompleter(e,t,n,r,h.options||{}):[]},getKeywords:function(){return[]},getCompletions:function(e,t,n,r){return this.autocompleter(e,t,n,r)},dispose:function(){var e=this;e.$tokenizer=e.foldingRules=e.autocompleter=null,p.dispose()}});return p.$id=g("ace_grammar_mode"),p.$markers=p.$id+"$markers",p.$parser=new tr.Parser(T(e),t),p.$folder=function d(e,t,r){var o,i,d=p.$parser,l=d.fold(e,r,n);if("markbeginend"===t){if(l)return l.start=!0,l.end=!1,l;for(i=r,o=pn(0,r-200);r>o&&(!l||i!==l[2]);)l=d.fold(e,--r,n);if(l&&i===l[2])return l.start=!1,l.end=!0,l}else if(l)return l.start=!0,l.end=!1,l},p.$autocompleter=function(e,t,r,o,i){return p.$parser.autocomplete(e,t,r,o,i,n)},p.dispose=function(){p.$parser&&p.$parser.dispose(),p.$parser=p.$folder=p.$autocompleter=p.autocompleter=null},new p}var st=1,at=2,ut=32,ct=4,pt=8,ft=~ct,mt=~pt,ht=ct|pt,gt=0,dt=4,kt=8,$t=16,bt=17,yt=32,vt=33,xt=128,wt=129,_t=2,Ot=4,Et=8,qt=4,Lt=8,St=9,Mt=16,Ft=32,Rt=128,jt=256,Dt=512,Tt=1024,At=1025,Ct=2048,Nt=4096,zt=8192,It=8193,Pt=8194,Ut=8195,Wt=16384,Bt=Wt,Gt=16385,Yt=32768,Kt=Nt|Yt,Qt=Ct|Nt|zt|Wt|Yt,Vt={action:qt,simple:Dt,block:Tt,comment:At,alternation:Ct,sequence:Nt,repeat:zt,zeroorone:It,zeroormore:Pt,oneormore:Ut,positivelookahead:Bt,negativelookahead:Gt,ngram:Yt},Zt="$|SOF|$",Ht="$|NONBLANK|$",Jt="$|SOL|$",Xt="$|EOL|$",en="$|ENDLINE|$",tn="$|EMPTY|$",nn="$|NONSPACE|$",rn=void 0,on="prototype",ln="hasOwnProperty",sn="propertyIsEnumerable",an=Object[on],un=an.toString,cn=Object.create,pn=Math.max,fn=Math.min,mn="toLowerCase",hn="charAt",gn=1/0,dn=4,kn=8,$n=16,bn=32,yn=33,vn=34,xn=64,wn=128,_n=129,On=130,En=256,qn=512,Ln=1024,Sn=2048,Mn=4096,Fn=wn|bn,Rn=wn|En,jn=Sn|En,Dn=wn|En|Sn,Tn={"[object Number]":bn,"[object String]":wn,"[object Array]":En,"[object RegExp]":Sn,"[object Date]":Mn,"[object Function]":Ln,"[object Object]":qn},An=/^\s+|\s+$/g,Cn=String[on].trim?function(e){return e.trim() +}:function(e){return e.replace(An,"")},Nn=function(e,t){return t.length-e.length},zn=/\r\n|\r|\n/g,In=/[\-_]/g,Pn=0,Un=/([.*+?^${}()|[\]\/\\\-])/g,Wn=/^([.!&\[\]{}()*+?\/|'"]|\s)/,Bn="(\\s|\\W|$)",Gn=/[*+]$/;Z.$SPC$=/^[\s\u00a0]+/,Z.$NONSPC$=/[^\s\u00a0]/,Z.$NOTEMPTY$=/\S/,Z.$SPACE$=/^\s*/;var Yn=k({constructor:function(e,t,n){var r=this;r.$grammar=e,r.$DEF=t||null,r.$ERR=n||null,r.DEF=r.$DEF,r.ERR=r.$ERR,r.$folders=[]},$grammar:null,$folders:null,$n$:"name",$t$:"type",$v$:"token",$DEF:null,$ERR:null,DEF:null,ERR:null,dispose:function(){var e=this;return e.$grammar=null,e.$folders=null,e.$n$=e.$t$=e.$v$=null,e.$DEF=e.$ERR=e.DEF=e.ERR=null,e},token:function(e,t){var n,r,o,i,l,s,a,u,c,p,m,h,g,d,k,$=this,b=$.$grammar,y=b.Style,v=$.DEF,x=$.ERR,w={},_=$.$n$,O=$.$t$,E=$.$v$,q=b.$interleaved,L=b.$parser,S=L.length,M=q?q.length:0;if(e.sol()&&(t.$eol$&&(t.$blank$&&(t.bline=t.line),t.$eol$=!1,t.line++),t.$blank$=t.bline+1===t.line),t.$actionerr$=!1,i=t.stack,l=t.line,s=e.pos,m=!1,g=!0,h=!1,d=!1,k=t.block?t.block.name:rn,i.length&&Mt===i[i.length-1].type&&e.sol()&&i.pop(),(!i.length||jt!==i[i.length-1].type&&k!==i[i.length-1].name)&&e.spc()&&(g=!1,d=!0),w[_]=null,w[O]=v,w[E]=null,g)for(o=new z,a=0;g&&(i.length||S>a)&&!e.eol();){if(c=e.pos,p=i.length,M&&!t.block){for(u=0;M>u;u++)if(n=q[u],m=W(n,e,t,o),!1!==m){g=!1;break}if(!g)break}if(!i.length&&a>=S)break;if(n=i.length?i.pop():L[a++],m=W(n,e,t,o),!1===m){if(n.status&ht){f(i,n.$id),e.nxt(!0)||(e.spc(),d=!0),h=!0,g=!1;break}}else{if(i.length&&qt===i[i.length-1].type)for(;i.length&&qt===i[i.length-1].type;)r=i.pop(),B(r,e,t,o),r.status&pt&&(t.$actionerr$=!0);else if(i.length>1&&e.eol()&&Tt&i[i.length-1].type&&t.block&&t.block.name===i[i.length-1].name)for(u=i.length-2;u>=0&&qt===i[u].type;)r=i[u--],B(r,e,t,o),r.status&pt&&(t.$actionerr$=!0);if(!0!==m){g=!1;break}}}return g&&e.nxt(1),w[E]=e.cur(1),!1!==m?(m=y[m]||v,w[_]=n.name):h?(m=x,t.status&at&&U(t,l,s,l,e.pos,n)):m=v,w[O]=m,t.$eol$=e.eol(),t.$blank$=t.$blank$&&(d||t.$eol$),w},tokenize:function(e,t){var n=this,r=[];if(e.eol())t.line++,t.$blank$&&t.bline++;else for(;!e.eol();)r.push(n.token(e,t));return r},parse:function(e,t){var n,r,i,l,s,a=this,u=(e||"").split(zn),c=u.length,p=null;if(t=t||st,r=!!(t&at),i=!!(t&st),n=new Q(0,t),n.$full_parse$=!0,o(function(e){u[e]+="\n"},0,c-2),i?p=o(t&ut?function(e,t){t._=t._.concat(a.tokenize(Z(u[e]),n,e))}:function(e,t){t._.push(a.tokenize(Z(u[e]),n,e))},0,c-1,{_:[]})._:o(function(e){var t=Z(u[e]);if(t.eol())n.line++,n.$blank$&&n.bline++;else for(;!t.eol();)a.token(t,n)},0,c-1),r&&n.queu&&n.queu.length)for(;n.queu.length;)l=n.queu.shift(),U(n,l[1],l[2],l[3],l[4],null,l[5]);return s=i&&r?{tokens:p,errors:n.err}:i?p:n.err,V(n),s},iterator:function(){},validate:function(){},autocomplete:function(){},indent:function(){},fold:function(){}}),Kn={Pattern:function(){return function(){}},Indented:function(e){return e=e||Z.$NOTEMPTY$,function(t){var n,r,o,i,l,s,a,u,c,p=t.row;if(n=t.line(p),e.test(n)){for(r=t.indentation(n),s=null,l=n.length,u=p+1,c=t.last();c>=u;++u)if(o=t.line(u),i=t.indentation(o),i>r)s=u,a=o.length;else if(e.test(o))break;return s?[p,l,s,a]:void 0}}},Delimited:function(e,t,n){return e&&t?(n=n||s,function(r){var o,i,l,s,a,u,c,p,f,m,h,g,d,k,$,b=r.row,y=r.col;for(o=r.line(b),l=y,s=0;;){var a=0>=l?-1:o.lastIndexOf(e,l-1);if(-1!==a){if(1===s&&y>a)return;if(n(u=r.token(b,a+1))){i=a+e.length;break}l=a-1}else{if(1===s)return;s=1,l=o.length}}c=1,p=r.last();e:for(h=b;p>=h;++h)for(g=r.line(h),d=h===b?i:0;k=g.indexOf(e,d),$=g.indexOf(t,d),0>k&&(k=g.length),0>$&&($=g.length),d=fn(k,$),!(d>=g.length);){if(r.token(h,d+1)==u)if(d===k)++c;else if(!--c){f=h,m=d;break e}++d}return null==f||b===f&&m===i?void 0:[b,i,f,m]}):function(){}},MarkedUp:function(e,t,n,r,o){return e=e||s,t=t||"<",n=n||">",r=r||"/",o=o||b($(t)+"("+$(r)+"?)([a-zA-Z_\\-][a-zA-Z0-9_\\-:]*)","g"),function(i){i.col=0,i.min=i.first(),i.max=i.last(),i.text=i.line(i.row);for(var l,s,a,u,c,p,f,m,h,g=i.row;;){if(l=X(i,e,o,t,n,r),!l||i.row!==g||!(s=et(i,e,o,t,n,r)))return;if(!l[1]&&"autoclosed"!==s)for(a=[i.row,i.col],c=l[2],u=null,p=[];;){if(f=X(i,e,o,t,n,r),g=i.row,m=i.col-(f?f[0].length:0),!f||!(s=et(i,e,o,t,n,r)))return;if("autoclosed"!==s)if(f[1]){for(h=p.length-1;h>=0;--h)if(p[h]===f[2]){p.length=h;break}if(0>h&&(!c||c===f[2]))return[a[0],a[1],g,m]}else p.push(f[2])}}}}},Qn=!("undefined"==typeof global||"[object global]"!==un.call(global)),Vn=!(Qn||"undefined"==typeof navigator),Zn=!!(Vn&&"function"==typeof importScripts&&navigator instanceof WorkerNavigator),Hn=function(e,t,n){var r,o=null,i=null,l=null;return e?(o=__filename,i=__dirname,l=__dirname):n?(o=self.location.href,i=o.split("/").slice(0,-1).join("/")):t&&(l=document.location.href.split("#")[0].split("?")[0].split("/").slice(0,-1).join("/"),(r=document.getElementsByTagName("script"))&&r.length&&(o=r[r.length-1].src,i=o.split("/").slice(0,-1).join("/"))),{path:i,file:o,base:l}}(Qn,Vn,Zn),Jn="?nocache="+g("nonce")+"_"+~~(1e3*Math.random()),Xn="undefined"!=typeof ace?ace:{require:function(){return{}},config:{}},er=k(Yn,{constructor:function nr(e,n,r){var i,l=this,a=null;if(Yn.call(l,e,"text","invalid"),l.$v$="value",l.DEF=n||l.$DEF,l.ERR=e.Style.error||l.$ERR,l.LC=e.$comments.line||null,l.BC=e.$comments.block?{start:e.$comments.block[0][0],end:e.$comments.block[0][1]}:null,!1!==r){if(e.$comments.block&&e.$comments.block.length){i=nr.Type("comment");for(var u=0,c=e.$comments.block.length;c>u;u++)l.$folders.push(nr.Fold.Delimited(e.$comments.block[u][0],e.$comments.block[u][1],i))}e.Fold&&wn&t(e.Fold)?a=e.Fold[mn]():e.$extra.fold&&(a=e.$extra.fold[mn]()),a&&(a=a.split("+"),o(function(t,n){var r=Cn(n[t]);if("brace"===r||"cstyle"===r){var o=D(e,1);i=o.length?nr.Type(o,!1):s,l.$folders.push(nr.Fold.Delimited("{","}",i)),l.$folders.push(nr.Fold.Delimited("[","]",i))}else"indent"===r||"indentation"===r?l.$folders.push(nr.Fold.Indented()):("markup"===r||"html"===r||"xml"===r)&&(l.$folders.push(nr.Fold.Delimited("",nr.Type(["comment","tag"],!1))),l.$folders.push(nr.Fold.MarkedUp(nr.Type("tag"),"<",">","/")))},0,a.length-1,a))}},LC:null,BC:null,dispose:function(){var e=this;return e.LC=e.BC=null,Yn[on].dispose.call(e)},getLineTokens:function(e,t,n){var r=this;return t=new Q(1,t),{tokens:r.tokenize(Z(e),t,n),state:t}},autocomplete:function(e,t,n,o,i){var l=this;if(l.$grammar.$autocomplete&&o.length){i=i||{};var s=i[ln]("caseInsesitiveMatch")?!!i.caseInsesitiveMatch:!1,a=i[ln]("prefixMatch")?!!i.prefixMatch:!0,u=o,c=u[mn](),p=u.length;return r(l.$grammar.$autocomplete,function(e,t){var n,r,o,i,l,f,m,h=t.word,g=h.length;return g>=p&&(n=t.meta,r=!!h.ci,m=s||r,m?(l=h[mn](),f=c):(l=h,f=u),(i=l.indexOf(f))>=0&&(!a||0===i)&&(o=m?h.indexOf(u):i,e.push({name:h,value:h,meta:n,score:1e3-10*(g-p)-5*(0>o?i+3:o)}))),e},[])}return[]},iterator:function(e){var t=e.getTabSize();return{row:0,col:0,min:0,max:0,line:function(t){return e.getLine(t)},first:function(){return 0},last:function(){return e.getLength()-1},next:function(){var e=this;if(!(e.row>=e.max))return e.col=0,e.row++,!0},prev:function(){var e=this;if(!(e.row<=e.min))return e.col=0,e.row--,!0},indentation:function(e){return H(e,null,t)},token:function(t,n){return e.getTokenAt(t,n).type}}},fold:function(e,t,n){var r,o,i,l=this,s=l.$folders,a=s.length;if(a)for(o=l.iterator(e,n),o.row=t,o.col=0,r=0;a>r;r++)if(i=s[r](o))return i}});er.Type=J,er.Fold=Kn,Zn&&(onmessage=tt);var tr=e.AceGrammar={VERSION:"2.6.0",clone:i,extend:l,pre_process:S,parse:T,getMode:lt,Parser:er};return e.AceGrammar}); \ No newline at end of file diff --git a/editor-grammar b/editor-grammar index d18f3ee..739980f 160000 --- a/editor-grammar +++ b/editor-grammar @@ -1 +1 @@ -Subproject commit d18f3ee990c26c51b222626af827f4b579a42921 +Subproject commit 739980fbc439fb67ffd826b4fbf11be856348406 diff --git a/src/main.js b/src/main.js index 8f7812d..424e7cf 100644 --- a/src/main.js +++ b/src/main.js @@ -42,6 +42,9 @@ this_path = (function(isNode, isBrowser, isWorker) { return { path: path, file: file, base: base }; })(isNode, isBrowser, isWorker), +// browser caches worker source file, even with reset/reload, try to not cache +NOCACHE = '?nocache=' + uuid('nonce') + '_' + (~~(1000*Math.random( ))), + // ace supposed to be available $ace$ = (typeof ace !== 'undefined') ? ace : { require: function() { return { }; }, config: {} } ; @@ -50,8 +53,8 @@ $ace$ = (typeof ace !== 'undefined') ? ace : { require: function() { return { }; // // parser factories var AceParser = Class(Parser, { - constructor: function AceParser( grammar, DEFAULT ) { - var self = this, rxLine, FOLD = null, TYPE; + constructor: function AceParser( grammar, DEFAULT, withFolders ) { + var self = this, FOLD = null, TYPE; Parser.call(self, grammar, "text", "invalid"); self.$v$ = 'value'; @@ -61,22 +64,9 @@ var AceParser = Class(Parser, { // support comments toggle self.LC = grammar.$comments.line || null; self.BC = grammar.$comments.block ? { start: grammar.$comments.block[0][0], end: grammar.$comments.block[0][1] } : null; - if ( self.LC ) - { - if ( T_ARRAY & get_type(self.LC) ) - rxLine = map( self.LC, esc_re ).join( "|" ); - - else - rxLine = esc_re( self.LC ); - - self.rxLine = new_re("^(\\s*)(?:" + rxLine + ")?"); - } - if ( self.BC ) - { - self.rxStart = new_re("^(\\s*)(?:" + esc_re(self.BC.start) + ")"); - self.rxEnd = new_re("(?:" + esc_re(self.BC.end) + ")\\s*$"); - } + if ( false !== withFolders ) + { // comment-block folding if ( grammar.$comments.block && grammar.$comments.block.length ) { @@ -116,17 +106,15 @@ var AceParser = Class(Parser, { } }, 0, FOLD.length-1, FOLD); } + } } ,LC: null ,BC: null - ,rxLine: null - ,rxStart: null - ,rxEnd: null ,dispose: function( ) { var self = this; - self.LC = self.BC = self.rxLine = self.rxStart = self.rxEnd = null; + self.LC = self.BC = null; return Parser[PROTO].dispose.call( self ); } @@ -137,21 +125,6 @@ var AceParser = Class(Parser, { return {tokens:self.tokenize( Stream( line ), state, row ), state:state}; } - ,keywords: function( append, ace ) { - var self = this; - if ( self.$grammar.$autocomplete ) - { - return map(self.$grammar.$autocomplete, function( word ){ - return { - name: word.word, - value: word.word, - meta: word.meta, - score: 1 - }; - }); - } - return []; - } ,autocomplete: function( state, session, position, prefix, options, ace ) { var self = this; if ( self.$grammar.$autocomplete && prefix.length ) @@ -188,10 +161,6 @@ var AceParser = Class(Parser, { return []; } - ,indent: function( state, line, tab, ace ) { - return line.match(Stream.$SPACE$)[0]; - } - ,iterator: function( session, ace ) { var tabSize = session.getTabSize(); return { @@ -228,193 +197,6 @@ var AceParser = Class(Parser, { return fold; } } - - // toggle comment lines - ,tCL: function( state, session, startRow, endRow ) { - var parser = self, doc = session.doc, - ignoreBlankLines = true, - shouldRemove = true, - minIndent = Infinity, - tabSize = session.getTabSize(), - insertAtTabStop = false, - comment, uncomment, testRemove, shouldInsertSpace, - lineCommentStart, lineCommentEnd, regexpStart, regexpEnd, - minEmptyLength, regexpLine, commentWithSpace - ; - - if ( !parser.LC ) - { - if ( !parser.BC ) return false; - - lineCommentStart = parser.BC.start; - lineCommentEnd = parser.BC.end; - regexpStart = parser.rxStart; - regexpEnd = parser.rxEnd; - - comment = function( i ) { - var line = doc.getLine(i); - if (testRemove(line, i)) return; - if (!ignoreBlankLines || /\S/.test(line)) - { - doc.insertInLine({row: i, column: line.length}, lineCommentEnd); - doc.insertInLine({row: i, column: minIndent}, lineCommentStart); - } - }; - - uncomment = function( i ) { - var line = doc.getLine(i), m; - if (m = line.match(regexpEnd)) - doc.removeInLine(i, line.length - m[0].length, line.length); - if (m = line.match(regexpStart)) - doc.removeInLine(i, m[1].length, m[0].length); - }; - - testRemove = function( line, row ) { - if (regexpStart.test(line)) return true; - var tokens = session.getTokens(row); - for (var i = 0; i < tokens.length; i++) - { - if (tokens[i].type === 'comment') return true; - } - }; - } - else - { - lineCommentStart = (T_ARRAY === get_type(parser.LC)) ? parser.LC[0] : parser.LC; - regexpLine = parser.rxLine; - commentWithSpace = lineCommentStart + " "; - - insertAtTabStop = session.getUseSoftTabs(); - - uncomment = function( i ) { - var line = doc.getLine(i), m = line.match(regexpLine), start, end; - if (!m) return; - start = m[1].length; end = m[0].length; - if (!shouldInsertSpace(line, start, end) && m[0][end - 1] == " ") end--; - doc.removeInLine(i, start, end); - }; - - comment = function( i ) { - var line = doc.getLine(i); - if (!ignoreBlankLines || /\S/.test(line)) - { - if (shouldInsertSpace(line, minIndent, minIndent)) - doc.insertInLine({row: i, column: minIndent}, commentWithSpace); - else - doc.insertInLine({row: i, column: minIndent}, lineCommentStart); - } - }; - - testRemove = function( line, i ) { - return regexpLine.test(line); - }; - - shouldInsertSpace = function(line, before, after) { - var spaces = 0; - while (before-- && line[CHAR](before) == " ") spaces++; - if (spaces % tabSize != 0) return false; - spaces = 0; - while (line[CHAR](after++) == " ") spaces++; - if (tabSize > 2) return spaces % tabSize != tabSize - 1; - else return spaces % tabSize == 0; - return true; - }; - } - - minEmptyLength = Infinity; - - iterate(function( i ) { - var line = doc.getLine(i), indent = line.search(/\S/); - if (indent !== -1) - { - if (indent < minIndent) minIndent = indent; - if (shouldRemove && !testRemove(line, i)) shouldRemove = false; - } - else if (minEmptyLength > line.length) - { - minEmptyLength = line.length; - } - }, startRow, endRow); - - if (Infinity == minIndent) - { - minIndent = minEmptyLength; - ignoreBlankLines = false; - shouldRemove = false; - } - - if (insertAtTabStop && minIndent % tabSize != 0) - minIndent = Math.floor(minIndent / tabSize) * tabSize; - - iterate(shouldRemove ? uncomment : comment, startRow, endRow); - } - - // toggle block comment - ,tCB: function( state, session, range, cursor, TokenIterator, Range ) { - var parser = self, comment = parser.BC, iterator, token, sel, - initialRange, startRow, colDiff, - startRange, endRange, i, row, column, - comment_re = /comment/ - ; - if (!comment) return; - - iterator = new TokenIterator( session, cursor.row, cursor.column ); - token = iterator.getCurrentToken(); - - sel = session.selection; - initialRange = sel.toOrientedRange(); - - if (token && comment_re.test(token.type)) - { - while (token && comment_re.test(token.type)) - { - i = token.value.indexOf(comment.start); - if (i != -1) - { - row = iterator.getCurrentTokenRow(); - column = iterator.getCurrentTokenColumn() + i; - startRange = new Range(row, column, row, column + comment.start.length); - break; - } - token = iterator.stepBackward(); - }; - - iterator = new TokenIterator(session, cursor.row, cursor.column); - token = iterator.getCurrentToken(); - while (token && comment_re.test(token.type)) - { - i = token.value.indexOf(comment.end); - if (i != -1) - { - row = iterator.getCurrentTokenRow(); - column = iterator.getCurrentTokenColumn() + i; - endRange = new Range(row, column, row, column + comment.end.length); - break; - } - token = iterator.stepForward(); - } - if (endRange) - session.remove(endRange); - if (startRange) - { - session.remove(startRange); - startRow = startRange.start.row; - colDiff = -comment.start.length; - } - } - else - { - colDiff = comment.start.length; - startRow = range.start.row; - session.insert(range.end, comment.end); - session.insert(range.start, comment.start); - } - if (initialRange.start.row == startRow) - initialRange.start.column += colDiff; - if (initialRange.end.row == startRow) - initialRange.end.column += colDiff; - session.selection.fromOrientedRange(initialRange); - } }); AceParser.Type = Type; AceParser.Fold = Folder; @@ -433,10 +215,10 @@ function grammar_worker_init( e ) ace.define('ace/grammar_worker', ['require', 'exports', 'module' , 'ace/worker/mirror'], function( require, exports, module ) { - var WorkerMirror = require("./worker/mirror").Mirror, AceGrammarWorker; + var WorkerMirror = require("./worker/mirror").Mirror; // extends require("./worker/mirror").Mirror - exports.AceGrammarWorker = AceGrammarWorker = Class(WorkerMirror, { + exports.AceGrammarWorker = Class(WorkerMirror, { constructor: function AceGrammarWorker( sender ) { var self = this; WorkerMirror.call( self, sender ); @@ -447,7 +229,7 @@ function grammar_worker_init( e ) ,init_parser: function( grammar, id ) { var self = this; - self.$parser = new AceParser( parse_grammar( grammar ) ); + self.$parser = new AceParser( parse_grammar( grammar ), null, false ); self.sender.callback( 1, id ); } @@ -486,9 +268,11 @@ function grammar_worker_init( e ) } } +/* // adapted from ace Marker renderer +// https://github.com/ajaxorg/ace/issues/2720 // renderer(html, range, left, top, config); -/*function getBorderClass(tl, tr, br, bl) +function getBorderClass(tl, tr, br, bl) { return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0); } @@ -522,8 +306,8 @@ function custom_text_marker( clazz, popup, session, Range ) ); } }; -}*/ - +} +*/ function clear_markers( session, $markers ) { if ( !session[$markers] ) session[$markers] = []; @@ -570,49 +354,63 @@ function update_annotations( session, errors, $markers, Range ) session.setAnnotations( errors ); } - function get_mode( grammar, DEFAULT, ace ) { - // ace required helpers ace = ace || $ace$; /* pass ace reference if not already available */ - var ace_mode, grammar_copy = clone( grammar ) + var grammar_copy = clone( grammar ) + // ace required helpers ,Range = ace.require('ace/range').Range - ,TokenIterator = ace.require('ace/token_iterator').TokenIterator - // adapted from ace directly - ,WorkerClient = ace.require("ace/worker/worker_client").WorkerClient + ,WorkerClient = ace.require('ace/worker/worker_client').WorkerClient ,AceWorker = Class(WorkerClient, { - constructor: function AceWorker( topLevelNamespaces, mod, classname ) { + constructor: function AceWorker( topLevelNamespaces, mod, classname, workerUrl ) { var self = this, require = ace.require, config = ace.config; self.$sendDeltaQueue = self.$sendDeltaQueue.bind(self); self.changeListener = self.changeListener.bind(self); self.onMessage = self.onMessage.bind(self); if (require.nameToUrl && !require.toUrl) require.toUrl = require.nameToUrl; - - var workerUrl; + + if ( !workerUrl ) + { if (config.get("packaged") || !require.toUrl) { - workerUrl = config.moduleUrl(mod, "worker"); + workerUrl = workerUrl || config.moduleUrl(mod, "worker"); } else { var normalizePath = self.$normalizePath; - workerUrl = normalizePath(require.toUrl("ace/worker/worker.js", null, "_")); + workerUrl = workerUrl || normalizePath(require.toUrl("ace/worker/worker.js", null, "_")); var tlns = {}; topLevelNamespaces.forEach(function(ns) { tlns[ns] = normalizePath(require.toUrl(ns, null, "_").replace(/(\.js)?(\?.*)?$/, "")); }); } - - self.$worker = new Worker( workerUrl ); - + } + + try { + self.$worker = new Worker(workerUrl); + } catch(e) { + if (e instanceof window.DOMException) { + var blob = self.$workerBlob(workerUrl); + var URL = window.URL || window.webkitURL; + var blobURL = URL.createObjectURL(blob); + + self.$worker = new Worker(blobURL); + URL.revokeObjectURL(blobURL); + } else { + throw e; + } + } + self.$worker.postMessage({ load: true, - ace_worker_base: this_path.base + '/' + config.moduleUrl("ace/worker/json") + // browser caches worker source file, even with reset/reload, try to not cache + // https://github.com/ajaxorg/ace/issues/2730 + ace_worker_base: this_path.base + '/' + config.moduleUrl("ace/worker/json") + NOCACHE }); self.$worker.postMessage({ init : true, - tlns: tlns, - module: mod, - classname: classname + tlns : tlns, + module : mod, + classname : classname }); self.callbackId = 1; @@ -621,145 +419,129 @@ function get_mode( grammar, DEFAULT, ace ) self.$worker.onmessage = self.onMessage; } }) - // adapted from ace directly - ,FoldMode = ace.require("ace/mode/folding/fold_mode").FoldMode + ,FoldMode = ace.require('ace/mode/folding/fold_mode').FoldMode ,AceFold = Class(FoldMode, { constructor: function( $folder ) { var self = this; FoldMode.call( self ); self.$findFold = $folder; + self.$lastFold = null; } ,getFoldWidget: function( session, foldStyle, row ) { - var self = this, fold = self.$findFold( session, foldStyle, row ); - if ( fold ) - { - if ( "markbeginend" === foldStyle && fold.end ) return "end"; - else return "start"; - } - return ""; + var fold = this.$lastFold = this.$findFold( session, foldStyle, row ); + // cache the fold to be re-used in getFoldWidgetRange + // it is supposed that getFoldWidgetRange is called after getFoldWidget succeeds + // on same row and with same style, so same fold should be re-used for efficiency + return fold + ? ("markbeginend" === foldStyle && fold.end ? "end" : "start") + : ""; } ,getFoldWidgetRange: function( session, foldStyle, row, forceMultiline ) { - var fold = this.$findFold( session, foldStyle, row ); + // cache the fold to be re-used in getFoldWidgetRange + // it is supposed that getFoldWidgetRange is called after getFoldWidget succeeds + // on same row and with same style, so same fold should be re-used for efficiency + var fold = this.$lastFold;// this.$findFold( session, foldStyle, row ); if ( fold ) return new Range(fold[0], fold[1], fold[2], fold[3]); } }) - ; - - // ACE-compatible Mode - ace_mode = { - $id: uuid("ace_grammar_mode") - ,$parser: new AceGrammar.Parser( parse_grammar( grammar ), DEFAULT ) - - /* - // maybe needed in later versions..? - ,createModeDelegates: function (mapping) { } - ,$delegator: function(method, args, defaultHandler) { } - ,HighlightRules: null - ,$behaviour: parser.$behaviour || null - ,lineCommentStart: parser.LC - ,blockComment: parser.BC - ,$getIndent: function(line) { return parser.indent(line); } - ,$createKeywordList: function() { return parser.$createKeywordList(); } - */ - - ,getTokenizer: function( ) { - return ace_mode.$parser; - } - - ,toggleCommentLines: function( state, session, startRow, endRow ) { - return ace_mode.$parser.tCL( state, session, startRow, endRow ); - } - ,toggleBlockComment: function( state, session, range, cursor ) { - return ace_mode.$parser.tCB( state, session, range, cursor, TokenIterator, Range ); + ,Mode = ace.require('ace/mode/text').Mode + ,AceMode = Class(Mode, { + constructor: function AceMode( ) { + var self = this; + Mode.call( self ); + self.$id = AceMode.$id; + self.$tokenizer = AceMode.$parser; + // comment-toggle functionality + self.lineCommentStart = AceMode.$parser.LC; + self.blockComment = AceMode.$parser.BC; + // custom, user-defined, code folding generated from grammar + self.foldingRules = new AceFold( self.folder.bind( self ) ); } - ,transformAction: function( state, action, editor, session, param ) { } - - ,getNextLineIndent: function( state, line, tab ) { - return ace_mode.$parser.indent( state, line, tab ); - } - ,checkOutdent: function( state, line, input ) { - return false; - } - ,autoOutdent: function( state, doc, row ) { } - - // custom, user-defined, code folding generated from grammar - ,supportCodeFolding: true - ,$folder: function folder( session, foldStyle, row ) { - var fold, min_row, current_row, folder; - if ( ace_mode.supportCodeFolding && ace_mode.$parser ) - { - folder = ace_mode.$parser; - - if ( "markbeginend" === foldStyle ) - { - current_row = row; min_row = MAX(0, row-500); // check up to 500 rows up - fold = folder.fold( session, row, ace ); - if ( fold ) - { - fold.start = true; fold.end = false; - return fold; - } - // try to find if any block ends on this row, backwards - // TODO, maybe a bit slower, than direct backwards search - while ( row > min_row && (!fold || current_row !== fold[2]) ) fold = folder.fold( session, --row, ace ); - if ( fold && current_row === fold[2] ) - { - fold.start = false; fold.end = true; - return fold; // found end of fold, return end marker - } - } - - else if ( fold = folder.fold( session, row, ace ) ) - { - fold.start = true; fold.end = false; - return fold; - } - } - } - ,foldingRules: null /* added below */ // custom, user-defined, syntax lint-like validation/annotations generated from grammar ,supportGrammarAnnotations: false ,createWorker: function( session ) { - if ( !ace_mode.supportGrammarAnnotations ) + if ( !this.supportGrammarAnnotations ) { - clear_annotations( session, ace_mode.$id+'$markers' ); + clear_annotations( session, AceMode.$markers ); return null; } // add this worker as an ace custom module - ace.config.setModuleUrl("ace/grammar_worker", this_path.file); - var worker = new AceWorker(['ace'], "ace/grammar_worker", 'AceGrammarWorker'); + //ace.config.setModuleUrl("ace/grammar_worker", this_path.file + NOCACHE); + var worker = new AceWorker(['ace'], "ace/grammar_worker", 'AceGrammarWorker', this_path.file + NOCACHE); worker.attachToDocument( session.getDocument( ) ); // create a worker for this grammar worker.call('init_parser', [grammar_copy], function( ){ // hook worker to enable error annotations worker.on("ace_grammar_worker_error", function( e ) { var errors = e.data; - update_annotations( session, errors, ace_mode.$id+'$markers', Range ) + update_annotations( session, errors, AceMode.$markers, Range ) }); worker.on("ace_grammar_worker_ok", function() { - clear_annotations( session, ace_mode.$id+'$markers' ); + clear_annotations( session, AceMode.$markers ); }); }); + worker.on("terminate", function() { + clear_annotations( session, AceMode.$markers ); + }); return worker; } + + // custom, user-defined, code folding generated from grammar + ,supportCodeFolding: true + ,folder: function folder( session, foldStyle, row ) { + return !this.supportCodeFolding + ? null + : AceMode.$folder( session, foldStyle, row, folder.options||{} ); + } + // custom, user-defined, autocompletions generated from grammar ,supportAutoCompletion: true + ,autocompleter: function autocompleter( state, session, position, prefix ) { + return !this.supportAutoCompletion + ? [] + : AceMode.$autocompleter( state, session, position, prefix, autocompleter.options||{} ); + } + ,getKeywords: function( append ) { + return []; // use getCompletions + } ,getCompletions: function( state, session, position, prefix ) { - return ace_mode.supportAutoCompletion && ace_mode.$parser - ? ace_mode.$parser.autocomplete( state, session, position, prefix, options, ace ) - : []; + return this.autocompleter( state, session, position, prefix ); } ,dispose: function( ) { - if ( ace_mode.$parser ) ace_mode.$parser.dispose( ); - ace_mode.$parser = null; - ace_mode.foldingRules = ace_mode.$folder = null; + var self = this; + self.$tokenizer = self.foldingRules = self.autocompleter = null; + AceMode.dispose( ); } + }); + AceMode.$id = uuid("ace_grammar_mode"); + AceMode.$markers = AceMode.$id+'$markers'; + AceMode.$parser = new AceGrammar.Parser( parse_grammar( grammar ), DEFAULT ); + AceMode.$folder = function folder( session, foldStyle, row, options ) { + var min_row, current_row, folder = AceMode.$parser, + fold = folder.fold( session, row, ace ); + if ( "markbeginend" === foldStyle ) + { + if ( fold ) { fold.start = true; fold.end = false; return fold; } + current_row = row; min_row = MAX(0, row-200); // check up to 200 rows up for efficiency + // try to find if any block ends on this row, backwards + // TODO, maybe a bit slower, than direct backwards search + while ( row > min_row && (!fold || current_row !== fold[2]) ) fold = folder.fold( session, --row, ace ); + // found end of fold, return end marker + if ( fold && current_row === fold[2] ) { fold.start = false; fold.end = true; return fold; } + } + else if ( fold ) { fold.start = true; fold.end = false; return fold; } + }; + AceMode.$autocompleter = function autocompleter( state, session, position, prefix, options ) { + return AceMode.$parser.autocomplete( state, session, position, prefix, options, ace ); + }; + AceMode.dispose = function( ) { + if ( AceMode.$parser ) AceMode.$parser.dispose( ); + AceMode.$parser = AceMode.$folder = AceMode.$autocompleter = AceMode.autocompleter = null; }; - ace_mode.foldingRules = new AceFold( ace_mode.$folder ); - return ace_mode; + return new AceMode( ); // object } diff --git a/test/demo.js b/test/demo.js index b78d884..cca4828 100644 --- a/test/demo.js +++ b/test/demo.js @@ -12,6 +12,7 @@ function ace_grammar_demo(_editor, code, grammar) mode.supportGrammarAnnotations = true; // enable auto-completion mode.supportAutoCompletion = true; + mode.autocompleter.options = {prefixMatch:true, caseInsensitiveMatch:false}; // enable code-folding mode.supportCodeFolding = true; diff --git a/test/grammar-css.png b/test/grammar-css.png new file mode 100644 index 0000000..074a0b1 Binary files /dev/null and b/test/grammar-css.png differ diff --git a/test/grammar-js-recursion-2.png b/test/grammar-js-recursion-2.png index 63770b5..0028ddd 100644 Binary files a/test/grammar-js-recursion-2.png and b/test/grammar-js-recursion-2.png differ diff --git a/test/grammar-js-recursion.png b/test/grammar-js-recursion.png index 30e3539..b1bbaee 100644 Binary files a/test/grammar-js-recursion.png and b/test/grammar-js-recursion.png differ diff --git a/test/grammar-js.html b/test/grammar-js.html index e4805bd..0d8a014 100644 --- a/test/grammar-js.html +++ b/test/grammar-js.html @@ -7,6 +7,7 @@ + + + ACE: Dynamic Scheme Grammar Demo + + + +

ACE (v.0) Grammar (v.0): Dynamic Scheme Grammar

+ +

+
+        

+ + + + diff --git a/test/grammar-scheme.png b/test/grammar-scheme.png new file mode 100644 index 0000000..27f12cc Binary files /dev/null and b/test/grammar-scheme.png differ diff --git a/test/grammar-xml-2.png b/test/grammar-xml-2.png index 504b1b6..37bfd31 100644 Binary files a/test/grammar-xml-2.png and b/test/grammar-xml-2.png differ diff --git a/test/grammar-xml.png b/test/grammar-xml.png index b1d8d91..a795f8e 100644 Binary files a/test/grammar-xml.png and b/test/grammar-xml.png differ diff --git a/test/grammars/javascript-recursion.js b/test/grammars/javascript-recursion.js index 7706ad9..dd5ad33 100644 --- a/test/grammars/javascript-recursion.js +++ b/test/grammars/javascript-recursion.js @@ -56,13 +56,13 @@ var js_grammar = { ] ,"string:escaped-block" : ["RE::/(['\"])/", 1] ,"regex:escaped-line-block" : ["/", "RE::#/[gimy]{0,4}#"] - ,"atom" : {"autocomplete":true,"meta":"JavaScript ATOM","tokens":[ + ,"atom" : {"autocomplete":true,"meta":"JavaScript Atom","tokens":[ "this", "true", "false", "null", "undefined", "NaN", "Infinity" ]} - ,"keyword" : {"autocomplete":true,"meta":"JavaScript KEYWORD","tokens":[ + ,"keyword" : {"autocomplete":true,"meta":"JavaScript Keyword","tokens":[ "if", "while", "with", "else", "do", "try", "finally", "return", "break", "continue", "new", "delete", "throw", "var", "const", "let", "function", "catch", diff --git a/test/grammars/scheme.js b/test/grammars/scheme.js new file mode 100644 index 0000000..aa359ac --- /dev/null +++ b/test/grammars/scheme.js @@ -0,0 +1,85 @@ +// 1. a partial scheme grammar in simple JSON format +// https://people.csail.mit.edu/jaffer/r5rs_9.html +var scheme_grammar = { + +// prefix ID for regular expressions used in the grammar +"RegExpID" : "RE::", + +"Extra" : { + + "fold" : "indent" + +}, + +// Style model +"Style" : { + + "comment" : "comment" + ,"keyword" : "keyword" + ,"expression_keyword" : "keyword" + ,"identifier" : "identifier" + ,"peculiar_identifier" : "identifier" + ,"number" : "constant.numeric" + ,"boolean" : "constant.support" + ,"string" : "string" + +}, + +// Lexical model +"Lex" : { + + "comment:comment" : {"interleave":true,"tokens":[[";", null],["#|", "|#"]]} + ,"string:escaped-block" : [ "\"" ] + ,"identifier" : "RE::/[a-z!$%&*\\/:<=>?\\^_~][0-9a-z!$%&*\\/:<=>?\\^_~+\\-.@]*/i" + ,"peculiar_identifier" : "RE::/\\.\\.\\.|\\+|-/" + ,"number" : [ + "RE::/^(?:[-+]i|[-+][01]+#*(?:\\/[01]+#*)?i|[-+]?[01]+#*(?:\\/[01]+#*)?@[-+]?[01]+#*(?:\\/[01]+#*)?|[-+]?[01]+#*(?:\\/[01]+#*)?[-+](?:[01]+#*(?:\\/[01]+#*)?)?i|[-+]?[01]+#*(?:\\/[01]+#*)?)(?=[()\\s;\"]|$)/i", + "RE::/^(?:[-+]i|[-+][0-7]+#*(?:\\/[0-7]+#*)?i|[-+]?[0-7]+#*(?:\\/[0-7]+#*)?@[-+]?[0-7]+#*(?:\\/[0-7]+#*)?|[-+]?[0-7]+#*(?:\\/[0-7]+#*)?[-+](?:[0-7]+#*(?:\\/[0-7]+#*)?)?i|[-+]?[0-7]+#*(?:\\/[0-7]+#*)?)(?=[()\\s;\"]|$)/i", + "RE::/^(?:[-+]i|[-+][\\da-f]+#*(?:\\/[\\da-f]+#*)?i|[-+]?[\\da-f]+#*(?:\\/[\da-f]+#*)?@[-+]?[\\da-f]+#*(?:\\/[\\da-f]+#*)?|[-+]?[\\da-f]+#*(?:\\/[\\da-f]+#*)?[-+](?:[\\da-f]+#*(?:\\/[\da-f]+#*)?)?i|[-+]?[\\da-f]+#*(?:\\/[\\da-f]+#*)?)(?=[()\\s;\"]|$)/i", + "RE::/^(?:[-+]i|[-+](?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*)i|[-+]?(?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*)@[-+]?(?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*)|[-+]?(?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*)[-+](?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*)?i|(?:(?:(?:\\d+#+\\.?#*|\\d+\\.\\d*#*|\\.\\d+#*|\\d+)(?:[esfdl][-+]?\\d+)?)|\\d+#*\\/\\d+#*))(?=[()\\s;\"]|$)/i" + ] + ,"boolean" : {"autocomplete":true,"tokens":["#t", "#f"]} + ,"expression_keyword" : {"autocomplete":true,"tokens":[ + "lambda", "if", + "set!", "begin", "cond", "and", "or", "case", + "let", "let*", "letrec", "do", "delay" + ]} + ,"keyword" : {"autocomplete":true,"tokens":[ + "case-lambda", "call/cc", "class", "define-class", "exit-handler", + "field", "import", "inherit", "init-field", "interface", "let*-values", "let-values", "let/ec", "mixin", "opt-lambda", + "override", "protect", "provide", "public", "rename", "require", "require-for-syntax", "syntax", "syntax-case", + "syntax-error", "unit/sig", "unless", "when", "with-syntax", "and", "begin", "call-with-current-continuation", + "call-with-input-file", "call-with-output-file", "case", "cond", "define", "define-syntax", "delay", "do", + "dynamic-wind", "else", "for-each", "if", "lambda", "let", "let*", "let-syntax", "letrec", "letrec-syntax", "map", + "or", "syntax-rules", "abs", "acos", "angle", "append", "apply", "asin", "assoc", "assq", "assv", "atan", "boolean?", + "caar", "cadr", "call-with-input-file", "call-with-output-file", "call-with-values", "car", "cdddar", "cddddr", + "cdr", "ceiling", "char->integer", "char-alphabetic?", "char-ci<=?", "char-ci=?", "char-ci>?", + "char-downcase", "char-lower-case?", "char-numeric?", "char-ready?", "char-upcase", "char-upper-case?", "char-whitespace?", + "char<=?", "char=?", "char>?", "char?", "close-input-port", "close-output-port", "complex?", "cons", + "cos", "current-input-port", "current-output-port", "denominator", "display", "eof-object?", "eq?", "equal?", "eqv?", "eval", + "even?", "exact->inexact", "exact?", "exp", "expt", "floor", "force", "gcd", "imag-part", "inexact->exact", "inexact?", + "input-port?", "integer->char", "integer?", "interaction-environment", "lcm", "length", "list", "list->string", "list->vector", + "list-ref", "list-tail", "list?", "load", "log", "magnitude", "make-polar", "make-rectangular", "make-string", "make-vector", + "max", "member", "memq", "memv", "min", "modulo", "negative?", "newline", "not", "null-environment", "null?", "number->string", "number?", + "numerator", "odd?", "open-input-file", "open-output-file", "output-port?", "pair?", "peek-char", "port?", "positive?", "procedure?", + "quasiquote", "quote", "quotient", "rational?", "rationalize", "read", "read-char", "real-part", "real?", "remainder", "reverse", "round", "r-cdr", "f-cons", + "scheme-report-environment", "set!", "set-car!", "set-cdr!", "sin", "sqrt", "string", "string->list", "string->number", "string->symbol", + "string-append", "string-ci<=?", "string-ci=?", "string-ci>?", "string-copy", "string-fill!", "string-length", + "string-ref", "string-set!", "string<=?", "string=?", "string>?", "string?", "substring", "symbol->string", + "symbol?", "tan", "transcript-off", "transcript-on", "truncate", "values", "vector", "vector->list", "vector-fill!", "vector-length", + "vector-ref", "vector-set!", "with-input-from-file", "with-output-to-file", "write", "write-char", "zero?" + ]} + +}, + +// Syntax model (optional) +"Syntax" : { + + "token" : "boolean | number | string | keyword | identifier | peculiar_identifier" + +}, + +// what to parse and in what order +"Parser" : [ "comment", [ "token" ] ] + +};