152 lines
4.8 KiB
C#
152 lines
4.8 KiB
C#
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<char,bool> predicate)
|
|
{
|
|
for (int i=0;i<s.Length;i++)
|
|
{
|
|
if (predicate(s[i]))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public static void SkipWhiteSpace(this TextReader reader)
|
|
{
|
|
while (char.IsWhiteSpace((char)reader.Peek()))
|
|
{
|
|
reader.Read();
|
|
}
|
|
}
|
|
public static String PopWord(this TextReader reader)
|
|
{
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
while ((reader.Peek()!=-1) && !char.IsWhiteSpace((char)reader.Peek()))
|
|
{
|
|
stringBuilder.Append((char)reader.Read());
|
|
}
|
|
reader.SkipWhiteSpace();
|
|
return stringBuilder.ToString();
|
|
}
|
|
}
|
|
}
|