Beispiel #1
0
        private bool TryParseBinaryOperation(List <TokenOrExpression> tokens)
        {
            BinaryOperation operation;

            if (tokens.Count >= 3 && IsBinaryOperator(tokens[1].Token.Type, out operation))
            {
                // Binary expression
                TokenOrExpression lhs = tokens[0];
                TokenType         op  = tokens[1].Token.Type;
                tokens.RemoveRange(0, 2);
                TryParseLeftToRight(tokens);
                if (tokens.Count != 1)
                {
                    throw new ParseException();
                }

                IExpression leftHandSide  = Parse(lhs);
                IExpression rightHandSide = tokens[0].Expression;

                var expression = new BinaryExpression(leftHandSide, operation, rightHandSide);
                tokens.RemoveAt(0);
                tokens.Insert(0, new TokenOrExpression(expression));
                return(true);
            }

            return(false);
        }
Beispiel #2
0
        private bool TryParseSpecialCharsAsLiteral(List <TokenOrExpression> tokens,
                                                   bool consumeItemListSeparator)
        {
            if (tokens.Count >= 1)
            {
                TokenType type = tokens[0].Token.Type;
                switch (type)
                {
                case TokenType.Not:
                case TokenType.OpenBracket:
                case TokenType.CloseBracket:
                case TokenType.Quotation:
                case TokenType.Arrow:
                    tokens[0] = new TokenOrExpression(new StringLiteral(Tokenizer.ToString(type)));
                    return(true);

                case TokenType.ItemListSeparator:
                    if (consumeItemListSeparator)
                    {
                        tokens[0] = new TokenOrExpression(
                            new StringLiteral(Tokenizer.ToString(type))
                            );
                        return(true);
                    }
                    break;

                case TokenType.Whitespace:
                    tokens[0] = new TokenOrExpression(new StringLiteral(tokens[0].Token.Value));
                    return(true);
                }
            }

            return(false);
        }
Beispiel #3
0
        private bool TryParseOperatorsAsLiteral(List <TokenOrExpression> tokens)
        {
            UnaryOperation unaryOperation;

            if (tokens.Count >= 1 &&
                IsUnaryOperator(tokens[0].Token.Type, out unaryOperation))
            {
                tokens[0] = new TokenOrExpression(new StringLiteral(
                                                      Tokenizer.ToString(tokens[0].Token.Type)
                                                      ));
                return(true);
            }

            BinaryOperation binaryOperation;

            if (tokens.Count >= 1 &&
                IsBinaryOperator(tokens[0].Token.Type, out binaryOperation))
            {
                tokens[0] = new TokenOrExpression(new StringLiteral(
                                                      Tokenizer.ToString(tokens[0].Token.Type)
                                                      ));
                return(true);
            }

            return(false);
        }
Beispiel #4
0
        private IExpression Parse(TokenOrExpression tokenOrExpression)
        {
            if (tokenOrExpression.Expression != null)
            {
                return(tokenOrExpression.Expression);
            }

            return(Parse(tokenOrExpression.Token));
        }
Beispiel #5
0
        private bool TryParseItemListReference(List <TokenOrExpression> tokens)
        {
            if (Matches(tokens, TokenType.At, TokenType.OpenBracket, TokenType.Literal, TokenType.CloseBracket))
            {
                TokenOrExpression name = tokens[2];
                tokens.RemoveRange(0, 4);
                tokens.Insert(0, new TokenOrExpression(new ItemListReference(name.Token.Value)));
                return(true);
            }

            return(false);
        }
Beispiel #6
0
        private bool TryParseLiteral(List <TokenOrExpression> tokens)
        {
            if (tokens.Count >= 1 &&
                (tokens[0].Token.Type == TokenType.Literal))
            {
                string value = tokens[0].Token.Value;
                tokens[0] = new TokenOrExpression(
                    new StringLiteral(value));
                return(true);
            }

            return(false);
        }
Beispiel #7
0
        private bool TryParseOne(List <TokenOrExpression> tokens)
        {
            if (TryParseVariableReference(tokens))
            {
                return(true);
            }

            if (TryParseItemListReference(tokens))
            {
                return(true);
            }

            if (TryParseFunctionCall(tokens))
            {
                return(true);
            }

            if (TryParseBinaryOperation(tokens))
            {
                return(true);
            }

            if (TryParseUnaryOperation(tokens))
            {
                return(true);
            }

            if (tokens.Count >= 1)
            {
                if (tokens[0].Expression != null)
                {
                    return(true);
                }

                if (tokens[0].Token.Type == TokenType.Literal)
                {
                    tokens[0] = new TokenOrExpression(new StringLiteral(tokens[0].Token.Value));
                    return(true);
                }
            }

            return(false);
        }
