我正在编写一个C#程序,它使用以下格式执行一些过滤表达式(通过二进制运算AND和OR连接的条件)
Name==Me && Age>18 || City== NewYork
有一个标记器
{Name, ==, Me , &&, Age, >, 18, ||, City, ==, NewYork}.
之后,过滤逻辑将创建一个过滤器。
问题:我想对令牌化器上的令牌数进行第一级验证。但我无法弄清楚令牌的数量是多少。
if(!IsValidCount(tokens.Count)) return false;
IsValidCount()中的逻辑是什么?
这可能是比C#更多的数学,任何帮助都表示赞赏
答案 0 :(得分:1)
每个条件必须包含3个令牌(2个字段+ 1个比较器)。 另外,对于每个附加条件,我们必须添加一个二进制操作(AND / OR)来分隔它们(使它总共4个令牌)。
因此,有效的标记化程序将包含以下数量的标记:
3 + 4 + 4 + 4 ......
因此,您可以使用以下公式验证令牌的数量是否有效:
string tokenizer = "{Name, ==, Me , &&, Age, >, 18, ||, City, ==, NewYork}";
var tokens = tokenizer.Split(',');
if (tokens.Length % 4 == 3)
{
//valid
}
else
{
//not valid
}
你可以更加严格,并检查每个第四个令牌确实是一个二进制操作,但这是由你来决定的。我希望我有所帮助
答案 1 :(得分:0)
以下是我对此问题的看法。我猜这可能写得更清洁,更容易理解,但是...... :) 此外,在所有情况下它可能无法正常工作,但您应该明白这一点。我还添加了几个例子。
好的,这是带注释的代码。如果您有任何疑问,请随时提出。
static void Main(string[] args)
{
string s = "{ Name, ==, Me, &&, Age, >, 18, ||, City, ==, NewYork }";
bool ok1 = IsValidExpression(s);
s = "{ Name, ==, Me, &&, Age, >, 18 }";
bool ok2 = IsValidExpression(s);
s = "{ Name, ==, ==, Me, &&, Age, >, 18 }";
bool notok = IsValidExpression(s);
s = "{ Name, Me, &&, Age, >, 18 }";
bool notok2 = IsValidExpression(s);
s = "{ Name, ==, Me, &&, Age, > ||, City, ==, NewYork }";
bool notok3 = IsValidExpression(s);
Console.ReadLine();
}
static bool IsValidExpression(string stringToValidate)
{
List<string> tokens = stringToValidate.Replace("{", "").Replace("}", "").Split(',').Select(t => t = t.Trim()).ToList();
List<string> operators = new List<string>() { "==", "!=", "<", ">" };
List<string> boolOps = new List<string>() { "&&", "||" };
//split by and/or
var boolOpsIndexes = tokens.Where(t => boolOps.Contains(t)).Select(t => tokens.IndexOf(t)).ToList();
//check for AND/OR positions
if (boolOpsIndexes.Any(b => b == 0) || boolOpsIndexes.Any(b => b == tokens.Count - 1)) //bool op is at first or last position
return false;
//make "virtual one at the end, so the program enters loop one or more times
boolOpsIndexes.Add(tokens.Count - 1);
int lastOpIndex = 0;
//iterate through all indexes where and/or were found
foreach (var boolOpIndex in boolOpsIndexes)
{
//take expressions from last AND/OR to next one
var tokensPart = tokens.Skip(lastOpIndex).Take(boolOpIndex).ToList();
if (tokensPart.Count != 3) //there is not 3 parts there... not ok
return false;
//if there is more or less than one comparison operator
if (tokensPart.Count(t => operators.Contains(t)) != 1)
return false; //not ok
//check for both sides of operators
int opIndex = tokensPart.Where(t => operators.Contains(t)).Select(t => tokensPart.IndexOf(t)).First();
//check for operators positions
if (opIndex == 0 || opIndex == tokensPart.Count - 1) //operator is at first or last position
return false; //not ok
//check if left and right side od operator contains something and not operator
if (tokensPart[opIndex - 1] != string.Empty && !operators.Contains(tokensPart[opIndex - 1])
&&
tokensPart[opIndex + 1] != string.Empty && !operators.Contains(tokensPart[opIndex + 1]))
continue;
lastOpIndex = boolOpIndex + 1;
}
return true;
}
答案 2 :(得分:0)
我认为MathParser-org-mXparser可以轻松提供帮助 - 您可以计算表达式,但也可以使用表达式标记。
Expression e = new Expression("Name==Me && Age>18 || City== NewYork");
mXparser.consolePrintTokens(e.getCopyOfInitialTokens());
结果:
[mXparser-v.4.0.0] --------------------
[mXparser-v.4.0.0] | Expression tokens: |
[mXparser-v.4.0.0] ---------------------------------------------------------------------------------------------------------------
[mXparser-v.4.0.0] | TokenIdx | Token | KeyW | TokenId | TokenTypeId | TokenLevel | TokenValue | LooksLike |
[mXparser-v.4.0.0] ---------------------------------------------------------------------------------------------------------------
[mXparser-v.4.0.0] | 0 | Name | | -1 | -1 | 0 | NaN | argument |
[mXparser-v.4.0.0] | 1 | == | == | 1 | 3 | 0 | NaN | |
[mXparser-v.4.0.0] | 2 | Me | | -1 | -1 | 0 | NaN | argument |
[mXparser-v.4.0.0] | 3 | && | && | 1 | 2 | 0 | NaN | |
[mXparser-v.4.0.0] | 4 | Age | | -1 | -1 | 0 | NaN | argument |
[mXparser-v.4.0.0] | 5 | > | > | 4 | 3 | 0 | NaN | |
[mXparser-v.4.0.0] | 6 | 18 | _num_ | 1 | 0 | 0 | 18 | |
[mXparser-v.4.0.0] | 7 | || | || | 3 | 2 | 0 | NaN | |
[mXparser-v.4.0.0] | 8 | City | | -1 | -1 | 0 | NaN | argument |
[mXparser-v.4.0.0] | 9 | == | == | 1 | 3 | 0 | NaN | |
[mXparser-v.4.0.0] | 10 | NewYork | | -1 | -1 | 0 | NaN | argument |
[mXparser-v.4.0.0] ---------------------------------------------------------------------------------------------------------------
此致