Parsing for generic and template parameters. (#2685)

Also cleans up some comments about related parse nodes. Currently basic and not heavily validated.

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
Jon Ross-Perkins
2023-03-16 10:50:35 -07:00
committed by GitHub
co-authored by Richard Smith
parent 7d553107dd
commit d7ab71ba7d
9 changed files with 153 additions and 44 deletions
+47 -19
View File
@@ -1451,23 +1451,26 @@ auto Parser::HandleParenExpressionFinishAsTupleState() -> void {
state.has_error);
}
auto Parser::ConsumeIfPatternKeyword(TokenKind keyword_token,
ParserState keyword_state,
int subtree_start) -> void {
if (auto token = ConsumeIf(keyword_token)) {
PushState(StateStackEntry(
keyword_state, PrecedenceGroup::ForTopLevelExpression(),
PrecedenceGroup::ForTopLevelExpression(), *token, subtree_start));
}
}
auto Parser::HandlePattern(PatternKind pattern_kind) -> void {
auto state = PopState();
// Ensure the finish state always follows, including for errors.
state.state = ParserState::PatternFinish;
// Parameters may have an `addr` keyword prefixing the pattern. This becomes
// the parent for the full PatternBinding.
// Parameters may have keywords prefixing the pattern. They become the parent
// for the full PatternBinding.
if (pattern_kind != PatternKind::Variable) {
if (auto addr = ConsumeIf(TokenKind::Addr)) {
// Mirror information including subtree_size, but we need to change a copy
// to avoid affecting the token.
auto addr_state = state;
addr_state.state = ParserState::PatternAddress;
addr_state.token = *addr;
PushState(addr_state);
}
ConsumeIfPatternKeyword(TokenKind::Template, ParserState::PatternTemplate,
state.subtree_start);
ConsumeIfPatternKeyword(TokenKind::Addr, ParserState::PatternAddress,
state.subtree_start);
}
// Handle an invalid pattern introducer for parameters and variables.
@@ -1487,6 +1490,8 @@ auto Parser::HandlePattern(PatternKind pattern_kind) -> void {
break;
}
}
// Still use the finish state for errors.
state.state = ParserState::PatternFinishAsRegular;
state.has_error = true;
PushState(state);
};
@@ -1506,9 +1511,13 @@ auto Parser::HandlePattern(PatternKind pattern_kind) -> void {
return;
}
if (auto colon = ConsumeIf(TokenKind::Colon)) {
// Use the colon for the root node.
state.token = *colon;
if (auto kind = PositionKind();
kind == TokenKind::Colon || kind == TokenKind::ColonExclaim) {
state.state = kind == TokenKind::Colon
? ParserState::PatternFinishAsRegular
: ParserState::PatternFinishAsGeneric;
// Use the `:` or `:!` for the root node.
state.token = Consume();
PushState(state);
PushStateForExpression(PrecedenceGroup::ForType());
} else {
@@ -1529,7 +1538,7 @@ auto Parser::HandlePatternAsVariableState() -> void {
HandlePattern(PatternKind::Variable);
}
auto Parser::HandlePatternFinishState() -> void {
auto Parser::HandlePatternFinish(ParseNodeKind node_kind) -> void {
auto state = PopState();
// If an error was encountered, propagate it without adding a node.
@@ -1539,8 +1548,15 @@ auto Parser::HandlePatternFinishState() -> void {
}
// TODO: may need to mark has_error if !type.
AddNode(ParseNodeKind::PatternBinding, state.token, state.subtree_start,
/*has_error=*/false);
AddNode(node_kind, state.token, state.subtree_start, /*has_error=*/false);
}
auto Parser::HandlePatternFinishAsGenericState() -> void {
HandlePatternFinish(ParseNodeKind::GenericPatternBinding);
}
auto Parser::HandlePatternFinishAsRegularState() -> void {
HandlePatternFinish(ParseNodeKind::PatternBinding);
}
auto Parser::HandlePatternAddressState() -> void {
@@ -1555,6 +1571,18 @@ auto Parser::HandlePatternAddressState() -> void {
}
}
auto Parser::HandlePatternTemplateState() -> void {
auto state = PopState();
AddNode(ParseNodeKind::Template, state.token, state.subtree_start,
state.has_error);
// If an error was encountered, propagate it while adding a node.
if (state.has_error) {
ReturnErrorOnState();
}
}
auto Parser::HandleStatementState() -> void {
PopAndDiscardState();