I got a fairly simple one working. It might not perform as well as a more sophisticated option, but it is easy to understand.
Logic
public class BooleanExpression
{
static Boolean orJoin(String x, String y) { return evaluate(x) || evaluate(y); }
static Boolean andJoin(String x, String y) { return evaluate(x) && evaluate(y); }
static Boolean isSimpleExpression(String x) { return x == 'true' || x == 'false'; }
static String simplify(String x)
{
x = x.trim();
while (x.contains('('))
{
String sub = x.substringAfterLast('(').substringBefore(')');
x = x.replace('(' + sub + ')', String.valueOf(evaluate(sub)));
}
return x;
}
static Boolean evaluate(String x)
{
x = simplify(x);
if (!isSimpleExpression(x))
{
if (x.contains('&&')) return andJoin(x.split('&&', 2));
if (x.contains('||')) return orJoin(x.split('||', 2));
if (x.startsWith('!')) return !evaluate(x.substring(1));
}
return Boolean.valueOf(x);
}
}
Tests
I know you can just use assert(evaluate(expression))
, but that feels kind of dirty here.
@IsTest
class BooleanExpressionTests
{
static testMethod void testExpressions()
{
system.assertEquals(true, evaluate('true'));
system.assertEquals(false, evaluate('!true'));
system.assertEquals(true, evaluate('!false'));
system.assertEquals(false, evaluate('false'));
system.assertEquals(false, evaluate('true && !true'));
system.assertEquals(true, evaluate('false || !false'));
system.assertEquals(true,
evaluate('false || (false || (!true || (false || true)))'));
}
}
!
.