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