Reorganize interface parsing to be more consistent with other declarations. (#2646)

The comments in parse_node_kind.def capture the change being made here.

Before:

```
//   _external_: DeclaredName
//     InterfaceBodyStart
//     _external_: statements
//   InterfaceBodyEnd
// InterfaceDefinition
```

After:

```
//     InterfaceIntroducer
//     DeclaredName
//   InterfaceDefinitionStart
//   _external_: declarations
// InterfaceDefinition
```

Really I just want to treat introduced things consistently. `var` defines my philosophy here: it doesn't always have a `DeclaredName`, so the `VarIntroducer` _must_ be the bounding node. By being consistent with that, I believe that overall the structure becomes easier to understand (that is, there are fewer inconsistencies to understand).

This also adds InterfaceDeclaration, since I think it can be predicted we'll have that, and it's helpful for making recover consistent with HandleDeclarationError.

Similarly, I'm also trying to standardize the loop processing a little with HandleDeclarationLoop. In the current approach, InterfaceDefinitionFinish isn't a necessary state, so I'm removing it.
This commit is contained in:
Jon Ross-Perkins
2023-03-06 16:31:01 -08:00
committed by GitHub
parent bfe5c36bfc
commit 4083d7f5b9
12 changed files with 266 additions and 252 deletions
+15 -9
View File
@@ -79,8 +79,9 @@ CARBON_PARSE_NODE_KIND_BRACKET(CodeBlock, CodeBlockStart)
// _external_: statements
// FunctionDefinition
//
// The above is a definition; for a declaration, FunctionDeclaration will end it
// where FunctionDefinitionStart is for a definition.
// The above is the structure for a definition; for a declaration,
// FunctionDefinitionStart and later nodes are removed and replaced by
// FunctionDeclaration.
CARBON_PARSE_NODE_KIND_CHILD_COUNT(FunctionIntroducer, 0)
CARBON_PARSE_NODE_KIND_CHILD_COUNT(ReturnType, 1)
CARBON_PARSE_NODE_KIND_BRACKET(FunctionDefinitionStart, FunctionIntroducer)
@@ -282,14 +283,19 @@ CARBON_PARSE_NODE_KIND_BRACKET(StructTypeLiteral,
StructLiteralOrStructTypeLiteralStart)
// `interface`:
// _external_: DeclaredName
// InterfaceBodyStart
// _external_: statements
// InterfaceBodyEnd
// InterfaceIntroducer
// DeclaredName
// InterfaceDefinitionStart
// _external_: declarations
// InterfaceDefinition
CARBON_PARSE_NODE_KIND_CHILD_COUNT(InterfaceBodyStart, 0)
CARBON_PARSE_NODE_KIND_BRACKET(InterfaceBody, InterfaceBodyStart)
CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDefinition, DeclaredName)
//
// The above is the structure for a definition; for a declaration,
// InterfaceDefinitionStart and later nodes are removed and replaced by
// InterfaceDeclaration.
CARBON_PARSE_NODE_KIND_CHILD_COUNT(InterfaceIntroducer, 0)
CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDefinitionStart, InterfaceIntroducer)
CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDefinition, InterfaceDefinitionStart)
CARBON_PARSE_NODE_KIND_BRACKET(InterfaceDeclaration, InterfaceIntroducer)
// A pattern binding for `self` deduced parameter:
// `self`
+55 -64
View File
@@ -28,9 +28,6 @@ CARBON_DIAGNOSTIC(ExpectedParenAfter, Error, "Expected `(` after `{0}`.",
CARBON_DIAGNOSTIC(ExpectedSemiAfterExpression, Error,
"Expected `;` after expression.");
CARBON_DIAGNOSTIC(UnrecognizedDeclaration, Error,
"Unrecognized declaration introducer.");
// A relative location for characters in errors.
enum class RelativeLocation : int8_t {
Around,
@@ -465,6 +462,31 @@ auto Parser::GetDeclarationContext() -> DeclarationContext {
llvm_unreachable("Should always be able to find DeclarationLoop");
}
auto Parser::HandleDeclarationError(StateStackEntry state,
ParseNodeKind parse_node_kind,
bool skip_past_likely_end) -> void {
auto token = state.token;
if (skip_past_likely_end) {
if (auto semi = SkipPastLikelyEnd(token)) {
token = *semi;
}
}
AddNode(parse_node_kind, token, state.subtree_start,
/*has_error=*/true);
}
auto Parser::HandleUnrecognizedDeclaration() -> void {
CARBON_DIAGNOSTIC(UnrecognizedDeclaration, Error,
"Unrecognized declaration introducer.");
emitter_->Emit(*position_, UnrecognizedDeclaration);
auto cursor = *position_;
auto semi = SkipPastLikelyEnd(cursor);
// Locate the EmptyDeclaration at the semi when found, but use the
// original cursor location for an error when not.
AddLeafNode(ParseNodeKind::EmptyDeclaration, semi ? *semi : cursor,
/*has_error=*/true);
}
auto Parser::HandleBraceExpressionState() -> void {
auto state = PopState();
@@ -731,7 +753,6 @@ auto Parser::HandleDeclarationLoopState() -> void {
}
case TokenKind::Fn: {
PushState(ParserState::FunctionIntroducer);
AddLeafNode(ParseNodeKind::FunctionIntroducer, Consume());
break;
}
case TokenKind::Package: {
@@ -748,17 +769,10 @@ auto Parser::HandleDeclarationLoopState() -> void {
}
case TokenKind::Interface: {
PushState(ParserState::InterfaceIntroducer);
++position_;
break;
}
default: {
emitter_->Emit(*position_, UnrecognizedDeclaration);
auto cursor = *position_;
auto semi = SkipPastLikelyEnd(cursor);
// Locate the EmptyDeclaration at the semi when found, but use the
// original cursor location for an error when not.
AddLeafNode(ParseNodeKind::EmptyDeclaration, semi ? *semi : cursor,
/*has_error=*/true);
HandleUnrecognizedDeclaration();
break;
}
}
@@ -1017,21 +1031,11 @@ auto Parser::HandleExpressionStatementFinishState() -> void {
ReturnErrorOnState();
}
auto Parser::HandleFunctionError(StateStackEntry state,
bool skip_past_likely_end) -> void {
auto token = state.token;
if (skip_past_likely_end) {
if (auto semi = SkipPastLikelyEnd(token)) {
token = *semi;
}
}
AddNode(ParseNodeKind::FunctionDeclaration, token, state.subtree_start,
/*has_error=*/true);
}
auto Parser::HandleFunctionIntroducerState() -> void {
auto state = PopState();
AddLeafNode(ParseNodeKind::FunctionIntroducer, Consume());
if (!ConsumeAndAddLeafNodeIf(TokenKind::Identifier,
ParseNodeKind::DeclaredName)) {
CARBON_DIAGNOSTIC(ExpectedFunctionName, Error,
@@ -1040,7 +1044,8 @@ auto Parser::HandleFunctionIntroducerState() -> void {
// TODO: We could change the lexer to allow us to synthesize certain
// kinds of tokens and try to "recover" here, but unclear that this is
// really useful.
HandleFunctionError(state, true);
HandleDeclarationError(state, ParseNodeKind::FunctionDeclaration,
/*skip_past_likely_end=*/true);
return;
}
@@ -1073,7 +1078,8 @@ auto Parser::HandleFunctionAfterDeducedParameterListState() -> void {
CARBON_DIAGNOSTIC(ExpectedFunctionParams, Error,
"Expected `(` after function name.");
emitter_->Emit(*position_, ExpectedFunctionParams);
HandleFunctionError(state, true);
HandleDeclarationError(state, ParseNodeKind::FunctionDeclaration,
/*skip_past_likely_end=*/true);
return;
}
@@ -1154,7 +1160,8 @@ auto Parser::HandleFunctionSignatureFinishState() -> void {
MethodImplNotAllowed, Error,
"Method implementations are not allowed in interfaces.");
emitter_->Emit(*position_, MethodImplNotAllowed);
HandleFunctionError(state, /*skip_past_likely_end=*/true);
HandleDeclarationError(state, ParseNodeKind::FunctionDeclaration,
/*skip_past_likely_end=*/true);
break;
}
@@ -1175,7 +1182,8 @@ auto Parser::HandleFunctionSignatureFinishState() -> void {
// Only need to skip if we've not already found a new line.
bool skip_past_likely_end =
tokens_->GetLine(*position_) == tokens_->GetLine(state.token);
HandleFunctionError(state, skip_past_likely_end);
HandleDeclarationError(state, ParseNodeKind::FunctionDeclaration,
skip_past_likely_end);
break;
}
}
@@ -1190,39 +1198,37 @@ auto Parser::HandleFunctionDefinitionFinishState() -> void {
auto Parser::HandleInterfaceIntroducerState() -> void {
auto state = PopState();
AddLeafNode(ParseNodeKind::InterfaceIntroducer, Consume());
if (!ConsumeAndAddLeafNodeIf(TokenKind::Identifier,
ParseNodeKind::DeclaredName)) {
CARBON_DIAGNOSTIC(ExpectedInterfaceName, Error,
"Expected interface name after `interface` keyword.");
emitter_->Emit(*position_, ExpectedInterfaceName);
state.has_error = true;
// Add a name node even when it's not present because it's used for subtree
// bracketing on interfaces.
// TODO: Either fix this or normalize it, still deciding on the right
// approach.
AddLeafNode(ParseNodeKind::DeclaredName, state.token, /*has_error=*/true);
HandleDeclarationError(state, ParseNodeKind::InterfaceDeclaration,
/*skip_past_likely_end=*/true);
return;
}
bool parse_body = true;
if (auto semi = ConsumeIf(TokenKind::Semi)) {
AddNode(ParseNodeKind::InterfaceDeclaration, *semi, state.subtree_start,
state.has_error);
return;
}
if (!PositionIs(TokenKind::OpenCurlyBrace)) {
CARBON_DIAGNOSTIC(ExpectedInterfaceOpenCurlyBrace, Error,
"Expected `{{` to start interface definition.");
emitter_->Emit(*position_, ExpectedInterfaceOpenCurlyBrace);
state.has_error = true;
SkipPastLikelyEnd(state.token);
parse_body = false;
HandleDeclarationError(state, ParseNodeKind::InterfaceDeclaration,
/*skip_past_likely_end=*/true);
return;
}
state.state = ParserState::InterfaceDefinitionFinish;
state.state = ParserState::InterfaceDefinitionLoop;
PushState(state);
if (parse_body) {
PushState(ParserState::InterfaceDefinitionLoop);
AddLeafNode(ParseNodeKind::InterfaceBodyStart, Consume());
}
AddNode(ParseNodeKind::InterfaceDefinitionStart, Consume(),
state.subtree_start, state.has_error);
}
auto Parser::HandleInterfaceDefinitionLoopState() -> void {
@@ -1232,36 +1238,21 @@ auto Parser::HandleInterfaceDefinitionLoopState() -> void {
switch (PositionKind()) {
case TokenKind::CloseCurlyBrace: {
auto state = PopState();
AddNode(ParseNodeKind::InterfaceBody, Consume(), state.subtree_start,
state.has_error);
AddNode(ParseNodeKind::InterfaceDefinition, Consume(),
state.subtree_start, state.has_error);
break;
}
case TokenKind::Fn: {
PushState(ParserState::FunctionIntroducer);
AddLeafNode(ParseNodeKind::FunctionIntroducer, Consume());
break;
}
default: {
emitter_->Emit(*position_, UnrecognizedDeclaration);
if (auto semi = SkipPastLikelyEnd(*position_)) {
AddLeafNode(ParseNodeKind::EmptyDeclaration, *semi,
/*has_error=*/true);
} else {
ReturnErrorOnState();
}
HandleUnrecognizedDeclaration();
break;
}
}
}
auto Parser::HandleInterfaceDefinitionFinishState() -> void {
auto state = PopState();
AddNode(ParseNodeKind::InterfaceDefinition, state.token, state.subtree_start,
state.has_error);
}
auto Parser::HandlePackageState() -> void {
auto state = PopState();
+11 -6
View File
@@ -262,6 +262,17 @@ class Parser {
// parses should only need to look down a couple steps.
auto GetDeclarationContext() -> DeclarationContext;
// Handles error recovery in a declaration, particularly before any possible
// definition has started (although one could be present). Recover to a
// semicolon when it makes sense as a possible end, otherwise use the
// introducer token for the error.
auto HandleDeclarationError(StateStackEntry state,
ParseNodeKind parse_node_kind,
bool skip_past_likely_end) -> void;
// Handles an unrecognized declaration, adding an error node.
auto HandleUnrecognizedDeclaration() -> void;
// Propagates an error up the state stack, to the parent state.
auto ReturnErrorOnState() -> void { state_stack_.back().has_error = true; }
@@ -292,12 +303,6 @@ class Parser {
// Handles DesignatorAs.
auto HandleDesignator(bool as_struct) -> void;
// When handling errors before the start of the definition, treat it as a
// declaration. Recover to a semicolon when it makes sense as a possible
// function end, otherwise use the fn token for the error.
auto HandleFunctionError(StateStackEntry state, bool skip_past_likely_end)
-> void;
// Handles ParenConditionAs(If|While)
auto HandleParenCondition(ParseNodeKind start_kind, ParserState finish_state)
-> void;
+6 -13
View File
@@ -300,15 +300,9 @@ CARBON_PARSER_STATE(FunctionSignatureFinish)
// (state done)
CARBON_PARSER_STATE(FunctionDefinitionFinish)
// Finishes an interface definition.
//
// Always:
// (state done)
CARBON_PARSER_STATE(InterfaceDefinitionFinish)
// Handles parsing the body of an interface.
//
// If `}`:
// If `CloseCurlyBrace`:
// (state done)
// Else:
// 1. InterfaceDefinitionLoop
@@ -316,13 +310,12 @@ CARBON_PARSER_STATE(InterfaceDefinitionLoop)
// Handles processing of a intefaces's `interface <name> {`.
//
// If invalid:
// 1. InterfaceDefinitionFinish
// If `{` is missing:
// 1. InterfaceDefinitionFinish
// Else:
// If `Semi`:
// (state done)
// If `OpenCurlyBrace`:
// 1. InterfaceDefinitionLoop
// 2. InterfaceDefinitionFinish
// Else:
// (state done)
CARBON_PARSER_STATE(InterfaceIntroducer)
// Handles `package`.
+71 -71
View File
@@ -5,84 +5,84 @@
// AUTOUPDATE
// RUN: %{carbon-run-parser}
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'},
// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 15},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'},
// CHECK:STDOUT: {kind: 'NameReference', text: 'foo'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 15},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: ':'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PatternBinding', text: 'self', subtree_size: 4},
// CHECK:STDOUT: {kind: 'Address', text: 'addr', subtree_size: 5},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 15},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'},
// CHECK:STDOUT: {kind: 'NameReference', text: 'foo'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 17},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: ':'},
// CHECK:STDOUT: {kind: 'NameReference', text: 'foo'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PatternBinding', text: 'self', subtree_size: 4},
// CHECK:STDOUT: {kind: 'Address', text: 'addr', subtree_size: 5},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 15},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: ':'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PatternBinding', text: 'self', subtree_size: 4},
// CHECK:STDOUT: {kind: 'Address', text: 'addr', subtree_size: 5},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 17},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'FooFactory'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 17},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: ':'},
// CHECK:STDOUT: {kind: 'NameReference', text: 'foo'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PatternBinding', text: 'self', subtree_size: 4},
// CHECK:STDOUT: {kind: 'Address', text: 'addr', subtree_size: 5},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 7},
// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 73},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', subtree_size: 75},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 17},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'FooFactory'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 7},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 75},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
interface foo {
interface Foo {
fn Add[self: Self](b: Self) -> Self;
fn Add[self: foo](b: Self) -> Self;
@@ -0,0 +1,13 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// RUN: %{carbon-run-parser}
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'},
// CHECK:STDOUT: {kind: 'InterfaceDeclaration', text: ';', subtree_size: 3},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
interface Foo;
+5 -5
View File
@@ -5,11 +5,11 @@
// AUTOUPDATE
// RUN: %{carbon-run-parser}
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'},
// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'},
// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 2},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', subtree_size: 4},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 4},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
interface foo {
interface Foo {
}
@@ -5,10 +5,8 @@
// AUTOUPDATE
// RUN: %{not} %{carbon-run-parser}
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'interface', has_error: yes},
// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'},
// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 2},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', has_error: yes, subtree_size: 4},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'InterfaceDeclaration', text: 'interface', has_error: yes, subtree_size: 2},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
@@ -5,15 +5,17 @@
// AUTOUPDATE
// RUN: %{not} %{carbon-run-parser}
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'bar'},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', has_error: yes, subtree_size: 2},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', has_error: yes, subtree_size: 2},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Bar'},
// CHECK:STDOUT: {kind: 'InterfaceDeclaration', text: 'interface', has_error: yes, subtree_size: 3},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'},
// CHECK:STDOUT: {kind: 'InterfaceDeclaration', text: 'interface', has_error: yes, subtree_size: 3},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
// CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon:[[@LINE+1]]:15: Expected `{` to start interface definition.
interface bar baz {}
interface Bar Baz {}
// CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon:[[@LINE+1]]:14: Expected `{` to start interface definition.
interface foo
interface Foo
@@ -5,28 +5,28 @@
// AUTOUPDATE
// RUN: %{not} %{carbon-run-parser}
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'},
// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfDeducedParameter', text: 'self'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 15},
// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 17},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', subtree_size: 19},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 15},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 19},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
interface foo {
interface Foo {
// CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_no_impl_allowed.carbon:[[@LINE+1]]:39: Method implementations are not allowed in interfaces.
fn Add[self: Self](b: Self) -> Self {
print("You can't do that.");
@@ -5,59 +5,59 @@
// AUTOUPDATE
// RUN: %{not} %{carbon-run-parser}
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'foo'},
// CHECK:STDOUT: {kind: 'InterfaceBodyStart', text: '{'},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Foo'},
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Add'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 10},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', has_error: yes, subtree_size: 2},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 10},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Sub'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', has_error: yes, subtree_size: 2},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Mul'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', has_error: yes, subtree_size: 2},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Mul'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', has_error: yes, subtree_size: 2},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Rem'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'Rem'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12},
// CHECK:STDOUT: {kind: 'InterfaceBody', text: '}', subtree_size: 48},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: 'interface', subtree_size: 50},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
// CHECK:STDOUT: {kind: 'SelfType', text: 'Self'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12},
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 50},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
interface foo {
interface Foo {
fn Add(b: Self) -> Self;
// CHECK:STDERR: {{.*}}/toolchain/parser/testdata/generics/interface/fail_self_param_syntax.carbon:[[@LINE+1]]:10: Deduced parameters must be of the form: `<name>: <Type>` or `addr <name>: <Type>`.
@@ -576,15 +576,9 @@ auto SemanticsParseTreeHandler::HandleInfixOperator(ParseTree::Node parse_node)
return true;
}
auto SemanticsParseTreeHandler::HandleInterfaceBody(ParseTree::Node parse_node)
-> bool {
emitter_->Emit(parse_node, SemanticsTodo, "HandleInterfaceBody");
return false;
}
auto SemanticsParseTreeHandler::HandleInterfaceBodyStart(
auto SemanticsParseTreeHandler::HandleInterfaceDeclaration(
ParseTree::Node parse_node) -> bool {
emitter_->Emit(parse_node, SemanticsTodo, "HandleInterfaceBodyStart");
emitter_->Emit(parse_node, SemanticsTodo, "HandleInterfaceDeclaration");
return false;
}
@@ -594,6 +588,18 @@ auto SemanticsParseTreeHandler::HandleInterfaceDefinition(
return false;
}
auto SemanticsParseTreeHandler::HandleInterfaceDefinitionStart(
ParseTree::Node parse_node) -> bool {
emitter_->Emit(parse_node, SemanticsTodo, "HandleInterfaceDefinitionStart");
return false;
}
auto SemanticsParseTreeHandler::HandleInterfaceIntroducer(
ParseTree::Node parse_node) -> bool {
emitter_->Emit(parse_node, SemanticsTodo, "HandleInterfaceIntroducer");
return false;
}
auto SemanticsParseTreeHandler::HandleLiteral(ParseTree::Node parse_node)
-> bool {
auto token = parse_tree_->node_token(parse_node);