Skip to content

Commit 8ce840f

Browse files
committed
[Syntax] Introduce UnresolvedIsExpr/UnresolvedAsExpr
SequenceExprSyntax should have odd number elements. Previously 'a as b' was parsed like: ``` (sequence_expr (identifier_expr "a"), (as_expr 'as' (typeidentifier "b"))) ``` So it had even number elements. Now it's parsed ``` (sequence_expr (identifier_expr "a"), (unresolved_as_expr 'as') (type_expr (typeidentifier "b"))) ```
1 parent 064b713 commit 8ce840f

File tree

4 files changed

+57
-14
lines changed

4 files changed

+57
-14
lines changed

lib/Parse/ParseExpr.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,15 @@ ParserResult<Expr> Parser::parseExprImpl(Diag<> Message,
7272
/// expr-is:
7373
/// 'is' type
7474
ParserResult<Expr> Parser::parseExprIs() {
75-
SourceLoc isLoc = consumeToken(tok::kw_is);
75+
SourceLoc isLoc;
76+
{
77+
SyntaxParsingContext IsExprCtx(SyntaxContext, SyntaxKind::UnresolvedIsExpr);
78+
isLoc = consumeToken(tok::kw_is);
79+
}
7680

7781
ParserResult<TypeRepr> type = parseType(diag::expected_type_after_is);
82+
SyntaxContext->createNodeInPlace(SyntaxKind::TypeExpr);
83+
7884
if (type.hasCodeCompletion())
7985
return makeParserCodeCompletionResult<Expr>();
8086
if (type.isNull())
@@ -89,19 +95,25 @@ ParserResult<Expr> Parser::parseExprIs() {
8995
/// 'as?' type
9096
/// 'as!' type
9197
ParserResult<Expr> Parser::parseExprAs() {
92-
// Parse the 'as'.
93-
SourceLoc asLoc = consumeToken(tok::kw_as);
94-
95-
// Parse the postfix '?'.
98+
SourceLoc asLoc;
9699
SourceLoc questionLoc;
97100
SourceLoc exclaimLoc;
98-
if (Tok.is(tok::question_postfix)) {
99-
questionLoc = consumeToken(tok::question_postfix);
100-
} else if (Tok.is(tok::exclaim_postfix)) {
101-
exclaimLoc = consumeToken(tok::exclaim_postfix);
101+
102+
{
103+
SyntaxParsingContext AsExprCtx(SyntaxContext, SyntaxKind::UnresolvedAsExpr);
104+
// Parse the 'as'.
105+
asLoc = consumeToken(tok::kw_as);
106+
107+
// Parse the postfix '?'.
108+
if (Tok.is(tok::question_postfix)) {
109+
questionLoc = consumeToken(tok::question_postfix);
110+
} else if (Tok.is(tok::exclaim_postfix)) {
111+
exclaimLoc = consumeToken(tok::exclaim_postfix);
112+
}
102113
}
103114

104115
ParserResult<TypeRepr> type = parseType(diag::expected_type_after_as);
116+
SyntaxContext->createNodeInPlace(SyntaxKind::TypeExpr);
105117

106118
if (type.hasCodeCompletion())
107119
return makeParserCodeCompletionResult<Expr>();
@@ -295,7 +307,6 @@ ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
295307
}
296308

297309
case tok::kw_is: {
298-
SyntaxParsingContext IsContext(SyntaxContext, SyntaxKind::IsExpr);
299310
// Parse a type after the 'is' token instead of an expression.
300311
ParserResult<Expr> is = parseExprIs();
301312
if (is.isNull() || is.hasCodeCompletion())
@@ -313,7 +324,6 @@ ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
313324
}
314325

315326
case tok::kw_as: {
316-
SyntaxParsingContext AsContext(SyntaxContext, SyntaxKind::AsExpr);
317327
ParserResult<Expr> as = parseExprAs();
318328
if (as.isNull() || as.hasCodeCompletion())
319329
return as;

lib/Parse/SyntaxParsingContext.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ void SyntaxParsingContext::createNodeInPlace(SyntaxKind Kind,
278278
case SyntaxKind::AvailabilityLabeledArgument:
279279
case SyntaxKind::MetatypeType:
280280
case SyntaxKind::OptionalType:
281-
case SyntaxKind::ImplicitlyUnwrappedOptionalType: {
281+
case SyntaxKind::ImplicitlyUnwrappedOptionalType:
282+
case SyntaxKind::TypeExpr: {
282283
auto Pair = SyntaxFactory::countChildren(Kind);
283284
assert(Pair.first == Pair.second);
284285
createNodeInPlace(Kind, Pair.first, nodeCreateK);

utils/gyb_syntax_support/ExprNodes.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,16 +351,46 @@
351351
is_optional=True),
352352
]),
353353

354-
# is TypeName
354+
# 'is'
355+
# "is" type casting ooperator without operands.
356+
# NOTE: This appears only in SequenceExpr.
357+
Node('UnresolvedIsExpr', kind='Expr',
358+
children=[
359+
Child("IsTok", kind='IsToken'),
360+
]),
361+
362+
# expression is TypeName
363+
# NOTE: This won't come directly out of the parser. Rather, it is the
364+
# result of "folding" a SequenceExpr based on knowing the precedence
365+
# relationships amongst the different infix operators.
355366
Node('IsExpr', kind='Expr',
356367
children=[
368+
Child("Expression", kind="Expr"),
357369
Child("IsTok", kind='IsToken'),
358370
Child("TypeName", kind='Type')
359371
]),
360372

361-
# as TypeName
373+
# 'as' ('?'|'!')
374+
# "as" type casting ooperator without operands.
375+
# NOTE: This appears only in SequenceExpr.
376+
Node('UnresolvedAsExpr', kind='Expr',
377+
children=[
378+
Child("AsTok", kind='AsToken'),
379+
Child("QuestionOrExclamationMark", kind='Token',
380+
is_optional=True,
381+
token_choices=[
382+
'PostfixQuestionMarkToken',
383+
'ExclamationMarkToken',
384+
]),
385+
]),
386+
387+
# expression as TypeName
388+
# NOTE: This won't come directly out of the parser. Rather, it is the
389+
# result of "folding" a SequenceExpr based on knowing the precedence
390+
# relationships amongst the different infix operators.
362391
Node('AsExpr', kind='Expr',
363392
children=[
393+
Child("Expression", kind="Expr"),
364394
Child("AsTok", kind='AsToken'),
365395
Child("QuestionOrExclamationMark", kind='Token',
366396
is_optional=True,

utils/gyb_syntax_support/NodeSerializationCodes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@
272272
'InfixOperatorExpr': 268,
273273
'MoveExpr': 269,
274274
'UnresolvedTernaryExpr': 270,
275+
'UnresolvedIsExpr': 271,
276+
'UnresolvedAsExpr': 272,
275277
}
276278

277279

0 commit comments

Comments
 (0)