Beispiel #8
0
        private bool TryParseItemListProjection(List <TokenOrExpression> tokens)
        {
            int index;

            if (Matches(tokens, TokenType.At, TokenType.OpenBracket, TokenType.Literal, TokenType.Whitespace, TokenType.Arrow, TokenType.Whitespace) &&
                TryFindClosingBracket(tokens, out index))
            {
                TokenOrExpression        name    = tokens[2];
                List <TokenOrExpression> content = tokens.Splice(6, index - 6);
                content.Trim(TokenType.Whitespace);
                content.Trim(TokenType.Quotation);
                tokens.RemoveRange(0, index + 1);

                bool parsed;
                do
                {
                    parsed = false;
                    if (TryParseOneConcatenationContent(content, consumeItemListSeparator: false, includeMetadataReference: true))
                    {
                        parsed = true;
                    }
                    if (TryParseConcatenation(content, consumeItemListSeparator: false, includeMetadataReference: true))
                    {
                        parsed = true;
                    }
                } while (parsed && content.Count > 1);

                if (content.Count != 1 || content[0].Expression == null)
                {
                    throw new ParseException();
                }

                IExpression projectionRule = content[0].Expression;
                tokens.Insert(0, new TokenOrExpression(new ItemListProjection(
                                                           name.Token.Value,
                                                           projectionRule
                                                           )));
                return(true);
            }

            return(false);
        }
Beispiel #9
0
        private bool TryParseConcatenation(List <TokenOrExpression> tokens,
                                           bool consumeItemListSeparator,
                                           bool includeMetadataReference)
        {
            Func <TokenOrExpression, bool> isLiteralOrVariable = (pair) =>
            {
                if (pair.Expression is StringLiteral)
                {
                    return(true);
                }
                if (pair.Expression is ItemListReference)
                {
                    return(true);
                }
                if (pair.Expression is PropertyReference)
                {
                    return(true);
                }
                if (pair.Expression is ConcatExpression)
                {
                    return(true);
                }
                if (pair.Expression is MetadataReference)
                {
                    return(includeMetadataReference);
                }

                switch (pair.Token.Type)
                {
                case TokenType.Equals:
                case TokenType.NotEquals:
                case TokenType.And:
                case TokenType.Or:
                case TokenType.GreaterThan:
                case TokenType.GreaterOrEquals:
                case TokenType.LessThan:
                case TokenType.LessOrEquals:
                case TokenType.Literal:
                case TokenType.Not:
                case TokenType.OpenBracket:
                case TokenType.CloseBracket:
                case TokenType.Quotation:
                case TokenType.Whitespace:
                    return(true);

                case TokenType.Percent:
                    return(includeMetadataReference);

                case TokenType.ItemListSeparator:
                    return(consumeItemListSeparator);
                }

                return(false);
            };

            if (tokens.Count >= 2 &&
                isLiteralOrVariable(tokens[0]) &&
                (consumeItemListSeparator || tokens[1].Token.Type != TokenType.ItemListSeparator))
            {
                List <TokenOrExpression> lhs = tokens.Cut(0, 1);
                if (!TryParseOneConcatenationContent(lhs, consumeItemListSeparator, includeMetadataReference))
                {
                    throw new ParseException("Internal error");
                }

                IExpression leftHandSide = lhs[0].Expression;

                if (!TryParseOneConcatenationContent(tokens, consumeItemListSeparator, includeMetadataReference))
                {
                    throw new ParseException("Internal error");
                }

                IExpression rightHandSide = tokens[0].Expression;
                tokens[0] = new TokenOrExpression(
                    new ConcatExpression(leftHandSide, rightHandSide));
                return(true);
            }

            return(false);
        }
Beispiel #10
0
        private IExpression Parse(IEnumerable <Token> tokens)
        {
            var stack                    = new List <TokenOrExpression>();
            int highestPrecedence        = 0;
            IEnumerator <Token> iterator = tokens.GetEnumerator();

            while (iterator.MoveNext())
            {
                Token token = iterator.Current;
                if (token.Type == TokenType.Whitespace)
                {
                    continue;
                }

                if (IsOperator(token.Type))
                {
                    int precedence = Precedence(token.Type);
                    if (precedence < highestPrecedence)
                    {
                        TryParseLeftToRight(stack);
                    }

                    stack.Add(token);
                    highestPrecedence = precedence;
                }
                else if (token.Type == TokenType.Quotation)
                {
                    // Consume everything until the quote closes again...
                    var content   = new List <TokenOrExpression>();
                    var arguments = new List <IExpression>();
                    while (iterator.MoveNext() &&
                           iterator.Current.Type != TokenType.Quotation)
                    {
                        content.Add(iterator.Current);
                        if (TryParseLeftToRight(content))
                        {
                            arguments.Add(content[0].Expression);
                            content.Clear();
                        }
                    }

                    if (content.Count != 0)
                    {
                        throw new ParseException();
                    }

                    stack.Add(new TokenOrExpression(new ConcatExpression(arguments)));
                }
                else
                {
                    stack.Add(token);
                }
            }

            if (stack.Count == 0)
            {
                return(null);
            }

            if (!TryParseLeftToRight(stack))
            {
                throw new ParseException();
            }

            TokenOrExpression tok = stack[0];

            return(tok.Expression);
        }