C# - parsing a complex string containing logical operators
Asked Answered
H

2

7

I've got a logical string read in from a configuration file written by someone else that contains expressions such as the following:

(VALUE_1)OR((NOT(VALUE_2))AND(NOT(VALUE_3)))

However, I'm a little stumped as to where to start parsing this and comparing the values of the variables that I have stored as the same string name elsewhere. Am I correct in thinking LambdaExpression is the thing that needs to be used? Does the string need splitting in some way and to be analysed as the constituent parts rather than as a whole?

EDIT:

It seems as though Flee does what I need it to do, I can define the names of the VALUE_x as true or false before evaluating the expression using that library.

Hathcock answered 1/2, 2012 at 12:56 Comment(2)
You may use the Dynamic Linq Library: #821865Ensheathe
That link helped, thanks - it led me to Flee which seems to have done everything I needed it to do...Hathcock
G
2

Typical approach for evaluating string expressions in C# is building expression tree and compiling it into delegate (this job is covered by .NET framework). In most cases dynamic linq library is recommended but it has several drawbacks: it is not supported as reusable library (actually it is just illustration of LINQ capabilities published by Scott Gu) and it can evaluate only strongly typed expressions which is bad in most real life applications.

I suggest better alternative: lambda expressions parser from NReco Commons (this is free and open source library). It also builds expression tree but uses quite different approach to expression parsing and evaluating it as expression tree: it performs all types harmonization and invocations at runtime (like dynamic languages), supports property and methods calls, arrays construction and conditional operator. Some examples:

var lambdaParser = new NReco.LambdaParser();

var varContext = new Dictionary<string,object>();
varContext["pi"] = 3.14M;
varContext["one"] = 1M;
varContext["two"] = 2M;
varContext["test"] = "test";
varContext["arr1"] = new double[] { 1.5, 2.5 };
Console.WriteLine( lambdaParser.Eval("pi>one && 0<one ? (1+8)/3+1*two : 0", varContext) ); // --> 5
Console.WriteLine( lambdaParser.Eval(" arr1[0]+arr1[1] ", varContext) ); // -> 4
Console.WriteLine( lambdaParser.Eval(" (new[]{1,2})[1]  ", varContext) ); // -> 2

(more examples and documentation could be found at NReco Commons library page)

Grownup answered 3/7, 2014 at 6:34 Comment(0)
J
0

I think you can convert string into array of words and then check each words against your stored variables.

    //Convert the string into an array of words
        string[] source = line.Split(new char[] { '.', '?', '!', ' ', ';', ',','(',')' }, StringSplitOptions.RemoveEmptyEntries);

        // Create and execute the query. It executes immediately 
        // because a singleton value is produced.
        // Use ToLowerInvariant to match "data" and "Data" 
        var matchQuery = from word in source
                         where word.ToLowerInvariant().Contains("your stored variable elsewhere")
                         select word;

        // Count the matches. 
        int varCount = matchQuery.Count();

use match query to deal with matched variable names.

Hope this helps

Jilly answered 1/2, 2012 at 13:9 Comment(2)
I'll need this to parse my variable names and convert them it would seem, might be back here to ask for more information on this aspect!Hathcock
this link might be useful to you - #821865Jilly

© 2022 - 2024 — McMap. All rights reserved.