
// From http://goessner.net/articles/jsont/


/*	This work is licensed under Creative Commons GNU LGPL License.

	License: http://creativecommons.org/licenses/LGPL/2.1/
   Version: 0.9
	Author:  Stefan Goessner/2006
	Web:     http://goessner.net/ 
*/

// NOTE: IE 5 doesn't support string.replace(regex,function)

function jsonT(self, rules) {
   var T = {
      output: false,
      init: function() {
         for (var rule in rules)
         {
            if (rule.substr(0,4) != "self")
            {
               rules["self."+rule] = rules[rule];
            }
         }
         return this;
      },
      apply: function(expr) {
         var trf = function(s){ return s.replace(/\{([A-Za-z0-9_\$\.\[\]\'@\(\)]+)\}/g, 
                                  function($0,$1){return T.processArg($1, expr);});},
             x = expr.replace(/\[[0-9]+\]/g, "[*]"), res;
         if (typeof(rules[x]) != "undefined") 
         {
            if (typeof(rules[x]) == "string")
            {
               res = trf(rules[x]);
            }
            else if (typeof(rules[x]) == "function")
            {
               res = trf(rules[x](eval(expr)).toString());
            }
         }
         else
         { 
            res = T.evaluate(expr);
         }
         return res;
      },
      processArg: function(arg, parentExpr) {
         var expand = function(a,e){return (e=a.replace(/^\$/,e)).substr(0,4)!="self" ? ("self."+e) : e; },
             res = "";
         T.output = true;
         if (arg.charAt(0) == "@")
         {
            res = eval(arg.replace(/@([A-za-z0-9_]+)\(([A-Za-z0-9_\$\.\[\]\']+)\)/, 
                                   function($0,$1,$2){return "rules['self."+$1+"']("+expand($2,parentExpr)+")";}));
         }
         else if (arg != "$")
         {
            res = T.apply(expand(arg, parentExpr));
         }
         else
         {
            res = T.evaluate(parentExpr);
         }
         T.output = false;
         return res;
      },
      evaluate: function(expr) {
         var v = eval(expr), res = "";
         if (typeof(v) != "undefined") {
            if (v instanceof Array) 
            {
               for (var i=0; i<v.length; i++)
               {
                  if (typeof(v[i]) != "undefined")
                  {
                     res += T.apply(expr+"["+i+"]");
                  }
               }
            }
            else if (typeof(v) == "object") 
            {
               for (var m in v)
               {
                  if (typeof(v[m]) != "undefined")
                  {
                     res += T.apply(expr+"."+m);
                  }
               }
            }
            else if (T.output)
            {
               res += v;
            }
         }
         return res;
      }
   };
   return T.init().apply("self");
}
