/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // The helper functions can be found at: // http://grimore.org/fuss:lsl ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // Returns a reversed list. ////////////////////////////////////////////////////////// list wasListReverse(list lst) { if(llGetListLength(lst)<=1) return lst; return wasListReverse(llList2List(lst, 1, llGetListLength(lst))) + llList2List(lst,0,0); } ////////////////////////////////////////////////////////// // Deletes elements delete from list input. ////////////////////////////////////////////////////////// list wasSubtractSubList(list input, list delete) { do { string tok = llList2String(delete, 0); list clean = input; do { if(llList2String(clean, 0) == tok) { integer idx = llListFindList(input, (list)tok); input = llDeleteSubList(input, idx, idx); } } while(clean = llDeleteSubList(clean, 0, 0)); } while(delete = llDeleteSubList(delete, 0, 0)); return input; } ////////////////////////////////////////////////////////// // Returns a list of operators and operands. ////////////////////////////////////////////////////////// list wasInfixTokenize(string input) { list op = [ "+", "-", "(", ")", "%", "*", "/", "^", "sin", "asin", "cos", "acos", "tan", "sqrt", "ln" ]; list result = llParseString2List(input, [], op); return wasSubtractSubList(result, [" "]); } ////////////////////////////////////////////////////////// // Transforms an infix expression to a postfix expression. ////////////////////////////////////////////////////////// list wasInfixToPostfix(list infix) { list op = [ "+", "-", "%", "*", "/", "^", "sin", "asin", "cos", "acos", "tan", "sqrt", "ln" ]; list opStack = []; list result = []; do { string t = llList2String(infix, 0); infix = llDeleteSubList(infix, 0, 0); if(t == "(") { opStack += "("; jump continue; } if(t == ")") { while(llGetListLength(opStack) != 0) { string topa = llList2String(opStack, llGetListLength(opStack)-1); opStack = llDeleteSubList(opStack, llGetListLength(opStack)-1, llGetListLength(opStack)-1); if(topa != "(" && topa != ")") result += topa; } opStack = llDeleteSubList(opStack, llGetListLength(opStack)-1, llGetListLength(opStack)-1); jump continue; } integer idx = llListFindList(op, (list)t); if(idx == -1) { result += t; jump continue; } @repeat; string topb = llList2String(opStack, llGetListLength(opStack)-1); integer odx = llListFindList(op, (list)topb); if(odx >= idx) { opStack = llDeleteSubList(opStack, llGetListLength(opStack)-1, llGetListLength(opStack)-1); result += topb; if(llGetListLength(opStack) != 0) jump repeat; } opStack += t; @continue; } while(llGetListLength(infix) != 0); result += wasListReverse(opStack); return result; } ////////////////////////////////////////////////////////// // Evaluate a postfix expression. ////////////////////////////////////////////////////////// float wasPostfixEval(list postfix) { list op = [ "+", "-", "%", "*", "/", "^", "sin", "asin", "cos", "acos", "tan", "sqrt", "ln" ]; list orStack = []; do { string t = llList2String(postfix, 0); postfix = llDeleteSubList(postfix, 0, 0); integer idx = llListFindList(op, (list)t); if(idx == -1) { orStack += t; jump continue; } float a = llList2Float(orStack, llGetListLength(orStack)-1); orStack = llDeleteSubList(orStack, llGetListLength(orStack)-1, llGetListLength(orStack)-1); float b = llList2Float(orStack, llGetListLength(orStack)-1); float r = 0; if(t == "+") { orStack = llDeleteSubList(orStack, llGetListLength(orStack)-1, llGetListLength(orStack)-1); r = b + a; jump push; } if(t == "-") { orStack = llDeleteSubList(orStack, llGetListLength(orStack)-1, llGetListLength(orStack)-1); r = b - a; jump push; } if(t == "*") { orStack = llDeleteSubList(orStack, llGetListLength(orStack)-1, llGetListLength(orStack)-1); r = b * a; jump push; } if(t == "/") { orStack = llDeleteSubList(orStack, llGetListLength(orStack)-1, llGetListLength(orStack)-1); if(a == 0) { r = (float)"NaN"; jump push; } r = b / a; jump push; } if(t == "^") { orStack = llDeleteSubList(orStack, llGetListLength(orStack)-1, llGetListLength(orStack)-1); r = llPow(b,a); jump push; } if(t == "%") { orStack = llDeleteSubList(orStack, llGetListLength(orStack)-1, llGetListLength(orStack)-1); r = (integer)b % (integer)a; jump push; } if(t == "sin") { r = llSin(a * DEG_TO_RAD); jump push; } if(t == "asin") { r = llAsin(a * DEG_TO_RAD); jump push; } if(t == "cos") { r = llCos(a * DEG_TO_RAD); jump push; } if(t == "acos") { r = llAcos(a * DEG_TO_RAD); jump push; } if(t == "tan") { r = llTan(a * DEG_TO_RAD); jump push; } if(t == "ln") { r = llLog(a); jump push; } if(t == "sqrt") { r = llSqrt(a); } @push; orStack += r; @continue; } while(llGetListLength(postfix) != 0); return llList2Float(orStack, 0); } list cmd = []; default { link_message(integer sender_num, integer num, string str, key id) { cmd = llCSV2List(str); if(llList2String(cmd,1) != "calculate") return; llMessageLinked(LINK_THIS, 0, "glow:MAIN:HALT", NULL_KEY); state calculate; } on_rez(integer num) { llResetScript(); } } state calculate { state_entry() { llSay(0, "I evaluated that to: " + (string)wasPostfixEval(wasInfixToPostfix(wasInfixTokenize(llDumpList2String(llList2List(cmd, 2, -1),""))))); llMessageLinked(LINK_THIS, 0, "glow:MAIN:CONT", NULL_KEY); state default; } link_message(integer sender_num, integer num, string str, key id) { if(str != "glow:PLUG:HALT") return; state default; } on_rez(integer num) { llResetScript(); } }