Skip to content

Commit 5923e4f

Browse files
committed
[libSyntax] Support parsing collection types
1 parent 4426883 commit 5923e4f

File tree

6 files changed

+73
-41
lines changed

6 files changed

+73
-41
lines changed

include/swift/Parse/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ class Parser {
963963
/// type-simple:
964964
/// '[' type ']'
965965
/// '[' type ':' type ']'
966-
ParserResult<TypeRepr> parseTypeCollection();
966+
SyntaxParserResult<syntax::TypeSyntax, TypeRepr> parseTypeCollection();
967967
ParserResult<OptionalTypeRepr> parseTypeOptional(TypeRepr *Base);
968968

969969
ParserResult<ImplicitlyUnwrappedOptionalTypeRepr>

include/swift/Parse/SyntaxParserResult.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ template <typename Syntax, typename AST> class SyntaxParserResult {
2424
public:
2525
SyntaxParserResult(std::nullptr_t = nullptr)
2626
: SyntaxNode(None), ASTResult(nullptr) {}
27+
SyntaxParserResult(ParserStatus Status)
28+
: SyntaxNode(None), ASTResult(Status) {}
2729
SyntaxParserResult(llvm::Optional<Syntax> SyntaxNode, AST *ASTNode)
2830
: SyntaxNode(SyntaxNode), ASTResult(ASTNode) {}
2931
SyntaxParserResult(ParserStatus Status, llvm::Optional<Syntax> SyntaxNode,

lib/Parse/ParseType.cpp

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,13 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(Diag<> MessageID,
215215
// Eat the code completion token because we handled it.
216216
consumeToken(tok::code_complete);
217217
return makeParserCodeCompletionResult<TypeRepr>();
218-
case tok::l_square:
219-
ty = parseTypeCollection();
218+
case tok::l_square: {
219+
auto Result = parseTypeCollection();
220+
if (Result.hasSyntax())
221+
SyntaxContext->addSyntax(Result.getSyntax());
222+
ty = Result.getASTResult();
220223
break;
224+
}
221225
case tok::kw_protocol:
222226
if (startsWithLess(peekToken())) {
223227
ty = parseOldStyleProtocolComposition();
@@ -1051,14 +1055,16 @@ ParserResult<TypeRepr> Parser::parseTypeArray(TypeRepr *Base) {
10511055
return makeParserResult(ATR);
10521056
}
10531057

1054-
ParserResult<TypeRepr> Parser::parseTypeCollection() {
1058+
SyntaxParserResult<TypeSyntax, TypeRepr> Parser::parseTypeCollection() {
1059+
ParserStatus Status;
10551060
// Parse the leading '['.
10561061
assert(Tok.is(tok::l_square));
10571062
Parser::StructureMarkerRAII parsingCollection(*this, Tok);
10581063
SourceLoc lsquareLoc = consumeToken();
10591064

10601065
// Parse the element type.
10611066
ParserResult<TypeRepr> firstTy = parseType(diag::expected_element_type);
1067+
Status |= firstTy;
10621068

10631069
// If there is a ':', this is a dictionary type.
10641070
SourceLoc colonLoc;
@@ -1068,36 +1074,57 @@ ParserResult<TypeRepr> Parser::parseTypeCollection() {
10681074

10691075
// Parse the second type.
10701076
secondTy = parseType(diag::expected_dictionary_value_type);
1077+
Status |= secondTy;
10711078
}
10721079

10731080
// Parse the closing ']'.
10741081
SourceLoc rsquareLoc;
1075-
parseMatchingToken(tok::r_square, rsquareLoc,
1076-
colonLoc.isValid()
1077-
? diag::expected_rbracket_dictionary_type
1078-
: diag::expected_rbracket_array_type,
1079-
lsquareLoc);
1082+
if (parseMatchingToken(tok::r_square, rsquareLoc,
1083+
colonLoc.isValid()
1084+
? diag::expected_rbracket_dictionary_type
1085+
: diag::expected_rbracket_array_type,
1086+
lsquareLoc))
1087+
Status.setIsParseError();
10801088

1081-
if (firstTy.hasCodeCompletion() || secondTy.hasCodeCompletion())
1082-
return makeParserCodeCompletionStatus();
1089+
if (Status.hasCodeCompletion())
1090+
return Status;
10831091

10841092
// If we couldn't parse anything for one of the types, propagate the error.
1085-
if (firstTy.isNull() || (colonLoc.isValid() && secondTy.isNull()))
1093+
if (Status.isError())
10861094
return makeParserError();
10871095

1088-
// Form the dictionary type.
1096+
TypeRepr *TyR;
1097+
llvm::Optional<TypeSyntax> SyntaxNode;
1098+
10891099
SourceRange brackets(lsquareLoc, rsquareLoc);
1090-
if (colonLoc.isValid())
1091-
return makeParserResult(ParserStatus(firstTy) | ParserStatus(secondTy),
1092-
new (Context) DictionaryTypeRepr(firstTy.get(),
1093-
secondTy.get(),
1094-
colonLoc,
1095-
brackets));
1100+
if (colonLoc.isValid()) {
1101+
// Form the dictionary type.
1102+
TyR = new (Context)
1103+
DictionaryTypeRepr(firstTy.get(), secondTy.get(), colonLoc, brackets);
1104+
if (SyntaxContext->isEnabled()) {
1105+
DictionaryTypeSyntaxBuilder Builder;
1106+
Builder
1107+
.useRightSquareBracket(SyntaxContext->popToken())
1108+
.useValueType(SyntaxContext->popIf<TypeSyntax>().getValue())
1109+
.useColon(SyntaxContext->popToken())
1110+
.useKeyType(SyntaxContext->popIf<TypeSyntax>().getValue())
1111+
.useLeftSquareBracket(SyntaxContext->popToken());
1112+
SyntaxNode.emplace(Builder.build());
1113+
}
1114+
} else {
1115+
// Form the array type.
1116+
TyR = new (Context) ArrayTypeRepr(firstTy.get(), brackets);
1117+
if (SyntaxContext->isEnabled()) {
1118+
ArrayTypeSyntaxBuilder Builder;
1119+
Builder
1120+
.useRightSquareBracket(SyntaxContext->popToken())
1121+
.useElementType(SyntaxContext->popIf<TypeSyntax>().getValue())
1122+
.useLeftSquareBracket(SyntaxContext->popToken());
1123+
SyntaxNode.emplace(Builder.build());
1124+
}
1125+
}
10961126

1097-
// Form the array type.
1098-
return makeParserResult(firstTy,
1099-
new (Context) ArrayTypeRepr(firstTy.get(),
1100-
brackets));
1127+
return makeSyntaxResult(Status, SyntaxNode, TyR);
11011128
}
11021129

11031130
bool Parser::isOptionalToken(const Token &T) const {

test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,5 @@ class C {
5858

5959
typealias A = <SimpleTypeIdentifier>Any</SimpleTypeIdentifier>
6060
typealias B = (<MemberTypeIdentifier><SimpleTypeIdentifier>Array<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>Array<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>Any</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SimpleTypeIdentifier>.Element</MemberTypeIdentifier>)
61+
typealias C = <ArrayType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>]</ArrayType>
62+
typealias D = <DictionaryType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>: <SimpleTypeIdentifier>String</SimpleTypeIdentifier>]</DictionaryType>

test/Syntax/round_trip_parse_gen.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,5 @@ class C {
5858

5959
typealias A = Any
6060
typealias B = (Array<Array<Any>>.Element)
61+
typealias C = [Int]
62+
typealias D = [Int: String]

utils/gyb_syntax_support/TypeNodes.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@
3434
is_optional=True),
3535
]),
3636

37+
# array-type -> '[' type ']'
38+
Node('ArrayType', kind='Type',
39+
children=[
40+
Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
41+
Child('ElementType', kind='Type'),
42+
Child('RightSquareBracket', kind='RightSquareBracketToken'),
43+
]),
44+
45+
# dictionary-type -> '[' type ':' type ']'
46+
Node('DictionaryType', kind='Type',
47+
children=[
48+
Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
49+
Child('KeyType', kind='Type'),
50+
Child('Colon', kind='ColonToken'),
51+
Child('ValueType', kind='Type'),
52+
Child('RightSquareBracket', kind='RightSquareBracketToken'),
53+
]),
3754

3855
# metatype-type -> type '.' 'Type'
3956
# | type '.' 'Protocol
@@ -48,16 +65,6 @@
4865
]),
4966
]),
5067

51-
# dictionary-type -> '[' type ':' type ']'
52-
Node('DictionaryType', kind='Type',
53-
children=[
54-
Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
55-
Child('KeyType', kind='Type'),
56-
Child('Colon', kind='ColonToken'),
57-
Child('ValueType', kind='Type'),
58-
Child('RightSquareBracket', kind='RightSquareBracketToken'),
59-
]),
60-
6168
# throwing-specifier -> 'throws' | 'rethrows'
6269
# function-type -> attribute-list '(' function-type-argument-list ')'
6370
# throwing-specifier? '->'? type?
@@ -99,14 +106,6 @@
99106
is_optional=True),
100107
]),
101108

102-
# array-type -> '[' type ']'
103-
Node('ArrayType', kind='Type',
104-
children=[
105-
Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
106-
Child('ElementType', kind='Type'),
107-
Child('RightSquareBracket', kind='RightSquareBracketToken'),
108-
]),
109-
110109
# type-annotation -> attribute-list 'inout'? type
111110
Node('TypeAnnotation', kind='Syntax',
112111
children=[

0 commit comments

Comments
 (0)