protected override string TryParse(ParseContext ctx)
        {
            if (ctx.PeekNext(1) != "\"")
            {
                return(null);
            }
            ctx.ReadNext(1); //Read open quote
            var closingPos = ctx.FindNextBracket('"', true);

            if (closingPos <= -1)
            {
                return(null);
            }
            var value = ctx.ReadUntilPosition(closingPos);

            return(ctx.ReadNext(1) == "\"" ? value.Replace("\"\"", "\"") : null);
        }
        public IExpression TryParseValue(ParseContext ctx)
        {
            ctx.StartRangeMeasure();
            if (ctx.PeekNext(1) == "(")
            {
                ctx.ReadNext(1); //Read the first bracket
                var nextBracket = ctx.FindNextBracket('(', ')');

                if (nextBracket != -1)
                {
                    var ctxClone = ctx.Clone(false);

                    var result = InnerPattern.Parse(ctxClone);
                    var value  = result.Matches.OfType <ExpressionParseMatch>().FirstOrDefault()?.Expression;
                    var oldPos = ctxClone.CurrentPosition;
                    if (result.IsSuccess)
                    {
                        ctx.ReadUntilPosition(oldPos);
                    }

                    if (value != null && ctx.ReadNext(1) == ")")
                    {
                        return(new ParenthesesExpression(value, this)
                        {
                            Range = ctx.EndRangeMeasure()
                        });
                    }

                    //Rollback in case of it not working
                    ctx.CurrentPosition = oldPos;
                }
            }

            ctx.UndoRangeMeasure();
            return(null);
        }
        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);
        }
 public static SkriptVariable TryParse(ParseContext ctx)
 {
     if (ctx.ReadNext(1) == "{")
     {
         var variable    = new SkriptVariable();
         var nextBracket = ctx.FindNextBracket('{', '}', matchExclusions: new[] { ('{', '}') });