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)); }