Difference between revisions of "User:Zocky"
Line 1: | Line 1: | ||
{ | { | ||
− | function OP(h,t,opc,valc) { | + | 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; | if (!t.length) return h; | ||
opc = opc || 1; | opc = opc || 1; | ||
valc = valc || 3; | valc = valc || 3; | ||
− | var ret = [h]; | + | var ret = [c,h]; |
t.forEach(function(n) { | t.forEach(function(n) { | ||
ret.push(n[opc]); | ret.push(n[opc]); | ||
Line 12: | Line 22: | ||
} | } | ||
function EVAL(nodes,ctx) { | function EVAL(nodes,ctx) { | ||
− | if (!Array.isArray(nodes)) return nodes; | + | 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}), | + | program = e:statements { return [EVAL(e,{a:3}),e];} |
− | statements = h:statement t:(_ ';' _ statement)* ';'? { return OP(h,t)} | + | statements = h:statement t:(_ ';' _ statement)* ';'? { return OP('O',h,t)} |
statement = assign/expr | statement = assign/expr | ||
− | assign = n:ident _ "=" _ e:expr { return [ | + | assign = n:ident _ "=" _ e:expr { return ['A',n,e] } |
− | expr = addsub | + | expr = or |
− | addsub = h:muldiv t:( _ [+-] _ muldiv)* { return OP(h,t)} | + | or = h:and t:( _ ("||") _ and)* { return OP(TOKEN.LOGICAL,h,t)} |
− | muldiv = h:atom t:( _ [*/%] _ atom)* { return OP(h,t)} | + | and = h:compare t:( _ ("&&") _ compare)* { return OP(TOKEN.LOGICAL,h,t)} |
− | atom = path | + | 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} | brackets = _ "(" _ e:expr _ ")" _ { return e} | ||
− | path = h:head t:( _ [.] _ key)* { return OP(h,t)} | + | path = h:head t:( _ [.] _ key)* { return OP('P',h,t)} |
head = i:ident { return [i,'$']; }/brackets | head = i:ident { return [i,'$']; }/brackets | ||
key = ident/digits/brackets | key = ident/digits/brackets | ||
− | number = n:$( d:digits ('.' digits)? ([Ee] digits)?) { return Number(n) | + | |
+ | 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]+ | digits = [0-9]+ | ||
ident = $([A-Z_]i [A-Z0-9_]i*) | ident = $([A-Z_]i [A-Z0-9_]i*) | ||
+ | eow = ![a-z0-9i] | ||
_ = [ \n\r\t]* | _ = [ \n\r\t]* | ||
__ = [ \n\r\t]+ | __ = [ \n\r\t]+ |
Revision as of 01:11, 24 August 2016
{ 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]+