Source: mvc/parser/templateParseUtils.js

  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. * A Utility class for parsing (eHTML) templates.<br>
  28. *
  29. * @class ParserUtils
  30. *
  31. * @see mmir.parser.ParserUtils#constructor
  32. *
  33. * @example mmir.ParserUtils.parse(str, view)
  34. */
  35. //mmir.parser.ParserUtils = (function(){});
  36. //(function ( mmir ) {
  37. define([ 'mmirf/parserModule','mmirf/parsingResult','mmirf/templateProcessor'
  38. ,'mmirf/templateLexer','mmirf/ES3Lexer','mmirf/ES3Parser','mmirf/contentLexer','mmirf/contentParser'
  39. ,'mmirf/scriptLexer','mmirf/scriptParser','mmirf/antlr3'
  40. ],
  41. /**
  42. * Utility functions for parsing templates (and template elements, e.g. JS-parts of template expressions)
  43. *
  44. * @class
  45. * @name ParserUtils
  46. * @memberOf mmir.parser
  47. * @static
  48. *
  49. * @public
  50. */
  51. function( parser, ParsingResult, templateProcessor
  52. , MmirTemplateLexer, ES3Lexer, ES3Parser, MmirScriptContentLexer, MmirScriptContentParser
  53. , MmirScriptLexer, MmirScriptParser, org
  54. ){
  55. /**
  56. * add extend-function for MmirTemplateLexer objects:
  57. * attaches the main processing functionality for parsing the template files
  58. *
  59. * (NOTE the extend-function is called in the constructor, see MmirTemplate.g and MmirTemplateLexer.js)
  60. *
  61. * @type Function
  62. * @memberOf MmirTemplateLexer.prototype
  63. */
  64. MmirTemplateLexer.__mmirExtend = templateProcessor;
  65. /**
  66. * @memberOf ES3Parser.prototype
  67. */
  68. ES3Parser.prototype.getVarReferences = function(){
  69. var size = this.ampersatIdentifiers.length;
  70. if(size === 0){
  71. return null;
  72. }
  73. var varRefs = new Array(size);
  74. for(var i=0; i < size; ++i){
  75. var ref = this.ampersatIdentifiers[i];
  76. var refObj = new ParsingResult(ref);
  77. // refObj.start = ref.start;
  78. //correct end-position (token's stop-index is exactly the last char-index, whereas ParsingResult's end-position is token.stopIndex + 1)
  79. refObj.end = refObj.getEnd() + 1;
  80. refObj.type = parser.element.VAR_REFERENCE;
  81. varRefs[i] = refObj;
  82. }
  83. return varRefs;
  84. };
  85. ////////////////////////////////////helper for debugging / printing error details ////////////////////////
  86. /**
  87. * -2: internal debug
  88. * -1: interanl info
  89. * 0: debug
  90. * 1: info
  91. * 2: warn
  92. * 3: error
  93. * TODO make this set-able (export getter/setter? use configurationManager?)
  94. *
  95. * @private
  96. * @memberOf ParserUtils#
  97. */
  98. var errorLevel = 2;
  99. /**
  100. * HELPER print internal debug messages during parsing (VERY VERBOSE)
  101. *
  102. * @private
  103. * @memberOf ParserUtils#
  104. */
  105. function _print(msg){//FIXME
  106. if ( errorLevel <= -2 ) console.log(msg);
  107. };
  108. parser.print = _print;
  109. /**
  110. * HELPER print internal, informational messages during parsing (VERBOSE)
  111. *
  112. * @private
  113. * @memberOf ParserUtils#
  114. */
  115. function _printInfo(prefix, msg){//FIXME
  116. if ( errorLevel <= -1 ) console.info(parser.parserCreatePrintMessage(prefix,msg));
  117. };
  118. parser.printInfo = _printInfo;
  119. /**
  120. * HELPER print debug messages during parsing
  121. *
  122. * @private
  123. * @memberOf ParserUtils#
  124. */
  125. function _parserPrintDebug(prefix, msg, source){//FIXME
  126. if ( errorLevel <= 0 ) console.debug(parser.parserCreatePrintMessage(prefix,msg, source));
  127. };
  128. parser.parserPrintDebug = _parserPrintDebug;
  129. /**
  130. * HELPER print informational messages during parsing
  131. *
  132. * @private
  133. * @memberOf ParserUtils#
  134. */
  135. function _parserPrintInfo(prefix, msg, source){//FIXME
  136. if ( errorLevel <= 1 ) console.info(parser.parserCreatePrintMessage(prefix,msg, source));
  137. };
  138. parser.parserPrintInfo = _parserPrintInfo;
  139. /**
  140. * HELPER print warnings during parsing
  141. *
  142. * @private
  143. * @memberOf ParserUtils#
  144. */
  145. function _parserPrintWarning(prefix, msg, source){//FIXME
  146. if ( errorLevel <= 2 ) console.warn(parser.parserCreatePrintMessage(prefix,msg, source));
  147. };
  148. parser.parserPrintWarning = _parserPrintWarning;
  149. /**
  150. * HELPER print errors during parsing
  151. *
  152. * @private
  153. * @memberOf ParserUtils#
  154. */
  155. function _parserPrintError(prefix, msg, source){
  156. if ( errorLevel <= 3 ) console.error(parser.parserCreatePrintMessage(prefix,msg, source));
  157. };
  158. parser.parserPrintError = _parserPrintError;
  159. /**
  160. * HELPER: attach internal print-functions to all classes (ie. prototypes) in the list
  161. *
  162. * @private
  163. * @memberOf ParserUtils#
  164. */
  165. var _attachInternalPrintFunc = function(list){
  166. var _prototype;
  167. for(var i=0, size=list.length; i < size; ++i){
  168. _prototype = list[i].prototype;
  169. _prototype.printInfo = parser.printInfo;
  170. _prototype.printDebug = parser.print;
  171. }
  172. };
  173. //attach the internal debug/print functions to all lexers/parsers:
  174. // (-> see import-list in define() above)
  175. _attachInternalPrintFunc([
  176. MmirTemplateLexer, ES3Lexer, ES3Parser, MmirScriptContentLexer, MmirScriptContentParser
  177. , MmirScriptLexer, MmirScriptParser
  178. ]);
  179. /**
  180. * @type View
  181. * @private
  182. * @memberOf ParserUtils#
  183. */
  184. var _currentParsedView = null;//FIXME make this an argument in the printXXX functions (e.g. the current mechanism will not work, if templates are parsed concurrently/in parallel/using threads)
  185. /**
  186. * Creates a message with parsing-information.
  187. *
  188. * In case the <code>msg</code> is an error message containing relative/incorrect location information,
  189. * an heuristic will be used to fix the location information; in addition the references location
  190. * will be extracted from the source-String and a "pointer-String" will be generated, e.g.
  191. * <pre>
  192. * source: " @{ mmmm.['sd']=wer ;}@"
  193. * pointer: " ^"
  194. * </pre>
  195. *
  196. * @function
  197. * @param {String} prefix
  198. * a prefix for the message
  199. * @param {String} msg
  200. * the original message (may contain location-information "line <line_i>:<position_j>")
  201. * @param {Object} [tokenSource] OPTIONAL
  202. * the token-source, from where the error/message was triggered
  203. * If the argument has the field <code>tokenSource.offset</code> (Number)
  204. * if will be used to correct/fix the location information in the original message.
  205. * If the argument has the fields <code>tokenSource.start</code> (Number) and
  206. * <code>tokenSource.end</code> (Number), then this will be used to correct/fix
  207. * the location information in the original message text.
  208. * @param {Object} [viewObj] OPTIONAL
  209. * currently not used!
  210. * (will replace _currentParsedView in the future!)
  211. *
  212. * @private
  213. * @memberOf ParserUtils#
  214. */
  215. var parserCreatePrintMessage = (function(){//return function(prefix, msg, tokenSource, viewObj)
  216. /**
  217. *
  218. * Get the index in the String str, where line number lineNo
  219. * starts.
  220. *
  221. * New lines begin after \n, \r\n, or \r.
  222. *
  223. * If lineNo is <= 1, the function returns always 0.
  224. *
  225. * If the lineNo is greater than the count of lines in str, the string length itself is returned.
  226. *
  227. * <p>
  228. * NOTE used by {@link #parserCreatePrintMessage}
  229. *
  230. * @function
  231. * @param {String} str the string
  232. * @param {Number} lineNo the line number (first line is 1)
  233. *
  234. * @private
  235. * @memberOf ParserUtils.parserCreatePrintMessage
  236. */
  237. var getIndexForLine = (function(){
  238. var detectLinebreak = /(\r?\n|\r)/igm;
  239. return function(str, lineNo){
  240. if(lineNo <= 1){
  241. return 0;
  242. }
  243. var match;
  244. var count = 1;
  245. while(match = detectLinebreak.exec(str)){
  246. //ASSERT: lineNo >= 2
  247. if(++count == lineNo){
  248. break;
  249. }
  250. }
  251. //reset regexpr:
  252. detectLinebreak.lastIndex = 0;
  253. if(match){
  254. return match.index + match[1].length;
  255. }
  256. //request line-no. >= 2 AND loop "detect enough" linebreaks => the request line index starts after strings ends => return string's length
  257. return str.length;
  258. };
  259. })();//END getIndexForLine
  260. /**
  261. *
  262. * Get the line in the String str, in which the char at index is included.
  263. *
  264. * New lines begin after \n, \r\n, or \r,
  265. * e.g. for line X:
  266. * <pre>
  267. * ...\r\n
  268. * ^
  269. * </pre>
  270. * the line number will be X (i.e. the line-break itself is still included in the current line).
  271. * <p>
  272. * If index is < 0, the function returns always 1.
  273. * <p>
  274. * If the index is greater than str.length, -1 is returned.
  275. * <p>
  276. * NOTE used by {@link #extractErrorPosition}
  277. *
  278. * @function
  279. * @param {String} str the string
  280. * @param {Number} index the char index for which to find the line number (first line is 1)
  281. *
  282. * @private
  283. *
  284. * @memberOf ParserUtils.parserCreatePrintMessage
  285. *
  286. */
  287. var getLineForIndex = (function(){
  288. var detectLinebreak = /(\r?\n|\r)/ig;
  289. return function(str, index){
  290. if(index < 0){
  291. return 1;
  292. }
  293. if(index >= str.length){
  294. return -1;
  295. }
  296. //ASSERT index is at least within line 1
  297. var match;
  298. var count = 1;
  299. var isNextLineFound = false;
  300. var currentPos = -1;
  301. var lastPos = 0;
  302. while(match = detectLinebreak.exec(str)){
  303. currentPos = match.index + match[1].length;
  304. if(currentPos > index){
  305. isNextLineFound = true;
  306. break;
  307. }
  308. lastPos = currentPos;
  309. ++count;
  310. }
  311. //reset regexpr:
  312. detectLinebreak.lastIndex = 0;
  313. return {
  314. line : count,
  315. index: index - lastPos
  316. };
  317. };
  318. })();//END getLineForIndex
  319. /**
  320. *
  321. * NOTE used by {@link #parserCreatePrintMessage}
  322. *
  323. * @private
  324. * @function
  325. * @memberOf ParserUtils.parserCreatePrintMessage
  326. */
  327. var extractErrorPosition = (function(){
  328. var detectLineNo = /line (\d+):(-?\d+)/i;
  329. return function extractErrorPositionImpl(msg, offset, originalContent, tokenSource){
  330. // console.log('\nTEST1_extractErrorPositionImpl with arguments '+arguments.length+'\n');
  331. var result = detectLineNo.exec(msg);
  332. //reset regexpr:
  333. detectLineNo.lastIndex = 0;
  334. // console.log('\nTEST2_result for "'+msg+'": '+result+'\n');
  335. var pos = null;
  336. if(result){
  337. var line = parseInt(result[1],10);
  338. var index = parseInt(result[2],10);
  339. var isCorrected = false;
  340. if(tokenSource){
  341. //if we have "invalid" position-info.:
  342. // -> the error probably occured at the very beginning of the parsed expression
  343. // -> try to extract position from parent parser/lexer
  344. if(line === 0 || index === -1){
  345. line = tokenSource.getLine();
  346. index = tokenSource.getCharPositionInLine();
  347. }
  348. //if there is an offest supplied by the tokenSource -> use it:
  349. if(tokenSource.offset){
  350. var iOffset = tokenSource.offset;
  351. // if(line === 1){
  352. // //
  353. // //this position information is derived from a script-eval (-> ConentElement.ScriptEvalError)
  354. // // -> need to increase offset by 1 or 2, since all script-elements have
  355. // // an additional, internal offset of 1 or 2 (this is only an heuristical value...)
  356. // // e.g. @( ...
  357. // // @{ ...
  358. // // @for( ...
  359. // iOffset += 2;
  360. // }
  361. var contentOffset = getLineForIndex(originalContent, iOffset);
  362. //if it is "relatively" the first line, we need to adjust to index
  363. // (i.e. the position within the line)
  364. if(line === 1){
  365. index += contentOffset.index;
  366. }
  367. //adjust the line, i.e. make "relative" -> "absolute" line number
  368. line += contentOffset.line - 1;
  369. isCorrected = true;
  370. }
  371. }
  372. pos = {
  373. line: line,
  374. index: index
  375. };
  376. // console.log('\nTEST3_pos: '+JSON.stringify(pos)+', offset: '+offset+'\n');
  377. if(offset && offset !== 0){
  378. // console.log('\nTEST4_offset: '+offset+'\n');
  379. var newLine = line;
  380. var newIndex = index;
  381. if( ! isCorrected){
  382. var lineOffset = getLineForIndex(originalContent, offset);
  383. if(line < 2){
  384. newIndex = lineOffset.index + index;
  385. pos.originalIndex = index;
  386. pos.index = newIndex;
  387. }
  388. newLine = lineOffset.line + line - 1;
  389. pos.originalLine = line;
  390. pos.line = newLine;
  391. }
  392. var fixed = msg.substring(0,result.index + 'line '.length) + newLine + ':' + newIndex + msg.substring(result.index + result[0].length);
  393. pos.text = fixed;
  394. // pos.originalContent = originalContent;
  395. // pos.offset = offset + pos.index;
  396. }
  397. else {
  398. pos.text = msg;
  399. }
  400. }
  401. else if(tokenSource && tokenSource.start && tokenSource.end){
  402. pos = getLineForIndex(originalContent, tokenSource.start);
  403. pos.text = ' near /';
  404. }
  405. return pos;
  406. };
  407. })();//END extractErrorPosition
  408. /**
  409. * Create a message for parsing-information.
  410. *
  411. * In case the <code>msg</code> is an error message containing relative/incorrect location information,
  412. * an heuristic will be used to fix the location information; in addition the references location
  413. * will be extracted from the source-String and a "pointer-String" will be generated, e.g.
  414. * <pre>
  415. * source: " @{ mmmm.['sd']=wer ;}@"
  416. * pointer: " ^"
  417. * </pre>
  418. *
  419. * @private
  420. *
  421. * @param {String} prefix
  422. * a prefix for the message
  423. * @param {String} msg
  424. * the original message (may contain location-information "line <line_i>:<position_j>")
  425. * @param {Object} [tokenSource] OPTIONAL
  426. * the token-source, from where the error/message was triggered
  427. * If the argument has the field <code>tokenSource.offset</code> (Number)
  428. * if will be used to correct/fix the location information in the original message.
  429. * If the argument has the fields <code>tokenSource.start</code> (Number) and
  430. * <code>tokenSource.end</code> (Number), then this will be used to correct/fix
  431. * the location information in the original message text.
  432. * @param {Object} [viewObj] OPTIONAL
  433. * currently not used!
  434. * (will replace _currentParsedView in the future!)
  435. */
  436. return function parserCreatePrintMessageImpl(prefix, msg, tokenSource, viewObj){//FIXME
  437. var currentView = _currentParsedView;
  438. if(currentView != null){
  439. var rootView = null;
  440. var details = '';
  441. if(currentView.getController){
  442. details += 'CTRL("' + currentView.getController().getName() + '")';
  443. }
  444. if(currentView.getView){
  445. if(details.length > 0){
  446. details += '->';
  447. }
  448. details += 'VIEW("' + currentView.getView().getName() + '")';
  449. rootView = currentView.getView();
  450. }
  451. if(details.length > 0){
  452. details += '->';
  453. }
  454. details += currentView.constructor.name;
  455. if(currentView.getName){
  456. details += '("' + currentView.getName() + '")';
  457. }
  458. if(rootView && typeof currentView.getStart !== 'undefined'){
  459. var pos = extractErrorPosition(msg, currentView.getOffset(), rootView.getDefinition(), tokenSource);
  460. // console.log('\nTEST_A_pos: '+JSON.stringify(pos)+', offset: '+currentView.getStart() +'\n');
  461. if(pos){
  462. msg = pos.text;
  463. //msg += '\n\t at line '+pos.line+', index '+pos.index;
  464. var content = rootView.getDefinition();
  465. var line = null;
  466. var offset = currentView.getStart();
  467. if(content){
  468. var start = getIndexForLine(content, pos.line);
  469. var end = start;
  470. var len = content.length;
  471. while(end < len && (content[end] != '\r' && content[end] != '\n')){
  472. ++end;
  473. }
  474. line = content.substring(start,end);
  475. }
  476. if(line){
  477. //marker for "pointing" the error
  478. var marker = [];
  479. for(var i=0; i < pos.index; ++i){
  480. if(line[i] == '\t'){
  481. //need to include tabs themselves, since they
  482. // take more than 1 char-positions when displayed:
  483. marker.push('\t');
  484. }
  485. else {
  486. marker.push(' ');
  487. }
  488. }
  489. //add marker symbol, that points to error in the line above:
  490. marker.push('^');
  491. msg += ' at line '+pos.line+':';
  492. msg += '\n "'+line+'"'; //<- the line with the error
  493. msg += '\n '+marker.join(''); //<- the marker line (will only be correctly aligned for fixed-width fonts)
  494. }
  495. }
  496. }
  497. return prefix + 'in ' + details + ' - ' + msg;
  498. }
  499. else {
  500. return prefix+msg;
  501. }
  502. };//END parserCreatePrintMessage
  503. })();//END var parserCreatePrintMessage = ...
  504. parser.parserCreatePrintMessage = parserCreatePrintMessage;
  505. //////////////////////////////////// END: helper for debugging, error details etc. ////////////////////////
  506. /**
  507. * Object containing the instance of the class ParserUtils
  508. *
  509. * @type ParserUtils
  510. * @private
  511. *
  512. * @memberOf ParserUtils#
  513. */
  514. var instance = null;
  515. /**
  516. * @private
  517. * @memberOf ParserUtils#
  518. */
  519. var isDebug = true;//TODO read/set from configuration
  520. MmirTemplateLexer.prototype.emitErrorMessage = function(msg) {
  521. parser.parserPrintError('[ERROR] TemplateLexer: ', msg, this);
  522. };
  523. // MmirTemplateParser.prototype.emitErrorMessage = function(msg) {
  524. // parser.parserPrintError('[ERROR] TemplateParser: ',msg);
  525. // };
  526. ES3Lexer.prototype.emitErrorMessage = function(msg) {
  527. parser.parserPrintError('[ERROR] JavaScriptLexer_ES3: ', msg, this);
  528. };
  529. ES3Parser.prototype.emitErrorMessage = function(msg) {
  530. parser.parserPrintError('[ERROR] JavaScriptParser_ES3: ', msg, this.getTokenStream().getTokenSource());
  531. };
  532. MmirScriptLexer.prototype.emitErrorMessage = function(msg) {
  533. var mode = this.isStatementMode()? 'Statement' : 'Block';
  534. parser.parserPrintError('[ERROR] Script'+mode+'Lexer: ',msg, this);
  535. };
  536. MmirScriptParser.prototype.emitErrorMessage = function(msg) {
  537. parser.parserPrintError('[ERROR] ScriptParser: ',msg, this.getTokenStream().getTokenSource());
  538. };
  539. MmirScriptContentLexer.prototype.emitErrorMessage = function(msg) {
  540. parser.parserPrintError('[ERROR] ContentLexer: ',msg, this);
  541. };
  542. MmirScriptContentParser.prototype.emitErrorMessage = function(msg) {
  543. parser.parserPrintError('[ERROR] ContentParser: ',msg, this.getTokenStream().getTokenSource());
  544. };
  545. /**
  546. * @private
  547. * @memberOf ParserUtils#
  548. */
  549. function internalParse(text) {
  550. var input = new org.antlr.runtime.ANTLRStringStream(text);//FIXME change, how dependency 'mmirf/antlr3' is exported?
  551. var lexer = new MmirTemplateLexer(input);
  552. lexer.isDebug = isDebug;
  553. var tokens = new org.antlr.runtime.CommonTokenStream(lexer);//FIXME change, how dependency 'mmirf/antlr3' is exported?
  554. var result = {};
  555. result.rawTemplateText = tokens.toString();
  556. result.scripts = lexer.includeScripts;
  557. result.styles = lexer.includeStyles;
  558. result.localizations = lexer.locales;
  559. result.ifs = lexer.ifs;
  560. result.fors = lexer.fors;
  561. result.yields = lexer.yields;
  562. result.contentFors = lexer.yieldContents;
  563. result.helpers = lexer.helpers;
  564. result.partials = lexer.renderPartials;
  565. result.escapes = lexer.escape;
  566. result.scriptStatements = lexer.scriptStatements;
  567. result.scriptBlocks = lexer.scriptBlocks;
  568. result.vars = lexer.vars;
  569. result.comments = lexer.comments;
  570. //end: parsing results
  571. lexer = null;
  572. return result;
  573. }
  574. /**
  575. * @private
  576. * @memberOf ParserUtils#
  577. */
  578. function internalParseJS(text, entryRuleName, offset) {
  579. var input = new org.antlr.runtime.ANTLRStringStream(text);
  580. var lexer = new ES3Lexer(input);
  581. lexer.isDebug = isDebug;
  582. lexer.offset = offset;
  583. var tokens = new org.antlr.runtime.CommonTokenStream(lexer);
  584. var parser = new ES3Parser(tokens);
  585. parser.offset = offset;
  586. if(!entryRuleName){
  587. // var parseResult =
  588. parser.program();//<- parse with main rule 'program' in ES3Parser
  589. }
  590. else {
  591. // var parseResult =
  592. parser[entryRuleName]();//<- parse with main rule 'program' in ES3Parser
  593. }
  594. var result = new Object();
  595. result.rawTemplateText = tokens.toString();
  596. var varRefs = parser.getVarReferences();
  597. if(varRefs){
  598. result.varReferences = varRefs;
  599. } else {
  600. result.varReferences = [];
  601. }
  602. //TODO handle potentially global var-declaration (i.e. assignments without preceding var, where the variable is undefined yet)
  603. //end: parsing results
  604. lexer = null;
  605. parser = null;
  606. return result;
  607. }
  608. // var getVarReferences = function(parser){
  609. //
  610. // var size = parser.ampersatIdentifiers.length;
  611. //
  612. // if(size === 0){
  613. // return null;
  614. // }
  615. //
  616. // var varRefs = new Array(size);
  617. // for(var i=0; i < size; ++i){
  618. // var ref = parser.ampersatIdentifiers[i];
  619. //
  620. // var refObj = new mmir.parser.ParsingResult(ref);
  621. //// refObj.start = ref.start;
  622. //
  623. // //correct end-position (token's stop-index is exactly the last char-index, whereas ParsingResult's end-position is token.stopIndex + 1)
  624. // refObj.end = refObj.getEnd() + 1;
  625. //
  626. // refObj.type = mmir.parser.element.VAR_REFERENCE;
  627. //
  628. // varRefs[i] = refObj;
  629. // }
  630. // return varRefs;
  631. // };
  632. /**
  633. * Constructor-Method of Singleton mmir.parser.ParserUtils
  634. *
  635. * @constructs ParserUtils
  636. * @memberOf ParserUtils.prototype
  637. * @private
  638. * @ignore
  639. *
  640. */
  641. function constructor(){
  642. //private members (currently none)
  643. /** @lends mmir.parser.ParserUtils.prototype */
  644. return {
  645. //public members:
  646. /**
  647. * Parse a text as view template (e.g. *.ehtml files).
  648. *
  649. * @param {String} rawTemplateString the text that should be parsed
  650. * @param {Object} [view] (optional) the view to which the <tt>rawTemplateString</tt> belongs (only used for error messages)
  651. * @returns {mmir.parser.ParsingResult} the parsing result
  652. *
  653. * @public
  654. * @memberOf mmir.parser.ParserUtils.prototype
  655. */
  656. parse: function(rawTemplateString, view){
  657. if(view){
  658. _currentParsedView = view;
  659. }
  660. else {
  661. _currentParsedView = null;
  662. }
  663. return internalParse(rawTemplateString);
  664. },
  665. /**
  666. * Parse a text as JavaScript.
  667. *
  668. * @param {String} rawTemplateString the text that should be parsed
  669. * @param {String} [parseEntryRuleName] (optional) specifies the JavaScript element that should be parsed for
  670. * @param {Object} [view] (optional) the view to which the <tt>rawTemplateString</tt> belongs (only used for error messages)
  671. * @returns {mmir.parser.ParsingResult} the parsing result
  672. *
  673. * @public
  674. * @memberOf mmir.parser.ParserUtils.prototype
  675. */
  676. parseJS: function(rawTemplateString, parseEntryRuleName, view, inViewOffset){
  677. //in case only 2 or 3 arguments are present: is 2nd the View object?
  678. if(!inViewOffset && typeof parseEntryRuleName !== 'string' && parseEntryRuleName !== null && typeof parseEntryRuleName === 'object'){
  679. if(typeof view === 'number'){
  680. inViewOffset = view;
  681. }
  682. view = parseEntryRuleName;
  683. parseEntryRuleName = null;
  684. }
  685. if(view){
  686. _currentParsedView = view;
  687. }
  688. else {
  689. _currentParsedView = null;
  690. }
  691. return internalParseJS(rawTemplateString, parseEntryRuleName, inViewOffset);
  692. }
  693. };//END: return{}
  694. }//END: constructor()
  695. instance = new constructor();
  696. //FIXME should the renderer be exported to parser.ParserUtils here?
  697. parser.ParserUtils = instance;
  698. return instance;
  699. });//END define(..., function(){