public static bool TryParseNode(IParser parser, out TypeReference defNode, bool mimickingRecord = false, bool isPublic = false) { defNode = null; bool result = false; ArrayTypeReference arrayType; RecordDefinitionNode recordDef; if (ArrayTypeReference.TryParseNode(parser, out arrayType) && arrayType != null) { result = true; defNode = new TypeReference(); defNode.StartIndex = arrayType.StartIndex; defNode.EndIndex = arrayType.EndIndex; defNode._isPublic = isPublic; defNode.Children.Add(arrayType.StartIndex, arrayType); defNode.IsComplete = true; } else if (RecordDefinitionNode.TryParseNode(parser, out recordDef, isPublic) && recordDef != null) { result = true; defNode = new TypeReference(); defNode.StartIndex = recordDef.StartIndex; defNode.EndIndex = recordDef.EndIndex; defNode._isPublic = isPublic; defNode.Children.Add(recordDef.StartIndex, recordDef); defNode.IsComplete = true; } else if (parser.PeekToken(TokenKind.LikeKeyword)) { result = true; parser.NextToken(); defNode = new TypeReference(); defNode.StartIndex = parser.Token.Span.Start; defNode._isPublic = isPublic; // get db info if (!parser.PeekToken(TokenCategory.Identifier) && parser.PeekToken(TokenKind.Colon, 2)) { parser.NextToken(); // advance to the database name defNode.DatabaseName = parser.Token.Token.Value.ToString(); parser.NextToken(); // advance to the colon } if (!parser.PeekToken(TokenCategory.Identifier)) { parser.ReportSyntaxError("Database table name expected."); } else if (!parser.PeekToken(TokenKind.Dot, 2) && !parser.PeekToken(TokenCategory.Identifier)) { parser.ReportSyntaxError("A mimicking type must reference a table as follows: \"[tablename].[recordname]\"."); } else { parser.NextToken(); // advance to the table name defNode.TableName = parser.Token.Token.Value.ToString(); parser.NextToken(); // advance to the dot if (parser.Token.Token.Kind == TokenKind.Dot) { if (parser.PeekToken(TokenKind.Multiply) || parser.PeekToken(TokenCategory.Identifier) || parser.PeekToken(TokenCategory.Keyword)) { parser.NextToken(); // advance to the column name defNode.ColumnName = parser.Token.Token.Value.ToString(); if (!mimickingRecord && defNode.ColumnName == "*") { parser.ReportSyntaxError("A variable cannot mimic an entire table without being a record. The variable must be defined as a mimicking record."); } defNode.IsComplete = true; defNode.EndIndex = parser.Token.Span.End; } else { if (mimickingRecord) { parser.ReportSyntaxError("A mimicking variable must use the format \"like table.*\""); } else { parser.ReportSyntaxError("A mimicking variable must use the format \"like table.column\""); } } } else { if (mimickingRecord) { parser.ReportSyntaxError("A mimicking variable must use the format \"like table.*\""); } else { parser.ReportSyntaxError("A mimicking variable must use the format \"like table.column\""); } } } } else { var tok = parser.PeekToken(); var cat = Tokenizer.GetTokenInfo(tok).Category; if (cat == TokenCategory.Keyword || cat == TokenCategory.Identifier) { StringBuilder sb = new StringBuilder(); result = true; parser.NextToken(); defNode = new TypeReference(); defNode.StartIndex = parser.Token.Span.Start; sb.Append(parser.Token.Token.Value.ToString()); // determine if there are any constraints on the type keyword string typeString; if (TypeConstraints.VerifyValidConstraint(parser, out typeString)) { defNode._typeNameString = typeString; defNode._isConstrainedType = true; } else { // see if we're referencing an extension type (dotted name) while (parser.PeekToken(TokenKind.Dot)) { sb.Append(parser.NextToken().Value.ToString()); if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { sb.Append(parser.NextToken().Value.ToString()); } else { parser.ReportSyntaxError("Unexpected token in type reference."); } } defNode._typeNameString = sb.ToString(); } AttributeSpecifier attribSpec; if (AttributeSpecifier.TryParseNode(parser, out attribSpec)) { defNode.Attribute = attribSpec; } defNode.EndIndex = parser.Token.Span.End; defNode.IsComplete = true; } else if (cat == TokenCategory.EndOfStream) { parser.ReportSyntaxError("Unexpected end of type definition"); result = false; } } return(result); }
public static bool TryParseNode(IParser parser, out ConstantDefinitionNode defNode, bool isPublic = false) { defNode = null; bool result = false; // parse constant definition if (parser.PeekToken(TokenCategory.Identifier) || parser.PeekToken(TokenCategory.Keyword)) { defNode = new ConstantDefinitionNode(); result = true; parser.NextToken(); defNode.StartIndex = parser.Token.Span.Start; defNode._location = parser.TokenLocation; defNode._isPublic = isPublic; defNode.Identifier = parser.Token.Token.Value.ToString(); if (parser.PeekToken(TokenCategory.Identifier) || parser.PeekToken(TokenCategory.Keyword)) { parser.NextToken(); defNode.Typename = parser.Token.Token.Value.ToString(); string typeStr; // This gets things like char(50), etc. if (TypeConstraints.VerifyValidConstraint(parser, out typeStr)) { defNode.Typename = typeStr; } } if (!parser.PeekToken(TokenKind.Equals) && !(parser.PeekToken(2) is ConstantValueToken)) { parser.ReportSyntaxError("A constant must be defined with a value."); } else { parser.NextToken(); // advance to equals if (parser.PeekToken(TokenCategory.StringLiteral)) { parser.NextToken(); defNode.Literal = string.Format("\"{0}\"", parser.Token.Token.Value.ToString()); defNode.Typename = "string"; } else if (parser.PeekToken(TokenCategory.CharacterLiteral)) { parser.NextToken(); defNode.Literal = string.Format("\'{0}\'", parser.Token.Token.Value.ToString()); defNode.Typename = "string"; } else if (parser.PeekToken(TokenKind.Subtract)) { parser.NextToken(); if (parser.PeekToken(TokenCategory.NumericLiteral)) { parser.NextToken(); defNode.Literal = string.Format("-{0}", parser.Token.Token.Value.ToString()); } } else if (parser.PeekToken(TokenCategory.NumericLiteral)) { parser.NextToken(); defNode.Literal = parser.Token.Token.Value.ToString(); } else if (parser.PeekToken(TokenCategory.IncompleteMultiLineStringLiteral)) { StringBuilder sb = new StringBuilder(parser.NextToken().Value.ToString()); while (parser.PeekToken(TokenCategory.IncompleteMultiLineStringLiteral)) { parser.NextToken(); sb.Append(parser.Token.Token.Value.ToString()); } defNode.Literal = sb.ToString(); defNode.IsComplete = true; defNode.Typename = "string"; } else if (parser.PeekToken(TokenKind.MdyKeyword)) { StringBuilder sb = new StringBuilder(parser.NextToken().Value.ToString()); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); sb.Append("("); while (!parser.PeekToken(TokenKind.Comma)) { if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.ReportSyntaxError("Invalid token found in MDY specification."); return(result); } sb.Append(parser.NextToken().Value.ToString()); } sb.Append(", "); parser.NextToken(); while (!parser.PeekToken(TokenKind.Comma)) { if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.ReportSyntaxError("Invalid token found in MDY specification."); return(result); } sb.Append(parser.NextToken().Value.ToString()); } sb.Append(", "); parser.NextToken(); while (!parser.PeekToken(TokenKind.RightParenthesis)) { if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.ReportSyntaxError("Invalid token found in MDY specification."); return(result); } sb.Append(parser.NextToken().Value.ToString()); } sb.Append(")"); parser.NextToken(); defNode.Literal = sb.ToString(); defNode.IsComplete = true; defNode.Typename = "date"; } else { parser.ReportSyntaxError("Date constant found with an invalid MDY expression."); } } else if (parser.PeekToken(TokenKind.DatetimeKeyword)) { StringBuilder sb = new StringBuilder(parser.NextToken().Value.ToString()); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); sb.Append("("); while (!parser.PeekToken(TokenKind.RightParenthesis)) { if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.ReportSyntaxError("Invalid token found in MDY specification."); return(result); } sb.Append(parser.NextToken().Value.ToString()); } sb.Append(") "); parser.NextToken(); string constraintStr; if (TypeConstraints.VerifyValidConstraint(parser, out constraintStr, TokenKind.DatetimeKeyword)) { sb.Append(constraintStr); defNode.Literal = sb.ToString(); defNode.IsComplete = true; defNode.Typename = "datetime"; } else { parser.ReportSyntaxError("Datetime constant has an invalid constraint."); } } else { parser.ReportSyntaxError("Datetime constant found with an invalid expression."); } } else if (parser.PeekToken(TokenKind.IntervalKeyword)) { StringBuilder sb = new StringBuilder(parser.NextToken().Value.ToString()); if (parser.PeekToken(TokenKind.LeftParenthesis)) { parser.NextToken(); sb.Append("("); while (!parser.PeekToken(TokenKind.RightParenthesis)) { if (parser.PeekToken(TokenCategory.Keyword) || parser.PeekToken(TokenCategory.Identifier)) { parser.ReportSyntaxError("Invalid token found in MDY specification."); return(result); } sb.Append(parser.NextToken().Value.ToString()); } sb.Append(") "); parser.NextToken(); string constraintStr; if (TypeConstraints.VerifyValidConstraint(parser, out constraintStr, TokenKind.IntervalKeyword)) { sb.Append(constraintStr); defNode.Literal = sb.ToString(); defNode.IsComplete = true; defNode.Typename = "interval"; } else { parser.ReportSyntaxError("Interval constant has an invalid constraint."); } } else { parser.ReportSyntaxError("Interval constant found with an invalid expression."); } } else { // look for the constant in the system constants var tok = parser.PeekToken(); IAnalysisResult sysConst; if (Genero4glAst.SystemConstants.TryGetValue(tok.Value.ToString(), out sysConst)) { parser.NextToken(); defNode.Literal = sysConst.Name; defNode.Typename = sysConst.Typename; } } } } return(result); }
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); }