/* * Copyright (C) 2012-2013 Nicolas Froidure * * This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 3. It is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. * */ // AMD + global + NodeJS : You can use this object by inserting a script // or using an AMD loader (like RequireJS) or using NodeJS (function(root,define){ define([], function() { 'use strict'; // START: Module logic start // Constructor function VarStreamReader (scope, prop, options) { // Keep a ref to the root scope this.rootScope={root: scope, prop: prop}; // Save the options this.options=options; // Store current scopes for backward references this.previousNodes=[]; // The parse state this.state=PARSE_NEWLINE; // The current values this.leftValue=''; this.rightValue=''; this.operator=''; this.escaped=ESC_NONE; } // Static consts VarStreamReader.STRICT_MODE=1; VarStreamReader.OPTIONS=VarStreamReader.STRICT_MODE; // Constants // Chars var CHR_ENDL = '\n' , CHR_CR = '\r' , CHR_SEP = '.' , CHR_BCK = '^' , CHR_EQ = '=' , CHR_ESC = '\\' , CHR_PLU = '+' , CHR_MIN = '-' , CHR_MUL = '*' , CHR_DIV = '/' , CHR_MOD = '%' , CHR_REF = '&' , CHR_NEW = '!' , CHR_COM = '#' // Chars sets , EQ_OPS = [CHR_PLU,CHR_MIN,CHR_MUL,CHR_DIV,CHR_MOD,CHR_REF] , ARRAY_OPS = [CHR_PLU,CHR_MUL,CHR_NEW] , ARRAY_NODE_CHARS = /^[0-9]+$/ , PROP_NODE_CHARS = /^[a-zA-Z0-9_]+$/ , BCK_CHARS = /^\^[0-9]*$/ // Parsing status , PARSE_NEWLINE = 1 , PARSE_LVAL = 2 , PARSE_OPERATOR = 3 , PARSE_RVAL = 4 , PARSE_MLSTRING = 5 , PARSE_COMMENT = 6 , PARSE_SILENT = 7 // Escape status , ESC_NONE = 0 , ESC_LF = 1 , ESC_ALL = 3 ; VarStreamReader.prototype.resolveScope = function (val) { var nodes = val.split(CHR_SEP) , scope = this.rootScope , n = 0 ; // Looking for backward refs in the first node if(nodes[0] && nodes[0][0] == CHR_BCK) { // if no numbers adding every previous nodes if(nodes[0] == CHR_BCK) { n = this.previousNodes.length ? this.previousNodes.length - 1 : 0; // if numbers } else { // check it if(!BCK_CHARS.test(nodes[0])) { if(this.options&VarStreamReader.STRICT_MODE) { throw new Error('Malformed backward reference.'); } return null; } n = parseInt(nodes[0].substring(1), 10); } if(n > this.previousNodes.length) { if(this.options&VarStreamReader.STRICT_MODE) { throw new SyntaxError('Backward reference index is greater than the' + ' previous node max index.'); } return null; } this.previousNodes.length = n; nodes.shift(); nodes.unshift.apply(nodes,this.previousNodes); } // Looping throught each nodes for(var i=0, j=nodes.length; i