예제 #1
0
        /// <summary>
        /// This only really happens with conjunctive operators (ie. +, -, AND, OR..)
        /// </summary>
        /// <param name="xoContext.CurrentNode"></param>
        /// <param name="xoContext.List"></param>
        public static void HandlePreconsumptionError(ParsingContext xoContext)
        {
            // Its good to know whats next
            SyntaxKind eNextTokenKind = SyntaxKind.UnknownNode;

            // If we have an arithmatic operator, we know we need the types to match
            if (SyntaxKindFacts.IsArithmaticOperator(xoContext.CurrentNode.ExpectedType) ||
                SyntaxKindFacts.IsConditionalOperator(xoContext.CurrentNode.ExpectedType))
            {
                //
                if (SyntaxKindFacts.IsLiteral(xoContext.List.Peek().ExpectedType))
                {
                    // Set the return kind
                    eNextTokenKind = xoContext.List.Peek().ExpectedType;
                }
            }
            // Conjunctive or Adjunct will not matter what types we have
            else if (SyntaxKindFacts.IsAdjunctConditionalOperator(xoContext.CurrentNode.ExpectedType))
            {
                // MUST BE BOOLEAN
                eNextTokenKind = SyntaxKind.BooleanToken;
            }

            // Default to unknown Filler
            xoContext.CurrentNode.Add(
                new FillerNode(
                    eNextTokenKind,
                    "Missing (" + SyntaxKindUtilities.GetStringFromKind(eNextTokenKind) + ")"));
        }
예제 #2
0
        /// <summary>
        /// Used by WHERE and ON
        /// </summary>
        /// <param name="xoContext.CurrentNode"></param>
        /// <param name="xoContext.List"></param>
        /// <returns></returns>
        private static CanConsumeResult ExpressionCanConsumeNext(ParsingContext xoContext, Boolean xbIsPreconsumption = false)
        {
            SyntaxKind eKind = xoContext.List.Peek().ExpectedType;

            if (
                SyntaxKindFacts.IsIdentifierOrExpression(eKind) ||     // Identifiers and Expressions are allowed here
                SyntaxKindFacts.IsAdjunctConditionalOperator(eKind) || // AND OR
                SyntaxKindFacts.IsConditionalOperator(eKind) ||        // = >= IN
                SyntaxKindFacts.IsUnaryOperator(eKind) ||              // NOT
                SyntaxKindFacts.IsFunction(eKind) ||
                SyntaxKindFacts.IsArithmaticOperator(eKind))
            {
                return(CheckIfConsumptionIsAllowed(xoContext));
            }


            CanConsumeResult eResult = DefaultCanConsumeNext(xoContext);

            // Post execution check
            if (eResult == CanConsumeResult.Complete && xoContext.CurrentNode.Count != 1)
            {
                ResolutionGenerator.HandleIncompleteNode(xoContext);
            }

            return(eResult);
        }
예제 #3
0
 private static Boolean EligibleColumnSymbol(SyntaxKind xeKind)
 {
     return
         (SyntaxKindFacts.IsIdentifierOrExpression(xeKind) ||
          SyntaxKindFacts.IsFunction(xeKind) ||
          xeKind == SyntaxKind.StarToken ||
          xeKind == SyntaxKind.BarBarToken ||
          SyntaxKindFacts.IsArithmaticOperator(xeKind));
 }
