/// ------------------------------------------------------------------------------------
        public SearchEngine(SearchQuery query)
        {
            CurrentSearchQuery = query;

            _errors.Clear();

            try
            {
                var parser = new PatternParser(App.Project);
                SrchItemPatternGroup  = parser.Parse(query.SearchItem, EnvironmentType.Item);
                EnvBeforePatternGroup = parser.Parse(query.PrecedingEnvironment, EnvironmentType.Before);
                EnvAfterPatternGroup  = parser.Parse(query.FollowingEnvironment, EnvironmentType.After);
            }
            catch
            {
                var error = new SearchQueryValidationError(
                    string.Format(GetPatternSyntaxErrorMsg(), App.kEmptyDiamondPattern));

                _errors.Add(error);
            }

            m_srchItemStr  = query.SearchItem;
            m_envBeforeStr = query.PrecedingEnvironment;
            m_envAfterStr  = query.FollowingEnvironment;

            if (_errors != null && _errors.Count > 0)
            {
                query.Errors.AddRange(_errors);
            }
        }
        /// ------------------------------------------------------------------------------------
        public void VerifyDiacriticPlaceholders(string pattern)
        {
            var match = PatternParser.FindInnerMostSquareBracketPairs(pattern);

            while (match.Success)
            {
                var bracketedText = match.Result("${bracketedText}");
                if (bracketedText.Contains(App.DottedCircleC))
                {
                    bracketedText = bracketedText.Replace(App.DottedCircle, string.Empty);
                    if (bracketedText.Contains("+") && bracketedText.Contains("*"))
                    {
                        var error = new SearchQueryValidationError(
                            LocalizationManager.GetString("PhoneticSearchingMessages.InvalidDiacriticPlaceholderSyntaxMsg",
                                                          "The symbols '*' and '+' may not appear between square brackets together " +
                                                          "with a diacritic placeholder. One or the other is allowed, but not both."));

                        error.HelpLinks.AddRange(new[] { "hidSearchPatternsDiacriticPlaceholders", "hidSearchPatternsExamples" });
                        Errors.Add(error);
                    }

                    if (bracketedText.Count(s => s == '+') > 1)
                    {
                        var error = new SearchQueryValidationError(
                            LocalizationManager.GetString("PhoneticSearchingMessages.TooManyOneOrMoreSymbolsInDiacriticPlaceholderMsg",
                                                          "The One-Or-More-Diacritics symbol (+) appears too many times with a diacritic " +
                                                          "placeholder. Only one is allowed."));

                        error.HelpLinks.AddRange(new[] { "hidSearchPatternsDiacriticPlaceholders", "hidSearchPatternsExamples" });
                        Errors.Add(error);
                    }

                    if (bracketedText.Count(s => s == '*') > 1)
                    {
                        var error = new SearchQueryValidationError(
                            LocalizationManager.GetString("PhoneticSearchingMessages.TooManyZeroOrMoreSymbolsInDiacriticPlaceholderMsg",
                                                          "The Zero-Or-More-Diacritics symbol (*) appears too many times with a " +
                                                          "diacritic placeholder. Only one is allowed."));

                        error.HelpLinks.AddRange(new[] { "hidSearchPatternsDiacriticPlaceholders", "hidSearchPatternsExamples" });
                        Errors.Add(error);
                    }

                    foreach (var symbolInfo in bracketedText.Where(s => s != '+' && s != '*')
                             .Select(s => App.IPASymbolCache[s]).Where(s => s != null && s.IsBase))
                    {
                        var msg = LocalizationManager.GetString("PhoneticSearchingMessages.InvalidSymbolInDiacriticPlaceholderMsg",
                                                                "The symbol '{0}' is a base character and was found between square brackets " +
                                                                "together with a diacritic placeholder. Base characters are not allowed with " +
                                                                "diacritic placeholders.");

                        var error = new SearchQueryValidationError(string.Format(msg, symbolInfo.Literal));
                        error.HelpLinks.AddRange(new[] { "hidSearchPatternsDiacriticPlaceholders", "hidSearchPatternsExamples" });
                        Errors.Add(error);
                    }
                }

                match = match.NextMatch();
            }
        }
        /// ------------------------------------------------------------------------------------
        private void VerifyDiacriticPlaceholdersAreInAndGroups(string pattern)
        {
            while (true)
            {
                var match = PatternParser.FindInnerMostSquareBracketPairs(pattern);
                if (!match.Success)
                {
                    break;
                }

                if (!match.Value.Contains(App.DottedCircleC))
                {
                    pattern = pattern.Replace(match.Value, string.Empty);
                }
                else
                {
                    _tokenBins[++_token] = match.Value;
                    pattern = pattern.Replace(match.Value, _token.ToString());
                }
            }

            var fmt = LocalizationManager.GetString("PhoneticSearchingMessages.DiacriticPlaceholderNotInAndGroupMsg",
                                                    "The diacritic placeholder pattern '{0}' is not inside an AND group. Diacritic placeholder " +
                                                    "patterns must be placed inside AND groups.");

            foreach (var error in pattern.Where(c => c > kMinToken)
                     .Select(c => new SearchQueryValidationError(string.Format(fmt, _tokenBins[c]))))
            {
                error.HelpLinks.AddRange(new[] { "hidSearchPatternsDiacriticPlaceholders", "hidSearchPatternsAndGroups" });
                Errors.Add(error);
            }

            _tokenBins.Clear();
            _token = kMinToken;
        }
        /// ------------------------------------------------------------------------------------
        public void VerifyTextInSquareBrackets(string pattern)
        {
            var match = PatternParser.FindInnerMostSquareBracketPairs(pattern);

            while (match.Success)
            {
                var bracketedText = match.Result("${bracketedText}");

                if (bracketedText != string.Empty &&
                    !bracketedText.Contains(App.DottedCircle) &&
                    bracketedText != "C" && bracketedText != "V" &&
                    !App.AFeatureCache.Keys.Any(f => f == bracketedText) &&
                    !App.BFeatureCache.Keys.Any(f => f == bracketedText) && !bracketedText.Contains(App.ProportionalToSymbol))
                {
                    var msg = LocalizationManager.GetString("PhoneticSearchingMessages.InvalidTextInSquareBracketsMsg",
                                                            "The text '{0}' in square brackets is invalid. Other than surrounding " +
                                                            "'AND' groups, square brackets are only used to surround descriptive or " +
                                                            "distinctive features, the designators for consonant or vowel classes " +
                                                            "('[C]' and '[V]'), or a diacritic placeholder with its diacritics and wildcards.");

                    var error = new SearchQueryValidationError(string.Format(msg, bracketedText));
                    error.HelpLinks.AddRange(new[] { "hidSearchPatternsAndGroups", "hidSearchPatternsExamples" });
                    Errors.Add(error);
                }

                match = match.NextMatch();
            }
        }
        /// ------------------------------------------------------------------------------------
        public void ValidateOrGroups(string item)
        {
            var orGroupValidator = new OrGroupValidator(_project);
            var match            = PatternParser.FindInnerMostBracesPair(item);

            while (match.Success)
            {
                orGroupValidator.Verify(match.Value);
                if (orGroupValidator.HasErrors)
                {
                    Errors.AddRange(orGroupValidator.Errors);
                }

                match = match.NextMatch();
            }
        }
        /// ------------------------------------------------------------------------------------
        public string StripOutStuffWithValidPlusAndStarSymbols(string pattern)
        {
            var match = PatternParser.FindInnerMostSquareBracketPairs(pattern);

            while (match.Success)
            {
                if (match.Value.Contains('+') || match.Value.Contains('*'))
                {
                    pattern = pattern.Replace(match.Value, new string('$', match.Value.Length));
                }

                match = match.NextMatch();
            }

            return(pattern.Replace("$", string.Empty));
        }
