internal static IList <AbstractSkriptPatternElement> Flatten(AbstractSkriptPatternElement element)
 {
     return(element switch
     {
         SkriptPattern skriptPattern => skriptPattern.Children.SelectMany(Flatten).ToList(),
         _ => new List <AbstractSkriptPatternElement> {
             element
         }
     });
        public static SkriptPattern ParsePattern(ParseContext ctx, bool fastFail = false)
        {
            var pattern        = new SkriptPattern();
            var literalBuilder = new StringBuilder();

            void AddLiteralIfExists()
            {
                if (string.IsNullOrEmpty(literalBuilder.ToString()))
                {
                    return;
                }
                pattern.Children.Add(new LiteralPatternElement(literalBuilder.ToString()));
                literalBuilder.Clear();
            }

            var isNextCharEscaped = false;

            foreach (var c in ctx)
            {
                if (c == '\\' && !isNextCharEscaped)
                {
                    isNextCharEscaped = true;
                    continue;
                }

                var(type, info) = GroupTypes
                                  .Select(cc => (Type: cc, Info: cc.GetCustomAttribute <GroupPatternElementInfoAttribute>()))
                                  .FirstOrDefault(cc => cc.Item2.OpeningBracket == c);

                if (!isNextCharEscaped && info != null)
                {
                    AddLiteralIfExists();
                    var closingBracketPos =
                        ctx.FindNextBracket(info.OpeningBracket, info.ClosingBracket, escapeWithBackSlash: true);

                    if (closingBracketPos >= 0)
                    {
                        var innerText = ctx.ReadUntilPosition(closingBracketPos);

                        //Read closing bracket
                        ctx.ReadNext(1);

                        pattern.Children.Add(
                            Activator.CreateInstance(type, innerText) as AbstractGroupPatternElement);
                    }
                }
                else
                {
                    var isWhiteSpace = char.IsWhiteSpace(c);
                    if (isWhiteSpace)
                    {
                        AddLiteralIfExists();
                        pattern.Children.Add(new LiteralPatternElement(c.ToString()));
                    }
                    else
                    {
                        literalBuilder.Append(c);
                    }
                }

                isNextCharEscaped = false;
            }

            AddLiteralIfExists();

            pattern.FastFail = fastFail;
            return(pattern);
        }