Reputation: 1368
I need to write a function that can take an if statement at runtime (eg. user input, or from a data file). Ideally it should be able to solve an expression no less complex than:
a && ( b || !c || ( d && e ) )
I imagine what I need is a recursive function (one that calls itself). Of course, the function needs to return true or false.
Because of the complexity of the example above, the function would need to not only loop through the individual conditions, but understand the operators, know the order in which to evaluate them and preferably prioritise them for speed (eg. in the example, if a is false there is no need to evaluate the rest of the statement).
Does anyone have any ideas?
Upvotes: 3
Views: 335
Reputation: 5135
One solution would be using shunting yard algorithm to convert the expression to RPN, and then evaluate it as RPN (because RPN is much easier to evaluate than infix). The first part, conversion to RPN (in pseudocode):
while (tokens left) {
t = read_token();
if (t is number) {
output(t);
} else if (t is unary operator) {
push(t);
} else if (t is binary operator) {
r = pop();
if (r is operator and precedence(t)<=precedence(r)) {
output(r);
} else {
push(r);
}
push(t);
} else if (t is left parenthesis) {
push(t);
} else if (r is right parenthesis) {
while ((r = pop()) is not left parenthesis) {
output(r);
if (stack is empty) {
mismatched parenthesis!
}
}
if (top() is unary operator) {
output(pop());
}
}
}
while (stack is not empty) {
if (top() is parenthesis) {
mismatched parenthesis!
}
output(pop());
}
read_token
reads a token from input queueoutput
inserts a value into output queuepush
pushes a value into the stack (you only need one)pop
pops a value out of a stacktop
peeks the value at the top of the stack without poppingThe RPN evaluation is simpler:
while (tokens left) {
t = read_token();
if (t is number) {
push(t);
} else if (t is unary operator) {
push(eval(t, pop()));
} else if (t is binary operator) {
val1 = pop();
val2 = pop();
push(eval(t, val1, val2));
}
}
result = pop();
read_token()
reads values from the RPN queue generated in previous stepeval(t, val)
evaluates unary operator t
with operand val
eval(t, val1, val2)
evaluates binary operator t
with operands val1
and val2
result
is the final value of the expressionThis simplified algorithm should work if all your operators are left-associative and no functions are used. Note that no recursion is necessary, because we use our own stack implementation. For examples and more information, see Rosetta Code on Shunting-yard and Rosetta Code on RPN
Upvotes: 3