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 /** 29 * Dependencies: 30 * 31 * * parser.element (parserModule.js) 32 * * OPTIONALLY: ANTLR TokenStream (antlr3-all.js) 33 * (if present, the constructor may be able to automatically derive start/end properties from given argument) 34 * 35 * 36 * @requires antlr3-all.js as <code>org</code> (see comment above) 37 * 38 */ 39 40 define(['parserModule'], 41 //this comment is needed by jsdoc2 [copy of comment for: function ParsingResult(...] 42 /** 43 * ParsingResult represents an element that was detected during parsing. 44 * 45 * <p> 46 * The detected element is referenced by the properties <code>start</code> and <code>end</code> 47 * that refer to the start-index and end-index within the parsed text. 48 * 49 * <p> 50 * The ParsingResult has a <code>type</code> property which refers to the kind of element 51 * that was detected (see constants in {@link mmir.parser.element}). 52 * 53 * <p> 54 * In addition, the ParsingResult may have several properties that depend of its type. In general, 55 * these properties refer to detected parts of the element (e.g. for a invocation-statement, these 56 * may refer to its arguments). 57 * 58 * 59 * <p> 60 * Properties for <strong>INCLUDE_SCRIPT</strong> type: 61 * <ul> 62 * <li><strong>scriptPath</strong>: the path / URL to the resource</li> 63 * <li><strong>scriptPathType</strong>: the type of the <tt>scriptPath</tt> 64 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 65 * </ul> 66 * <p> 67 * Properties for <strong>INCLUDE_STYLE</strong> type: 68 * <ul> 69 * <li><strong>stylePath</strong>: </li> 70 * <li><strong>stylePathType</strong>: the type of the <tt>stylePath</tt> 71 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 72 * </ul> 73 * <p> 74 * Properties for <strong>LOCALIZE</strong> type: 75 * <ul> 76 * <li><strong>name</strong>: the name/identifier for the localized String</li> 77 * <li><strong>nameType</strong>: the type of the <tt>name</tt> 78 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 79 * </ul> 80 * <p> 81 * Properties for <strong>YIELD_DECLARATION</strong> type: 82 * <ul> 83 * <li><strong>name</strong>: the name/identifier for the yield section</li> 84 * <li><strong>nameType</strong>: the type of the <tt>name</tt> 85 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 86 * </ul> 87 * Properties for <strong>BLOCK</strong> type: 88 * <ul> 89 * <li><strong>scriptContent</strong> {String}: <tt>OPTIONALLY</tt> the script code as a String</li> 90 * <li><strong>scriptEval</strong> {Function}: the compiled script code in form of a function. The 91 * function takes one argument: the current data-object.</li> 92 * </ul> 93 * <p> 94 * Properties for <strong>STATEMENT</strong> type: 95 * <ul> 96 * <li><strong>scriptContent</strong> {String}: <tt>OPTIONALLY</tt> the script code as a String</li> 97 * <li><strong>scriptEval</strong> {Function}: the compiled script code in form of a function. The 98 * function takes one argument: the current data-object.</li> 99 * </ul> 100 * <p> 101 * Properties for <strong>HELPER</strong> type: 102 * <ul> 103 * <li><strong>helper</strong>: the name of the helper function</li> 104 * <li><strong>helperType</strong>: the type of the <tt>helper</tt> 105 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 106 * <li><strong>argsEval</strong> {Function}: OPTIONALLY compiled getter Function for retrieving the current ARGS 107 * (optional argument) of the helper expression. The function takes one argument: the current data-object.</li> 108 * </ul> 109 * <p> 110 * Properties for <strong>IF</strong> type: 111 * <ul> 112 * <li><strong>ifEval</strong> {Function}: the condition statement, that was compiled into a Function. The 113 * function takes one argument: the current data-object.</li> 114 * <li><strong>content</strong> {ContentElement}: the HTML / template content that should be render, in case the 115 * if-expression evaluates to <code>true</code>.</li> 116 * <li><strong>elseContent</strong> {@link mmir.parser.ParsingResult}: OPTIONALLY a ParsingResult 117 * representing an else-expression, see {@link mmir.parser.element.ELSE}.</li> 118 * </ul> 119 * <p> 120 * Properties for <strong>ELSE</strong> type: 121 * <ul> 122 * <li><strong>content</strong> {ContentElement}: the HTML / template content that should be render, in case the 123 * if-expression (to which the else-expression belongs) evaluates to <code>false</code>.</li> 124 * </ul> 125 * <p> 126 * Properties for <strong>FOR</strong> type: 127 * <ul> 128 * <li><strong>forControlType</strong> {String}: the type of for-loop, either <code>FORITER</code> or <code>FORSTEP</code></li> 129 * <li><strong>forInitEval</strong> {Function}: the initialization statement of the for-expression, compiled into 130 * a Function. The function takes one argument: the current data-object.</li> 131 * 132 * <li><code>FORITER</code>: <code>@for(PROP in OBJ){ ... }@</code> 133 * <ul> 134 * <li><strong>forIterator</strong> {Object}: an iterator object with functions <code>hasNext() : Boolean</code> and 135 * <code>next() : String</code> (which returns the name of the property currently iterated).</li> 136 * <li><strong>forPropName</strong> {String}: the variable name for the property which is currently iterated over.</li> 137 * </ul> 138 * </li> 139 * <li><code>FORSTEP</code>: <code>@for(INIT; CONDITION; INCREMENT){ ... }@</code> 140 * <ul> 141 * <li><strong>forConditionEval</strong> {Function}: the condition statement of the for-expression, compiled into 142 * a Function. The function takes one argument: the current data-object.</li> 143 * <li><strong>forIncrementEval</strong> {Function}: the increment statement of the for-expression, compiled into 144 * a Function. The function takes one argument: the current data-object.</li> 145 * </ul> 146 * </li> 147 * <li><strong>content</strong> {ContentElement}: the HTML / template content that should be rendered 148 * during each iteration of the for-loop.</li> 149 * </ul> 150 * <p> 151 * Properties for <strong>RENDER</strong> type: 152 * <ul> 153 * <li><strong>partial</strong>: the name of the partial view</li> 154 * <li><strong>partialType</strong>: the type of the <tt>partial</tt> 155 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 156 * <li><strong>controller</strong>: the name of the controller, to which the partial view definition belongs</li> 157 * <li><strong>controllerType</strong>: the type of the <tt>controller</tt> 158 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 159 * <li><strong>argsEval</strong> {Function}: OPTIONALLY compiled getter Function for retrieving the current ARGS 160 * (optional argument) of the render expression. The function takes one argument: the current data-object.</li> 161 * </ul> 162 * <p> 163 * Properties for <strong>ESCAPE_ENTER</strong> type: 164 * <ul> 165 * <li><strong>text</strong> {String}: the text that will be rendered (i.e. without the escape-character(s) itself).</li> 166 * </ul> 167 * <p> 168 * Properties for <strong>ESCAPE_EXIT</strong> type: 169 * <ul> 170 * <li><strong>text</strong> {String}: the text that will be rendered (i.e. without the escape-character(s) itself).</li> 171 * </ul> 172 * <p> 173 * Properties for <strong>VAR_DECLARATION</strong> type: 174 * <ul> 175 * <li><strong>name</strong>: the name for the variable (without the leading <tt>@</tt> of template variables)</li> 176 * <li><strong>nameType</strong>: the type of the <tt>name</tt> field: <code>StringLiteral</code></li> 177 * </ul> 178 * 179 * <p> 180 * 181 * @param {org.antlr.runtime.CommonTokenStream|org.antlr.runtime.Token} [thetokens] OPTIONAL 182 * if <code>org.antlr.runtime.CommonTokenStream</code>: 183 * the TokenStream that corresponds to this parsed element; 184 * when provided, the TokenStream is used to set the start- and end- 185 * property of the new instance.<br> 186 * if <code>org.antlr.runtime.Token</code>: 187 * if the parameter is a single Token object, then the start- and end- 188 * property for the new instance is set by this token object 189 * @class 190 * @name ParsingResult 191 * @memberOf mmir.parser 192 */ 193 function(parser){ 194 //set to @ignore in order to avoid doc-duplication in jsdoc3 195 /** 196 * @ignore 197 * 198 * ParsingResult represents an element that was detected during parsing. 199 * 200 * <p> 201 * The detected element is referenced by the properties <code>start</code> and <code>end</code> 202 * that refer to the start-index and end-index within the parsed text. 203 * 204 * <p> 205 * The ParsingResult has a <code>type</code> property which refers to the kind of element 206 * that was detected (see constants in {@link mmir.parser.element}). 207 * 208 * <p> 209 * In addition, the ParsingResult may have several properties that depend of its type. In general, 210 * these properties refer to detected parts of the element (e.g. for a invocation-statement, these 211 * may refer to its arguments). 212 * 213 * 214 * <p> 215 * Properties for <strong>INCLUDE_SCRIPT</strong> type: 216 * <ul> 217 * <li><strong>scriptPath</strong>: the path / URL to the resource</li> 218 * <li><strong>scriptPathType</strong>: the type of the <tt>scriptPath</tt> 219 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 220 * </ul> 221 * <p> 222 * Properties for <strong>INCLUDE_STYLE</strong> type: 223 * <ul> 224 * <li><strong>stylePath</strong>: </li> 225 * <li><strong>stylePathType</strong>: the type of the <tt>stylePath</tt> 226 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 227 * </ul> 228 * <p> 229 * Properties for <strong>LOCALIZE</strong> type: 230 * <ul> 231 * <li><strong>name</strong>: the name/identifier for the localized String</li> 232 * <li><strong>nameType</strong>: the type of the <tt>name</tt> 233 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 234 * </ul> 235 * <p> 236 * Properties for <strong>YIELD_DECLARATION</strong> type: 237 * <ul> 238 * <li><strong>name</strong>: the name/identifier for the yield section</li> 239 * <li><strong>nameType</strong>: the type of the <tt>name</tt> 240 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 241 * </ul> 242 * Properties for <strong>BLOCK</strong> type: 243 * <ul> 244 * <li><strong>scriptContent</strong> {String}: <tt>OPTIONALLY</tt> the script code as a String</li> 245 * <li><strong>scriptEval</strong> {Function}: the compiled script code in form of a function. The 246 * function takes one argument: the current data-object.</li> 247 * </ul> 248 * <p> 249 * Properties for <strong>STATEMENT</strong> type: 250 * <ul> 251 * <li><strong>scriptContent</strong> {String}: <tt>OPTIONALLY</tt> the script code as a String</li> 252 * <li><strong>scriptEval</strong> {Function}: the compiled script code in form of a function. The 253 * function takes one argument: the current data-object.</li> 254 * </ul> 255 * <p> 256 * Properties for <strong>HELPER</strong> type: 257 * <ul> 258 * <li><strong>helper</strong>: the name of the helper function</li> 259 * <li><strong>helperType</strong>: the type of the <tt>helper</tt> 260 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 261 * <li><strong>argsEval</strong> {Function}: OPTIONALLY compiled getter Function for retrieving the current ARGS 262 * (optional argument) of the helper expression. The function takes one argument: the current data-object.</li> 263 * </ul> 264 * <p> 265 * Properties for <strong>IF</strong> type: 266 * <ul> 267 * <li><strong>ifEval</strong> {Function}: the condition statement, that was compiled into a Function. The 268 * function takes one argument: the current data-object.</li> 269 * <li><strong>content</strong> {ContentElement}: the HTML / template content that should be render, in case the 270 * if-expression evaluates to <code>true</code>.</li> 271 * <li><strong>elseContent</strong> {@link mmir.parser.ParsingResult}: OPTIONALLY a ParsingResult 272 * representing an else-expression, see {@link mmir.parser.element.ELSE}.</li> 273 * </ul> 274 * <p> 275 * Properties for <strong>ELSE</strong> type: 276 * <ul> 277 * <li><strong>content</strong> {ContentElement}: the HTML / template content that should be render, in case the 278 * if-expression (to which the else-expression belongs) evaluates to <code>false</code>.</li> 279 * </ul> 280 * <p> 281 * Properties for <strong>FOR</strong> type: 282 * <ul> 283 * <li><strong>forControlType</strong> {String}: the type of for-loop, either <code>FORITER</code> or <code>FORSTEP</code></li> 284 * <li><strong>forInitEval</strong> {Function}: the initialization statement of the for-expression, compiled into 285 * a Function. The function takes one argument: the current data-object.</li> 286 * 287 * <li><code>FORITER</code>: <code>@for(PROP in OBJ){ ... }@</code> 288 * <ul> 289 * <li><strong>forIterator</strong> {Object}: an iterator object with functions <code>hasNext() : Boolean</code> and 290 * <code>next() : String</code> (which returns the name of the property currently iterated).</li> 291 * <li><strong>forPropName</strong> {String}: the variable name for the property which is currently iterated over.</li> 292 * </ul> 293 * </li> 294 * <li><code>FORSTEP</code>: <code>@for(INIT; CONDITION; INCREMENT){ ... }@</code> 295 * <ul> 296 * <li><strong>forConditionEval</strong> {Function}: the condition statement of the for-expression, compiled into 297 * a Function. The function takes one argument: the current data-object.</li> 298 * <li><strong>forIncrementEval</strong> {Function}: the increment statement of the for-expression, compiled into 299 * a Function. The function takes one argument: the current data-object.</li> 300 * </ul> 301 * </li> 302 * <li><strong>content</strong> {ContentElement}: the HTML / template content that should be rendered 303 * during each iteration of the for-loop.</li> 304 * </ul> 305 * <p> 306 * Properties for <strong>RENDER</strong> type: 307 * <ul> 308 * <li><strong>partial</strong>: the name of the partial view</li> 309 * <li><strong>partialType</strong>: the type of the <tt>partial</tt> 310 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 311 * <li><strong>controller</strong>: the name of the controller, to which the partial view definition belongs</li> 312 * <li><strong>controllerType</strong>: the type of the <tt>controller</tt> 313 * field: one of <code>StringLiteral</code>, <code>Identifier</code>, <code>IdentifierNameAmpersatStart</code></li> 314 * <li><strong>argsEval</strong> {Function}: OPTIONALLY compiled getter Function for retrieving the current ARGS 315 * (optional argument) of the render expression. The function takes one argument: the current data-object.</li> 316 * </ul> 317 * <p> 318 * Properties for <strong>ESCAPE_ENTER</strong> type: 319 * <ul> 320 * <li><strong>text</strong> {String}: the text that will be rendered (i.e. without the escape-character(s) itself).</li> 321 * </ul> 322 * <p> 323 * Properties for <strong>ESCAPE_EXIT</strong> type: 324 * <ul> 325 * <li><strong>text</strong> {String}: the text that will be rendered (i.e. without the escape-character(s) itself).</li> 326 * </ul> 327 * <p> 328 * Properties for <strong>VAR_DECLARATION</strong> type: 329 * <ul> 330 * <li><strong>name</strong>: the name for the variable (without the leading <tt>@</tt> of template variables)</li> 331 * <li><strong>nameType</strong>: the type of the <tt>name</tt> field: <code>StringLiteral</code></li> 332 * </ul> 333 * 334 * <p> 335 * 336 * @constructs ParsingResult 337 * @param {org.antlr.runtime.CommonTokenStream|org.antlr.runtime.Token} [thetokens] OPTIONAL 338 * if <code>org.antlr.runtime.CommonTokenStream</code>: 339 * the TokenStream that corresponds to this parsed element; 340 * when provided, the TokenStream is used to set the start- and end- 341 * property of the new instance.<br> 342 * if <code>org.antlr.runtime.Token</code>: 343 * if the parameter is a single Token object, then the start- and end- 344 * property for the new instance is set by this token object 345 * 346 */ 347 function ParsingResult (thetokens){ 348 var isSet = false; 349 350 //try to extract start-/end-indexes from the argument: 351 if(thetokens){ 352 353 if(typeof org !== 'undefined'){ 354 //NOTE: must invoke getTokens() for initializing size() etc.! 355 if(thetokens instanceof org.antlr.runtime.CommonTokenStream && thetokens.getTokens() && thetokens.size() > 0){ 356 this.start = thetokens.getTokens()[0].getStartIndex(); 357 this.end = thetokens.getTokens()[thetokens.size()-1].getStopIndex(); 358 359 isSet = true; 360 } 361 else if(thetokens instanceof org.antlr.runtime.CommonToken || thetokens instanceof org.antlr.runtime.Token){ 362 this.start = thetokens.getStartIndex(); 363 this.end = thetokens.getStopIndex(); 364 365 isSet = true; 366 } 367 } 368 369 //if not already set, try... 370 if( isSet === false && typeof thetokens.getToken !== 'undefined' && (typeof thetokens.getToken().getStartIndex !== 'undefined' && typeof thetokens.getToken().getStopIndex !== 'undefined')){ 371 this.start = thetokens.getToken().getStartIndex(); 372 this.end = thetokens.getToken().getStopIndex(); 373 374 isSet = true; 375 } 376 else if(typeof thetokens.getStartIndex !== 'undefined' && typeof thetokens.getStopIndex !== 'undefined'){ 377 this.start = thetokens.getStartIndex(); 378 this.end = thetokens.getStopIndex(); 379 380 isSet = true; 381 } 382 else if(isSet === false) { 383 var type = Object.prototype.toString.call(thetokens);//.match(/^\[object (.*)\]$/)[1]; 384 console.warn('unknown argument type: '+type);//debug 385 } 386 } 387 388 if(isSet === false) { 389 this.start = -1; 390 this.end = -1; 391 } 392 }; 393 394 /** 395 * Set the start position (index) for this parsed element with regard to the TokenStream of the complete input. 396 * 397 * @function 398 * @param {org.antlr.runtime.CommonTokenStream} thetokens (optional) the TokenStream that corresponds to this parsed element; 399 * when provided, the TokenStream is used to set the start-property of this object. 400 * 401 * @public 402 */ 403 ParsingResult.prototype.setStartFrom = function(thetokens){ 404 //NOTE: must invoke getTokens() for initializing size() etc.! 405 if(thetokens.getTokens() && thetokens.size() > 0){ 406 this.start = thetokens.getTokens()[0].getStartIndex(); 407 } 408 else { 409 this.start = -1; 410 } 411 }; 412 413 /** 414 * Set the end position (index) for this parsed element with regard to the TokenStream of the complete input. 415 * 416 * @function 417 * @param {org.antlr.runtime.CommonTokenStream} thetokens (optional) the TokenStream that corresponds to this parsed element; 418 * when provided, the TokenStream is used to set the end-property of this object. 419 * 420 * @public 421 * @alias mmir.parser.ParsingResult 422 */ 423 ParsingResult.prototype.setEndFrom = function(thetokens){ 424 //NOTE: must invoke getTokens() for initializing size() etc.! 425 if(thetokens.getTokens() && thetokens.size() > 0){ 426 this.end = thetokens.getTokens()[thetokens.size()-1].getStopIndex(); 427 } 428 else { 429 this.end = -1; 430 } 431 }; 432 ParsingResult.prototype.getStart = function(){ 433 return this.start; 434 }; 435 ParsingResult.prototype.getEnd = function(){ 436 return this.end; 437 }; 438 439 /** 440 * Get the type of this parsed element, i.e. as which type this element was parsed. 441 * 442 * The type corresponds to one of the type defined in {mmir.parser.element}. 443 * 444 * @function 445 * @return {mmir.parser.element} the type for this ParsingResult 446 * 447 * @public 448 */ 449 ParsingResult.prototype.getType = function(){ 450 return this.type; 451 }; 452 453 //helper function for converting properties to the correct value. 454 // By default, the ParsingResult only contains "raw" property values. 455 // Which properties are available, depends on the type of the ParsingResult (see templateProcessor.js) 456 ParsingResult.prototype.getValue = function(rawPropertyValue, proptertyType, data){ 457 458 if(proptertyType === 'StringLiteral'){ 459 return rawPropertyValue.substring(1, rawPropertyValue.length-1); 460 } 461 else if(proptertyType === 'Identifier'){ 462 if(data){ 463 return data['@' + rawPropertyValue]; 464 } 465 else { 466 //just return variable name 467 return rawPropertyValue; 468 } 469 } 470 else if(proptertyType === 'IdentifierNameAmpersatStart'){ 471 if(data){ 472 return data[rawPropertyValue]; 473 } 474 else { 475 //just return variable name, but remove leading @: 476 return rawPropertyValue.substring(1); 477 } 478 } 479 else if(proptertyType === 'OBJECT'){ 480 return rawPropertyValue;//TODO 481 } 482 else if(proptertyType === 'DecimalLiteral'){ 483 return parseFloat(rawPropertyValue); 484 } 485 // else if(typeof proptertyType === 'undefined'){ 486 // return rawPropertyValue; 487 // } 488 else 489 return rawPropertyValue; 490 }; 491 492 ParsingResult.prototype.hasVarReferences = function(){ 493 return false;//TODO implement this 494 }; 495 496 ParsingResult.prototype.isScriptTag = function(){ 497 if( parser.element.INCLUDE_SCRIPT === this.getType() ){ 498 return true; 499 } 500 return false; 501 }; 502 503 ParsingResult.prototype.isStyleTag = function(){ 504 if( parser.element.INCLUDE_STYLE === this.getType() ){ 505 return true; 506 } 507 return false; 508 }; 509 510 ParsingResult.prototype.isLocalize = function(){ 511 if( parser.element.LOCALIZE === this.getType() ){ 512 return true; 513 } 514 return false; 515 }; 516 517 ParsingResult.prototype.isYield = function(){ 518 if( parser.element.YIELD_DECLARATION === this.getType() ){ 519 return true; 520 } 521 return false; 522 }; 523 524 ParsingResult.prototype.isYieldContent = function(){ 525 if( parser.element.YIELD_CONTENT === this.getType() ){ 526 return true; 527 } 528 return false; 529 }; 530 531 ParsingResult.prototype.isScriptBlock = function(){ 532 if( parser.element.BLOCK === this.getType() ){ 533 return true; 534 } 535 return false; 536 }; 537 538 ParsingResult.prototype.isScriptStatement = function(){ 539 if( parser.element.STATEMENT === this.getType() ){ 540 return true; 541 } 542 return false; 543 }; 544 545 ParsingResult.prototype.isHelper = function(){ 546 if( parser.element.HELPER === this.getType() ){ 547 return true; 548 } 549 return false; 550 }; 551 552 ParsingResult.prototype.isIf = function(){ 553 if( parser.element.IF === this.getType() ){ 554 return true; 555 } 556 return false; 557 }; 558 559 ParsingResult.prototype.hasElse = function(){ 560 if(this.isIf() && typeof this.elseContent != 'undefined'){ 561 return true; 562 } 563 return false; 564 }; 565 566 ParsingResult.prototype.isElse = function(){ 567 if( parser.element.ELSE === this.getType() ){ 568 return true; 569 } 570 return false; 571 }; 572 573 ParsingResult.prototype.isFor = function(){ 574 if( parser.element.FOR === this.getType() ){ 575 return true; 576 } 577 return false; 578 }; 579 580 ParsingResult.prototype.isRender = function(){ 581 if( parser.element.RENDER === this.getType() ){ 582 return true; 583 } 584 return false; 585 }; 586 587 ParsingResult.prototype.isEscapeEnter = function(){ 588 if( parser.element.ESCAPE_ENTER === this.getType() ){ 589 return true; 590 } 591 return false; 592 }; 593 594 ParsingResult.prototype.isEscapeExit = function(){ 595 if( parser.element.ESCAPE_EXIT === this.getType() ){ 596 return true; 597 } 598 return false; 599 }; 600 601 ParsingResult.prototype.isEscape = function(){ 602 return this.isEscapeEnter() || this.isEscapeExit(); 603 }; 604 605 /** 606 * WARNING: do use sparingly -- an invocation triggers a list evaluation. 607 * 608 * @returns {String} a String representation (name) for this ParsingResult's type 609 * 610 * @see #getType 611 */ 612 ParsingResult.prototype.getTypeName = function(){ 613 614 if(this.typeName){ 615 return this.typeName;/////////////////// EARLY EXIT ////////////////////////// 616 } 617 618 for(var prop in parser.element){ 619 if(parser.element.hasOwnProperty(prop) && parser.element[prop] === this.getType()){ 620 this.typeName = prop; 621 return prop;/////////////////// EARLY EXIT ////////////////////////// 622 } 623 } 624 625 return void(0); 626 }; 627 628 ParsingResult.prototype.hasCallData = function(){ 629 return typeof this.dataPos !== 'undefined'; 630 }; 631 632 ParsingResult.prototype.getCallDataStart = function(){ 633 return this.dataPos.start; 634 }; 635 636 ParsingResult.prototype.getCallDataEnd = function(){ 637 return this.dataPos.end; 638 }; 639 640 ParsingResult.prototype.getCallDataType = function(){ 641 return this.dataType; 642 }; 643 644 ParsingResult.prototype.stringify = function(){ 645 646 //TODO use constants for lists 647 648 //typed properties: 649 // for each typed properties '<prop>' there is an additional property with name '<prop>Type' 650 // (both of these properties are Strings themselves) 651 var typedPropList = [ 652 'scriptPath', 653 'stylePath', 654 'name', 655 'helper', 656 'partial', 657 'controller' 658 ]; 659 660 //primitive-type properties: 661 // write values 'as is' for these properties 662 var propList = [ 663 'start', 664 'end', 665 'type', 666 'dataType', 667 'text', 668 'forControlType', 669 'forPropName' 670 ]; 671 672 //"stringify-able" object properties: 673 var strPropList = [ 674 'content', 675 'elseContent' 676 ]; 677 678 //function properties: 679 var funcPropList = [ 680 'scriptEval', 681 'argsEval', 682 'ifEval', 683 'forInitEval', 684 'forIterator', 685 'forConditionEval', 686 'forIncrementEval' 687 ]; 688 689 //default function properties: 690 // these functions from the prototype may have been overwritten 691 // -> if one is overwritten, i.e. not the default implementation, then store that one too 692 var overwrittenFuncPropList = [ 693 'getEnd', 694 'getStart', 695 'getType', 696 'getValue', 697 'getTypeName', 698 'getCallDataStart', 699 'getCallDataEnd', 700 'getCallDataType' 701 ]; 702 703 //function for iterating over the property-list and generating JSON-like entries in the string-buffer 704 var appendStringified = parser.appendStringified; 705 706 var sb = ['require("storageUtils").restoreObject({ classConstructor: "parsingResult"', ',']; 707 708 //TODO property dataPos: {start: Number, end: Number} 709 if(this['dataPos']){ 710 sb.push( 'dataPos:{start:' ); 711 sb.push( this.dataPos.start ); 712 sb.push( ',end:' ); 713 sb.push( this.dataPos.end ); 714 sb.push( '}' ); 715 //NOTE: need to add comma in a separate entry 716 // (-> in order to not break the removal method of last comma, see below) 717 sb.push( ',' ); 718 } 719 720 721 appendStringified(this, typedPropList, sb); 722 appendStringified(this, typedPropList, sb, 'Type'); 723 appendStringified(this, propList, sb); 724 //non-primitives with stringify() function: 725 appendStringified(this, strPropList, sb, null, function stringifyableExtractor(name, value){ 726 return value.stringify(); 727 }); 728 //function definitions 729 appendStringified(this, funcPropList, sb, null, function functionExtractor(name, value){ 730 return value.toString(); 731 }); 732 //add "overwritten" function definitions 733 appendStringified(this, overwrittenFuncPropList, sb, null, function nonDefaultFunctionExtractor(name, value){ 734 var instanceImpl = value.toString(); 735 var defaultImpl = ParsingResult.prototype[name].toString(); 736 if(instanceImpl !== defaultImpl){ 737 return instanceImpl; 738 } 739 //DEFAULT: return void (will omit this from storage -> use default impl. of the prototype) 740 return; 741 }); 742 743 //if last element is a comma, remove it 744 if(sb[sb.length - 1] === ','){ 745 sb.splice( sb.length - 1, 1); 746 } 747 748 sb.push(' })'); 749 return sb.join(''); 750 }; 751 752 parser.ParsingResult = ParsingResult; 753 754 return parser.ParsingResult; 755 756 });//END: define(..., function(){