예제 #4
0
        private static CanConsumeResult BinaryExpressionCanConsumeNext(ParsingContext xoContext, Boolean xbIsPreconsumption = false)
        {
            // Intermediate var
            SyntaxKind eKind = xoContext.List.Peek().ExpectedType;

            // If we have something we are actually allowed to consume
            if ((xbIsPreconsumption && SyntaxKindFacts.IsAdjunctConditionalOperator(eKind)) || // Allow AND/OR in preconsump
                SyntaxKindFacts.IsIdentifierOrExpression(eKind) ||                             // Identifiers and Expressions are allowed here
                SyntaxKindFacts.IsConditionalOperator(eKind) ||                                // = >= IN
                SyntaxKindFacts.IsUnaryOperator(eKind) ||                                      // NOT
                SyntaxKindFacts.IsArithmaticOperator(eKind))
            {
                CanConsumeResult eResult = CheckIfConsumptionIsAllowed(xoContext);

                switch (eResult)
                {
                // Possible erroroneous
                case CanConsumeResult.Unknown:

                // Definitely finished
                case CanConsumeResult.Complete:
                    // Perform final checks
                    break;

                // Break immediately
                case CanConsumeResult.Skip:
                case CanConsumeResult.Consume:
                    return(eResult);
                }
            }

            // Closing condition
            if (xoContext.CurrentNode.IsFull() ||
                SyntaxKindFacts.IsTerminatingNode(eKind) ||
                SyntaxKindFacts.IsKeyword(eKind) ||
                eKind == SyntaxKind.CloseParenthesisToken)
            {
                // Post execution check
                if (xoContext.CurrentNode.Count != 2)
                {
                    ResolutionGenerator.HandleIncompleteNode(xoContext);
                }

                return(CanConsumeResult.Complete);
            }

            //
            return(DefaultCanConsumeNext(xoContext));
        }
예제 #5
0
        private static CanConsumeResult ElseCanConsume(ParsingContext xoContext, Boolean xbIsPreconsumption = false)
        {
            SyntaxKind eNextKind = xoContext.List.Peek().ExpectedType;

            // Any Expression/Identifier
            if (SyntaxKindFacts.IsIdentifierOrExpression(eNextKind) ||     // Identifiers and Expressions are allowed here
                SyntaxKindFacts.IsAdjunctConditionalOperator(eNextKind) || // AND OR
                SyntaxKindFacts.IsConditionalOperator(eNextKind) ||        // = >= IN
                SyntaxKindFacts.IsUnaryOperator(eNextKind) ||              // NOT
                SyntaxKindFacts.IsFunction(eNextKind) ||
                SyntaxKindFacts.IsArithmaticOperator(eNextKind))
            {
                return(CanConsumeResult.Consume);
            }
            else
            {
                return(CanConsumeResult.Complete);
            }
        }
예제 #6
0
        /// <summary>
        /// This only really happens with conjunctive operators (ie. +, -, AND, OR..)
        /// </summary>
        /// <param name="xoContext.CurrentNode"></param>
        /// <param name="xoContext.List"></param>
        public static void HandleIncompleteNode(ParsingContext xoContext)
        {
            // Its good to know whats next
            SyntaxKind eNextTokenKind = SyntaxKind.UnknownNode;

            // If we have an arithmatic operator, we know we need the types to match
            if (SyntaxKindFacts.IsArithmaticOperator(xoContext.CurrentNode.ExpectedType) ||
                SyntaxKindFacts.IsConditionalOperator(xoContext.CurrentNode.ExpectedType))
            {
                // Only when we have children
                if (xoContext.CurrentNode.Count > 0)
                {
                    // Set the return kind
                    eNextTokenKind = xoContext.CurrentNode[0].ExpectedType;
                }
            }
            // Boolean
            else if (
                SyntaxKindFacts.IsAdjunctConditionalOperator(xoContext.CurrentNode.ExpectedType) || // Conjunctive or Adjunct must have bool
                xoContext.CurrentNode.ExpectedType == SyntaxKind.WhereKeyword ||                    // Where must be bool
                xoContext.CurrentNode.ExpectedType == SyntaxKind.OnKeyword                          // On must be bool
                )
            {
                // MUST BE BOOLEAN
                eNextTokenKind = SyntaxKind.BooleanToken;
            }
            // Identifier
            else if (
                xoContext.CurrentNode.ExpectedType == SyntaxKind.FromKeyword    // Table Missing
                )
            {
                // MUST BE Identifier
                eNextTokenKind = SyntaxKind.IdentifierToken;
            }

            // Default to unknown
            xoContext.CurrentNode.Add(
                new FillerNode(
                    eNextTokenKind,
                    "Missing (" + SyntaxKindUtilities.GetStringFromKind(eNextTokenKind) + ")"));
        }
