1 2 3 define(['constants', 'jsccGen', 'asyncGen', 'jquery'], 4 /** 5 * Asynchronous generator for executable language-grammars (i.e. converted JSON grammars). 6 * 7 * <p> 8 * This generator uses JS/CC for compiling the JSON grammar. 9 * 10 * <p> 11 * Usage of this compile is the same as for synchronously working JsccGenerator. 12 * 13 * @see JsccGenerator 14 * 15 * @class 16 * @constant 17 * @public 18 * @name JsccAsyncGenerator 19 * @memberOf mmir.env.grammar 20 * 21 * @requires JsccGenerator 22 * @requires jQuery.extend 23 * @requires jQuery.deferred 24 */ 25 function(constants, jsccGen, asyncGen, $){ 26 27 /** 28 * Counter for generating IDs for compile-jobs that 29 * are sent to the WebWorker 30 * 31 * @private 32 * @memberOf JsccAsyncGenerator# 33 */ 34 var _taskId = 1; 35 36 /** 37 * WebWorker instance for compiling parser asynchronously 38 * 39 * @private 40 * @memberOf JsccAsyncGenerator# 41 */ 42 var asyncCompiler = asyncGen.createWorker(jsccGen.engineId); 43 44 /** 45 * printError function reference for compile-errors 46 * 47 * @private 48 * @memberOf JsccAsyncGenerator# 49 */ 50 var printError = jsccGen.printError; 51 52 /** 53 * HELPER for applying the compile-results (i.e. parser-code) to the parser-template 54 * 55 * @see JsccGenerator#_getGenerated 56 * @see JsccGenerator#_applyGenerated 57 * 58 * @private 59 * @memberOf JsccAsyncGenerator# 60 */ 61 var _applyGenerated = jsccGen._applyGenerated; 62 63 //////////////////// init async compiler/thread ///////////////////////// 64 65 asyncCompiler._onerror = printError; 66 67 //setup async init-signaling: 68 var initDef = $.Deferred(); 69 var initMsg = asyncCompiler.prepareOnInit(jsccGen, initDef, require); 70 asyncCompiler.postMessage(initMsg); 71 72 73 /** 74 * Exported (public) functions for the PEG.js grammar-engine. 75 * @public 76 * @type GrammarGenerator 77 * @memberOf JsccAsyncGenerator# 78 */ 79 var jsccAsyncGen = { 80 /** @scope JsccAsyncGenerator.prototype */ 81 82 /** 83 * @see JsccAsyncGenerator#init 84 * @memberOf JsccAsyncGenerator.prototype 85 */ 86 init: function(callback){ 87 //overwrite with own async "init signal" 88 if(callback){ 89 initDef.always(callback); 90 } 91 return initDef; 92 }, 93 /** @returns {Boolean} if this engine compilation works asynchronously. 94 * The current implementation works asynchronously (returns TRUE) 95 * 96 * @memberOf JsccAsyncGenerator.prototype 97 */ 98 isAsyncCompilation: function(){ return true; }, 99 /** 100 * @see JsccAsyncGenerator#_compileParser 101 * @protected 102 */ 103 _compileParser: function(grammarDefinition, options, onAfterCompileParserResult){ 104 105 //start compilation in web-worker: 106 asyncCompiler.postMessage({ 107 cmd: 'parse', 108 id: onAfterCompileParserResult, 109 config: options, 110 text: grammarDefinition 111 }); 112 113 }, 114 /** 115 * @see JsccAsyncGenerator#_preparePrintError 116 * @protected 117 */ 118 _preparePrintError: function(){},//<- overwrite with NOOP 119 /** 120 * @see JsccAsyncGenerator#_afterCompileParser 121 * @protected 122 */ 123 _afterCompileParser: function(compileParserModuleFunc){ 124 125 //callback-ID: 126 var taskId = '' + _taskId++; 127 128 //register callback for messages from web-worker: 129 asyncCompiler.addCallback(taskId, function(evtData){ 130 131 if(evtData.error){ 132 133 //handle error message: 134 135 if(printError){ 136 printError(evtData.error); 137 } 138 else { 139 console.error(evtData.error); 140 } 141 142 //////////////////// EARLY EXIT ///////////////// 143 //NOTE this is not the final message from the compiler-thread... 144 return; 145 } 146 147 var hasError = evtData.isError; 148 var grammarParserData = evtData.def; 149 150 var grammarParser = jsccGen._applyGenerated(grammarParserData, jsccGen.template); 151 152 compileParserModuleFunc(grammarParser, hasError); 153 }); 154 155 return taskId; 156 } 157 }; 158 159 //extend/overload sync-compiler with async-compiler: 160 return $.extend({}, jsccGen, jsccAsyncGen); 161 162 }); 163