/// <summary>
        /// Parse schema definition extension.
        /// <see cref="SchemaExtensionNode" />:
        /// * - extend schema Directives[Const]? { OperationTypeDefinition+ }
        /// * - extend schema Directives[Const]
        /// </summary>
        /// <param name="context">The parser context.</param>
        private SchemaExtensionNode ParseSchemaExtension(ParserContext context)
        {
            SyntaxToken start = context.Current;

            context.ExpectExtendKeyword();
            context.ExpectSchemaKeyword();

            List <DirectiveNode> directives =
                ParseDirectives(context, true);

            List <OperationTypeDefinitionNode> operationTypeDefinitions =
                ParseOperationTypeDefinitions(context);

            if (directives.Count == 0 && operationTypeDefinitions.Count == 0)
            {
                throw context.Unexpected(start);
            }

            Location location = context.CreateLocation(start);

            return(new SchemaExtensionNode
                   (
                       location,
                       directives,
                       operationTypeDefinitions
                   ));
        }
        private ITypeExtensionNode ParseTypeExtension(ParserContext context)
        {
            SyntaxToken keywordToken = context.Current.Peek();

            if (keywordToken.Kind == TokenKind.Name)
            {
                switch (keywordToken.Value)
                {
                case Keywords.Schema:
                    return(ParseSchemaExtension(context));

                case Keywords.Scalar:
                    return(ParseScalarTypeExtension(context));

                case Keywords.Type:
                    return(ParseObjectTypeExtension(context));

                case Keywords.Interface:
                    return(ParseInterfaceTypeExtension(context));

                case Keywords.Union:
                    return(ParseUnionTypeExtension(context));

                case Keywords.Enum:
                    return(ParseEnumTypeExtension(context));

                case Keywords.Input:
                    return(ParseInputObjectTypeExtension(context));
                }
            }

            throw context.Unexpected(keywordToken);
        }
        private EnumTypeExtensionNode ParseEnumTypeExtension(ParserContext context)
        {
            SyntaxToken start = context.Current;

            context.ExpectExtendKeyword();
            context.ExpectEnumKeyword();
            NameNode             name       = context.ParseName();
            List <DirectiveNode> directives =
                ParseDirectives(context, true);
            List <EnumValueDefinitionNode> values =
                ParseEnumValuesDefinition(context);
            Location location = context.CreateLocation(start);

            if (directives.Count == 0 && values.Count == 0)
            {
                throw context.Unexpected(start);
            }

            return(new EnumTypeExtensionNode
                   (
                       location,
                       name,
                       directives,
                       values
                   ));
        }
        private InputObjectTypeExtensionNode ParseInputObjectTypeExtension(ParserContext context)
        {
            SyntaxToken start = context.Current;

            context.ExpectExtendKeyword();
            context.ExpectInputKeyword();
            NameNode             name       = context.ParseName();
            List <DirectiveNode> directives =
                ParseDirectives(context, true);
            List <InputValueDefinitionNode> fields =
                ParseInputFieldsDefinition(context);
            Location location = context.CreateLocation(start);

            if (directives.Count == 0 && fields.Count == 0)
            {
                throw context.Unexpected(start);
            }

            return(new InputObjectTypeExtensionNode
                   (
                       location,
                       name,
                       directives,
                       fields
                   ));
        }
        private ObjectTypeExtensionNode ParseObjectTypeExtension(ParserContext context)
        {
            SyntaxToken start = context.Current;

            context.ExpectExtendKeyword();
            context.ExpectTypeKeyword();
            NameNode             name       = context.ParseName();
            List <NamedTypeNode> interfaces =
                ParseImplementsInterfaces(context);
            List <DirectiveNode> directives =
                ParseDirectives(context, true);
            List <FieldDefinitionNode> fields =
                ParseFieldsDefinition(context);
            Location location = context.CreateLocation(start);

            if (interfaces.Count == 0 &&
                directives.Count == 0 &&
                fields.Count == 0)
            {
                throw context.Unexpected(start);
            }

            return(new ObjectTypeExtensionNode
                   (
                       location,
                       name,
                       directives,
                       interfaces,
                       fields
                   ));
        }
        private UnionTypeExtensionNode ParseUnionTypeExtension(ParserContext context)
        {
            SyntaxToken start = context.Current;

            context.ExpectExtendKeyword();
            context.ExpectUnionKeyword();
            NameNode             name       = context.ParseName();
            List <DirectiveNode> directives =
                ParseDirectives(context, true);
            List <NamedTypeNode> types =
                ParseUnionMemberTypes(context);
            Location location = context.CreateLocation(start);

            if (directives.Count == 0 && types.Count == 0)
            {
                throw context.Unexpected(start);
            }

            return(new UnionTypeExtensionNode
                   (
                       location,
                       name,
                       directives,
                       types
                   ));
        }
        /// <summary>
        /// Parses a value.
        /// <see cref="IValueNode" />:
        /// - Variable [only if isConstant is <c>false</c>]
        /// - IntValue
        /// - FloatValue
        /// - StringValue
        /// - BooleanValue
        /// - NullValue
        /// - EnumValue
        /// - ListValue[isConstant]
        /// - ObjectValue[isConstant]
        /// <see cref="BooleanValueNode" />: true or false.
        /// <see cref="NullValueNode" />: null
        /// <see cref="EnumValueNode" />: Name but not true, false or null.
        /// </summary>
        /// <param name="context">The parser context.</param>
        /// <param name="isConstant">
        /// Defines if only constant values are allowed;
        /// otherwise, variables are allowed.
        /// </param>
        internal static IValueNode ParseValueLiteral(
            ParserContext context, bool isConstant)
        {
            SyntaxToken start = context.Current;

            if (start.Kind == TokenKind.LeftBracket)
            {
                return(ParseList(context, isConstant));
            }

            if (start.Kind == TokenKind.LeftBrace)
            {
                return(ParseObject(context, isConstant));
            }

            if (start.IsScalarValue())
            {
                return(ParseScalarValue(context));
            }

            if (start.IsName())
            {
                return(ParseEnumValue(context));
            }

            if (start.IsDollar() && !isConstant)
            {
                return(ParseVariable(context));
            }

            throw context.Unexpected(start);
        }
        private static IValueNode ParseScalarValue(ParserContext context)
        {
            if (context.Current.IsString())
            {
                return(ParseStringLiteral(context));
            }

            SyntaxToken start    = context.ExpectScalarValue();
            Location    location = context.CreateLocation(start);

            if (start.Kind == TokenKind.Float)
            {
                return(new FloatValueNode
                       (
                           location,
                           start.Value
                       ));
            }

            if (start.Kind == TokenKind.Integer)
            {
                return(new IntValueNode
                       (
                           location,
                           start.Value
                       ));
            }

            throw context.Unexpected(start);
        }
        /// <summary>
        /// Parses a type reference.
        /// <see cref="ITypeNode" />:
        /// - NamedType
        /// - ListType
        /// - NonNullType
        /// </summary>
        /// <param name="context">The parser context.</param>
        private ITypeNode ParseTypeReference(ParserContext context)
        {
            SyntaxToken start = context.Current;
            ITypeNode   type;
            Location    location;

            if (context.Skip(TokenKind.LeftBracket))
            {
                type = ParseTypeReference(context);
                context.ExpectRightBracket();
                location = context.CreateLocation(start);

                type = new ListTypeNode(location, type);
            }
            else
            {
                type = ParseNamedType(context);
            }

            if (context.Skip(TokenKind.Bang))
            {
                if (type is INullableType nt)
                {
                    return(new NonNullTypeNode
                           (
                               context.CreateLocation(start),
                               nt
                           ));
                }
                context.Unexpected(context.Current.Previous);
            }

            return(type);
        }
