/// <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) + ")")); }
/// <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); }
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)); }
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); } }
/// <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) + ")")); }
/// <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); }
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); } }