|
|
Line 1: |
Line 1: |
− | { | + | {{Special:Prefixindex/{{FULLPAGENAME}}}} |
− | 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]+
| |