验证表达式中的标记计数

时间:2017-03-07 11:56:42

标签: c# math

我正在编写一个C#程序,它使用以下格式执行一些过滤表达式(通过二进制运算AND和OR连接的条件)

Name==Me && Age>18 || City== NewYork

有一个标记器

 {Name, ==, Me , &&, Age, >, 18, ||, City, ==, NewYork}.

之后,过滤逻辑将创建一个过滤器。

问题:我想对令牌化器上的令牌数进行第一级验证。但我无法弄清楚令牌的数量是多少。

if(!IsValidCount(tokens.Count)) return false;

IsValidCount()中的逻辑是什么?

这可能是比C#更多的数学,任何帮助都表示赞赏

3 个答案:

答案 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]  ---------------------------------------------------------------------------------------------------------------

请关注mXparser tutorial

此致