1 /*
  2  * 	Copyright (C) 2012-2013 DFKI GmbH
  3  * 	Deutsches Forschungszentrum fuer Kuenstliche Intelligenz
  4  * 	German Research Center for Artificial Intelligence
  5  * 	http://www.dfki.de
  6  * 
  7  * 	Permission is hereby granted, free of charge, to any person obtaining a 
  8  * 	copy of this software and associated documentation files (the 
  9  * 	"Software"), to deal in the Software without restriction, including 
 10  * 	without limitation the rights to use, copy, modify, merge, publish, 
 11  * 	distribute, sublicense, and/or sell copies of the Software, and to 
 12  * 	permit persons to whom the Software is furnished to do so, subject to 
 13  * 	the following conditions:
 14  * 
 15  * 	The above copyright notice and this permission notice shall be included 
 16  * 	in all copies or substantial portions of the Software.
 17  * 
 18  * 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 19  * 	OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 20  * 	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 21  * 	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 22  * 	CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 23  * 	TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 24  * 	SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 25  */
 26 
 27 	
 28 define([	  'core', 'commonUtils', 'parserModule', 'parsingResult'
 29         	, 'ES3Lexer', 'ES3Parser', 'contentLexer', 'contentParser'
 30         	, 'scriptLexer', 'scriptParser', 'antlr3'
 31         ],
 32         /**
 33          * Main implementation for parsing (view) templates.
 34          * 
 35          * @class
 36          * @name TemplateProcessor
 37          * @memberOf mmir.parser
 38          * @static
 39          * @public
 40          * 
 41          * @depends ParserUtils#printInfo ("hidden" dependency when printing log-messages; accessed through the passed-in theLexerInstance)
 42          */
 43         function ( 
 44         	  mmir, commonUtils, parser, ParsingResult
 45         	, ES3Lexer, ES3Parser, MmirScriptContentLexer, MmirScriptContentParser
 46         	, MmirScriptLexer, MmirScriptParser, org
 47 ){//hidden dependency: templateParserUtils (for parser.printInfo)
 48 
 49 		//TODO move to separate file (extension-file):
 50 		//START extensions
 51 		/**
 52 		 * @memberOf ES3Parser.prototype
 53 		 */
 54 		ES3Parser.prototype.getVarReferences = function(){
 55 			
 56 			var size = this.ampersatIdentifiers.length;
 57 			
 58 			if(size === 0){
 59 				return null;
 60 			}
 61 			
 62 			var varRefs = new Array(size);
 63 			for(var i=0; i < size; ++i){
 64 				var ref = this.ampersatIdentifiers[i];
 65 				
 66 				var refObj = new ParsingResult(ref);
 67 	//			refObj.start = ref.start;
 68 				
 69 				//correct end-position (token's stop-index is exactly the last char-index, whereas ParsingResult's end-position is token.stopIndex + 1)
 70 				refObj.end = refObj.getEnd() + 1;
 71 				
 72 				refObj.type = parser.element.VAR_REFERENCE;
 73 				
 74 				varRefs[i] = refObj;
 75 			}
 76 			return varRefs;
 77 		};
 78 		//END extensions
 79 	
 80 		
 81 		/**
 82 		 * @type TemplateParser
 83 		 * @memberOf mmir.parser.TemplateProcessor#
 84 		 */
 85 		var parserModule = parser;
 86 		
 87 		/**
 88 		 * "Processor" for the template parse-results:
 89 		 * 
 90 		 * This function is used by the generated (antlr) parsers.
 91 		 * 
 92 		 * @memberOf mmir.parser.TemplateProcessor#
 93 		 * @constructor
 94 		 * @ignore
 95 		 */
 96 		function _extend(theLexerInstance) {
 97 
 98 			/** @scope mmir.parser.TemplateProcessor.prototype */
 99 			
100 			
101 			/**
102 			 * @type Number
103 			 * @private
104 			 * @memberOf mmir.parser.TemplateProcessor#
105 			 */
106 			var INTERNAL_INCLUDE_SCRIPT 				= parser.element.INCLUDE_SCRIPT;
107 			theLexerInstance.INTERNAL_INCLUDE_SCRIPT 	= INTERNAL_INCLUDE_SCRIPT;
108 			/**
109 			 * @type Number
110 			 * @private
111 			 * @memberOf mmir.parser.TemplateProcessor#
112 			 */
113 			var INTERNAL_INCLUDE_STYLE 					= parser.element.INCLUDE_STYLE;
114 			theLexerInstance.INTERNAL_INCLUDE_STYLE 	= INTERNAL_INCLUDE_STYLE;
115 			/**
116 			 * @type Number
117 			 * @private
118 			 * @memberOf mmir.parser.TemplateProcessor#
119 			 */
120 			var INTERNAL_LOCALIZE 						= parser.element.LOCALIZE;
121 			theLexerInstance.INTERNAL_LOCALIZE 			= INTERNAL_LOCALIZE;
122 			/**
123 			 * @type Number
124 			 * @private
125 			 * @memberOf mmir.parser.TemplateProcessor#
126 			 */
127 			var INTERNAL_YIELD_DECLARATION 				= parser.element.YIELD_DECLARATION;
128 			theLexerInstance.INTERNAL_YIELD_DECLARATION = INTERNAL_YIELD_DECLARATION;
129 			/**
130 			 * @type Number
131 			 * @private
132 			 * @memberOf mmir.parser.TemplateProcessor#
133 			 */
134 			var INTERNAL_YIELD_CONTENT 					= parser.element.YIELD_CONTENT;
135 			theLexerInstance.INTERNAL_YIELD_CONTENT 	= INTERNAL_YIELD_CONTENT;
136 			/**
137 			 * @type Number
138 			 * @private
139 			 * @memberOf mmir.parser.TemplateProcessor#
140 			 */
141 			var INTERNAL_BLOCK 							= parser.element.BLOCK;
142 			theLexerInstance.INTERNAL_BLOCK 			= INTERNAL_BLOCK;
143 			/**
144 			 * @type Number
145 			 * @private
146 			 * @memberOf mmir.parser.TemplateProcessor#
147 			 */
148 			var INTERNAL_STATEMENT 						= parser.element.STATEMENT;
149 			theLexerInstance.INTERNAL_STATEMENT 		= INTERNAL_STATEMENT;
150 			/**
151 			 * @type Number
152 			 * @private
153 			 * @memberOf mmir.parser.TemplateProcessor#
154 			 */
155 			var INTERNAL_HELPER 						= parser.element.HELPER;
156 			theLexerInstance.INTERNAL_HELPER 			= INTERNAL_HELPER;
157 			/**
158 			 * @type Number
159 			 * @private
160 			 * @memberOf mmir.parser.TemplateProcessor#
161 			 */
162 			var INTERNAL_IF 							= parser.element.IF;
163 			theLexerInstance.INTERNAL_IF 				= INTERNAL_IF;
164 			/**
165 			 * @type Number
166 			 * @private
167 			 * @memberOf mmir.parser.TemplateProcessor#
168 			 */
169 			var INTERNAL_ELSE 							= parser.element.ELSE;
170 			theLexerInstance.INTERNAL_ELSE 				= INTERNAL_ELSE;
171 			/**
172 			 * @type Number
173 			 * @private
174 			 * @memberOf mmir.parser.TemplateProcessor#
175 			 */
176 			var INTERNAL_FOR 				= parser.element.FOR;
177 			theLexerInstance.INTERNAL_FOR 				= INTERNAL_FOR;
178 			/**
179 			 * @type Number
180 			 * @private
181 			 * @memberOf mmir.parser.TemplateProcessor#
182 			 */
183 			var INTERNAL_RENDER 						= parser.element.RENDER;
184 			theLexerInstance.INTERNAL_RENDER 			= INTERNAL_RENDER;
185 			/**
186 			 * @type Number
187 			 * @private
188 			 * @memberOf mmir.parser.TemplateProcessor#
189 			 */
190 			var INTERNAL_ESCAPE_ENTER					= parser.element.ESCAPE_ENTER;
191 			theLexerInstance.INTERNAL_ESCAPE_ENTER		= INTERNAL_ESCAPE_ENTER;
192 			/**
193 			 * @type Number
194 			 * @private
195 			 * @memberOf mmir.parser.TemplateProcessor#
196 			 */
197 			var INTERNAL_ESCAPE_EXIT 					= parser.element.ESCAPE_EXIT;
198 			theLexerInstance.INTERNAL_ESCAPE_EXIT 		= INTERNAL_ESCAPE_EXIT;
199 
200 			/**
201 			 * @type Number
202 			 * @private
203 			 * @memberOf mmir.parser.TemplateProcessor#
204 			 */
205 			var INTERNAL_FOR_TYPE_ITER					= parser.element.FOR_TYPE_ITER;
206 			theLexerInstance.INTERNAL_FOR_TYPE_ITER		= INTERNAL_FOR_TYPE_ITER;
207 			/**
208 			 * @type Number
209 			 * @private
210 			 * @memberOf mmir.parser.TemplateProcessor#
211 			 */
212 			var INTERNAL_FOR_TYPE_STEP					= parser.element.FOR_TYPE_STEP;
213 			theLexerInstance.INTERNAL_FOR_TYPE_STEP		= INTERNAL_FOR_TYPE_STEP;
214 
215 			/**
216 			 * @type Number
217 			 * @private
218 			 * @memberOf mmir.parser.TemplateProcessor#
219 			 */
220 			var INTERNAL_VAR_DECLARATION   = parser.element.VAR_DECLARATION;
221 			theLexerInstance.INTERNAL_VAR_DECLARATION   = INTERNAL_VAR_DECLARATION;
222 			/**
223 			 * @type Number
224 			 * @private
225 			 * @memberOf mmir.parser.TemplateProcessor#
226 			 */
227 			var INTERNAL_VAR_REFERENCE    				 = parser.element.VAR_REFERENCE;
228 			theLexerInstance.INTERNAL_VAR_REFERENCE     = INTERNAL_VAR_REFERENCE;
229 
230 			/**
231 			 * @type Number
232 			 * @private
233 			 * @memberOf mmir.parser.TemplateProcessor#
234 			 */
235 			var INTERNAL_COMMENT         				  = parser.element.COMMENT;
236 			theLexerInstance.INTERNAL_COMMENT           = INTERNAL_COMMENT;
237 
238 			/**
239 			 * @type Number
240 			 * @private
241 			 * @memberOf mmir.parser.TemplateProcessor#
242 			 */
243 			//"shortcut" for accessing the IF-type
244 			var IF_TYPE = theLexerInstance.INTERNAL_IF;
245 
246 			//internal "static" definitions for parsing mode/type
247 
248 			/**
249 			 * @private  
250 			 * @memberOf mmir.parser.TemplateProcessor#
251 			 */
252 			var PARSER_SCRIPT_BLOCK 				= 0;
253 			theLexerInstance.PARSER_SCRIPT_BLOCK 	= PARSER_SCRIPT_BLOCK;
254 			/**
255 			 * @private
256 			 * @memberOf mmir.parser.TemplateProcessor#
257 			 */
258 			var PARSER_SCRIPT_STATMENT 				= 2;
259 			theLexerInstance.PARSER_SCRIPT_STATMENT = PARSER_SCRIPT_STATMENT;
260 			/**
261 			 * @private
262 			 * @memberOf mmir.parser.TemplateProcessor#
263 			 */
264 			var PARSER_SCRIPT_CONTENT 				= 4;
265 			theLexerInstance.PARSER_SCRIPT_CONTENT 	= PARSER_SCRIPT_CONTENT;
266 			/**
267 			 * @private
268 			 * @memberOf mmir.parser.TemplateProcessor#
269 			 */
270 			var PARSER_JS_CODE	 					= 8;
271 			theLexerInstance.PARSER_JS_CODE	 		= PARSER_JS_CODE;
272 
273 
274 			/**
275 			 * @private
276 			 * @memberOf mmir.parser.TemplateProcessor#
277 			 */
278 			var isDebug = true;
279 			theLexerInstance.isDebug = isDebug;
280 
281 
282 			/**
283 			 * @private
284 			 * @memberOf mmir.parser.TemplateProcessor#
285 			 */
286 			var SCRIPT_CHANNEL = 1;
287 			theLexerInstance.SCRIPT_CHANNEL = SCRIPT_CHANNEL;
288 			//theLexerInstance.nesting = 0;
289 			
290 
291 			/**
292 			 * @private
293 			 * @memberOf mmir.parser.TemplateProcessor#
294 			 */
295 			theLexerInstance.scriptBlocks = new Array();
296 			/**
297 			 * @private
298 			 * @memberOf mmir.parser.TemplateProcessor#
299 			 */
300 			theLexerInstance.scriptStatements = new Array();
301 			/**
302 			 * @private
303 			 * @memberOf mmir.parser.TemplateProcessor#
304 			 */
305 			theLexerInstance.includeScripts = new Array();
306 			/**
307 			 * @private
308 			 * @memberOf mmir.parser.TemplateProcessor#
309 			 */
310 			theLexerInstance.includeStyles = new Array();
311 			/**
312 			 * @private
313 			 * @memberOf mmir.parser.TemplateProcessor#
314 			 */
315 			theLexerInstance.locales = new Array();
316 			/**
317 			 * @private
318 			 * @memberOf mmir.parser.TemplateProcessor#
319 			 */
320 			theLexerInstance.helpers = new Array();
321 			/**
322 			 * @private
323 			 * @memberOf mmir.parser.TemplateProcessor#
324 			 */
325 			theLexerInstance.renderPartials = new Array();
326 
327 			/**
328 			 * @private
329 			 * @memberOf mmir.parser.TemplateProcessor#
330 			 */
331 			theLexerInstance.escape = new Array();
332 
333 			/**
334 			 * @private
335 			 * @memberOf mmir.parser.TemplateProcessor#
336 			 */
337 			theLexerInstance.ifs = new Array();
338 			/**
339 			 * @private
340 			 * @memberOf mmir.parser.TemplateProcessor#
341 			 */
342 			theLexerInstance.fors = new Array();
343 
344 			/**
345 			 * @private
346 			 * @memberOf mmir.parser.TemplateProcessor#
347 			 */
348 			theLexerInstance.yields = new Array();
349 			/**
350 			 * @private
351 			 * @memberOf mmir.parser.TemplateProcessor#
352 			 */
353 			theLexerInstance.yieldContents = new Array();
354 
355 			/**
356 			 * @private
357 			 * @memberOf mmir.parser.TemplateProcessor#
358 			 */
359 			theLexerInstance.vars = new Array();
360 			/**
361 			 * @private
362 			 * @memberOf mmir.parser.TemplateProcessor#
363 			 */
364 			theLexerInstance.comments = new Array();
365 
366 			/**
367 			 * @private
368 			 * @memberOf mmir.parser.TemplateProcessor#
369 			 */
370 			theLexerInstance.lastParsedElement =  null;
371 			
372 			/**
373 			 * @function
374 			 * @private
375 			 * @memberOf mmir.parser.TemplateProcessor#
376 			 */
377 			var isArray = commonUtils.isArray;
378 			
379 			/**
380 			 * @param tokenType
381 			 * @param parser
382 			 * 
383 			 * @private
384 			 * @memberOf mmir.parser.TemplateProcessor#
385 			 */
386 			var getTokenName = (function(){
387 				
388 				var _jsTokens = null;
389 				
390 				return function getTokenNameImpl(tokenType, parser){
391 			
392 					if(!_jsTokens){
393 						_jsTokens = parser.getTokenNames();
394 					}
395 					return _jsTokens[tokenType];
396 				};
397 				
398 			})();
399 			//theLexerInstance.getTokenName = getTokenName;
400 			
401 			/**
402 			 * @private
403 			 * @memberOf mmir.parser.TemplateProcessor#
404 			 */
405 			function getFirstChild(treeNode, strChildType, parser){
406 				var type = getTokenName(treeNode.getType(), parser);
407 				if(type === strChildType){
408 					return treeNode;
409 				}
410 				else {
411 					if(treeNode.getChildCount() === 0){
412 						return null;
413 					}
414 					else {
415 						for(var i = 0, size = treeNode.getChildCount(); i < size; ++i){
416 							var result = getFirstChild(treeNode.getChild(i), strChildType, parser);
417 							if(result !== null){
418 								return result;
419 							}
420 						}
421 						return null;
422 					}
423 				}
424 			}
425 			
426 			/**
427 			 * @private
428 			 * @memberOf mmir.parser.TemplateProcessor#
429 			 */
430 			function extractBoundries(subTree, buffer){
431 				
432 				var start = subTree.getToken().getStartIndex();
433 				if(typeof start === 'number' && start !== -1){
434 					if(!buffer){
435 						buffer ={
436 								start: null,
437 								stop: null
438 						};
439 					}
440 					
441 					if(buffer.start == null || start < buffer.start){
442 						buffer.start = start;
443 					}
444 					var end = subTree.getToken().getStopIndex();
445 					if(buffer.end == null || end > buffer.end){
446 						buffer.end = end;
447 					}
448 				}
449 				
450 				if(subTree.getChildCount() === 0){
451 					return buffer;
452 				}
453 				else {
454 					for(var i = 0, size = subTree.getChildCount(); i < size; ++i){
455 						buffer = extractBoundries(subTree.getChild(i), buffer);
456 					}
457 					return buffer;
458 				}
459 			}
460 			
461 			/**
462 			 * @private
463 			 * @memberOf mmir.parser.TemplateProcessor#
464 			 */
465 			function getBoundries(treeNode){
466 				
467 				return {
468 					start : treeNode.getToken().getStartIndex(),
469 					end   : treeNode.stopIndex +1
470 				};
471 			}
472 			
473 			/**
474 			 * @private
475 			 * @memberOf mmir.parser.TemplateProcessor#
476 			 */
477 			function getStringFor(boundriesObj, tokens, offset){
478 				
479 				if(!boundriesObj){
480 					return '';
481 				}
482 				
483 				var start = boundriesObj.start - offset;
484 				var end = boundriesObj.end - offset;  
485 				return tokens.toString().substring(start,end+1);
486 				
487 			}
488 			/**
489 			 * @private
490 			 * @memberOf mmir.parser.TemplateProcessor#
491 			 */
492 			function getStringForSubTree(treeNode, tokens, offset){
493 				
494 				var start = treeNode.getToken().getStartIndex() - offset;
495 				var end = treeNode.stopIndex - offset;  
496 				return tokens.toString().substring(start,end+1);
497 				
498 			}
499 			
500 			/**
501 			 * @private
502 			 * @memberOf mmir.parser.TemplateProcessor#
503 			 */
504 			function createJSObjectFrom(parseElement, parentObject, parser){
505 				
506 				var type = getTokenName(parseElement.getType(), parser);
507 				if('StringLiteral' === type){
508 					var str = parseElement.getText();
509 					return str.substring(1,str.length - 1);
510 				}
511 				else if ( 'NAMEDVALUE' === type ){
512 					
513 					var name = createJSObjectFrom(parseElement.getChild(0), null, parser);
514 					
515 					var value = createJSObjectFrom(parseElement.getChild(1), null, parser);
516 					
517 					if(!parentObject){
518 						parentObject = new Object();
519 					}
520 					
521 					parentObject[name] = value;
522 					
523 					return parentObject;
524 				}
525 				else if ( 'OBJECT' === type ){
526 				
527 					var theValue = new Object();
528 					var current = null;
529 					
530 					for(var data_index = 0, data_size = parseElement.getChildCount(); data_index < data_size; ++ data_index){
531 						current = parseElement.getChild(data_index);
532 						theValue = createJSObjectFrom(current, theValue, parser);
533 					}
534 					return theValue;
535 				}
536 				else if ( 'ARRAY' === type ){
537 					
538 					var array_size = parseElement.getChildCount();
539 					var theValue = new Array();
540 					var current = null;
541 					
542 					for(var array_index = 0; array_index < array_size; ++ array_index){
543 						current = parseElement.getChild(array_index);
544 						theValue[array_index] = createJSObjectFrom(current.getChild(0), theValue, parser);
545 					}
546 					return theValue;
547 				}
548 				else {
549 					return parseElement.getText();
550 				}
551 			}
552 			//theLexerInstance.createJSObjectFrom = createJSObjectFrom;
553 			
554 			/**
555 			 * @private
556 			 * @memberOf mmir.parser.TemplateProcessor#
557 			 */
558 			function processBlock(parsingObj, result, tokens){
559 			
560 				parsingObj.scriptContent = result;
561 				
562 				if(!parsingObj.scriptContent){
563 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - BLOCK] WARNING: ','invalid "script block" at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
564 					return;
565 				}
566 				
567 				theLexerInstance.scriptBlocks.push(parsingObj);
568 				
569 			}
570 			theLexerInstance.processBlock = processBlock;
571 			
572 			/**
573 			 * @private
574 			 * @memberOf mmir.parser.TemplateProcessor#
575 			 */
576 			function processStatement(parsingObj, result, tokens){
577 			
578 				parsingObj.scriptContent = result;
579 				
580 				if(!parsingObj.scriptContent){
581 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - STATEMENT] WARNING: ','invalid "script statement" at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
582 					return;
583 				}
584 				
585 				theLexerInstance.scriptStatements.push(parsingObj);
586 				
587 			}
588 			theLexerInstance.processStatement = processStatement;
589 			
590 			/**
591 			 * @private
592 			 * @memberOf mmir.parser.TemplateProcessor#
593 			 */
594 			function processIncludeScript (parsingObj, result, tokens, parser){
595 			
596 				var tree = result.tree;
597 				var offset = tokens.tokens[0].getStartIndex();
598 				
599 				parsingObj.scriptPathType = getTokenName( tree.getChild(0).getType(), parser);
600 				parsingObj.scriptPath = getStringForSubTree(tree.getChild(0), tokens, offset);//createJSObjectFrom(tree.getChild(0), null, parser );
601 				
602 				if(!parsingObj.scriptPath){
603 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - SCRIPT LINK] WARNING: ','invalid "include script statement" at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
604 					return;
605 				}
606 				
607 				theLexerInstance.includeScripts.push(parsingObj);
608 				
609 			}
610 			theLexerInstance.processIncludeScript = processIncludeScript;
611 			
612 			/**
613 			 * @private
614 			 * @memberOf mmir.parser.TemplateProcessor#
615 			 */
616 			function processIncludeStyle(parsingObj, result, tokens, parser){
617 			
618 				var tree = result.tree;
619 				var offset = tokens.tokens[0].getStartIndex();
620 				
621 				parsingObj.stylePathType = getTokenName( tree.getChild(0).getType(), parser);
622 				parsingObj.stylePath = getStringForSubTree(tree.getChild(0), tokens, offset);//createJSObjectFrom(tree.getChild(0), null, parser );
623 				
624 				if(!parsingObj.stylePath){
625 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - STYLE LINK] WARNING: ','invalid "include style statement" at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
626 					return;
627 				}
628 				
629 				theLexerInstance.includeStyles.push(parsingObj);
630 				
631 			}
632 			theLexerInstance.processIncludeStyle = processIncludeStyle;
633 			
634 			/**
635 			 * @private
636 			 * @memberOf mmir.parser.TemplateProcessor#
637 			 */
638 			function processLocalize(parsingObj, result, tokens, parser){
639 			
640 				var tree = result.tree;
641 				var offset = tokens.tokens[0].getStartIndex();
642 				
643 				parsingObj.nameType = getTokenName( tree.getChild(0).getType(), parser);
644 				parsingObj.name = getStringForSubTree(tree.getChild(0), tokens, offset);//createJSObjectFrom(tree.getChild(0), null, parser );
645 				
646 				if(!parsingObj.name || parsingObj.name.length === 0){
647 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - LOCALIZE] WARNING: ','invalid "localize statement" at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
648 					return;
649 				}
650 				
651 				theLexerInstance.locales.push(parsingObj);
652 				
653 			}
654 			theLexerInstance.processLocalize = processLocalize;
655 			
656 			/**
657 			 * @private
658 			 * @memberOf mmir.parser.TemplateProcessor#
659 			 */
660 			function processDeclareVar(parsingObj, result, tokens, parser){
661 				
662 				var tree = result.tree;
663 				var offset = tokens.tokens[0].getStartIndex();
664 				
665 				parsingObj.nameType = getTokenName( tree.getChild(0).getType(), parser);
666 				parsingObj.name = getStringForSubTree(tree.getChild(0), tokens, offset);//createJSObjectFrom(tree.getChild(0), null, parser );
667 				
668 				if(!parsingObj.name || parsingObj.name.length === 0){
669 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - VAR DECLARATION] WARNING: ','invalid "var declaration statement" at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
670 					return;
671 				}
672 				
673 				theLexerInstance.vars.push(parsingObj);
674 				
675 			}
676 			theLexerInstance.processDeclareVar = processDeclareVar;
677 			
678 			/**
679 			 * @private
680 			 * @memberOf mmir.parser.TemplateProcessor#
681 			 */
682 			function processHelperFunction(parsingObj, result, tokens, parser){
683 			
684 				var tree = result.tree;
685 				var offset = tokens.tokens[0].getStartIndex();
686 				
687 				parsingObj.helperType = getTokenName( tree.getChild(0).getType(), parser);
688 //				parsingObj.helper = createJSObjectFrom(tree.getChild(0), null, parser );
689 				parsingObj.helper = getStringForSubTree(tree.getChild(0), tokens, offset);
690 				
691 				if(tree.getChildCount() === 2){
692 					parsingObj.dataType = getTokenName( tree.getChild(1).getType(), parser);
693 //					var param = null;
694 //					if('OBJECT' === parsingObj.dataType){
695 //						param = new Object();
696 //					}
697 //					parsingObj.dataArg = createJSObjectFrom(tree.getChild(1), param, parser );
698 					
699 					parsingObj.dataPos = getBoundries(tree.getChild(1));
700 					
701 				}
702 				
703 				if(!parsingObj.helper || parsingObj.helper.length === 0){
704 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - HELPER CALL] WARNING: ','invalid "helper function statement" at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
705 					return;
706 				}
707 				
708 				theLexerInstance.helpers.push(parsingObj);
709 				
710 			}
711 			theLexerInstance.processHelperFunction = processHelperFunction;
712 			
713 			/**
714 			 * @private
715 			 * @memberOf mmir.parser.TemplateProcessor#
716 			 */
717 			function processRenderPartial(parsingObj, result, tokens, parser){
718 			
719 				//parsingObj.controllerName = result.controller;
720 				//parsingObj.partialName = result.partial;
721 				//parsingObj.arguments = result.arguments;
722 				
723 						
724 				var tree = result.tree;
725 				var offset = tokens.tokens[0].getStartIndex();
726 				
727 				parsingObj.controllerType = getTokenName( tree.getChild(0).getType(), parser);
728 //				parsingObj.controller = createJSObjectFrom(tree.getChild(0), null, parser );
729 				parsingObj.controller = getStringForSubTree(tree.getChild(0), tokens, offset);
730 				
731 				parsingObj.partialType = getTokenName( tree.getChild(1).getType(), parser);
732 //				parsingObj.partial = createJSObjectFrom(tree.getChild(1), null, parser );
733 				parsingObj.partial = getStringForSubTree(tree.getChild(1), tokens, offset);
734 				
735 				if(tree.getChildCount() === 3){
736 					parsingObj.dataType = getTokenName( tree.getChild(2).getType(), parser);
737 //					var param = null;
738 //					if('OBJECT' === parsingObj.dataType){
739 //						param = new Object();
740 //					}
741 //					parsingObj.dataArg = createJSObjectFrom(tree.getChild(2), param, parser );
742 					
743 //					parsingObj.dataArg = getStringForSubTree(tree.getChild(2), tokens, offset);
744 					parsingObj.dataPos = getBoundries(tree.getChild(2));
745 					
746 				}
747 				
748 				if(false){//!parsingObj.partialName || parsingObj.partialName.length === 0){ TODO implement check
749 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - RENDER PARTIAL] WARNING: ','invalid "render partial statement" at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
750 					return;
751 				}
752 				
753 				theLexerInstance.renderPartials.push(parsingObj);
754 				
755 			}
756 			theLexerInstance.processRenderPartial = processRenderPartial;
757 			
758 			/**
759 			 * @private
760 			 * @memberOf mmir.parser.TemplateProcessor#
761 			 */
762 			function processYieldDeclaration(parsingObj, result, tokens, parser){
763 			
764 				var tree = result.tree;
765 				var offset = tokens.tokens[0].getStartIndex();
766 				
767 				parsingObj.nameType = getTokenName( tree.getChild(0).getType(), parser);
768 				parsingObj.name = getStringForSubTree(tree.getChild(0), tokens, offset);//createJSObjectFrom(tree.getChild(0), null, parser );
769 				
770 				if(!parsingObj.name || parsingObj.name.length === 0){
771 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - YIELD DECLARATION] WARNING: ','invalid "yield declaration" at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
772 					return;
773 				}
774 				
775 				theLexerInstance.yields.push(parsingObj);
776 				
777 			}
778 			theLexerInstance.processYieldDeclaration = processYieldDeclaration;
779 
780 			/**
781 			 * @private
782 			 * @memberOf mmir.parser.TemplateProcessor#
783 			 */
784 			function processYieldContentParam (parsingObj, result, tokens, parser){
785 			
786 				var tree = result.tree;
787 				var offset = tokens.tokens[0].getStartIndex();
788 				
789 				parsingObj.nameType = getTokenName( tree.getChild(0).getType(), parser);
790 				parsingObj.name = getStringForSubTree(tree.getChild(0), tokens, offset);//createJSObjectFrom(tree.getChild(0), null, parser );
791 				parsingObj.contentOffset = parsingObj.end + 1 + 2;// +2:  "){"
792 				
793 				if(!parsingObj.name){
794 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - YIELD CONTENT PARAMETER] WARNING: ','invalid "content for specification" (missing name) at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
795 					return;
796 				}
797 			}
798 			theLexerInstance.processYieldContentParam = processYieldContentParam;
799 			
800 			/**
801 			 * @private
802 			 * @memberOf mmir.parser.TemplateProcessor#
803 			 */
804 			function processYieldContent (parsingObj, result, tokens){
805 			
806 				parsingObj.content = result;
807 				
808 				if(!parsingObj.content){
809 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - YIELD CONTENT] WARNING: ','invalid "content for specification" (missing content) at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
810 					return;
811 				}
812 				
813 				theLexerInstance.yieldContents.push(parsingObj);
814 				
815 			}
816 			theLexerInstance.processYieldContent = processYieldContent;
817 			
818 			/**
819 			 * @private
820 			 * @memberOf mmir.parser.TemplateProcessor#
821 			 */
822 			function processIfExpr (parsingObj, result, tokens, parser){
823 			
824 				//TODO validate expr! (e.g. detect assignments to undeclared variables...)
825 //				var tree = result.tree;
826 //				parsingObj.exprType = getTokenName( tree.getChild(0).getType(), parser);
827 //				parsingObj.expr = createJSObjectFrom(tree.getChild(0), null, parser );
828 				parsingObj.contentOffset = parsingObj.end + 1 + 2;// +2:  "){"
829 
830 //				var lastElem = theLexerInstance.lastParsedElement;
831 				parsingObj.ifExpr = tokens.toString();
832 				
833 				if(!parsingObj.ifExpr){
834 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - IF EXPR] WARNING: ','invalid "if statement" (missing expression) at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
835 					return;
836 				}
837 			}
838 			theLexerInstance.processIfExpr = processIfExpr;
839 			
840 			/**
841 			 * @private
842 			 * @memberOf mmir.parser.TemplateProcessor#
843 			 */
844 			function processIfContent (parsingObj, result, tokens){
845 			
846 				parsingObj.content = result;
847 				
848 				if(!parsingObj.content){
849 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - IF CONTENT] WARNING: ','invalid "if statement" (missing content) at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
850 					return;
851 				}
852 				
853 				theLexerInstance.ifs.push(parsingObj);
854 				
855 			}
856 			theLexerInstance.processIfContent = processIfContent;
857 			
858 			/**
859 			 * @private
860 			 * @memberOf mmir.parser.TemplateProcessor#
861 			 */
862 			function processElse (parsingObj, result, tokens){
863 			
864 				parsingObj.content = result;
865 				
866 				if(!parsingObj.content){
867 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - ELSE CONTENT] WARNING: ','invalid "else statement" (missing content) at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
868 					return;
869 				}
870 				
871 				parsingObj.contentOffset = parsingObj.start + 1;// +1:  "{"
872 				
873 				var lastElem = theLexerInstance.lastParsedElement;
874 				if(lastElem.type !== IF_TYPE){
875 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - ELSE CONTENT] WARNING: ','invalid "else statement" (missing content) at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
876 					
877 					throw new org.antlr.runtime.NoViableAltException('invalid else statement: missing preceeding IF!', -1, -1, tokens);
878 				}
879 				
880 				var lastIf = theLexerInstance.ifs[theLexerInstance.ifs.length-1];
881 				if(lastIf.elseContent){
882 					
883 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - ELSE CONTENT] WARNING: ','invalid "else statement" (ELSE already defined) at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
884 					
885 					throw new org.antlr.runtime.NoViableAltException('invalid else statement: too many ELSE definitions - ELSE clause is already defined!', -1, -1, tokens);
886 				}
887 				
888 				lastIf.elseContent = parsingObj;
889 				//redefine getEnd of the if-element: use end of else-statement
890 				lastIf.getEnd = function(){
891 					return this.elseContent.getEnd();
892 				};
893 			}
894 			theLexerInstance.processElse = processElse;
895 			
896 			/**
897 			 * @private
898 			 * @memberOf mmir.parser.TemplateProcessor#
899 			 */
900 			function processForControl (parsingObj, result, tokens, parser){
901 			
902 				//TODO validate expr! (e.g. detect assignments to undeclared variables...)
903 				var tree = result.tree;
904 				var offset = tokens.tokens[0].getStartIndex();
905 				
906 				parsingObj.forControlType = getTokenName( tree.getChild(0).getType(), parser);
907 				//parsingObj.forControl = createJSObjectFrom(tree.getChild(0), null, parser );
908 				
909 				parsingObj.contentOffset =  parsingObj.end + 1 + 2;// +2:  "){"
910 				
911 //				parsingObj.forControl = tokens.toString();
912 				
913 				if(parsingObj.forControlType === 'FORITER'){
914 //					parsingObj.forIterationExpr = getFirstChild(tree.getChild(0).getChild(0), 'Identifier', parser).toString();
915 //					parsingObj.forObjectExpr    = getFirstChild(tree.getChild(0).getChild(1), 'Identifier', parser).toString();
916 					parsingObj.forControlVarPos = parser.getVarReferences();
917 					parsingObj.forControlPos  = extractBoundries(tree.getChild(0));
918 				}
919 				else {
920 					//-> type is 'FORSTEP'
921 					parsingObj.forInitExpr      = getStringFor( extractBoundries(tree.getChild(0).getChild(0)), tokens, offset);
922 					parsingObj.forConditionExpr = getStringFor( extractBoundries(tree.getChild(0).getChild(1)), tokens, offset);
923 					parsingObj.forIncrementExpr = getStringFor( extractBoundries(tree.getChild(0).getChild(2)), tokens, offset);
924 				}
925 				
926 //				if(!parsingObj.expr){
927 //					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - FOR EXPR] WARNING: ','invalid "for statement" (missing control statement) at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
928 //					return;
929 //				}
930 			}
931 			theLexerInstance.processForControl = processForControl;
932 			
933 			/**
934 			 * @private
935 			 * @memberOf mmir.parser.TemplateProcessor#
936 			 */
937 			function processForContent (parsingObj, result, tokens){
938 			
939 				parsingObj.content = result;
940 				
941 				if(!parsingObj.content){
942 					if(theLexerInstance.isDebug) parser.parserPrintWarning('[TemplateProcessor - FOR CONTENT] WARNING: ','invalid "for statement" (missing content) at ['+parsingObj.start+','+parsingObj.end+'] -> "'+theLexerInstance.input.data.substring(parsingObj.start,parsingObj.end)+'"');//debug
943 					return;
944 				}
945 				
946 				theLexerInstance.fors.push(parsingObj);
947 				
948 			}
949 			theLexerInstance.processForContent = processForContent;
950 			
951 			/**
952 			 * @private
953 			 * @memberOf mmir.parser.TemplateProcessor#
954 			 */
955 			function getLexerFor(self, parserType, input){
956 				if(self.PARSER_SCRIPT_BLOCK === parserType){
957 					var scriptLexer = new MmirScriptLexer(input);
958 					scriptLexer.setBlockMode();
959 					return scriptLexer;
960 				}
961 				else if(self.PARSER_SCRIPT_STATEMENT === parserType){
962 					var scriptLexer = new MmirScriptLexer(input);
963 					scriptLexer.setStatementMode();
964 					return scriptLexer;
965 				}
966 				else if(self.PARSER_SCRIPT_CONTENT === parserType){
967 					return new MmirScriptContentLexer(input);
968 				}
969 				else if(self.PARSER_JS_CODE === parserType){
970 					return new ES3Lexer(input);
971 				}
972 				parser.parserPrintWarning('[TemplateProcessor - creating Lexer] WARNING: ','getLexerFor unkonwn parser type '+parserType);
973 				return null;
974 			};
975 			
976 			/**
977 			 * @private
978 			 * @memberOf mmir.parser.TemplateProcessor#
979 			 */
980 			function getParserFor(self, parserType, tokens){
981 				if(self.PARSER_SCRIPT_BLOCK === parserType){
982 					return new MmirScriptParser(tokens);
983 				}
984 				else if(self.PARSER_SCRIPT_STATEMENT === parserType){
985 					return new MmirScriptParser(tokens);
986 				}
987 				else if(self.PARSER_SCRIPT_CONTENT === parserType){
988 					return new MmirScriptContentParser(tokens);
989 				}
990 				else if(self.PARSER_JS_CODE === parserType){
991 					return new ES3Parser(tokens);
992 				}
993 				parser.parserPrintWarning('[TemplateProcessor - creating parser] WARNING: ','getParserFor unkonwn parser type '+parserType);
994 				return null;
995 			};
996 			
997 			/**
998 			 * @private
999 			 * @memberOf mmir.parser.TemplateProcessor#
1000 			 */
1001 			function doEnter(parserType, self, currentChannel, entryFunc, processFunc, parseResultObject, msg){
1002 				
1003 				if(!entryFunc){
1004 					entryFunc = 'main';
1005 				}
1006 				
1007 				if(!parseResultObject){
1008 					parseResultObject = null;
1009 					if(typeof processFunc !== 'function'){
1010 						msg = processFunc;
1011 						processFunc = null;
1012 					}
1013 				}
1014 				if(!msg){
1015 					msg = '';
1016 				}
1017 				
1018 				if(self.isDebug) theLexerInstance.printDebug('enter embedded '+msg);//debug
1019 				
1020 				var lexer = getLexerFor(self, parserType, self.input);
1021 
1022 				lexer.isDebug = self.isDebug;
1023 				var tokens = new org.antlr.runtime.CommonTokenStream(lexer);
1024 				
1025 				
1026 				var result;
1027 				if(parseResultObject){
1028 					result = parseResultObject;
1029 					result.setEndFrom(tokens);
1030 				}
1031 				else {
1032 					result = new ParsingResult(tokens);
1033 				}
1034 				
1035 				if(self.isDebug){//debug
1036 					//alert(msg+'\n'+JSON.stringify(result));
1037 					var start = result.start;//tokens.getTokens()[0].getStartIndex();
1038 					var end = result.end;//tokens.getTokens()[tokens.size()-1].getStopIndex();
1039 					
1040 					theLexerInstance.printInfo(msg+'_tokens('+start+'->'+end+')',tokens);
1041 				}
1042 				
1043 				var parser = getParserFor(self, parserType, tokens);
1044 				
1045 				parser.isDebug = self.isDebug;
1046 				var parseResult = parser[entryFunc]();
1047 						
1048 				if(self.isDebug) theLexerInstance.printDebug(msg+'.'+entryFunc+'() result: >'+parseResult+'<');//debug
1049 				
1050 				if(result.rawResult){
1051 					if(isArray(result.rawResult)){
1052 						result.rawResult.push(rawResults);
1053 					}
1054 					else {
1055 						var rawResults = new Array(2);
1056 						rawResults[0] = result.rawResult;
1057 						rawResults[1] = parseResult;
1058 						result.rawResult = rawResults;
1059 					}
1060 				}
1061 				else {
1062 					result.rawResult = parseResult;
1063 				}
1064 				
1065 				if(parserType === self.PARSER_JS_CODE){
1066 					var varRefs = parser.getVarReferences();
1067 					if(varRefs){
1068 						if(result.varReferences){
1069 							result.varReferences = result.varReferences.concat(varRefs);
1070 						}
1071 						else{
1072 							result.varReferences = varRefs;
1073 						}
1074 					}
1075 				}
1076 				
1077 				if(typeof processFunc === 'function'){
1078 					processFunc(result, parseResult, tokens, parser);
1079 				}
1080 				
1081 				//FIXME NOOP? currentChannel is a function argument...
1082 				
1083 				// returns a SCRIPT token to the java parser but on a
1084 				// different channel than the normal token stream so it
1085 				// doesn't get in the way.
1086 				currentChannel = theLexerInstance.SCRIPT_CHANNEL;
1087 				
1088 				theLexerInstance.lastParsedElement = result;
1089 				
1090 				return result;
1091 			};
1092 			
1093 			/**
1094 			 * @private
1095 			 * @memberOf mmir.parser.TemplateProcessor#
1096 			 */
1097 			function processEscape(replacementText, msg){
1098 				
1099 				if(msg && typeof self !== 'undefined' && self.isDebug){//debug
1100 					theLexerInstance.printInfo(msg);
1101 				}
1102 				
1103 				var result = new ParsingResult(null);
1104 				result.text = replacementText;
1105 				this.escape.push(result);
1106 						
1107 				return result;
1108 			};
1109 			theLexerInstance.processEscape = processEscape; 
1110 			
1111 			/**
1112 			 * @private
1113 			 * @memberOf mmir.parser.TemplateProcessor#
1114 			 */
1115 			function processComment(msg){
1116 				
1117 				if(msg && typeof self !== 'undefined' && self.isDebug){//debug
1118 					theLexerInstance.printInfo(msg);
1119 				}
1120 				
1121 				var result = new ParsingResult(null);
1122 				this.comments.push(result);
1123 						
1124 				return result;
1125 			};
1126 			theLexerInstance.processComment = processComment;
1127 			
1128 			/**
1129 			 * @private
1130 			 * @memberOf mmir.parser.TemplateProcessor#
1131 			 */
1132 			function enterBlock(currentChannel, entryFunc, processFunc, msg, parseResultObject){
1133 				return doEnter(theLexerInstance.PARSER_SCRIPT_BLOCK, theLexerInstance, currentChannel, entryFunc, processFunc, parseResultObject, msg);
1134 			};
1135 			theLexerInstance.enterBlock = enterBlock;
1136 			
1137 			/**
1138 			 * @private
1139 			 * @memberOf mmir.parser.TemplateProcessor#
1140 			 */
1141 			function enterScript(currentChannel, entryFunc, processFunc, msg, parseResultObject){
1142 				return doEnter(theLexerInstance.PARSER_SCRIPT_STATEMENT, theLexerInstance, currentChannel, entryFunc, processFunc, parseResultObject, msg);
1143 			};
1144 			theLexerInstance.enterScript = enterScript;
1145 			
1146 			/**
1147 			 * @private
1148 			 * @memberOf mmir.parser.TemplateProcessor#
1149 			 */
1150 			function enterContent(currentChannel, entryFunc, processFunc, msg, parseResultObject){
1151 				return doEnter(theLexerInstance.PARSER_SCRIPT_CONTENT, theLexerInstance, currentChannel, entryFunc, processFunc, parseResultObject, msg);
1152 			};
1153 			theLexerInstance.enterContent = enterContent;
1154 			
1155 			/**
1156 			 * @private
1157 			 * @memberOf mmir.parser.TemplateProcessor#
1158 			 */
1159 			function enterJavaScript(currentChannel, entryFunc, processFunc, msg, parseResultObject){
1160 				return doEnter(theLexerInstance.PARSER_JS_CODE, theLexerInstance, currentChannel, entryFunc, processFunc, parseResultObject, msg);
1161 			};
1162 			theLexerInstance.enterJavaScript = enterJavaScript; 
1163 			
1164 		};//END: extendMmirTemplateProcessor(){
1165 		
1166 		parser.extendMmirTemplateProcessor = _extend;
1167 		
1168 		
1169 		return _extend;
1170 		
1171 	});//END: define
1172 	
1173 
1174