Exemple #10
0
 /// <summary>
 /// Parse fragment name.
 /// <see cref="NameNode" />:
 /// Name
 /// </summary>
 /// <param name="context">The parser context.</param>
 private static NameNode ParseFragmentName(ParserContext context)
 {
     if (context.Current.IsOnKeyword())
     {
         throw context.Unexpected(context.Current);
     }
     return(ParseName(context));
 }
        private NameNode ParseDirectiveLocation(ParserContext context)
        {
            SyntaxToken start = context.Current;
            NameNode    name  = context.ParseName();

            if (DirectiveLocation.IsValidName(name.Value))
            {
                return(name);
            }
            throw context.Unexpected(start);
        }
Exemple #12
0
        /// <summary>
        /// Parses a type definition.
        /// <see cref="ITypeSystemDefinitionNode" />:
        /// TypeSystemDefinition:
        /// - SchemaDefinition
        /// - TypeDefinition
        /// - TypeExtension
        /// - DirectiveDefinition
        ///
        /// TypeDefinition:
        /// - ScalarTypeDefinition
        /// - ObjectTypeDefinition
        /// - InterfaceTypeDefinition
        /// - UnionTypeDefinition
        /// - EnumTypeDefinition
        /// - InputObjectTypeDefinition
        /// </summary>
        /// <param name="context">The parser context.</param>
        private static ITypeSystemDefinitionNode ParseTypeSystemDefinition(
            ParserContext context)
        {
            // Many definitions begin with a description and require a lookahead.
            SyntaxToken keywordToken = context.Current;

            if (keywordToken.IsDescription())
            {
                keywordToken = keywordToken.Peek();
            }

            if (keywordToken.IsName())
            {
                switch (keywordToken.Value)
                {
                case Keywords.Schema:
                    return(ParseSchemaDefinition(context));

                case Keywords.Scalar:
                    return(ParseScalarTypeDefinition(context));

                case Keywords.Type:
                    return(ParseObjectTypeDefinition(context));

                case Keywords.Interface:
                    return(ParseInterfaceTypeDefinition(context));

                case Keywords.Union:
                    return(ParseUnionTypeDefinition(context));

                case Keywords.Enum:
                    return(ParseEnumTypeDefinition(context));

                case Keywords.Input:
                    return(ParseInputObjectTypeDefinition(context));

                case Keywords.Extend:
                    return(ParseTypeExtension(context));

                case Keywords.Directive:
                    return(ParseDirectiveDefinition(context));
                }
            }

            throw context.Unexpected(keywordToken);
        }
        /// <summary>
        /// Parses the <see cref="OperationType" />.
        /// </summary>
        /// <param name="context">The parser context.</param>
        private static OperationType ParseOperationType(ParserContext context)
        {
            SyntaxToken token = context.ExpectName();

            switch (token.Value)
            {
            case Keywords.Query:
                return(OperationType.Query);

            case Keywords.Mutation:
                return(OperationType.Mutation);

            case Keywords.Subscription:
                return(OperationType.Subscription);
            }

            throw context.Unexpected(token);
        }
