StackOverflow isn't a code writing service, but some code is fun to write.
Here is a class that parses the test phrase into an Expression
tree and then compiles the tree to return a Func
to test a HashSet<string>
:
public static class PhraseCompiler {
public static Regex tokenRE = new Regex(@"\(|\)|&|\||\w+", RegexOptions.Compiled);
static IEnumerable<string> Tokens(string phrase) {
foreach (Match m in tokenRE.Matches(phrase))
yield return m.Value;
}
static MethodInfo HSContainsMI = typeof(HashSet<string>).GetMethod("Contains");
static Expression subCompile(IEnumerator<string> te, ParameterExpression g) {
var stack = new Stack<Expression>();
while (te.MoveNext()) {
switch (te.Current) {
case "(":
break;
case ")":
goto exit_while;
case "|":
case "&":
var op = te.Current;
var lhs = stack.Pop();
var rhs = subCompile(te, g);
var opExpr = Expression.MakeBinary(op == "|" ? ExpressionType.OrElse : ExpressionType.AndAlso, lhs, rhs);
stack.Push(opExpr);
break;
default:
var v = Expression.Constant(te.Current, typeof(string));
var test = Expression.Call(g, HSContainsMI, v);
stack.Push(test);
break;
}
}
exit_while:
return stack.Pop();
}
public static Func<HashSet<string>, bool> Compile(string phrase) {
var g = Expression.Parameter(typeof(HashSet<string>), "g");
var te = Tokens(phrase).GetEnumerator();
var e = subCompile(te, g);
var ef = Expression.Lambda<Func<HashSet<string>, bool>>(e, g);
return ef.Compile();
}
}
Given your initial values
var A = "ab1, eb4, gr3";
var B = "((ut2 | eg1) | gr3) & ab1";
var C = "ke2 & pa5";
Then you can convert the test value to a HashSet<string>
:
var As = A.Split(", ").ToHashSet();
And then you can compile the tests:
var fB = PhraseCompiler.Compile(B);
var fC = PhraseCompiler.Compile(C);
and run the tests:
var testBresult = fB(As);
var testCresult = fC(As);
NOTE: The compiler does no error checking and is likely to throw an exception for bad test phrases.