Only allow designators when parsing where __ = ... (#4304)

Implements
[TODO](https://github.com/carbon-language/carbon-lang/pull/4275/files#r1751000646)
introduced in #4275 . Note that this enforces the restriction
syntactically in parse, following the
[design](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#rewrite-constraints).

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
This commit is contained in:
josh11b
2024-09-12 01:39:22 +00:00
committed by GitHub
co-authored by Josh L
parent de57c9988c
commit 35dfa5f03c
5 changed files with 234 additions and 11 deletions
+31 -9
View File
@@ -9,9 +9,23 @@
namespace Carbon::Parse {
auto HandleRequirementBegin(Context& context) -> void {
context.PopAndDiscardState();
// TODO: Peek ahead for `.designator = ...`, and give it special handling.
context.PushState(State::RequirementOperator);
auto state = context.PopState();
// Peek ahead for `.designator = ...`, and give it special handling.
if (context.PositionKind() == Lex::TokenKind::Period &&
context.PositionKind(Lookahead::NextToken) ==
Lex::TokenKind::Identifier &&
context.PositionKind(static_cast<Lookahead>(2)) ==
Lex::TokenKind::Equal) {
auto period = context.Consume();
context.AddNode(NodeKind::IdentifierName, context.Consume(),
/*has_error=*/false);
context.AddNode(NodeKind::DesignatorExpr, period, /*has_error=*/false);
state.token = context.Consume();
context.PushState(state, State::RequirementOperatorFinish);
} else {
context.PushState(State::RequirementOperator);
}
context.PushStateForExpr(PrecedenceGroup::ForRequirements());
}
@@ -19,14 +33,22 @@ auto HandleRequirementOperator(Context& context) -> void {
auto state = context.PopState();
switch (context.PositionKind()) {
case Lex::TokenKind::Impls: {
// Accept either `impls` or `==`
case Lex::TokenKind::Impls:
case Lex::TokenKind::EqualEqual:
break;
}
// Reject `=` since correct usage is consumed in `HandleRequirementBegin`.
case Lex::TokenKind::Equal: {
break;
}
case Lex::TokenKind::EqualEqual: {
break;
if (!state.has_error) {
CARBON_DIAGNOSTIC(
RequirementEqualAfterNonDesignator, Error,
"Requirement can only use `=` after `.member` designator.");
context.emitter().Emit(*context.position(),
RequirementEqualAfterNonDesignator);
}
context.ReturnErrorOnState();
return;
}
default: {
if (!state.has_error) {