예제 #7
0
        private static CanConsumeResult SymbolListCanConsumeNext(ParsingContext xoContext, Boolean xbIsPreconsumption = false)
        {
            // Intermediate var
            SyntaxKind oKind = xoContext.List.Peek().ExpectedType;

            // Manually terminate if we have a keyword here
            if (SyntaxKindFacts.IsKeyword(oKind))
            {
                return(CanConsumeResult.Complete);
            }
            else if (xoContext.CurrentNode.Count == 0 && // If this is the first item, it can consume an IDN
                     EligibleColumnSymbol(oKind))
            {
                return(CanConsumeResult.Consume);
            }
            // If we have some items
            else if (xoContext.CurrentNode.Count > 0)
            {
                if (oKind == SyntaxKind.CommaToken)
                {
                    // Consume next
                    xoContext.List.Pop();             // drop the comma
                    return(CanConsumeResult.Consume); // consume next
                }
                // Can consume conjunctive items
                else if (
                    oKind == SyntaxKind.BarBarToken ||
                    SyntaxKindFacts.IsArithmaticOperator(oKind)
                    )
                {
                    return(CanConsumeResult.Consume);
                }
                // Goes to default
            }

            // Try default
            return(DefaultCanConsumeNext(xoContext));
        }
예제 #8
0
        /// <summary>
        /// A factory method for interpreting what kind of Open Parenthesis construct
        /// we have here.
        /// </summary>
        /// <param name="xoCurrentToken"></param>
        /// <param name="xoList"></param>
        /// <returns></returns>
        private static SyntaxNode FactoryInterpretOpenParenthesisToken(ParsingContext xoContext)
        {
            // Given a (, Try and guess what type of () this is
            SyntaxNode oReturn;
            ISyntax    xoCurrentToken = xoContext.List.Pop();

            // 1. ( SubQuery ) - (SELECT * FROM ..) svc
            // 4. SubQuery in Expression - Where X IN (SELECT Svc_IDNTY FROM svc)

            // First Keyword in is SELECT
            if (xoContext.List.Peek().ExpectedType == SyntaxKind.SelectKeyword)
            {
                // Create SubQuery Symbol
                oReturn = FactoryCreateTable(xoContext);
            }
            // 2. ( Symbol List ) - (1, 2, 3) or (svc.MKT_PROD_CD, svc.SVC_STAT_CD)
            // 3. ( Expressions ) - WHERE (X =Y) or (X <> Y AND X = 0)
            else
            {
                Boolean bCommaFound           = false; // If you find any commas before the closing bracket
                Boolean bAllIdentifiersOrDots = true;

                for (int iIndex = 0; iIndex < xoContext.List.Count; iIndex++)
                {
                    ISyntax oLoopingNode = xoContext.List.Peek(iIndex);
                    // Scan until we find something that helps us determine what this parenthesis is
                    // Or a close parenthesis
                    if (oLoopingNode.ExpectedType == SyntaxKind.CloseParenthesisToken ||
                        bCommaFound
                        )
                    {
                        break;
                    }
                    // Found Comma -> SymbolList
                    else if (oLoopingNode.ExpectedType == SyntaxKind.CommaToken)
                    {
                        bCommaFound           = true;
                        bAllIdentifiersOrDots = false;
                    }
                    // Found an operaotr -> Expression
                    else if (
                        SyntaxKindFacts.IsAdjunctConditionalOperator(oLoopingNode.ExpectedType) || // And or
                        SyntaxKindFacts.IsConditionalOperator(oLoopingNode.ExpectedType) ||        // <> >= =
                        SyntaxKindFacts.IsArithmaticOperator(oLoopingNode.ExpectedType))           // +
                    {
                        bAllIdentifiersOrDots = false;
                    }
                    // Found something to say this is not a single column
                    else if (bAllIdentifiersOrDots &&
                             (oLoopingNode.ExpectedType != SyntaxKind.IdentifierToken ||
                              oLoopingNode.ExpectedType != SyntaxKind.DotDotToken ||
                              oLoopingNode.ExpectedType != SyntaxKind.DotToken)
                             )
                    {
                        bAllIdentifiersOrDots = false;
                    }
                }

                // Symbol List
                if (bCommaFound)
                {
                    //
                    xoCurrentToken.ExpectedType = SyntaxKind.ColumnListNode;
                    oReturn = new SymbolList(xoCurrentToken);
                }
                // Single column
                else if (bAllIdentifiersOrDots)
                {
                    // This must have an openning and closing parenthesis
                    oReturn = FactoryCreateColumn(xoContext);

                    // Ignore a trailing Close parenthesis
                    if (xoContext.List.Peek().ExpectedType == SyntaxKind.CloseParenthesisToken)
                    {
                        xoContext.List.Pop();
                    }
                }
                // Default to expression
                else
                {
                    // Probably an expression type
                    return(new SyntaxNode(xoCurrentToken, NodeStrategyFactory.UNARY_EXPRESSION_STRATEGY)); // UnaryExpression;
                }
            }

            return(oReturn);
        }
