C # - анализ сложной строки, содержащей логические операторы - PullRequest
2 голосов
/ 01 февраля 2012

У меня есть логическая строка, прочитанная из файла конфигурации, написанного кем-то другим, который содержит выражения, такие как:

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

Тем не менее, я немного озадачен тем, с чего начать разбор этого и сравнивать значения переменных, которые я сохранил, с тем же именем строки в другом месте. Правильно ли я считаю, что LambdaExpression - это то, что нужно использовать? Нужно ли каким-то образом разбивать строку и анализировать ее как составные части, а не как целое?

EDIT:

Кажется, что Flee делает то, что мне нужно, я могу определить имена VALUE_x как true или false перед оценкой выражения с использованием этой библиотеки.

Ответы [ 2 ]

1 голос
/ 03 июля 2014

Типичным подходом для оценки строковых выражений в C # является построение дерева выражений и компиляция его в делегат (эта работа покрывается .NET framework). В большинстве случаев рекомендуется динамическая библиотека linq , но у нее есть несколько недостатков: она не поддерживается в качестве библиотеки многократного использования (на самом деле это просто иллюстрация возможностей LINQ, опубликованных Скоттом Гу) и может оценивать только строго типизированные выражения, которые плохо в большинстве реальных приложений.

Я предлагаю лучшую альтернативу: анализатор лямбда-выражений из NReco Commons (это бесплатная библиотека с открытым исходным кодом). Он также создает дерево выражений, но использует совершенно другой подход к разбору выражений и оценивает его как дерево выражений: он выполняет гармонизацию и вызовы всех типов во время выполнения (например, динамические языки), поддерживает вызовы свойств и методов, конструирование массивов и условный оператор. Некоторые примеры:

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

(дополнительные примеры и документацию можно найти на странице библиотеки NReco Commons)

0 голосов
/ 01 февраля 2012

Я думаю, что вы можете преобразовать строку в массив слов, а затем проверить каждое слово по вашим сохраненным переменным.

    //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();

использовать запрос на совпадение для работы с совпадающими именами переменных.

Надеюсь, это поможет

...