The following is a postfix calculator that transforms any text spoken by the owner of the script to postfix notation and then evaluates the expression.
+
- addition-
- subtraction*
- multiplication/
- division^
- exponentiation%
- modulosin
- sinecos
- cosinetan
- tangentasin
- arc-sineacos
- arc-cosine
From highest to lowest, the precedence is given by the last element in the array op
in the wasInfixToPostfix
function. In order from highest to lowest:
Operator |
---|
sin ,cos ,tan ,asin ,acos ,ln ,sqrt |
^ |
* , / |
% |
+ , - |
Șpecıaŀ K(gonor.chunker): ln(2+2)*3+50/2 Object whispers: Postfix is: 2 2 + ln 3 * 50 2 / + Object whispers: Value is: 25.000000
Șpecıaŀ K(gonor.chunker): 2*10/20 [WaS-K] Calculator whispers: Postfix is: 2 10 20 / * [WaS-K] Calculator whispers: Value is: 1
Șpecıaŀ K(gonor.chunker): 2^10/10 [WaS-K] Calculator whispers: Postfix is: 2 10 ^ 10 / [WaS-K] Calculator whispers: Value is: 102.400000
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2012 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // Most of 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); } default { state_entry() { llListen(0, "", llGetOwner(), ""); } listen(integer chan, string name, key id, string message) { // Tokenize the message. list tokenized = wasInfixTokenize(message); // Convert infix to postfix. list postfixExpression = wasInfixToPostfix(tokenized); // Evaluate postifx expression. float result = wasPostfixEval(postfixExpression); llWhisper(0, "Postfix is: " + llDumpList2String(postfixExpression, " ")); llWhisper(0, "Value is: " + (string)result); } }