예제 #1
0
        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();
        }
예제 #2
0
        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;
            }
        }
예제 #3
0
파일: Node.cs 프로젝트: danthomas/Parsing
 private Node(Node parent, TokenType tokenType, string text = "")
 {
     Parent = parent;
     TokenType = tokenType;
     Text = text ?? "";
     Children = new List<Node>();
 }
예제 #4
0
        public Node Expand(Node node)
        {
            Walk(node, ExpandDollar);
            Walk(node, ExpandIdentifier);
            Walk(node, ExpandIdentifierQuestion);
            Walk(node, ExpandIdentifierEqualToValue);

            return node;
        }
예제 #5
0
파일: Parser.cs 프로젝트: danthomas/Parsing
        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);
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
파일: Parser.cs 프로젝트: danthomas/Parsing
        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);
        }
예제 #8
0
파일: Parser.cs 프로젝트: danthomas/Parsing
        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())));
        }
예제 #9
0
 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);
     }
 }
예제 #10
0
        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);
            }
        }
예제 #11
0
파일: Parser.cs 프로젝트: danthomas/Parsing
        private Node ConsumeAs(Node node, TokenType tokenType)
        {
            var ret = node.AddChild(tokenType, _currentToken.Text);

            Next();

            return ret;
        }
예제 #12
0
파일: Parser.cs 프로젝트: danthomas/Parsing
        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();
            }
        }
예제 #13
0
파일: Parser.cs 프로젝트: danthomas/Parsing
        private Node Template(Node node)
        {
            Node template = Add(node, TokenType.Template);

            Expressions(template);

            return template;
        }
예제 #14
0
파일: Parser.cs 프로젝트: danthomas/Parsing
        private void Expressions(Node template)
        {
            Node expressions = Add(template, TokenType.Expressions);

            while (IsTokenType(TokenType.Text, TokenType.Dollar, TokenType.OpenCurly))
            {
                Expression(expressions);
            }
        }
예제 #15
0
파일: Node.cs 프로젝트: danthomas/Parsing
 public Node AddChild(TokenType tokenType, string text = "")
 {
     Node child = new Node(this, tokenType, text);
     Children.Add(child);
     return child;
 }
예제 #16
0
 private void Walk(Node parent, Action<Node> action)
 {
     foreach (Node child in parent.Children)
     {
         action(child);
         Walk(child, action);
     }
 }
예제 #17
0
파일: Parser.cs 프로젝트: danthomas/Parsing
 private Node Add(Node parent, TokenType tokenType, string text = "")
 {
     return parent.AddChild(tokenType, text);
 }
예제 #18
0
파일: Parser.cs 프로젝트: danthomas/Parsing
 private void Text(Node template)
 {
     Consume(template, TokenType.Text);
 }
예제 #19
0
            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);
            }
예제 #20
0
            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;
            }
예제 #21
0
파일: Node.cs 프로젝트: danthomas/Parsing
 public Node InsertChild(int index, TokenType tokenType, string text = "")
 {
     Node child = new Node(this, tokenType, text);
     Children.Insert(index, child);
     return child;
 }
예제 #22
0
파일: Parser.cs 프로젝트: danthomas/Parsing
        private void Expression(Node expressions)
        {
            Node expression = Add(expressions, TokenType.Expression);

            if (IsTokenType(TokenType.Text))
            {
                Text(expression);
            }
            else
            {
                Statement(expression);
            }
        }