UNPKG

mmir-lib

Version:

MMIR (Mobile Multimodal Interaction and Relay) library

199 lines (171 loc) 4.71 kB
define(['mmirf/pegjsGen','mmirf/asyncGen','mmirf/util/deferred','mmirf/util/extend'], /** * Asynchronous generator for executable language-grammars (i.e. converted JSON grammars). * * <p> * This generator uses PEG.js for compiling the JSON grammar. * * <p> * Usage of this compile is the same as for synchronously working PegJsGenerator. * * @see PegJsGenerator * * @class * @constant * @public * @name PegJsAsyncGenerator * @memberOf mmir.env.grammar * @hideconstructor * * @requires PegJsGenerator */ function(pegjsGen, asyncGen, deferred, extend){ /** * Counter for generating IDs for compile-jobs that * are sent to the WebWorker * * @private * @memberOf PegJsAsyncGenerator# */ var _taskId = 1; /** * WebWorker instance for compiling parser asynchronously * * @private * @memberOf PegJsAsyncGenerator# */ var asyncCompiler; /** * printError function reference for compile-errors * * @private * @memberOf PegJsAsyncGenerator# */ var printError = pegjsGen.printError; /** * create & initialize the async compiler: * * creates the asyncCompiler and initDef, * and sends init-message to asyncCompiler. * * @private * @memberOf PegJsAsyncGenerator# */ function initAsyncCompiler(){ asyncCompiler = asyncGen.createWorker(pegjsGen.engineId); initDef = deferred(); var initMsg = asyncCompiler.prepareOnInit(pegjsGen, initDef); asyncCompiler.postMessage(initMsg); asyncCompiler._onerror = printError; } ////////////////////init async compiler/thread ///////////////////////// // for async init-signaling: var initDef; //immedately start initialization for async compiler: initAsyncCompiler(); /** * Exported (public) functions for the PEG.js grammar-engine. * @public * @type GrammarGenerator * @memberOf PegJsAsyncGenerator# */ var pegjsAsyncGen = { /** @scope PegJsAsyncGenerator.prototype */ /** * @see PegJsAsyncGenerator#init * @memberOf PegJsAsyncGenerator.prototype */ init: function(callback){ if(!asyncCompiler){ //in case the compiler was destroyed -> re-init: initAsyncCompiler(); } //overwrite with own async "init signal" if(callback){ initDef.then(callback, callback); } return initDef; }, /** * frees up the resources of the async compiler * ({@link #init} will re-initialize the resources) * * @param {Boolean} [force] OPTIONAL * if TRUE, immediately terminates the async worker, otherwise * will wait until no pending queries are registered any more * * @see CompileWebWorker#hasPendingCallback * @see CompileWebWorker#addCallback * * @memberOf PegJsAsyncGenerator.prototype */ destroy: function(force){ if(asyncCompiler && asyncCompiler.terminate){ if(!force){ if(asyncCompiler.hasPendingCallback()){ var tis = this; asyncCompiler._onidle = function(){ tis.destroy(); } return; } } asyncCompiler.terminate(); asyncCompiler = null; } }, /** @returns {Boolean} if this engine compilation works asynchronously. * The current implementation works asynchronously (returns TRUE) * * @memberOf PegJsAsyncGenerator.prototype */ isAsyncCompilation: function(){ return true; }, /** * @see PegJsAsyncGenerator#_compileParser * @protected */ _compileParser: function(grammarDefinition, options, onAfterCompileParserResult){ //start compilation in web-worker: asyncCompiler.postMessage({ cmd: 'parse', id: onAfterCompileParserResult, config: options, text: grammarDefinition }); }, /** * @see PegJsAsyncGenerator#_preparePrintError * @protected */ _preparePrintError: function(){},//<- overwrite with NOOP /** * @see PegJsAsyncGenerator#_afterCompileParser * @protected */ _afterCompileParser: function(compileParserModuleFunc){ //callback-ID: var taskId = '' + _taskId++; //register callback for messages from web-worker: asyncCompiler.addCallback(taskId, function(evtData){ if(evtData.error){ //handle error message: if(printError){ printError(evtData.error); } else { console.error(evtData.error); } //////////////////// EARLY EXIT ///////////////// //NOTE this is not the final message from the compiler-thread... return; } var hasError = evtData.isError; var grammarParser = evtData.def; compileParserModuleFunc(grammarParser, hasError); }); return taskId; } }; //extend/overload sync-compiler with async-compiler: return extend({}, pegjsGen, pegjsAsyncGen); });