Zocky

From Culture.si
Revision as of 02:11, 24 August 2016 by Zocky (talk | contribs)

{ var TOKEN = {

   	LITERAL:1,
       OPERATOR:2,
       COMPARE:3,
       LOGICAL:4,
       ASSIGN:5
   }
   function TRUE(n) {
   	return n===0 || !!n;
   }

function OP(c,h,t,opc,valc) {

   	if (!t.length) return h;
   	opc = opc || 1;
       valc = valc || 3;
       var ret =  [c,h];
       t.forEach(function(n) {
       	ret.push(n[opc]);
       	ret.push(n[valc]);
       })
       return ret;
   }
   function EVAL(nodes,ctx) {
   	function E(n) {
       	return EVAL(nodes[n],ctx); 
       }
       if (!Array.isArray(nodes)) console.log(nodes);
       var tok = nodes[0];
       switch (tok) {
       case TOKEN.LITERAL:
       	return nodes[1];
       case TOKEN.COMPARE:
         var cur = EVAL(nodes[1],ctx);
         var i = 2;
         while (i<nodes.length) {
             var op = nodes[i++];
             var val = EVAL(nodes[i++],ctx);
             console.log(cur,op,val);
             switch (op) {
               case '<': if(!(cur<val)) return false; break;
               case '>': if(!(cur>val)) return false; break;
               case '<=': if(!(cur<=val)) return false; break;
               case '>=': if(!(cur>=val)) return false; break;
               case '!=': if(!(cur!==val)) return false; break;
               case '==': if(!(cur===val)) return false; break;
             }
             cur = val;
          }
          return true;
       case TOKEN.LOGICAL:
         var acc = EVAL(nodes[1],ctx);
         var i = 2;
         while (i<nodes.length) {
             var op = nodes[i++];
             //var val = EVAL(nodes[i++],ctx);
             switch (op) {
             case '&&': if (!TRUE(acc)) return false; acc=EVAL(nodes[i++],ctx); break;
             case '||': if (TRUE(acc)) return acc; acc=EVAL(nodes[i++],ctx); break;
             }
          }
          return acc;
       case TOKEN.OPERATOR:
         var acc = EVAL(nodes[1],ctx);
         var i = 2;
         while (i<nodes.length) {
             var op = nodes[i++];
             var val = EVAL(nodes[i++],ctx);
             switch (op) {
             case '+': acc+=val; break;
             case '-': acc-=val; break;
             case '*': acc*=val; break;
             case '/': acc/=val; break;
             case '%': acc%=val; break;
             case ';':
             case ',': acc=val; break;
             }
          }

return acc;

       }

return "BAD TOKEN"

   }

} program = e:statements { return [EVAL(e,{a:3}),e];} statements = h:statement t:(_ ';' _ statement)* ';'? { return OP('O',h,t)} statement = assign/expr assign = n:ident _ "=" _ e:expr { return ['A',n,e] } expr = or or = h:and t:( _ ("||") _ and)* { return OP(TOKEN.LOGICAL,h,t)} and = h:compare t:( _ ("&&") _ compare)* { return OP(TOKEN.LOGICAL,h,t)} compare = h:addsub t:( _ ("!="/"=="/"<="/">="/">"/"<") _ addsub)* { return OP(TOKEN.COMPARE,h,t)} addsub = h:muldiv t:( _ [+-] _ muldiv)* { return OP(TOKEN.OPERATOR,h,t)} muldiv = h:atom t:( _ [*/%] _ atom)* { return OP(TOKEN.OPERATOR,h,t)} atom = literal/path/brackets brackets = _ "(" _ e:expr _ ")" _ { return e} path = h:head t:( _ [.] _ key)* { return OP('P',h,t)} head = i:ident { return [i,'$']; }/brackets key = ident/digits/brackets

literal = boolean/number boolean = "true" eow { return [TOKEN.LITERAL,true]; } / "false" eow { return [TOKEN.LITERAL,false] } number = n:$( d:digits ('.' digits)? ([Ee] digits)?) { return [TOKEN.LITERAL,Number(n)]} digits = [0-9]+ ident = $([A-Z_]i [A-Z0-9_]i*) eow = ![a-z0-9i] _ = [ \n\r\t]* __ = [ \n\r\t]+