Parsing of designators like .x or .Self (#4254)

These appear in `where` clauses, as in:

```
U:! InterfaceB where .C = Vector(.D)
V:! type where Vector(.Self) impls Sortable
```

`.Self` can additionally appear in type expressions in a binding pattern
such as `T:! InterfaceA(.Self)`.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
josh11b
2024-08-28 16:26:23 +00:00
committed by GitHub
co-authored by Josh L Jon Ross-Perkins
parent b9e9e66cee
commit 702d0d8a53
7 changed files with 360 additions and 0 deletions
+38
View File
@@ -169,6 +169,44 @@ auto HandleExprInPostfix(Context& context) -> void {
context.PushState(state);
break;
}
case Lex::TokenKind::Period: {
// For periods, we look at the next token to form a designator like
// `.Member` or `.Self`.
auto period = context.Consume();
if (context.ConsumeAndAddLeafNodeIf(Lex::TokenKind::Identifier,
NodeKind::IdentifierName)) {
// OK, `.` identifier.
} else if (context.ConsumeAndAddLeafNodeIf(
Lex::TokenKind::SelfTypeIdentifier,
NodeKind::SelfTypeName)) {
// OK, `.Self`.
} else {
CARBON_DIAGNOSTIC(ExpectedIdentifierOrSelfAfterPeriod, Error,
"Expected identifier or `Self` after `.`.");
context.emitter().Emit(*context.position(),
ExpectedIdentifierOrSelfAfterPeriod);
// Only consume if it is a number or word.
if (context.PositionKind().is_keyword()) {
context.AddLeafNode(NodeKind::IdentifierName, context.Consume(),
/*has_error=*/true);
} else if (context.PositionIs(Lex::TokenKind::IntLiteral)) {
context.AddLeafNode(NodeKind::InvalidParse, context.Consume(),
/*has_error=*/true);
} else {
context.AddLeafNode(NodeKind::InvalidParse, *context.position(),
/*has_error=*/true);
// Indicate the error to the parent state so that it can avoid
// producing more errors. We only do this on this path where we don't
// consume the token after the period, where we expect further errors
// since we likely haven't recovered.
context.ReturnErrorOnState();
}
state.has_error = true;
}
context.AddNode(NodeKind::DesignatorExpr, period, state.has_error);
context.PushState(state);
break;
}
default: {
// Add a node to keep the parse tree balanced.
context.AddLeafNode(NodeKind::InvalidParse, *context.position(),