예제 #9
0
        public static NodeStrategy FactoryCreateStrategy(SyntaxKind xeKind)
        {
            if (dsStrategyCache.ContainsKey(xeKind))
            {
                return(dsStrategyCache[xeKind]);
            }
            else
            {
                // Set everything to default
                NodeStrategy oReturnNode = new NodeStrategy(
                    DefaultCanConsumeNext,
                    DefaultTryConsumeNext,
                    DefaultValidation); // Default

                // Explicit Strategies
                switch (xeKind)
                {
                case SyntaxKind.SelectKeyword:
                    oReturnNode.EligibilityFn    = SelectCanConsumeNext;
                    oReturnNode.TryConsumeNextFn = SelectConsumeNext;
                    oReturnNode.ValidationFn     = SelectIsValid;

                    break;

                case SyntaxKind.FromKeyword:
                    oReturnNode.EligibilityFn    = FromCanConsumeNext;
                    oReturnNode.TryConsumeNextFn = TableSymbolConvertToken;
                    break;

                case SyntaxKind.WhereKeyword:
                case SyntaxKind.OnKeyword:
                case SyntaxKind.NotKeyword:
                    oReturnNode.EligibilityFn = ExpressionCanConsumeNext;
                    break;

                case SyntaxKind.CaseKeyword:
                    oReturnNode.EligibilityFn = CaseCanConsume;
                    break;

                case SyntaxKind.WhenKeyword:
                    oReturnNode.EligibilityFn = WhenCanConsume;
                    break;

                case SyntaxKind.ThenKeyword:
                case SyntaxKind.ElseKeyword:
                    oReturnNode.EligibilityFn = ElseCanConsume;
                    break;

                case SyntaxKind.IdentifierToken:
                case SyntaxKind.IdentifierColumnSymbol:
                case SyntaxKind.IdentifierTableSymbol:
                case SyntaxKind.IdentifierSchemaSymbol:
                case SyntaxKind.IdentifierDatabaseSymbol:
                    oReturnNode.EligibilityFn = NullTwoArgument;
                    break;

                case SyntaxKind.BarBarToken:
                    oReturnNode.EligibilityFn = ConcatCanConsume;
                    break;

                case SyntaxKind.IdentifierSubQuerySymbol:
                    oReturnNode.EligibilityFn = SubQueryCanConsumeNext;
                    break;

                case SyntaxKind.ColumnListNode:
                    oReturnNode.EligibilityFn = SymbolListCanConsumeNext;
                    break;
                }

                // Other Explicit conversions can be performed here (saves on writing every kind above)
                if (SyntaxKindFacts.IsFunction(xeKind))
                {
                    oReturnNode.EligibilityFn = FunctionCanConsumeNext;
                }
                // Join Keyword
                else if (SyntaxKindFacts.IsJoinKeyword(xeKind))
                {
                    oReturnNode.EligibilityFn    = JoinCanConsumeNext;
                    oReturnNode.TryConsumeNextFn = TableSymbolConvertToken;
                }
                // Arithmatic/Conditional/Adjunct operators
                else if (
                    SyntaxKindFacts.IsAdjunctConditionalOperator(xeKind) ||
                    SyntaxKindFacts.IsArithmaticOperator(xeKind) ||
                    SyntaxKindFacts.IsConditionalOperator(xeKind))
                {
                    oReturnNode.EligibilityFn = BinaryExpressionCanConsumeNext;
                }
                else if (SyntaxKindFacts.IsLiteral(xeKind))
                {
                    oReturnNode.EligibilityFn = NullTwoArgument;
                }

                // Cache it
                dsStrategyCache.Add(xeKind, oReturnNode);

                // return it
                return(oReturnNode);
            }
        }