WIP
parent
09be9fb80f
commit
fada8eea23
175
Expression.cs
175
Expression.cs
|
@ -3,6 +3,8 @@ using System.Reflection;
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
namespace ln.templates
|
||||
{
|
||||
delegate bool ConditionDelegate(char ch);
|
||||
|
@ -34,54 +36,99 @@ namespace ln.templates
|
|||
|
||||
private void Compile()
|
||||
{
|
||||
StringReader reader = new StringReader(Source);
|
||||
List<Token> tokens = new List<Token>();
|
||||
while (reader.Peek() != -1)
|
||||
ReadToken(reader, tokens);
|
||||
TopEval = BuildEval(tokens);
|
||||
try
|
||||
{
|
||||
StringReader reader = new StringReader(Source);
|
||||
List<Token> tokens = new List<Token>();
|
||||
while (reader.Peek() != -1)
|
||||
ReadToken(reader, tokens);
|
||||
|
||||
Queue<Token> qtokens = new Queue<Token>(tokens);
|
||||
|
||||
TopEval = BuildExpression(qtokens);
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw new Exception(String.Format("Failed to compile expression: {0}", Source), e);
|
||||
}
|
||||
}
|
||||
|
||||
private Eval BuildEval(List<Token> tokens)
|
||||
|
||||
private Eval BuildName(Token nameToken,Eval parent,Queue<Token> tokens)
|
||||
{
|
||||
Eval currentEval = null;
|
||||
if ((tokens.Count > 0) && (tokens.Peek().TokenType == TokenType.OPENLIST))
|
||||
{
|
||||
tokens.Dequeue();
|
||||
|
||||
List<Eval> pl = new List<Eval>();
|
||||
while (tokens.Peek().TokenType != TokenType.ENDLIST)
|
||||
{
|
||||
pl.Add(BuildExpression(tokens));
|
||||
|
||||
if (tokens.Peek().TokenType == TokenType.ENDLIST)
|
||||
break;
|
||||
|
||||
if (tokens.Peek().TokenType != TokenType.COMMA)
|
||||
throw new FormatException("Expected ',' between parameters to call statement");
|
||||
|
||||
tokens.Dequeue();
|
||||
}
|
||||
|
||||
tokens.Dequeue();
|
||||
|
||||
return new MethodCall(parent, nameToken.Value, pl.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Name(parent, nameToken.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private Eval BuildPath(Queue<Token> tokens)
|
||||
{
|
||||
Eval currentEval = BuildName(tokens.Dequeue(), null, tokens);
|
||||
|
||||
while (tokens.Count > 0)
|
||||
{
|
||||
Token token = tokens[0];
|
||||
tokens.RemoveAt(0);
|
||||
|
||||
Token token = tokens.Peek();
|
||||
switch (token.TokenType)
|
||||
{
|
||||
case TokenType.DOT:
|
||||
token = tokens[0];
|
||||
tokens.RemoveAt(0);
|
||||
if (token.TokenType != TokenType.NAME)
|
||||
throw new ArgumentException("missing fieldname after .");
|
||||
currentEval = new Name(currentEval, token.Value);
|
||||
tokens.Dequeue();
|
||||
currentEval = BuildName(tokens.Dequeue(), currentEval, tokens);
|
||||
break;
|
||||
case TokenType.NAME:
|
||||
currentEval = new Name(currentEval, token.Value);
|
||||
break;
|
||||
case TokenType.NUMBER:
|
||||
currentEval = new Number(token.Value);
|
||||
break;
|
||||
case TokenType.STRING:
|
||||
currentEval = new CString(token.Value);
|
||||
break;
|
||||
case TokenType.BRACKET:
|
||||
if (token.Value.Equals("["))
|
||||
{
|
||||
currentEval = new Indexer(currentEval, BuildEval(tokens));
|
||||
} else if (token.Value.Equals("]"))
|
||||
{
|
||||
return currentEval;
|
||||
}
|
||||
case TokenType.OPENINDEXER:
|
||||
tokens.Dequeue();
|
||||
Eval index = BuildExpression(tokens);
|
||||
token = tokens.Dequeue();
|
||||
if (token.TokenType != TokenType.ENDINDEXER)
|
||||
throw new FormatException("Expected ']'");
|
||||
currentEval = new Indexer(currentEval, index);
|
||||
break;
|
||||
default:
|
||||
return currentEval;
|
||||
}
|
||||
}
|
||||
return currentEval;
|
||||
}
|
||||
|
||||
|
||||
private Eval BuildExpression(Queue<Token> tokens)
|
||||
{
|
||||
Token next = tokens.Peek();
|
||||
|
||||
switch (next.TokenType)
|
||||
{
|
||||
case TokenType.NAME:
|
||||
return BuildPath(tokens);
|
||||
case TokenType.NUMBER:
|
||||
return new Number(tokens.Dequeue().Value);
|
||||
case TokenType.STRING:
|
||||
return new CString(tokens.Dequeue().Value);
|
||||
}
|
||||
|
||||
throw new FormatException(String.Format("unexpected Token: {0}", next.Value));
|
||||
}
|
||||
|
||||
private void ReadToken(TextReader reader, List<Token> tokens)
|
||||
{
|
||||
if (reader.Peek() == -1)
|
||||
|
@ -91,7 +138,7 @@ namespace ln.templates
|
|||
{
|
||||
reader.Read();
|
||||
}
|
||||
else if (char.IsLetter(ch))
|
||||
else if (char.IsLetter(ch) || (ch == '_'))
|
||||
{
|
||||
ReadName(reader, tokens);
|
||||
}
|
||||
|
@ -108,10 +155,30 @@ namespace ln.templates
|
|||
reader.Read();
|
||||
tokens.Add(new Token(TokenType.DOT, "."));
|
||||
}
|
||||
else if ((ch == '[')| (ch == ']'))
|
||||
else if (ch == '[')
|
||||
{
|
||||
reader.Read();
|
||||
tokens.Add(new Token(TokenType.BRACKET, new string(new char[] { ch })));
|
||||
tokens.Add(new Token(TokenType.OPENINDEXER, new string(new char[] { ch })));
|
||||
}
|
||||
else if (ch == ']')
|
||||
{
|
||||
reader.Read();
|
||||
tokens.Add(new Token(TokenType.ENDINDEXER, new string(new char[] { ch })));
|
||||
}
|
||||
else if (ch == '(')
|
||||
{
|
||||
reader.Read();
|
||||
tokens.Add(new Token(TokenType.OPENLIST, new string(new char[] { ch })));
|
||||
}
|
||||
else if (ch == ')')
|
||||
{
|
||||
reader.Read();
|
||||
tokens.Add(new Token(TokenType.ENDLIST, new string(new char[] { ch })));
|
||||
}
|
||||
else if (ch == ',')
|
||||
{
|
||||
reader.Read();
|
||||
tokens.Add(new Token(TokenType.COMMA, new string(new char[] { ch })));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -122,7 +189,7 @@ namespace ln.templates
|
|||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int ch = 0;
|
||||
while (char.IsLetterOrDigit((char)(ch = reader.Peek())))
|
||||
while (char.IsLetterOrDigit((char)(ch = reader.Peek())) || (ch == '_'))
|
||||
{
|
||||
sb.Append((char)reader.Read());
|
||||
}
|
||||
|
@ -176,7 +243,7 @@ namespace ln.templates
|
|||
}
|
||||
|
||||
|
||||
enum TokenType { NAME, DOT, NUMBER, STRING, BRACKET }
|
||||
enum TokenType { NAME, DOT, NUMBER, STRING, OPENINDEXER, ENDINDEXER, OPENLIST, ENDLIST, COMMA }
|
||||
class Token
|
||||
{
|
||||
public TokenType TokenType;
|
||||
|
@ -336,6 +403,40 @@ namespace ln.templates
|
|||
}
|
||||
}
|
||||
|
||||
class MethodCall : Eval
|
||||
{
|
||||
Eval[] Parameters;
|
||||
String Name;
|
||||
|
||||
public MethodCall(Eval parent, String name,params Eval[] p)
|
||||
: base(parent)
|
||||
{
|
||||
Name = name;
|
||||
Parameters = p;
|
||||
}
|
||||
|
||||
public override object Evaluate(Context context)
|
||||
{
|
||||
object p = Parent.Evaluate(context);
|
||||
|
||||
object[] pvalues = new object[Parameters.Length];
|
||||
Type[] ptypes = new Type[Parameters.Length];
|
||||
|
||||
for (int i=0;i<pvalues.Length;i++)
|
||||
{
|
||||
pvalues[i] = Parameters[i].Evaluate(context);
|
||||
if (pvalues[i] == null)
|
||||
ptypes[i] = null;
|
||||
else
|
||||
ptypes[i] = pvalues[i].GetType();
|
||||
}
|
||||
|
||||
MethodInfo methodInfo = p.GetType().GetRuntimeMethod(Name, ptypes);
|
||||
|
||||
return methodInfo.Invoke(p, pvalues);
|
||||
}
|
||||
}
|
||||
|
||||
class Number : Eval
|
||||
{
|
||||
object value;
|
||||
|
|
|
@ -70,7 +70,11 @@ namespace ln.templates
|
|||
|
||||
if (FrameExpression != null)
|
||||
{
|
||||
Template frame = context.Provider.FindTemplate(FrameExpression.Evaluate(null) as string);
|
||||
Template frame = context.Provider.FindTemplate(FrameExpression.Evaluate(context.ExpressionContext) as string);
|
||||
if (frame == null)
|
||||
{
|
||||
throw new NullReferenceException(String.Format("FindTemplate() returned null for {0}",FrameExpression.Source));
|
||||
}
|
||||
return frame.Generate(new Context(context, writer.ToString()));
|
||||
}
|
||||
return writer.ToString();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using System;
|
||||
namespace ln.templates
|
||||
{
|
||||
public abstract class TemplateProvider
|
||||
public interface TemplateProvider
|
||||
{
|
||||
public abstract Template FindTemplate(string templatePath);
|
||||
Template FindTemplate(string templatePath);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace ln.templates
|
|||
{
|
||||
t = Source;
|
||||
op = null;
|
||||
Source = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Web" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
Loading…
Reference in New Issue