Skip to content

Commit b1bfc47

Browse files
committed
parser: Extract optional_many utility function
Replicates graphql/graphql-js@b13f283
1 parent e6cbb48 commit b1bfc47

File tree

1 file changed

+39
-70
lines changed

1 file changed

+39
-70
lines changed

src/graphql/language/parser.py

+39-70
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Callable, Dict, List, Optional, Union, cast
1+
from typing import Callable, Dict, List, Optional, Union, TypeVar, cast
22
from functools import partial
33

44
from .ast import (
@@ -30,7 +30,6 @@
3030
Location,
3131
NameNode,
3232
NamedTypeNode,
33-
Node,
3433
NonNullTypeNode,
3534
NullValueNode,
3635
ObjectFieldNode,
@@ -66,6 +65,8 @@
6665

6766
__all__ = ["parse", "parse_type", "parse_value"]
6867

68+
T = TypeVar("T")
69+
6970
SourceType = Union[Source, str]
7071

7172

@@ -267,15 +268,8 @@ def parse_operation_type(self) -> OperationType:
267268

268269
def parse_variable_definitions(self) -> List[VariableDefinitionNode]:
269270
"""VariableDefinitions: (VariableDefinition+)"""
270-
return (
271-
cast(
272-
List[VariableDefinitionNode],
273-
self.many(
274-
TokenKind.PAREN_L, self.parse_variable_definition, TokenKind.PAREN_R
275-
),
276-
)
277-
if self.peek(TokenKind.PAREN_L)
278-
else []
271+
return self.optional_many(
272+
TokenKind.PAREN_L, self.parse_variable_definition, TokenKind.PAREN_R
279273
)
280274

281275
def parse_variable_definition(self) -> VariableDefinitionNode:
@@ -337,14 +331,7 @@ def parse_field(self) -> FieldNode:
337331
def parse_arguments(self, is_const: bool) -> List[ArgumentNode]:
338332
"""Arguments[Const]: (Argument[?Const]+)"""
339333
item = self.parse_const_argument if is_const else self.parse_argument
340-
return (
341-
cast(
342-
List[ArgumentNode],
343-
self.many(TokenKind.PAREN_L, item, TokenKind.PAREN_R),
344-
)
345-
if self.peek(TokenKind.PAREN_L)
346-
else []
347-
)
334+
return self.optional_many(TokenKind.PAREN_L, item, TokenKind.PAREN_R)
348335

349336
def parse_argument(self) -> ArgumentNode:
350337
"""Argument: Name : Value"""
@@ -671,15 +658,8 @@ def parse_implements_interfaces(self) -> List[NamedTypeNode]:
671658

672659
def parse_fields_definition(self) -> List[FieldDefinitionNode]:
673660
"""FieldsDefinition: {FieldDefinition+}"""
674-
return (
675-
cast(
676-
List[FieldDefinitionNode],
677-
self.many(
678-
TokenKind.BRACE_L, self.parse_field_definition, TokenKind.BRACE_R
679-
),
680-
)
681-
if self.peek(TokenKind.BRACE_L)
682-
else []
661+
return self.optional_many(
662+
TokenKind.BRACE_L, self.parse_field_definition, TokenKind.BRACE_R
683663
)
684664

685665
def parse_field_definition(self) -> FieldDefinitionNode:
@@ -702,15 +682,8 @@ def parse_field_definition(self) -> FieldDefinitionNode:
702682

703683
def parse_argument_defs(self) -> List[InputValueDefinitionNode]:
704684
"""ArgumentsDefinition: (InputValueDefinition+)"""
705-
return (
706-
cast(
707-
List[InputValueDefinitionNode],
708-
self.many(
709-
TokenKind.PAREN_L, self.parse_input_value_def, TokenKind.PAREN_R
710-
),
711-
)
712-
if self.peek(TokenKind.PAREN_L)
713-
else []
685+
return self.optional_many(
686+
TokenKind.PAREN_L, self.parse_input_value_def, TokenKind.PAREN_R
714687
)
715688

716689
def parse_input_value_def(self) -> InputValueDefinitionNode:
@@ -798,17 +771,8 @@ def parse_enum_type_definition(self) -> EnumTypeDefinitionNode:
798771

799772
def parse_enum_values_definition(self) -> List[EnumValueDefinitionNode]:
800773
"""EnumValuesDefinition: {EnumValueDefinition+}"""
801-
return (
802-
cast(
803-
List[EnumValueDefinitionNode],
804-
self.many(
805-
TokenKind.BRACE_L,
806-
self.parse_enum_value_definition,
807-
TokenKind.BRACE_R,
808-
),
809-
)
810-
if self.peek(TokenKind.BRACE_L)
811-
else []
774+
return self.optional_many(
775+
TokenKind.BRACE_L, self.parse_enum_value_definition, TokenKind.BRACE_R
812776
)
813777

814778
def parse_enum_value_definition(self) -> EnumValueDefinitionNode:
@@ -842,15 +806,8 @@ def parse_input_object_type_definition(self) -> InputObjectTypeDefinitionNode:
842806

843807
def parse_input_fields_definition(self) -> List[InputValueDefinitionNode]:
844808
"""InputFieldsDefinition: {InputValueDefinition+}"""
845-
return (
846-
cast(
847-
List[InputValueDefinitionNode],
848-
self.many(
849-
TokenKind.BRACE_L, self.parse_input_value_def, TokenKind.BRACE_R
850-
),
851-
)
852-
if self.peek(TokenKind.BRACE_L)
853-
else []
809+
return self.optional_many(
810+
TokenKind.BRACE_L, self.parse_input_value_def, TokenKind.BRACE_R
854811
)
855812

856813
def parse_schema_extension(self) -> SchemaExtensionNode:
@@ -859,14 +816,8 @@ def parse_schema_extension(self) -> SchemaExtensionNode:
859816
self.expect_keyword("extend")
860817
self.expect_keyword("schema")
861818
directives = self.parse_directives(True)
862-
operation_types = (
863-
self.many(
864-
TokenKind.BRACE_L,
865-
self.parse_operation_type_definition,
866-
TokenKind.BRACE_R,
867-
)
868-
if self.peek(TokenKind.BRACE_L)
869-
else []
819+
operation_types = self.optional_many(
820+
TokenKind.BRACE_L, self.parse_operation_type_definition, TokenKind.BRACE_R
870821
)
871822
if not directives and not operation_types:
872823
raise self.unexpected()
@@ -1088,24 +1039,42 @@ def unexpected(self, at_token: Token = None) -> GraphQLError:
10881039
)
10891040

10901041
def any(
1091-
self, open_kind: TokenKind, parse_fn: Callable[[], Node], close_kind: TokenKind
1092-
) -> List[Node]:
1042+
self, open_kind: TokenKind, parse_fn: Callable[[], T], close_kind: TokenKind
1043+
) -> List[T]:
10931044
"""Fetch any matching nodes, possibly none.
10941045
10951046
Returns a possibly empty list of parse nodes, determined by the `parse_fn`.
10961047
This list begins with a lex token of `open_kind` and ends with a lex token of
10971048
`close_kind`. Advances the parser to the next lex token after the closing token.
10981049
"""
10991050
self.expect_token(open_kind)
1100-
nodes: List[Node] = []
1051+
nodes: List[T] = []
11011052
append = nodes.append
11021053
while not self.expect_optional_token(close_kind):
11031054
append(parse_fn())
11041055
return nodes
11051056

1057+
def optional_many(
1058+
self, open_kind: TokenKind, parse_fn: Callable[[], T], close_kind: TokenKind
1059+
) -> List[T]:
1060+
"""Fetch matching nodes, maybe none.
1061+
1062+
Returns a list of parse nodes, determined by the `parse_fn`. It can be empty
1063+
only if the open token is missing, otherwise it will always return a non-empty
1064+
list that begins with a lex token of `open_kind` and ends with a lex token of
1065+
`close_kind`. Advances the parser to the next lex token after the closing token.
1066+
"""
1067+
if self.expect_optional_token(open_kind):
1068+
nodes = [parse_fn()]
1069+
append = nodes.append
1070+
while not self.expect_optional_token(close_kind):
1071+
append(parse_fn())
1072+
return nodes
1073+
return []
1074+
11061075
def many(
1107-
self, open_kind: TokenKind, parse_fn: Callable[[], Node], close_kind: TokenKind
1108-
) -> List[Node]:
1076+
self, open_kind: TokenKind, parse_fn: Callable[[], T], close_kind: TokenKind
1077+
) -> List[T]:
11091078
"""Fetch matching nodes, at least one.
11101079
11111080
Returns a non-empty list of parse nodes, determined by the `parse_fn`.

0 commit comments

Comments
 (0)