public override void ToString(StringBuilder sb, ScopedDictionary <string, ValueProviderBase> variables)
            {
                sb.Append("@");
                if (IsRaw)
                {
                    sb.Append("raw");
                }

                ValueProvider !.ToStringBrackets(sb, variables, Format.HasText() ? (":" + TemplateUtils.ScapeColon(Format)) : null);
            }
Beispiel #2
0
            void ParseInternal()
            {
                try
                {
                    this.mainBlock = new BlockNode(null);
                    this.stack     = new Stack <BlockNode>();
                    this.errors    = new List <TemplateError>();
                    PushBlock(mainBlock);

                    var matches = TemplateUtils.KeywordsRegex.Matches(text);

                    if (matches.Count == 0)
                    {
                        stack.Peek().Nodes.Add(new LiteralNode(text));
                        stack.Pop();
                        return;
                    }

                    int index = 0;
                    foreach (Match match in matches.Cast <Match>())
                    {
                        if (index < match.Index)
                        {
                            stack.Peek().Nodes.Add(new LiteralNode(text.Substring(index, match.Index - index)));
                        }
                        var expr     = match.Groups["expr"].Value;
                        var keyword  = match.Groups["keyword"].Value;
                        var variable = match.Groups["dec"].Value;
                        switch (keyword)
                        {
                        case "":
                        case "raw":
                            var s = TemplateUtils.SplitToken(expr);
                            if (s == null)
                            {
                                AddError(true, "{0} has invalid format".FormatWith(expr));
                            }
                            else
                            {
                                var t = ValueProviderBase.TryParse(s.Value.Token, variable, this);

                                stack.Peek().Nodes.Add(new ValueNode(t, s.Value.Format, isRaw: keyword.Contains("raw")));

                                DeclareVariable(t);
                            }
                            break;

                        case "declare":
                        {
                            var t = ValueProviderBase.TryParse(expr, variable, this);

                            stack.Peek().Nodes.Add(new DeclareNode(t, this.AddError));

                            DeclareVariable(t);
                        }
                        break;

                        case "any":
                        {
                            ConditionBase cond = TemplateUtils.ParseCondition(expr, variable, this);
                            AnyNode       any  = new AnyNode(cond);
                            stack.Peek().Nodes.Add(any);
                            PushBlock(any.AnyBlock);
                            if (cond is ConditionCompare cc)
                            {
                                DeclareVariable(cc.ValueProvider);
                            }
                            break;
                        }

                        case "notany":
                        {
                            var an = (AnyNode?)PopBlock(typeof(AnyNode))?.owner;
                            if (an != null)
                            {
                                PushBlock(an.CreateNotAny());
                            }
                            break;
                        }

                        case "endany":
                        {
                            PopBlock(typeof(AnyNode));
                            break;
                        }

                        case "foreach":
                        {
                            ValueProviderBase?vp = ValueProviderBase.TryParse(expr, variable, this);
                            if (vp is TokenValueProvider tvp && tvp.ParsedToken.QueryToken != null && QueryToken.IsCollection(tvp.ParsedToken.QueryToken.Type))
                            {
                                AddError(false, $"@foreach[{expr}] is a collection, missing 'Element' token at the end");
                            }

                            var fn = new ForeachNode(vp);
                            stack.Peek().Nodes.Add(fn);
                            PushBlock(fn.Block);
                            if (vp != null)
                            {
                                vp.IsForeach = true;
                            }
                            DeclareVariable(vp);
                            break;
                        }

                        case "endforeach":
                        {
                            PopBlock(typeof(ForeachNode));
                        }
                        break;

                        case "if":
                        {
                            ConditionBase cond = TemplateUtils.ParseCondition(expr, variable, this);
                            IfNode        ifn  = new IfNode(cond, this);
                            stack.Peek().Nodes.Add(ifn);
                            PushBlock(ifn.IfBlock);
                            if (cond is ConditionCompare cc)
                            {
                                DeclareVariable(cc.ValueProvider);
                            }
                            break;
                        }

                        case "else":
                        {
                            var ifn = (IfNode?)PopBlock(typeof(IfNode))?.owner;
                            if (ifn != null)
                            {
                                PushBlock(ifn.CreateElse());
                            }
                            break;
                        }

                        case "endif":
                        {
                            PopBlock(typeof(IfNode));
                            break;
                        }

                        default:
                            AddError(true, "'{0}' is deprecated".FormatWith(keyword));
                            break;
                        }
                        index = match.Index + match.Length;
                    }

                    if (stack.Count != 1)
                    {
                        AddError(true, "Last block is not closed: {0}".FormatWith(stack.Peek()));
                    }

                    var lastM = matches.Cast <Match>().LastOrDefault();
                    if (lastM != null && lastM.Index + lastM.Length < text.Length)
                    {
                        stack.Peek().Nodes.Add(new LiteralNode(text.Substring(lastM.Index + lastM.Length)));
                    }

                    stack.Pop();
                }
                catch (Exception e)
                {
                    AddError(true, e.Message);
                }
            }