public new static bool TryParseNode(IParser parser, out RecordDefinitionNode defNode, bool isPublic = false) { defNode = null; bool result = false; if (parser.PeekToken(TokenKind.RecordKeyword)) { result = true; defNode = new RecordDefinitionNode(); defNode.StartIndex = parser.Token.Span.Start; defNode.Location = parser.TokenLocation; defNode._isPublic = isPublic; parser.NextToken(); // move past the record keyword if (parser.PeekToken(TokenKind.LikeKeyword)) { // get db info parser.NextToken(); if (!parser.PeekToken(TokenCategory.Identifier) && parser.PeekToken(TokenKind.Colon, 2)) { parser.NextToken(); // advance to the database name defNode.MimicDatabaseName = parser.Token.Token.Value.ToString(); parser.NextToken(); // advance to the colon } FglNameExpression tableName; if (FglNameExpression.TryParseNode(parser, out tableName)) { defNode.MimicTableName = tableName; if (!tableName.Name.EndsWith(".*")) { parser.ReportSyntaxError("A mimicking record must reference a table as follows: \"[tablename].*\"."); } } else { parser.ReportSyntaxError("Invalid database table name found in record definition."); } } else { AttributeSpecifier attribSpec; if (AttributeSpecifier.TryParseNode(parser, out attribSpec)) { defNode.Attribute = attribSpec; } bool advance = true; TokenWithSpan tok = default(TokenWithSpan); while (parser.PeekToken(TokenCategory.Identifier) || parser.PeekToken(TokenCategory.Keyword)) { //if (advance) //{ parser.NextToken(); tok = parser.Token; //} //else //{ // // reset // tok = parser.Token.Token; // advance = true; //} TypeReference tr; if (TypeReference.TryParseNode(parser, out tr, true)) { if (!defNode.MemberDictionary.ContainsKey(tok.Token.Value.ToString())) { defNode.MemberDictionary.Add(tok.Token.Value.ToString(), new VariableDef(tok.Token.Value.ToString(), tr, tok.Span.Start, true, defNode.Location?.FilePath)); } else { parser.ReportSyntaxError(string.Format("Record field {0} defined more than once.", tok.Token.Value.ToString()), Severity.Error); } } AttributeSpecifier.TryParseNode(parser, out attribSpec); if (parser.MaybeEat(TokenKind.Comma)) { //advance = false; continue; } else if (parser.MaybeEat(TokenKind.EndKeyword)) { if (!parser.MaybeEat(TokenKind.RecordKeyword)) { parser.ReportSyntaxError("Invalid end token in record definition"); } else { defNode.EndIndex = parser.Token.Span.End; defNode.IsComplete = true; } break; } else { parser.ReportSyntaxError("Invalid token within record definition"); break; } } } } return(result); }
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); }