Example #7
0
        /// ------------------------------------------------------------------------------------
        public bool Parse()
        {
            if (!DoesPatternPassBasicChecks())
            {
                return(false);
            }

            _parser = new PatternParser(_project, _query);

            if (_parser.Parse())
            {
                return(true);
            }

            Errors.AddRange(_parser.Errors);
            return(false);
        }
        /// ------------------------------------------------------------------------------------
        private string GetPhonesRunInPattern(string pattern)
        {
            while (true)
            {
                var match = PatternParser.FindInnerMostParenthesePair(pattern);
                if (!match.Success)
                {
                    break;
                }
                pattern = pattern.Replace(match.Value, string.Empty);
            }

            while (true)
            {
                var match = PatternParser.FindInnerMostSquareBracketPairs(pattern);
                if (!match.Success)
                {
                    break;
                }
                pattern = pattern.Replace(match.Value, string.Empty);
            }

            while (true)
            {
                var match = PatternParser.FindInnerAngleBracketPairs(pattern);
                if (!match.Success)
                {
                    break;
                }
                pattern = pattern.Replace(match.Value, string.Empty);
            }

            pattern = pattern.Replace(",", string.Empty);
            pattern = pattern.Replace("[", string.Empty);
            pattern = pattern.Replace("]", string.Empty);
            pattern = pattern.Replace("{", string.Empty);
            pattern = pattern.Replace("}", string.Empty);
            pattern = pattern.Replace("_", string.Empty);
            pattern = pattern.Replace("/", string.Empty);
            pattern = pattern.Replace("*", string.Empty);
            pattern = pattern.Replace("+", string.Empty);
            pattern = pattern.Replace("NOT", string.Empty);
            return(pattern.Replace("#", string.Empty));
        }
        /// ------------------------------------------------------------------------------------
        public string TranslateInnerSquareBracketedTextToTokens(string pattern)
        {
            var match = PatternParser.FindInnerMostSquareBracketPairs(pattern);

            while (match.Success)
            {
                _tokenBins[++_token] = match.Value;
                var newPattern = pattern.Substring(0, match.Index) + _token + new string('$', match.Length - 1);
                if (match.Index + match.Length < pattern.Length)
                {
                    newPattern += pattern.Substring(match.Index + match.Length);
                }

                pattern = newPattern;
                match   = match.NextMatch();
            }

            return(pattern.Replace("$", string.Empty));
        }
        /// ------------------------------------------------------------------------------------
        public void VerifyOneDiacriticPlaceholderPerAndGroup(string pattern)
        {
            var originalPattern = pattern;

            var match = PatternParser.FindInnerMostSquareBracketPairs(pattern);

            while (match.Success)
            {
                var newPattern = pattern.Substring(0, match.Index) +
                                 (match.Value.Contains(App.DottedCircleC) ? '$' : '@');

                newPattern += new string('@', match.Length - 1);
                if (match.Index + match.Length < pattern.Length)
                {
                    newPattern += pattern.Substring(match.Index + match.Length);
                }

                pattern = newPattern;
                match   = match.NextMatch();
            }

            pattern = pattern.Replace("@", string.Empty);
            match   = PatternParser.FindInnerMostSquareBracketPairs(pattern);

            while (match.Success)
            {
                if (match.Value.Count(c => c == '$') > 1)
                {
                    var msg = LocalizationManager.GetString("PhoneticSearchingMessages.TooManyDiacriticPlaceholderMsg",
                                                            "The pattern '{0}' contains too many diacritic placeholders in one of the AND groups. " +
                                                            "Only one diacritic placeholder is allowed per AND group.");

                    var error = new SearchQueryValidationError(string.Format(msg, originalPattern));
                    error.HelpLinks.AddRange(new[] { "hidSearchPatternsDiacriticPlaceholders", "hidSearchPatternsExamples" });
                    Errors.Add(error);
                    return;
                }

                match = match.NextMatch();
            }
        }
        /// ------------------------------------------------------------------------------------
        public override void Verify(string pattern)
        {
            base.Verify(pattern);

            VerifyDiacriticPlaceholdersAreInAndGroups(pattern);

            pattern = TranslateInnerSquareBracketedTextToTokens(pattern);

            while (true)
            {
                var match = PatternParser.FindInnerMostSquareBracketPairs(pattern);
                if (!match.Success)
                {
                    return;
                }

                LookForMalformedGroup(match.Value);
                _tokenBins[++_token] = match.Value;
                pattern = pattern.Replace(match.Value, _token.ToString());
            }
        }
        public void TestSetup()
        {
            _parser = new PatternParser(_prj);
            SearchEngine.PhoneCache  = _prj.PhoneCache;
            App.DottedCircle         = "0";
            App.DottedCircleC        = '0';
            App.DiacriticPlaceholder = "[0]";

            _prj.PhoneCache["a"] = new PhoneInfo {
                Phone = "a", CharType = IPASymbolType.vowel
            };
            _prj.PhoneCache["d"] = new PhoneInfo {
                Phone = "d", CharType = IPASymbolType.consonant
            };
            ((PhoneInfo)_prj.PhoneCache["d"]).BFeatureNames = new List <string> {
                "+high", "-cons"
            };
            ((PhoneInfo)_prj.PhoneCache["d"]).AFeatureNames = new List <string> {
                "dental"
            };
        }
        /// ------------------------------------------------------------------------------------
        public void VerifyTextInAngleBrackets(string pattern)
        {
            var match = PatternParser.FindInnerAngleBracketPairs(pattern);

            while (match.Success)
            {
                var bracketedText = match.Result("${bracketedText}");

                if (!_project.SearchClasses.Any(c => c.Name == bracketedText))
                {
                    var msg = LocalizationManager.GetString("PhoneticSearchingMessages.InvalidTextInAngleBracketsMsg",
                                                            "The text '{0}' in angled brackets is not a valid class name.");

                    var error = new SearchQueryValidationError(string.Format(msg, bracketedText));
                    error.HelpLinks.Add("hidSearchPatternsExamples");
                    Errors.Add(error);
                }

                match = match.NextMatch();
            }
        }