Exemple #14
0
        private static IDefinitionNode ParseDefinition(ParserContext context)
        {
            SyntaxToken token = context.Current;

            if (token.IsDescription())
            {
                token = token.Peek();
            }

            if (token.IsName())
            {
                switch (token.Value)
                {
                case Keywords.Query:
                case Keywords.Mutation:
                case Keywords.Subscription:
                case Keywords.Fragment:
                    return(ParseExecutableDefinition(context));

                case Keywords.Schema:
                case Keywords.Scalar:
                case Keywords.Type:
                case Keywords.Interface:
                case Keywords.Union:
                case Keywords.Enum:
                case Keywords.Input:
                case Keywords.Extend:
                case Keywords.Directive:
                    return(ParseTypeSystemDefinition(context));
                }
            }
            else if (token.IsLeftBrace())
            {
                return(ParseExecutableDefinition(context));
            }
            else if (token.IsDescription())
            {
                return(ParseTypeSystemDefinition(context));
            }

            throw context.Unexpected(token);
        }
Exemple #15
0
        private IExecutableDefinitionNode ParseExecutableDefinition(ParserContext context)
        {
            if (context.Current.IsName())
            {
                switch (context.Current.Value)
                {
                case Keywords.Query:
                case Keywords.Mutation:
                case Keywords.Subscription:
                    return(ParseOperationDefinition(context));

                case Keywords.Fragment:
                    return(ParseFragmentDefinition(context));
                }
            }
            else if (context.Current.IsLeftBrace())
            {
                return(ParseOperationDefinition(context));
            }

            throw context.Unexpected(context.Current);
        }
        private ScalarTypeExtensionNode ParseScalarTypeExtension(
            ParserContext context)
        {
            SyntaxToken start = context.Current;

            context.ExpectExtendKeyword();
            context.ExpectScalarKeyword();
            NameNode             name       = context.ParseName();
            List <DirectiveNode> directives =
                ParseDirectives(context, true);

            if (directives.Count == 0)
            {
                throw context.Unexpected(start);
            }
            Location location = context.CreateLocation(start);

            return(new ScalarTypeExtensionNode
                   (
                       location,
                       name,
                       directives
                   ));
        }