Логические выражения для поиска в строке ( hello OR hi) AND world - C#

Узнай цену своей работы

Формулировка задачи:

Может кто-то видел готовые библиотеки? хотелось бы что-то пожирней и без напильника в комплекте чтоб например изменять ключевые слова (ИЛИ И НЕ -- || && !), оба регистра кушала, с кавычками дружила, ошибки обходила и всяческие мелкие тонкости? поисковики не понимают о чем речь
c# and not(VB or SQL)

Решение задачи: «Логические выражения для поиска в строке ( hello OR hi) AND world»

textual
Листинг программы
    [Serializable]
    public class StringExpression
    {
        private const string LBracket = "(";
        private const string RBracket = ")";
 
        private static Regex _splitRegex = new Regex(@"\b|(?<=[!&'""\(\)])|(?=[!&'""\(\)])", RegexOptions.Compiled);
 
 
        private static Dictionary<TokenType, byte> _prio = new Dictionary<TokenType, byte>
            {
                {TokenType.OR, 1},
                {TokenType.AND, 2},
                {TokenType.NOT, 3},
                //{TokenType.QUOTE, 4},
            };
 
        private static Dictionary<TokenType, List<string>> _keyWords = new Dictionary<TokenType, List<string>>
            {
                {TokenType.OR, new List<string>(3) {"OR", "|", "ИЛИ"}},
                {TokenType.AND, new List<string>(3) {"AND", "&", "И"}},
                {TokenType.NOT, new List<string>(3) {"NOT", "!", "НЕ"}},
                {TokenType.Quote, new List<string>(3) {"\"", "'"}},
                 {TokenType.LBracket, new List<string>(1) {LBracket}},
                  {TokenType.RBracket, new List<string>(1) {RBracket}},
            };
 
        private string originExpression;
        private bool ignoreCase;
        private bool fullWords;
 
        [XmlAttribute("IgnoreCase")]
        public bool IgnoreCase
        {
            get { return ignoreCase; }
            set { ignoreCase = value; }
        }
 
 
        [XmlAttribute("FullWords")]
        public bool FullWords
        {
            get { return fullWords; }
            set { fullWords = value; }
        }
 
        [XmlAttribute("Expression")]
        public string Expression
        {
            get { return originExpression; }
            set
            {
                originExpression = value;
                tokenizedExpression = null;
            }
        }
 
              
        public StringExpression()
            :this(null)
        {
            
        }
 
        public StringExpression(string expression, bool ignoreCase = true, bool fullWords = false)
        {
            this.fullWords = fullWords;
            IgnoreCase = ignoreCase;
            Expression = expression;
        }
 
 
        private List<string> tokenizedExpression;
 
        private IEnumerable<string> Tokenized
        {
            get
            {
                if (tokenizedExpression == null)
                {
                    tokenizedExpression = ToPostFix(originExpression);
                }
                return tokenizedExpression;
            }
        }
 
        protected virtual List<string> ToPostFix(string sourceString)
        {
            if (string.IsNullOrEmpty(sourceString))
                return new List<string>(0);
 
            string[] tokens = _splitRegex.Split(sourceString);
 
            if (tokens.Length == 1)
                return new List<string>(1) { tokens[0] };
 
            var result = new List<string>();
 
            var stack = new Stack<string>();
 
            bool isEscapedData = false;
 
            var quotedData = new StringBuilder();
 
            foreach (string rawToken in tokens)
            {
                if (string.IsNullOrEmpty(rawToken))
                    continue;
 
                var token = rawToken.Trim().ToUpper();
 
                TokenType typeToken = GetTokenType(token);
 
                if (isEscapedData)
                {
                    if (typeToken == TokenType.Quote)
                    {
                        result.Add(quotedData.ToString());
                        quotedData.Length = 0;
                        isEscapedData = false;
                    }
                    else
                    {
                        quotedData.Append(rawToken);
                    }
                }
                else
                {
                    if (StringExt.IsNullOrWhiteSpace(token))
                        continue;
 
                    switch (typeToken)
                    {
                        case TokenType.AND:
                        case TokenType.NOT:
                        case TokenType.OR:
                            while (stack.Count > 0)
                            {
                                string topToken = stack.Peek();
                                if (_prio.ContainsKey(GetTokenType(topToken)) &&
                                    _prio[typeToken] < _prio[GetTokenType(topToken)])
                                {
                                    result.Add(stack.Pop());
                                }
                                else
                                {
                                    break;
                                }
 
                                result.Add(stack.Pop());
                            }
                            stack.Push(token);
                            break;
 
                        case TokenType.LBracket:
                            stack.Push(rawToken);
                            break;
 
                        case TokenType.RBracket:
                            if (stack.Count <= 0)
                                throw new Exception("Некорректное выражение");
 
                            string op = stack.Pop();
                            while (op != LBracket)
                            {
                                result.Add(op);
 
                                if (stack.Count <= 0)
                                    throw new Exception("Некорректное количевство скобок");
 
                                op = stack.Pop();
                            }
                            break;
 
                        case TokenType.Quote:
                            isEscapedData = true;
                            break;
 
                        default:
                            result.Add(rawToken);
                            break;
                    }
                }
            }
 
            if (isEscapedData)
            {
                throw new Exception("Кавычка не закрыта");
            }
 
            foreach (string symbol in stack)
            {
                result.Add(symbol);
            }
 
            return result;
        }
 
 
        public virtual bool IsMatch(string text)
        {
            if (text == null) 
                throw new ArgumentNullException("text");
 
            var stackResult = new Stack<bool>();
 
            if (!Tokenized.Any())
                return true;
 
            foreach (var token in Tokenized)
            {
                if (StringExt.IsNullOrWhiteSpace(token))
                    continue;
 
                bool left;
                bool right;
                switch (GetTokenType(token))
                {
                    case TokenType.AND:
                        left = stackResult.Pop();
                        right = stackResult.Pop();
                        stackResult.Push(left && right);
                        break;
 
                    case TokenType.NOT:
                        left = stackResult.Pop();
                        stackResult.Push(!left);
                        break;
 
                    case TokenType.OR:
                        left = stackResult.Pop();
                        right = stackResult.Pop();
                        stackResult.Push(left || right);
                        break;
 
                    case TokenType.LBracket:
                        break;
                    case TokenType.RBracket:
                        break;
                    case TokenType.Quote:
                        break;
                    default:
 
                        bool exists;
                        if (fullWords)
                        {
                            exists = Regex.IsMatch(text, @"\b" + token + @"\b",
                                          ignoreCase
                                          ? RegexOptions.IgnoreCase
                                          : RegexOptions.None);
                        }
                        else
                        {
                            exists = text.IndexOf(token, ignoreCase ? StringComparison.OrdinalIgnoreCase :  StringComparison.Ordinal) >= 0;
                        }
 
                        stackResult.Push(exists);
                        break;
                }
            }
 
            if (stackResult.Count != 1)
            {
                throw new Exception("Ошибки при использовании выражения");
            }
 
            return stackResult.Pop();
        }
 
        private TokenType GetTokenType(string token)
        {
            if (StringExt.IsNullOrWhiteSpace(token))
                return TokenType.String;
 
 
 
            foreach (var keyWord in _keyWords)
            {
                if (keyWord.Value.Contains(token))
                {
                    return keyWord.Key;
                }
            }
 
            return TokenType.String;
        }
 
 
        public enum TokenType
        {
            NOT,
            AND,
            OR,
            LBracket,
            RBracket,
            Quote,
            String
        }
 
        private static class StringExt
        {
            public static bool IsNullOrWhiteSpace(string str)
            {
                if (string.IsNullOrEmpty(str))
                    return true;
 
                for (int i = 0; i < str.Length; i++)
                {
                    if (!char.IsWhiteSpace(str[i]))
                    {
                        return false;
                    }
                }
                return true;
            }
        }
    }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

13   голосов , оценка 4.154 из 5
Похожие ответы