public Func<IDictionary<string, string>, string> Build(Node node) { var dictionaryType = typeof(IDictionary<string, string>); var values = Expression.Parameter(dictionaryType); var helper = Expression.Variable(typeof(Helper)); var constructorInfo = typeof(Helper).GetConstructor(new[] { dictionaryType }); List<Expression> expressions = new List<Expression>(); var assign = Expression.Assign(helper, Expression.New(constructorInfo, values)); var getValue = Expression.Call(helper, typeof(Helper).GetMethod("GetValue")); expressions.Add(assign); expressions.Add(Expression.Block(_expressionBuilder.Build(node.Children[0], helper))); expressions.Add(getValue); Expression block = Expression.Block(new[] { helper }, expressions); return Expression.Lambda<Func<IDictionary<string, string>, string>>(block, values).Compile(); }
private void ExpandDollar(Node node) { if (node.TokenType == TokenType.Dollar) { node.TokenType = TokenType.Attrib; Node parent = node.Parent; string text = ""; while (parent != null) { Node identifier = parent.Children.FirstOrDefault(x => x.TokenType == TokenType.Identifier); if (identifier != null) { text = identifier.Text; break; } parent = parent.Parent; } node.Text = text; } }
private Node(Node parent, TokenType tokenType, string text = "") { Parent = parent; TokenType = tokenType; Text = text ?? ""; Children = new List<Node>(); }
public Node Expand(Node node) { Walk(node, ExpandDollar); Walk(node, ExpandIdentifier); Walk(node, ExpandIdentifierQuestion); Walk(node, ExpandIdentifierEqualToValue); return node; }
public Node Parse(string text) { text = text.Replace("\r\n", "").Replace("\r", "").Replace("\n", ""); _lexer = new Lexer(text); _currentToken = _lexer.Next(); _nextToken = _lexer.Next(); Node node = new Node(TokenType.StartOfFile); return Template(node); }
private void ExpandIdentifierQuestion(Node node) { if (node.Children.Count > 2 && node.Children[0].TokenType == TokenType.Identifier && node.Children[1].TokenType == TokenType.Question) { //identifier?expression -> identifier != null ? expression node.InsertChild(1, TokenType.NotEqualTo); Node values = node.InsertChild(2, TokenType.Values); values.AddChild(TokenType.Null); } }
private Node ConsumeAs(Node node, TokenType expectedTokenType, TokenType asTokenType) { if (IsTokenType(expectedTokenType)) { var ret = node.AddChild(asTokenType, _currentToken.Text); Next(); return ret; } throw new Exception("Expected " + expectedTokenType); }
private Node Consume(Node node, params TokenType[] tokenTypes) { if (IsTokenType(tokenTypes)) { var ret = node?.AddChild(_currentToken.TokenType, _currentToken.Text); Next(); return ret; } throw new Exception("Expected " + String.Join(", ", tokenTypes.Select(x => x.ToString()))); }
private void ExpandIdentifier(Node node) { if (node.Children.Count == 1 && node.Children[0].TokenType == TokenType.Identifier) { //identifier -> identifier != null ? attrib node.AddChild(TokenType.NotEqualTo); Node values = node.AddChild(TokenType.Values); values.AddChild(TokenType.Null); node.AddChild(TokenType.Question); Node expressions = node.AddChild(TokenType.Expressions); Node expression = expressions.AddChild(TokenType.Expression); expression.AddChild(TokenType.Attrib, node.Children[0].Text); } }
private void ExpandIdentifierEqualToValue(Node node) { if (node.Children.Count == 3 && node.Children[0].TokenType == TokenType.Identifier && (node.Children[1].TokenType == TokenType.EqualTo || node.Children[1].TokenType == TokenType.NotEqualTo) && node.Children[2].TokenType == TokenType.Values) { //identifier=text -> identifier=text?{identifier} node.AddChild(TokenType.Question); Node expressions = node.AddChild(TokenType.Expressions); Node expression = expressions.AddChild(TokenType.Expression); expression.AddChild(TokenType.Attrib, node.Children[0].Text); } }
private Node ConsumeAs(Node node, TokenType tokenType) { var ret = node.AddChild(tokenType, _currentToken.Text); Next(); return ret; }
private void Statement(Node expression) { if (IsTokenType(TokenType.Dollar)) { Consume(expression, TokenType.Dollar); } else if (IsTokenType(TokenType.OpenCurly)) { Consume(TokenType.OpenCurly); Consume(expression, TokenType.Identifier); if (IsTokenType(TokenType.EqualTo, TokenType.NotEqualTo)) { Consume(expression, TokenType.EqualTo, TokenType.NotEqualTo); Node values = Add(expression, TokenType.Values); Consume(values, TokenType.Value); while (IsTokenType(TokenType.Pipe)) { Consume(TokenType.Pipe); Consume(values, TokenType.Value); } } if (IsTokenType(TokenType.Question)) { Consume(expression, TokenType.Question); Expressions(expression); if (IsTokenType(TokenType.Colon)) { Consume(expression, TokenType.Colon); Expressions(expression); } } Consume(TokenType.CloseCurly); } else { throw new Exception(); } }
private Node Template(Node node) { Node template = Add(node, TokenType.Template); Expressions(template); return template; }
private void Expressions(Node template) { Node expressions = Add(template, TokenType.Expressions); while (IsTokenType(TokenType.Text, TokenType.Dollar, TokenType.OpenCurly)) { Expression(expressions); } }
public Node AddChild(TokenType tokenType, string text = "") { Node child = new Node(this, tokenType, text); Children.Add(child); return child; }
private void Walk(Node parent, Action<Node> action) { foreach (Node child in parent.Children) { action(child); Walk(child, action); } }
private Node Add(Node parent, TokenType tokenType, string text = "") { return parent.AddChild(tokenType, text); }
private void Text(Node template) { Consume(template, TokenType.Text); }
public Expression Build(Node node, ParameterExpression helper) { if (node.TokenType != TokenType.Expressions) { throw new Exception("Expressions Node expected"); } List<Expression> expressions = new List<Expression>(); foreach (Node child in node.Children) { expressions.Add(BuildExpression(child, helper)); } return Expression.Block(expressions); }
private Expression BuildExpression(Node node, ParameterExpression helper) { if (node.TokenType != TokenType.Expression) { throw new Exception("Expression Node expected"); } Expression expression; if (node.Children.Count == 1 && node.Children[0].TokenType == TokenType.Text) { expression = Expression.Call(helper, _appendText, Expression.Constant(node.Children[0].Text)); } else if (node.Children.Count == 1 && (node.Children[0].TokenType == TokenType.Identifier || node.Children[0].TokenType == TokenType.Attrib)) { expression = Expression.Call(helper, _appendValue, Expression.Constant(node.Children[0].Text)); } else { Expression condition = Expression.Call(helper, _isEqualTo, Expression.Constant(node.Children[0].Text), Expression.Constant(node.Children[2].Children[0].Text)); foreach (Node value in node.Children[2].Children.Skip(1)) { condition = Expression.Or(condition, Expression.Call(helper, _isEqualTo, Expression.Constant(node.Children[0].Text), Expression.Constant(value.Text))); } if (node.Children[1].TokenType == TokenType.NotEqualTo) { condition = Expression.Not(condition); } if (node.Children.Any(x => x.TokenType == TokenType.Question) && node.Children.Any(x => x.TokenType == TokenType.Colon)) { expression = Expression.IfThenElse(condition, Build(node.Children[4], helper), Build(node.Children[6], helper)); } else if (node.Children.Any(x => x.TokenType == TokenType.Question)) { expression = Expression.IfThen(condition, Build(node.Children[4], helper)); } else { throw new Exception(); } } return expression; }
public Node InsertChild(int index, TokenType tokenType, string text = "") { Node child = new Node(this, tokenType, text); Children.Insert(index, child); return child; }
private void Expression(Node expressions) { Node expression = Add(expressions, TokenType.Expression); if (IsTokenType(TokenType.Text)) { Text(expression); } else { Statement(expression); } }