Well, in the simplest case (without escape characters), no stranger cases (for example, when you [1;2]should consider it as "equal to the string" [1; 2] ", you can use only regular expressions:
List<KeyValuePair<String, String>> rules = new List<KeyValuePair<string, string>>() {
new KeyValuePair<String, String>("Max", @"^(?<Negation>!*)\[;(?<Value>.+?)\]$"),
new KeyValuePair<String, String>("Min", @"^(?<Negation>!*)\[(?<Value>.+?);\]$"),
new KeyValuePair<String, String>("Range", @"^(?<Negation>!*)\[(?<Value>.+?;.+?)\]$"),
new KeyValuePair<String, String>("In", @"^(?<Negation>!*)in\((?<Value>.+?(,.+?)*)\)$"),
new KeyValuePair<String, String>("StartsWith", @"^(?<Negation>!*)%(?<Value>.+?)$"),
new KeyValuePair<String, String>("EndsWith", @"^(?<Negation>!*)(?<Value>.+?)%$"),
new KeyValuePair<String, String>("Equals", @"^(?<Negation>!*)(?<Value>.+?)$"),
};
String filter = "!!in(abc,def,xy,pq)";
foreach (var rule in rules) {
Match match = Regex.Match(filter, rule.Value);
if (match.Success) {
String report = String.Format("RULE: \"{0}\"; Negation: \"{1}\"; Value: \"{2}\"",
rule.Key,
match.Groups["Negation"].Value.Length % 2 != 0,
match.Groups["Value"].Value);
Console.Write(report);
break;
}
}
Output signal
: ""; : ""; : "abc, def, xy, pq"
, Split:
// ["abc", "def", "xy", "pq"]
String[] parts = match.Groups["Value"].Value.Split(',');
, escape- ..,
: , , .
Types - int (e.g. 123)
float (e.g. -1.23e-54)
string (e.g. abc, "123", ab%c, ab_c, ab\%c, ab\_c, 100\%, ab\"c, ab\\c, "in")
, , _ %; , integer/float, " (, 100 "100" - ). , \ escape- (, , \" "\"")
Key words = in
Special symbols = [ ] ( ) , ; % _
equals (including wild cards)
in (including wild cards)
range (min, max, range)
negation (the only boolean operation)
:
.
!!in (12%3, ab\%c, pq_x%)
Tokenization: "!", "!", "in", "(", "12%3", "ab\%c", "pq_x%", ")"
Parsing: "negation",
"negation",
"in" (with three arguments: "12%3", "ab\%c", "pq_x%")
Validating: syntax is valid
Builder: My_Field like '12%3' or
My_Field like '12\%3' escape '\' or
My_Field like 'pq_x%'