private bool TryParseConv(string parameterText, EntryListType entryListType, ref Dictionary <string, MultiReplacementEntry> entries) { if (!IsInitialized(entryListType)) { SetInitialized(entryListType); int expectedSize; if (IntEx.TryParseInvariant(parameterText, out expectedSize) && expectedSize >= 0) { if (entries == null) { entries = new Dictionary <string, MultiReplacementEntry>(expectedSize); } return(true); } } if (entries == null) { entries = new Dictionary <string, MultiReplacementEntry>(); } var parts = parameterText.SplitOnTabOrSpace(); if (parts.Length < 2) { Builder.LogWarning($"Bad {entryListType}: {parameterText}"); return(false); } entries.AddReplacementEntry(Builder.Dedup(parts[0]), Builder.Dedup(parts[1])); return(true); }
private bool TryParseCompoundSyllable(string parameters) { var parts = parameters.SliceOnTabOrSpace(); if (parts.Length > 0) { int maxValue; if (IntEx.TryParseInvariant(parts[0], out maxValue)) { Builder.CompoundMaxSyllable = maxValue; } else { Builder.LogWarning("Failed to parse CompoundMaxSyllable value from: " + parameters); return(false); } } Builder.CompoundVowels = 1 < parts.Length ? CharacterSet.Create(parts[1]) : DefaultCompoundVowels; return(true); }
private bool TryParseStandardListItem <T>(EntryListType entryListType, string parameterText, ref List <T> entries, Func <string, List <T>, bool> parse) { if (!IsInitialized(entryListType)) { SetInitialized(entryListType); int expectedSize; if (IntEx.TryParseInvariant(parameterText, out expectedSize) && expectedSize >= 0) { if (entries == null) { entries = new List <T>(expectedSize); } return(true); } } if (entries == null) { entries = new List <T>(); } return(parse(parameterText, entries)); }
private static bool TryParseNumberFlag(StringSlice text, out FlagValue value) { if (!text.IsEmpty && IntEx.TryParseInvariant(text.ToString(), out int integerValue) && integerValue >= char.MinValue && integerValue <= char.MaxValue) { value = new FlagValue(unchecked ((char)integerValue)); return(true); } value = default(FlagValue); return(false); }
private static bool TryParseNumberFlag(string text, out FlagValue value) { if (!string.IsNullOrEmpty(text) && IntEx.TryParseInvariant(text, out int integerValue) && integerValue >= char.MinValue && integerValue <= char.MaxValue) { value = new FlagValue(unchecked ((char)integerValue)); return(true); } value = default(FlagValue); return(false); }
public static bool TryParseNumberFlag(string text, int startIndex, int length, out FlagValue value) { if (text != null) { int integerValue; if (IntEx.TryParseInvariant(text, startIndex, length, out integerValue) && integerValue >= char.MinValue && integerValue <= char.MaxValue) { value = new FlagValue(unchecked ((char)integerValue)); return(true); } } value = default(FlagValue); return(false); }
private bool AttemptToProcessInitializationLine(string line) { hasInitialized = true; var initLineMatch = InitialLineRegex.Match(line); if (initLineMatch.Success) { if (IntEx.TryParseInvariant(initLineMatch.Groups[1].Value, out int expectedSize)) { if (Builder.EntriesByRoot == null) { Builder.InitializeEntriesByRoot(expectedSize); } return(true); } } return(false); }
private bool AddWord(string word, FlagSet flags, MorphSet morphs, bool onlyUpperCase) { if (Affix.IgnoredChars.HasItems) { word = word.RemoveChars(Affix.IgnoredChars); } if (Affix.ComplexPrefixes) { word = word.Reverse(); if (morphs.HasItems && !Affix.IsAliasM) { var newMorphs = new string[morphs.Count]; for (int i = 0; i < morphs.Count; i++) { newMorphs[i] = morphs[morphs.Count - i - 1].Reverse(); } morphs = MorphSet.TakeArray(newMorphs); } } WordEntryOptions options; if (morphs.HasItems) { if (Affix.IsAliasM) { options = WordEntryOptions.AliasM; var morphBuilder = new List <string>(); foreach (var originalValue in morphs) { if (IntEx.TryParseInvariant(originalValue, out int morphNumber) && Affix.TryGetAliasM(morphNumber, out MorphSet aliasedMorph)) { morphBuilder.AddRange(aliasedMorph); } else { morphBuilder.Add(originalValue); } } morphs = MorphSet.Create(morphBuilder); } else { options = WordEntryOptions.None; } if (morphs.AnyStartsWith(MorphologicalTags.Phon)) { options |= WordEntryOptions.Phon; } } else { options = WordEntryOptions.None; } bool saveEntryList = false; word = Builder.Dedup(word); if (!Builder.EntriesByRoot.TryGetValue(word, out WordEntrySet entryList)) { saveEntryList = true; entryList = WordEntrySet.Empty; } var upperCaseHomonym = false; for (var i = 0; i < entryList.Count; i++) { var existingEntry = entryList[i]; if (!onlyUpperCase) { if (existingEntry.ContainsFlag(SpecialFlags.OnlyUpcaseFlag)) { existingEntry = new WordEntry( existingEntry.Word, flags, existingEntry.Morphs, existingEntry.Options); entryList.DestructiveReplace(i, existingEntry); return(false); } } else { upperCaseHomonym = true; } } if (!upperCaseHomonym) { saveEntryList = true; entryList = WordEntrySet.CopyWithItemAdded(entryList, new WordEntry( word, flags, Builder.Dedup(morphs), options)); } if (saveEntryList) { Builder.EntriesByRoot[word] = entryList; } return(false); }
private bool ParseLine(string line) { if (string.IsNullOrEmpty(line)) { return(true); } if (!hasInitialized && AttemptToProcessInitializationLine(line)) { return(true); } if (Builder.EntriesByRoot == null) { Builder.InitializeEntriesByRoot(-1); } var parsed = ParsedWordLine.Parse(line); if (string.IsNullOrEmpty(parsed.Word)) { return(false); } FlagSet flags; if (!string.IsNullOrEmpty(parsed.Flags)) { if (Affix.IsAliasF) { if (IntEx.TryParseInvariant(parsed.Flags, out int flagAliasNumber) && Affix.TryGetAliasF(flagAliasNumber, out FlagSet aliasedFlags)) { flags = aliasedFlags; } else { // TODO: warn return(false); } } else if (Affix.FlagMode == FlagMode.Uni) { var encodedBytes = Affix.Encoding.GetBytes(parsed.Flags); var utf8Flags = Encoding.UTF8.GetString(encodedBytes, 0, encodedBytes.Length); flags = Builder.Dedup(FlagValue.ParseFlags(utf8Flags, FlagMode.Char)); } else { flags = Builder.Dedup(FlagValue.ParseFlags(parsed.Flags, Affix.FlagMode)); } } else { flags = FlagSet.Empty; } MorphSet morphs; if (parsed.Morphs != null && parsed.Morphs.Length != 0) { var morphValues = new string[parsed.Morphs.Length]; for (int i = 0; i < parsed.Morphs.Length; i++) { morphValues[i] = parsed.Morphs[i]; } morphs = Builder.Dedup(MorphSet.TakeArray(morphValues)); } else { morphs = MorphSet.Empty; } return(AddWord(parsed.Word, flags, morphs)); }
private bool TryParseAffixIntoList <TEntry>(string parameterText, ref List <AffixEntryGroup.Builder <TEntry> > groups) where TEntry : AffixEntry, new() { if (groups == null) { groups = new List <AffixEntryGroup.Builder <TEntry> >(); } var lineMatch = AffixLineRegex.Match(parameterText); if (!lineMatch.Success) { Builder.LogWarning("Failed to parse affix line: " + parameterText); return(false); } var lineMatchGroups = lineMatch.Groups; FlagValue characterFlag; if (!TryParseFlag(lineMatchGroups[1].Value, out characterFlag)) { Builder.LogWarning($"Failed to parse affix flag for {lineMatchGroups[1].Value} from: {parameterText}"); return(false); } var affixGroup = groups.FindLast(g => g.AFlag == characterFlag); var contClass = FlagSet.Empty; if (lineMatchGroups[2].Success && lineMatchGroups[3].Success) { if (affixGroup != null) { Builder.LogWarning($"Duplicate affix group definition for {affixGroup.AFlag} from: {parameterText}"); return(false); } var options = AffixEntryOptions.None; if (lineMatchGroups[2].Value.StartsWith('Y')) { options |= AffixEntryOptions.CrossProduct; } if (Builder.IsAliasM) { options |= AffixEntryOptions.AliasM; } if (Builder.IsAliasF) { options |= AffixEntryOptions.AliasF; } int expectedEntryCount; IntEx.TryParseInvariant(lineMatchGroups[3].Value, out expectedEntryCount); affixGroup = new AffixEntryGroup.Builder <TEntry> { AFlag = characterFlag, Options = options, Entries = new List <TEntry>(expectedEntryCount) }; groups.Add(affixGroup); return(true); } else if (lineMatchGroups[4].Success && lineMatchGroups[5].Success && lineMatchGroups[6].Success) { // piece 3 - is string to strip or 0 for null var strip = lineMatchGroups[4].Value; if (strip == "0") { strip = string.Empty; } else if (EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes)) { strip = strip.Reverse(); } // piece 4 - is affix string or 0 for null var affixInput = lineMatchGroups[5].Value; var affixSlashIndex = affixInput.IndexOf('/'); StringBuilder affixText; if (affixSlashIndex >= 0) { var slashPartOffset = affixSlashIndex + 1; var slashPartLength = affixInput.Length - slashPartOffset; affixText = StringBuilderPool.Get(affixInput, 0, affixSlashIndex); if (Builder.IsAliasF) { int aliasNumber; if (IntEx.TryParseInvariant(affixInput.Subslice(slashPartOffset, slashPartLength), out aliasNumber) && aliasNumber > 0 && aliasNumber <= Builder.AliasF.Count) { contClass = Builder.AliasF[aliasNumber - 1]; } else { Builder.LogWarning($"Failed to parse contclasses from : {parameterText}"); return(false); } } else { contClass = ParseFlags(affixInput.Subslice(slashPartOffset, slashPartLength)); } } else { affixText = StringBuilderPool.Get(affixInput); } if (Builder.IgnoredChars != null && Builder.IgnoredChars.HasItems) { affixText.RemoveChars(Builder.IgnoredChars); } if (EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes)) { affixText.Reverse(); } if (affixText.Length == 1 && affixText[0] == '0') { affixText.Clear(); } // piece 5 - is the conditions descriptions var conditionText = lineMatchGroups[6].Value; if (EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes)) { conditionText = ReverseCondition(conditionText); } var conditions = CharacterCondition.Parse(conditionText); if (!string.IsNullOrEmpty(strip) && !conditions.AllowsAnySingleCharacter) { bool isRedundant; if (typeof(TEntry) == typeof(PrefixEntry)) { isRedundant = RedundantConditionPrefix(strip, conditions); } else if (typeof(TEntry) == typeof(SuffixEntry)) { isRedundant = RedundantConditionSuffix(strip, conditions); } else { throw new NotSupportedException(); } if (isRedundant) { conditions = CharacterConditionGroup.AllowAnySingleCharacter; } } // piece 6 MorphSet morph; if (lineMatchGroups[7].Success) { var morphAffixText = lineMatchGroups[7].Value; if (Builder.IsAliasM) { int morphNumber; if (IntEx.TryParseInvariant(morphAffixText, out morphNumber) && morphNumber > 0 && morphNumber <= Builder.AliasM.Count) { morph = Builder.AliasM[morphNumber - 1]; } else { Builder.LogWarning($"Failed to parse morph {morphAffixText} from: {parameterText}"); return(false); } } else { if (EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes)) { morphAffixText = morphAffixText.Reverse(); } morph = Builder.Dedup(MorphSet.TakeArray(Builder.DedupInPlace(morphAffixText.SplitOnTabOrSpace()))); } } else { morph = MorphSet.Empty; } if (affixGroup == null) { affixGroup = new AffixEntryGroup.Builder <TEntry> { AFlag = characterFlag, Options = AffixEntryOptions.None, Entries = new List <TEntry>() }; } if (!Builder.HasContClass && contClass.HasItems) { Builder.HasContClass = true; } affixGroup.Entries.Add(AffixEntry.Create <TEntry>( Builder.Dedup(strip), Builder.Dedup(StringBuilderPool.GetStringAndReturn(affixText)), Builder.Dedup(conditions), morph, contClass)); return(true); } else { Builder.LogWarning("Affix line not fully parsed: " + parameterText); return(false); } }
private bool TryHandleParameterizedCommand(string name, string parameters) { var commandName = name.ToUpperInvariant(); switch (commandName) { case "FLAG": // parse in the try string return(TrySetFlagMode(parameters)); case "KEY": // parse in the keyboard string Builder.KeyString = Builder.Dedup(parameters); return(true); case "TRY": // parse in the try string Builder.TryString = Builder.Dedup(parameters); return(true); case "SET": // parse in the name of the character set used by the .dict and .aff var encoding = EncodingEx.GetEncodingByName(parameters); if (encoding == null) { Builder.LogWarning("Failed to get encoding: " + parameters); return(false); } Builder.Encoding = encoding; return(true); case "LANG": // parse in the language for language specific codes Builder.Language = Builder.Dedup(parameters.Trim()); Builder.Culture = GetCultureFromLanguage(Builder.Language); return(true); case "SYLLABLENUM": // parse in the flag used by compound_check() method Builder.CompoundSyllableNum = Builder.Dedup(parameters); return(true); case "WORDCHARS": // parse in the extra word characters Builder.WordChars = CharacterSet.Create(parameters); return(true); case "IGNORE": // parse in the ignored characters (for example, Arabic optional diacretics characters) Builder.IgnoredChars = CharacterSet.Create(parameters); return(true); case "COMPOUNDFLAG": // parse in the flag used by the controlled compound words return(TryParseFlag(parameters, out Builder.CompoundFlag)); case "COMPOUNDMIDDLE": // parse in the flag used by compound words return(TryParseFlag(parameters, out Builder.CompoundMiddle)); case "COMPOUNDBEGIN": // parse in the flag used by compound words return(EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes) ? TryParseFlag(parameters, out Builder.CompoundEnd) : TryParseFlag(parameters, out Builder.CompoundBegin)); case "COMPOUNDEND": // parse in the flag used by compound words return(EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes) ? TryParseFlag(parameters, out Builder.CompoundBegin) : TryParseFlag(parameters, out Builder.CompoundEnd)); case "COMPOUNDWORDMAX": // parse in the data used by compound_check() method Builder.CompoundWordMax = IntEx.TryParseInvariant(parameters); return(Builder.CompoundWordMax.HasValue); case "COMPOUNDMIN": // parse in the minimal length for words in compounds Builder.CompoundMin = IntEx.TryParseInvariant(parameters); if (!Builder.CompoundMin.HasValue) { Builder.LogWarning("Failed to parse CompoundMin: " + parameters); return(false); } if (Builder.CompoundMin.GetValueOrDefault() < 1) { Builder.CompoundMin = 1; } return(true); case "COMPOUNDROOT": // parse in the flag sign compounds in dictionary return(TryParseFlag(parameters, out Builder.CompoundRoot)); case "COMPOUNDPERMITFLAG": // parse in the flag used by compound_check() method return(TryParseFlag(parameters, out Builder.CompoundPermitFlag)); case "COMPOUNDFORBIDFLAG": // parse in the flag used by compound_check() method return(TryParseFlag(parameters, out Builder.CompoundForbidFlag)); case "COMPOUNDSYLLABLE": // parse in the max. words and syllables in compounds return(TryParseCompoundSyllable(parameters)); case "NOSUGGEST": return(TryParseFlag(parameters, out Builder.NoSuggest)); case "NONGRAMSUGGEST": return(TryParseFlag(parameters, out Builder.NoNgramSuggest)); case "FORBIDDENWORD": // parse in the flag used by forbidden words Builder.ForbiddenWord = TryParseFlag(parameters); return(Builder.ForbiddenWord.HasValue); case "LEMMA_PRESENT": // parse in the flag used by forbidden words return(TryParseFlag(parameters, out Builder.LemmaPresent)); case "CIRCUMFIX": // parse in the flag used by circumfixes return(TryParseFlag(parameters, out Builder.Circumfix)); case "ONLYINCOMPOUND": // parse in the flag used by fogemorphemes return(TryParseFlag(parameters, out Builder.OnlyInCompound)); case "PSEUDOROOT": // parse in the flag used by `needaffixs' case "NEEDAFFIX": // parse in the flag used by `needaffixs' return(TryParseFlag(parameters, out Builder.NeedAffix)); case "REP": // parse in the typical fault correcting table return(TryParseStandardListItem(EntryListType.Replacements, parameters, ref Builder.Replacements, TryParseReplacements)); case "ICONV": // parse in the input conversion table return(TryParseConv(parameters, EntryListType.Iconv, ref Builder.InputConversions)); case "OCONV": // parse in the output conversion table return(TryParseConv(parameters, EntryListType.Oconv, ref Builder.OutputConversions)); case "PHONE": // parse in the phonetic conversion table return(TryParseStandardListItem(EntryListType.Phone, parameters, ref Builder.Phone, TryParsePhone)); case "CHECKCOMPOUNDPATTERN": // parse in the checkcompoundpattern table return(TryParseStandardListItem(EntryListType.CompoundPatterns, parameters, ref Builder.CompoundPatterns, TryParseCheckCompoundPatternIntoCompoundPatterns)); case "COMPOUNDRULE": // parse in the defcompound table return(TryParseStandardListItem(EntryListType.CompoundRules, parameters, ref Builder.CompoundRules, TryParseCompoundRuleIntoList)); case "MAP": // parse in the related character map table return(TryParseStandardListItem(EntryListType.Map, parameters, ref Builder.RelatedCharacterMap, TryParseMapEntry)); case "BREAK": // parse in the word breakpoints table return(TryParseStandardListItem(EntryListType.Break, parameters, ref Builder.BreakPoints, TryParseBreak)); case "VERSION": Builder.Version = parameters; return(true); case "MAXNGRAMSUGS": Builder.MaxNgramSuggestions = IntEx.TryParseInvariant(parameters); return(Builder.MaxNgramSuggestions.HasValue); case "MAXDIFF": Builder.MaxDifferency = IntEx.TryParseInvariant(parameters); return(Builder.MaxDifferency.HasValue); case "MAXCPDSUGS": Builder.MaxCompoundSuggestions = IntEx.TryParseInvariant(parameters); return(Builder.MaxCompoundSuggestions.HasValue); case "KEEPCASE": // parse in the flag used by forbidden words return(TryParseFlag(parameters, out Builder.KeepCase)); case "FORCEUCASE": return(TryParseFlag(parameters, out Builder.ForceUpperCase)); case "WARN": return(TryParseFlag(parameters, out Builder.Warn)); case "SUBSTANDARD": return(TryParseFlag(parameters, out Builder.SubStandard)); case "PFX": case "SFX": var parseAsPrefix = "PFX" == commandName; if (EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes)) { parseAsPrefix = !parseAsPrefix; } return(parseAsPrefix ? TryParseAffixIntoList(parameters, ref Builder.Prefixes) : TryParseAffixIntoList(parameters, ref Builder.Suffixes)); case "AF": return(TryParseStandardListItem(EntryListType.AliasF, parameters, ref Builder.AliasF, TryParseAliasF)); case "AM": return(TryParseStandardListItem(EntryListType.AliasM, parameters, ref Builder.AliasM, TryParseAliasM)); default: Builder.LogWarning($"Unknown command {commandName} with params: {parameters}"); return(false); } }
private bool TryHandleParameterizedCommand(string commandName, string parameters) { if (commandName == null || !CommandMap.TryGetValue(commandName, out AffixReaderCommandKind command)) { Builder.LogWarning($"Unknown command {commandName} with params: {parameters}"); return(false); } switch (command) { case AffixReaderCommandKind.Flag: return(TrySetFlagMode(parameters)); case AffixReaderCommandKind.KeyString: Builder.KeyString = Builder.Dedup(parameters); return(true); case AffixReaderCommandKind.TryString: Builder.TryString = Builder.Dedup(parameters); return(true); case AffixReaderCommandKind.SetEncoding: var encoding = EncodingEx.GetEncodingByName(parameters); if (encoding == null) { Builder.LogWarning("Failed to get encoding: " + parameters); return(false); } Builder.Encoding = encoding; return(true); case AffixReaderCommandKind.Language: Builder.Language = Builder.Dedup(parameters.Trim()); Builder.Culture = GetCultureFromLanguage(Builder.Language); return(true); case AffixReaderCommandKind.CompoundSyllableNum: Builder.CompoundSyllableNum = Builder.Dedup(parameters); return(true); case AffixReaderCommandKind.WordChars: Builder.WordChars = CharacterSet.Create(parameters); return(true); case AffixReaderCommandKind.Ignore: Builder.IgnoredChars = CharacterSet.Create(parameters); return(true); case AffixReaderCommandKind.CompoundFlag: return(TryParseFlag(parameters, out Builder.CompoundFlag)); case AffixReaderCommandKind.CompoundMiddle: return(TryParseFlag(parameters, out Builder.CompoundMiddle)); case AffixReaderCommandKind.CompoundBegin: return(EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes) ? TryParseFlag(parameters, out Builder.CompoundEnd) : TryParseFlag(parameters, out Builder.CompoundBegin)); case AffixReaderCommandKind.CompoundEnd: return(EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes) ? TryParseFlag(parameters, out Builder.CompoundBegin) : TryParseFlag(parameters, out Builder.CompoundEnd)); case AffixReaderCommandKind.CompoundWordMax: Builder.CompoundWordMax = IntEx.TryParseInvariant(parameters); return(Builder.CompoundWordMax.HasValue); case AffixReaderCommandKind.CompoundMin: Builder.CompoundMin = IntEx.TryParseInvariant(parameters); if (!Builder.CompoundMin.HasValue) { Builder.LogWarning("Failed to parse CompoundMin: " + parameters); return(false); } if (Builder.CompoundMin.GetValueOrDefault() < 1) { Builder.CompoundMin = 1; } return(true); case AffixReaderCommandKind.CompoundRoot: return(TryParseFlag(parameters, out Builder.CompoundRoot)); case AffixReaderCommandKind.CompoundPermitFlag: return(TryParseFlag(parameters, out Builder.CompoundPermitFlag)); case AffixReaderCommandKind.CompoundForbidFlag: return(TryParseFlag(parameters, out Builder.CompoundForbidFlag)); case AffixReaderCommandKind.CompoundSyllable: return(TryParseCompoundSyllable(parameters)); case AffixReaderCommandKind.NoSuggest: return(TryParseFlag(parameters, out Builder.NoSuggest)); case AffixReaderCommandKind.NoNGramSuggest: return(TryParseFlag(parameters, out Builder.NoNgramSuggest)); case AffixReaderCommandKind.ForbiddenWord: Builder.ForbiddenWord = TryParseFlag(parameters); return(Builder.ForbiddenWord.HasValue); case AffixReaderCommandKind.LemmaPresent: return(TryParseFlag(parameters, out Builder.LemmaPresent)); case AffixReaderCommandKind.Circumfix: return(TryParseFlag(parameters, out Builder.Circumfix)); case AffixReaderCommandKind.OnlyInCompound: return(TryParseFlag(parameters, out Builder.OnlyInCompound)); case AffixReaderCommandKind.NeedAffix: return(TryParseFlag(parameters, out Builder.NeedAffix)); case AffixReaderCommandKind.Replacement: return(TryParseStandardListItem(EntryListType.Replacements, parameters, ref Builder.Replacements, TryParseReplacements)); case AffixReaderCommandKind.InputConversions: return(TryParseConv(parameters, EntryListType.Iconv, ref Builder.InputConversions)); case AffixReaderCommandKind.OutputConversions: return(TryParseConv(parameters, EntryListType.Oconv, ref Builder.OutputConversions)); case AffixReaderCommandKind.Phone: return(TryParseStandardListItem(EntryListType.Phone, parameters, ref Builder.Phone, TryParsePhone)); case AffixReaderCommandKind.CheckCompoundPattern: return(TryParseStandardListItem(EntryListType.CompoundPatterns, parameters, ref Builder.CompoundPatterns, TryParseCheckCompoundPatternIntoCompoundPatterns)); case AffixReaderCommandKind.CompoundRule: return(TryParseStandardListItem(EntryListType.CompoundRules, parameters, ref Builder.CompoundRules, TryParseCompoundRuleIntoList)); case AffixReaderCommandKind.Map: return(TryParseStandardListItem(EntryListType.Map, parameters, ref Builder.RelatedCharacterMap, TryParseMapEntry)); case AffixReaderCommandKind.Break: return(TryParseStandardListItem(EntryListType.Break, parameters, ref Builder.BreakPoints, TryParseBreak)); case AffixReaderCommandKind.Version: Builder.Version = parameters; return(true); case AffixReaderCommandKind.MaxNgramSuggestions: Builder.MaxNgramSuggestions = IntEx.TryParseInvariant(parameters); return(Builder.MaxNgramSuggestions.HasValue); case AffixReaderCommandKind.MaxDifferency: Builder.MaxDifferency = IntEx.TryParseInvariant(parameters); return(Builder.MaxDifferency.HasValue); case AffixReaderCommandKind.MaxCompoundSuggestions: Builder.MaxCompoundSuggestions = IntEx.TryParseInvariant(parameters); return(Builder.MaxCompoundSuggestions.HasValue); case AffixReaderCommandKind.KeepCase: return(TryParseFlag(parameters, out Builder.KeepCase)); case AffixReaderCommandKind.ForceUpperCase: return(TryParseFlag(parameters, out Builder.ForceUpperCase)); case AffixReaderCommandKind.Warn: return(TryParseFlag(parameters, out Builder.Warn)); case AffixReaderCommandKind.SubStandard: return(TryParseFlag(parameters, out Builder.SubStandard)); case AffixReaderCommandKind.Prefix: case AffixReaderCommandKind.Suffix: var parseAsPrefix = AffixReaderCommandKind.Prefix == command; if (EnumEx.HasFlag(Builder.Options, AffixConfigOptions.ComplexPrefixes)) { parseAsPrefix = !parseAsPrefix; } return(parseAsPrefix ? TryParseAffixIntoList(parameters, ref Builder.Prefixes) : TryParseAffixIntoList(parameters, ref Builder.Suffixes)); case AffixReaderCommandKind.AliasF: return(TryParseStandardListItem(EntryListType.AliasF, parameters, ref Builder.AliasF, TryParseAliasF)); case AffixReaderCommandKind.AliasM: return(TryParseStandardListItem(EntryListType.AliasM, parameters, ref Builder.AliasM, TryParseAliasM)); default: Builder.LogWarning($"Unknown parsed command {command}"); return(false); } }