コード例 #1
0
            /// <summary>
            /// Recursive search for right ss - sharp s permutations
            /// </summary>
            private WordEntry SpellSharps(ref string @base, int nPos, int n, int repNum, ref SpellCheckResultType info, out string root)
            {
                var pos = @base.IndexOfOrdinal("ss", nPos);

                if (pos >= 0 && n < MaxSharps)
                {
                    var baseBuilder = StringBuilderPool.Get(@base, @base.Length);
                    baseBuilder[pos] = 'ß';
                    baseBuilder.Remove(pos + 1, 1);
                    @base = baseBuilder.ToString();

                    var h = SpellSharps(ref @base, pos + 1, n + 1, repNum + 1, ref info, out root);
                    if (h != null)
                    {
                        return(h);
                    }

                    baseBuilder.Clear();
                    baseBuilder.Append(@base);
                    baseBuilder[pos] = 's';
                    baseBuilder.Insert(pos + 1, 's');
                    @base = StringBuilderPool.GetStringAndReturn(baseBuilder);

                    h = SpellSharps(ref @base, pos + 2, n + 1, repNum, ref info, out root);
                    if (h != null)
                    {
                        return(h);
                    }
                }
                else if (repNum > 0)
                {
                    return(CheckWord(@base, ref info, out root));
                }

                root = null;
                return(null);
            }
コード例 #2
0
        public string ReadLine()
        {
            if (!hasCheckedForPreamble)
            {
                ReadPreamble();
            }

            var builder = StringBuilderPool.Get();

            while (ReadNextChars())
            {
                if (ProcessCharsForLine(builder))
                {
                    break;
                }
            }

            if (charBuffer == null && builder.Length == 0)
            {
                return(null);
            }

            return(ProcessLine(StringBuilderPool.GetStringAndReturn(builder)));
        }
コード例 #3
0
        public async Task <string> ReadLineAsync()
        {
            if (!hasCheckedForPreamble)
            {
                await ReadPreambleAsync().ConfigureAwait(false);
            }

            var builder = StringBuilderPool.Get();

            while (await ReadNextCharsAsync().ConfigureAwait(false))
            {
                if (ProcessCharsForLine(builder))
                {
                    break;
                }
            }

            if (charBuffer == null && builder.Length == 0)
            {
                return(null);
            }

            return(ProcessLine(StringBuilderPool.GetStringAndReturn(builder)));
        }
コード例 #4
0
        private static string ReverseCondition(string conditionText)
        {
            if (string.IsNullOrEmpty(conditionText))
            {
                return(conditionText);
            }

            var chars = StringBuilderPool.Get(conditionText);

            chars.Reverse();
            var neg       = false;
            var lastIndex = chars.Length - 1;

            for (int k = lastIndex; k >= 0; k--)
            {
                switch (chars[k])
                {
                case '[':
                    if (neg)
                    {
                        if (k < lastIndex)
                        {
                            chars[k + 1] = '[';
                        }
                    }
                    else
                    {
                        chars[k] = ']';
                    }

                    break;

                case ']':
                    chars[k] = '[';
                    if (neg && k < lastIndex)
                    {
                        chars[k + 1] = '^';
                    }

                    neg = false;

                    break;

                case '^':
                    if (k < lastIndex)
                    {
                        if (chars[k + 1] == ']')
                        {
                            neg = true;
                        }
                        else
                        {
                            chars[k + 1] = chars[k];
                        }
                    }

                    break;

                default:
                    if (neg && k < lastIndex)
                    {
                        chars[k + 1] = chars[k];
                    }
                    break;
                }
            }

            return(StringBuilderPool.GetStringAndReturn(chars));
        }
コード例 #5
0
        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);
            }
        }