using System; using System.Collections.Generic; using ln.templates.elements; using System.IO; using System.Text; namespace ln.templates { public class TemplateReader { public ContainerElement RootElement { get; private set; } = new ContainerElement(null); public ContainerElement CurrentElement { get; private set; } public Expression FrameExpression { get; private set; } public String Source { get; private set; } public TemplateReader(String source) { Source = source; Parse(); } private void Parse() { CurrentElement = RootElement; while (Source.Length > 0) { String t, op; int i, j; i = Source.IndexOf("<%"); if (i == -1) { t = Source; op = null; Source = ""; } else { t = Source.Substring(0, i); j = Source.IndexOf("%>", i + 1); if (j == -1) { throw new FormatException(String.Format("missing '%>' in {0}", Source.Substring(i, 64))); } op = Source.Substring(i + 2, j - i - 2); Source = Source.Substring(j + 2); } new TextElement(CurrentElement, t); if (op != null) ParseOP(op); } } private void ParseOP(String op) { StringReader reader = new StringReader(op); String opkey; if (reader.Peek() == '=') { reader.Read(); opkey = "="; } else { opkey = reader.PopWord(); } switch (opkey) { case "=": new ExpressionElement(CurrentElement, new Expression(reader.ReadToEnd())); break; case "frame": FrameExpression = new Expression(reader.ReadToEnd()); break; case "iterate": String iterName = reader.PopWord(); CurrentElement = new IteratorElement(CurrentElement, iterName, new Expression(reader.ReadToEnd())); break; case "if": CurrentElement = new ConditionalElement(CurrentElement, new Expression(reader.ReadToEnd())); break; case "else": if (CurrentElement is ConditionalElement) { ConditionalElement ce = CurrentElement as ConditionalElement; CurrentElement = ce.AlternativeContainer; } break; case "elseif": if (CurrentElement is ConditionalElement) { ConditionalElement ce = CurrentElement as ConditionalElement; CurrentElement = new ConditionalElement(null, new Expression(reader.ReadToEnd())); ce.AlternativeContainer = CurrentElement; } break; case "include": new IncludeElement(CurrentElement, new Expression(reader.ReadToEnd())); break; case "set": String setName = reader.PopWord(); new SetElement(CurrentElement, setName, new Expression(reader.ReadToEnd())); break; case "end": CurrentElement = CurrentElement.Container; break; default: throw new NotImplementedException(opkey); } } } static class StringHelper { public static int IndexOf(this String s,Func predicate) { for (int i=0;i