Jump to content

A better postfix evaluator


PeterCanessa Oh
 Share

You are about to reply to a thread that has been inactive for 4485 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I recently posted a routine to evaluate expression written in Postfix (reverse Polish notation). This one is better in that it doesn't have a separate Stack list. It is simpler, but slightly less efficient, in handling values as it tests them all to see if they're constants. Since I don't expect this routine to have heavy-duty use the simplicity and symmetry with the operator-handling seemed preferable.

 

float EvalPostfix(string Expr){
	// Evaluates string expressions written in reverse Polish notation (postfix)
	// PeterCanessa Oh
	// NB: All operands and operators must be space-delimited, all operators are binary
	// Supports operators +, -, *, /, % (mod) and ^ (exponentiation) and constants e, Phi and Pi
	list Parts = llParseString2List(Expr, ["  ", " "], []);
	integer Pointer;
	while(Pointer < llGetListLength(Parts)){
		Expr = llToUpper(llList2String(Parts, Pointer));
		if(-1 != llListFindList(["+", "-", "*", "/", "%", "^"], [Expr])){
			// Operator
			if(1 < Pointer){
				if("+" == Expr){
					Parts = llListReplaceList(Parts, [((float) llList2String(Parts, Pointer - 2)) + ((float) llList2String(Parts, Pointer - 1))], Pointer - 2, Pointer);
				}else if("-" == Expr){
					Parts = llListReplaceList(Parts, [((float) llList2String(Parts, Pointer - 2)) - ((float) llList2String(Parts, Pointer - 1))], Pointer - 2, Pointer);
				}else if("*" == Expr){
					Parts = llListReplaceList(Parts, [((float) llList2String(Parts, Pointer - 2)) * ((float) llList2String(Parts, Pointer - 1))], Pointer - 2, Pointer);
				}else if("/" == Expr){
					if((float) llList2String(Parts, Pointer - 1)){
						Parts = llListReplaceList(Parts, [((float) llList2String(Parts, Pointer - 2)) / ((float) llList2String(Parts, Pointer - 1))], Pointer - 2, Pointer);
					}else{
						// Division by zero error, just return zero
						Parts = [0.0];
						Pointer = 2;
					}
				}else if("%" == Expr){
					Parts = llListReplaceList(Parts, [((integer) llList2String(Parts, Pointer - 2)) % ((integer) llList2String(Parts, Pointer - 1))], Pointer - 2, Pointer);
				}else if("^" == Expr){
					Parts = llListReplaceList(Parts, [llPow(((float) llList2String(Parts, Pointer - 2)), ((float) llList2String(Parts, Pointer - 1)))], Pointer - 2, Pointer);
				}
				Pointer--;    // <-- As we've reduced the input list by 2 this is actually the 'next' element
			}else{
				// Stack error - there aren't enough operands for the operator to use so just return zero
				Parts = [0.0];
				Pointer++;
			}
		}else{
			// Translate constants
			if("E" == Expr){
				llListReplaceList(Parts, ["2.7182817"], Pointer, Pointer);
			}else if("PHI" == Expr){
				llListReplaceList(Parts, ["1.618034"], Pointer, Pointer);
			}else if("PI" == Expr){
				llListReplaceList(Parts, ["3.1415927"], Pointer, Pointer);
			}
			// Otherwise it's a value that doesn't need translating or a mistake that will take the value 0.0 anyway
			Pointer++;
		}  
	}
	if(1 != llGetListLength(Parts)){
		// Parse error; there should only be a single entry, the result, left on the stack if the expression was properly formed so just return zero
		return 0.0;
	}
	// Return the final result
	return (float) llList2String(Parts, 0);
}

default{
    state_entry(){
        llOwnerSay("Infix (or anything else) '2' = " + (string) EvalPostfix("2"));
        llOwnerSay("Infix 3 + 4 = " + (string) EvalPostfix("3 4 +"));
        llOwnerSay("Infix 2 + 3 / 6 - 4 (assuming strict L To R calculation) = " + (string) EvalPostfix("2 3 + 6 / 4 -"));
        llOwnerSay("Infix (2 + 3) / (6 - 4) = " + (string) EvalPostfix("2 3 + 6 4 - /"));
    }
}

 

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 4485 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...