public static bool TryGetExpressionNode(IParser parser, out ExpressionNode node, List <TokenKind> breakTokens = null, ExpressionParsingOptions options = null) { if (options == null) { options = new ExpressionParsingOptions(); } node = null; bool result = false; bool start = true; bool requireExpression = false; TokenExpressionNode startingToken = null; while (true) { // First check for allowed pre-expression tokens if (_preExpressionTokens.Contains(parser.PeekToken().Kind)) { parser.NextToken(); if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } requireExpression = true; } if (parser.PeekToken(TokenKind.LeftParenthesis)) { ParenWrappedExpressionNode parenExpr; if (ParenWrappedExpressionNode.TryParseExpression(parser, out parenExpr, options)) { if (node == null) { node = parenExpr; } else { node.AppendExpression(parenExpr); } result = true; } else { parser.ReportSyntaxError("Paren-nested expression expected."); } } else if (parser.PeekToken(TokenKind.LeftBracket)) { BracketWrappedExpressionNode brackNode; if (BracketWrappedExpressionNode.TryParseNode(parser, out brackNode)) { if (node == null) { node = brackNode; } else { node.AppendExpression(brackNode); } result = true; } else { parser.ReportSyntaxError("Bracket-nested expression expected."); } } else if (parser.PeekToken(TokenCategory.StringLiteral) || parser.PeekToken(TokenCategory.CharacterLiteral) || parser.PeekToken(TokenCategory.IncompleteMultiLineStringLiteral)) { result = true; parser.NextToken(); if (node == null) { node = new StringExpressionNode(parser.Token); } else { node.AppendExpression(new StringExpressionNode(parser.Token)); } } else if (parser.PeekToken(TokenCategory.NumericLiteral)) { result = true; parser.NextToken(); if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } } else if (parser.PeekToken(TokenKind.CurrentKeyword)) { result = true; parser.NextToken(); int currentExprStart = parser.Token.Span.Start; string currentTypeConstraint; if (TypeConstraints.VerifyValidConstraint(parser, out currentTypeConstraint, TokenKind.CurrentKeyword, true)) { result = true; StringExpressionNode strExpr = new StringExpressionNode(string.Format("current {0}", currentTypeConstraint)); strExpr.StartIndex = currentExprStart; strExpr.EndIndex = parser.Token.Span.End; if (node == null) { node = strExpr; } else { node.AppendExpression(strExpr); } } else { if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } } } else if (parser.PeekToken(TokenKind.IntervalKeyword)) { parser.NextToken(); TokenExpressionNode intervalNode = new TokenExpressionNode(parser.Token); if (node == null) { node = intervalNode; } else { node.AppendExpression(intervalNode); } if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); while (!parser.PeekToken(TokenKind.EndOfFile)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); if (parser.Token.Token.Kind == TokenKind.RightParenthesis) { break; } } string intervalString; if (TypeConstraints.VerifyValidConstraint(parser, out intervalString, TokenKind.IntervalKeyword, true)) { result = true; node.AppendExpression(new StringExpressionNode(intervalString)); } else { parser.ReportSyntaxError("Invalid interval expression found."); } } } else if (parser.PeekToken(TokenKind.SelectKeyword) && options.AllowNestedSelectStatement) { FglStatement selStmt; bool dummy; if (SqlStatementFactory.TryParseSqlStatement(parser, out selStmt, out dummy)) { result = true; if (node == null) { node = new FglStatementExpression(selStmt); } else { node.AppendExpression(new FglStatementExpression(selStmt)); } } else { parser.ReportSyntaxError("Invalid select statement found in expression."); } } else if (parser.PeekToken(TokenCategory.Identifier) || parser.PeekToken(TokenCategory.Keyword)) { bool isCustomExpression = false; if (options != null && options.AdditionalExpressionParsers != null) { ExpressionNode parsedExpr; foreach (var exprParser in options.AdditionalExpressionParsers) { if ((parsedExpr = exprParser(parser)) != null) { result = true; if (node == null) { node = parsedExpr; } else { node.AppendExpression(parsedExpr); } isCustomExpression = true; } } } if (!isCustomExpression) { FunctionCallExpressionNode funcCall; FglNameExpression nonFuncCallName; if (FunctionCallExpressionNode.TryParseExpression(parser, out funcCall, out nonFuncCallName, false, options)) { result = true; if (node == null) { node = funcCall; } else { node.AppendExpression(funcCall); } } else if (nonFuncCallName != null) { bool isDatetime = false; var dtToken = Tokens.GetToken(nonFuncCallName.Name); if (dtToken != null) { if (TypeConstraints.DateTimeQualifiers.Contains(dtToken.Kind)) { string dtString; isDatetime = true; if (TypeConstraints.VerifyValidConstraint(parser, out dtString, TokenKind.DatetimeKeyword, true, dtToken.Kind)) { result = true; var strExpr = new StringExpressionNode(dtString); if (node == null) { node = strExpr; } else { node.AppendExpression(strExpr); } } else { isDatetime = false; } } } if (!isDatetime) { // it's a name expression result = true; if (node == null) { node = nonFuncCallName; } else { node.AppendExpression(nonFuncCallName); } } } else { result = true; parser.NextToken(); if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } } } } else if (parser.PeekToken(TokenKind.Multiply) && options.AllowStarParam) { result = true; parser.NextToken(); if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } } else if (parser.PeekToken(TokenKind.QuestionMark) && options.AllowQuestionMark) { parser.NextToken(); if (node == null) { parser.ReportSyntaxError("Invalid token '?' found in expression."); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } } else { if (requireExpression) { var tok = parser.PeekToken(); if (breakTokens != null && !breakTokens.Contains(tok.Kind)) { parser.ReportSyntaxError("Invalid token type found in expression."); } else { parser.ReportSyntaxError("Expression required."); } } break; } requireExpression = false; Token nextTok = parser.PeekToken(); bool isOperator = true; while (isOperator && !requireExpression) { if ((breakTokens == null || (breakTokens != null && !breakTokens.Contains(nextTok.Kind))) && nextTok.Kind >= TokenKind.FirstOperator && nextTok.Kind <= TokenKind.LastOperator) { parser.NextToken(); // TODO: not sure if we want to do more analysis on what operators can start an expression if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } switch (parser.Token.Token.Kind) { case TokenKind.LessThan: // check for '<=' or '<>' if (parser.PeekToken(TokenKind.Equals) || parser.PeekToken(TokenKind.GreaterThan)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } break; case TokenKind.GreaterThan: // check for '>=' if (parser.PeekToken(TokenKind.Equals)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } break; case TokenKind.Exclamation: // check for '!=' if (parser.PeekToken(TokenKind.Equals)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } else { parser.ReportSyntaxError("Invalid token '!' found in expression."); } break; case TokenKind.Equals: // check for '==' if (parser.PeekToken(TokenKind.Equals)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } break; case TokenKind.SingleBar: // check for '||' if (parser.PeekToken(TokenKind.SingleBar)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } else { parser.ReportSyntaxError("Invalid token '|' found in expression."); } break; } requireExpression = true; } else { // check for non-symbol operators switch (nextTok.Kind) { case TokenKind.DoubleBar: case TokenKind.AsKeyword: case TokenKind.AndKeyword: case TokenKind.OrKeyword: case TokenKind.ModKeyword: case TokenKind.UsingKeyword: case TokenKind.InstanceOfKeyword: case TokenKind.UnitsKeyword: case TokenKind.LikeKeyword: case TokenKind.MatchesKeyword: case TokenKind.ThroughKeyword: case TokenKind.ThruKeyword: case TokenKind.BetweenKeyword: { // require another expression requireExpression = true; parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } break; case TokenKind.ClippedKeyword: case TokenKind.SpacesKeyword: { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } break; case TokenKind.IsKeyword: { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); if (parser.PeekToken(TokenKind.NotKeyword)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } if (parser.PeekToken(TokenKind.NullKeyword)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } else { parser.ReportSyntaxError("NULL keyword required in expression."); } } break; case TokenKind.NotKeyword: { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); if (parser.PeekToken(TokenKind.LikeKeyword) || parser.PeekToken(TokenKind.MatchesKeyword) || parser.PeekToken(TokenKind.InKeyword)) { // require another expression requireExpression = true; parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } else { parser.ReportSyntaxError("LIKE or MATCHES keyword required in expression."); } } break; default: { isOperator = false; break; } } if (!isOperator) { break; } else { nextTok = parser.PeekToken(); if (nextTok.Kind == TokenKind.EndOfFile) { break; } } } } if (!requireExpression) { break; } } if (result && node != null) { node.EndIndex = parser.Token.Span.End; } return(result); }
internal static ExpressionNode ParseAggregateReportFunction(IParser parser, ReportBlockNode reportNode) { ExpressionNode node = null; if (reportNode != null) { var tokStr = parser.PeekToken().Value.ToString(); if (reportNode.Variables.ContainsKey(tokStr)) { switch (tokStr.ToLower()) { case "group": { var nextTokKind = parser.PeekToken(2).Kind; if (nextTokKind != TokenKind.CountKeyword && nextTokKind != TokenKind.PercentKeyword && nextTokKind != TokenKind.SumKeyword && nextTokKind != TokenKind.AvgKeyword && nextTokKind != TokenKind.MinKeyword && nextTokKind != TokenKind.MaxKeyword) { return(null); } break; } case "count": case "percent": case "sum": case "avg": case "min": case "max": { if (!parser.PeekToken(TokenKind.LeftParenthesis, 2)) { return(null); } break; } } } } if (parser.PeekToken(TokenKind.GroupKeyword)) { parser.NextToken(); node = new TokenExpressionNode(parser.Token); } switch (parser.PeekToken().Kind) { case TokenKind.CountKeyword: case TokenKind.PercentKeyword: { parser.NextToken(); if (node == null) { node = new TokenExpressionNode(parser.Token); } else { node.AppendExpression(new TokenExpressionNode(parser.Token)); } if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); if (parser.PeekToken(TokenKind.Multiply)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } else { parser.ReportSyntaxError("Expected right-paren in report aggregate function."); } } else { parser.ReportSyntaxError("Expected '*' in report aggregate function."); } } else { parser.ReportSyntaxError("Expected left-paren in report aggregate function."); } // get the optional where clause if (parser.PeekToken(TokenKind.WhereKeyword)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); ExpressionNode whereExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out whereExpr)) { node.AppendExpression(whereExpr); } else { parser.ReportSyntaxError("Invalid expression in report aggregate function."); } } break; } case TokenKind.SumKeyword: case TokenKind.AvgKeyword: case TokenKind.MinKeyword: case TokenKind.MaxKeyword: { parser.NextToken(); if (node == null) { node = new TokenExpressionNode(parser.Token); } if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); ExpressionNode expr; if (FglExpressionNode.TryGetExpressionNode(parser, out expr)) { node.AppendExpression(expr); if (parser.PeekToken(TokenKind.RightParenthesis)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); } else { parser.ReportSyntaxError("Expected right-paren in report aggregate function."); } } else { parser.ReportSyntaxError("Invalid expression in report aggregate function."); } } else { parser.ReportSyntaxError("Expected left-paren in report aggregate function."); } // get the optional where clause if (parser.PeekToken(TokenKind.WhereKeyword)) { parser.NextToken(); node.AppendExpression(new TokenExpressionNode(parser.Token)); ExpressionNode whereExpr; if (FglExpressionNode.TryGetExpressionNode(parser, out whereExpr)) { node.AppendExpression(whereExpr); } else { parser.ReportSyntaxError("Invalid expression in report aggregate function."); } } break; } } return(node); }