Exemple #1
0
        private void Parse()
        {
            for (m = reConstruct.Match(inputString); m.Success; m = m.NextMatch())
            {
                if (lastIndex != m.Index)
                {
                    ParseTextContent(inputString.Substring(lastIndex, m.Index - lastIndex));
                }
                lastIndex = m.Index + m.Length;

                var m1 = m.Groups[1].Value;
                var m2 = m.Groups[2].Value;
                switch (m1)
                {
                case "!":
                    break;

                case "/":
                    Assert(controlStack.Count > 0 && m2 == controlStack.Peek().TokenName);
                    controlStack.Peek().Token.Index = this.Count;
                    if (m2 == TOKEN_FOREACH)
                    {
                        this.Add(new IterationEndToken(controlStack.Peek().TokenIndex + 1));
                    }
                    controlStack.Pop();
                    break;

                case TOKEN_IF:
                case TOKEN_IFNOT: {
                    ConditionToken t = new ConditionToken(CreatePipe(), m1 == TOKEN_IFNOT);
                    controlStack.Push(new ControlTokenInfo(TOKEN_IF, this.Count, t));
                    break;
                }

                case TOKEN_ELSE:
                case TOKEN_ELSEIF:
                case TOKEN_ELSEIFNOT: {
                    Assert(controlStack.Count > 0 && controlStack.Peek().TokenName == TOKEN_IF);
                    ControlTokenInfo previousControl = controlStack.Pop();
                    BranchToken      t = new BranchToken();
                    controlStack.Push(new ControlTokenInfo(TOKEN_IF, this.Count, t));

                    (previousControl.TokenIf ?? previousControl.Token).Index = this.Count;
                    if (previousControl.Token.Type == TokenType.OP_JUMP)
                    {
                        controlStack.Peek().Token = previousControl.Token;
                    }
                    this.Add(t);
                    if (m1 == TOKEN_ELSEIF || m1 == TOKEN_ELSEIFNOT)
                    {
                        controlStack.Peek().TokenIf = new ConditionToken(CreatePipe(), m1 == TOKEN_ELSEIFNOT);
                    }
                    break;
                }

                case TOKEN_FOREACH: {
                    IterationToken t = new IterationToken(CreatePipe());
                    controlStack.Push(new ControlTokenInfo(TOKEN_FOREACH, this.Count, t));
                    this.Add(t);
                    break;
                }

                default:
                    this.Add(new EvaluateToken(CreatePipe(), m1 == "&"));
                    break;
                }
            }
            if (lastIndex != inputString.Length)
            {
                ParseTextContent(inputString.Substring(lastIndex));
            }
        }
        private object Evaluate()
        {
            StringBuilder sb = new StringBuilder();

            try {
                int i = 0;
                int e = tokens.Count;
                while (i < e)
                {
                    Token t = tokens[i++];
                    switch (t.Type)
                    {
                    case TokenType.OP_EVAL:
                        EvaluateToken et        = (EvaluateToken)t;
                        int           prevCount = evalCount;
                        PipeValue     result    = et.Expression.Evaluate(this);
                        if (result.IsEvallable)
                        {
                            string str = result.Type == PipeValueType.Object ? JsonConvert.SerializeObject(result) : result.ToString();
                            if (evalCount != prevCount || et.SuppressHtmlEncode)
                            {
                                sb.Append(str);
                            }
                            else
                            {
                                sb.Append(HttpUtility.HtmlEncode(str));
                            }
                        }
                        break;

                    case TokenType.OP_ITER:
                        IterationToken it       = (IterationToken)t;
                        IEnumerator    iterable = it.Expression.Evaluate(this).GetEnumerator();
                        PushObjectStack(iterable);
                        if (!iterable.MoveNext())
                        {
                            i = it.Index;
                        }
                        break;

                    case TokenType.OP_ITER_END:
                        IterationEndToken iet = (IterationEndToken)t;
                        if (!((IEnumerator)objStack.Peek().Value).MoveNext())
                        {
                            PopObjectStack();
                        }
                        else
                        {
                            i = iet.Index;
                        }
                        break;

                    case TokenType.OP_TEST:
                        ConditionToken ct = (ConditionToken)t;
                        if (!(bool)ct.Expression.Evaluate(this) ^ ct.Negate)
                        {
                            i = ct.Index;
                        }
                        break;

                    case TokenType.OP_JUMP:
                        i = ((BranchToken)t).Index;
                        break;

                    default:
                        OutputToken ot = (OutputToken)t;
                        if (this.Options.OutputXml)
                        {
                            XmlElement      currentElm = xmlStack.Peek();
                            HtmlOutputToken ht         = (HtmlOutputToken)ot;
                            switch (t.Type)
                            {
                            case TokenType.HTMLOP_ELEMENT_START:
                                FlushOutput(sb, currentElm);
                                xmlStack.Push(currentElm.OwnerDocument.CreateElement(ht.TagName));
                                currentElm.AppendChild(xmlStack.Peek());
                                break;

                            case TokenType.HTMLOP_ELEMENT_END:
                                FlushOutput(sb, currentElm);
                                xmlStack.Pop();
                                break;

                            case TokenType.HTMLOP_ATTR_END:
                                XmlAttribute attr = currentElm.OwnerDocument.CreateAttribute(ht.AttributeName);
                                attr.Value = sb.ToString();
                                currentElm.Attributes.Append(attr);
                                sb.Clear();
                                break;

                            case TokenType.HTMLOP_TEXT:
                                sb.Append(ht.Text);
                                break;
                            }
                        }
                        else
                        {
                            sb.Append(ot.Value);
                            i = ot.Index;
                        }
                        break;
                    }
                }
            } finally {
                evalCount = (evalCount + 1) & 0xFFFF;
            }
            if (this.Options.OutputXml)
            {
                FlushOutput(sb, xmlStack.Peek());
                return(xmlStack.Peek());
            }
            return(Regex.Replace(sb.ToString(), @"^\s+(?=<)|(>)\s+(<|$)", m => m.Groups[1].Value + m.Groups[2].Value));
        }