mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:10:14 +01:00
Add parsing for 'fn destroy' (#5045)
Syntax is proposed in #5017, but has already been discussed with leads. Semantics is left as a TODO. --------- Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
This commit is contained in:
co-authored by
josh11b
parent
437d3b9af6
commit
c44e688e5d
@@ -152,6 +152,16 @@ auto HandleParseNode(Context& context, Parse::IdentifierNameExprId node_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context,
|
||||
Parse::KeywordNameNotBeforeParamsId node_id) -> bool {
|
||||
return context.TODO(node_id, "KeywordNameNotBeforeParamsId");
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::KeywordNameBeforeParamsId node_id)
|
||||
-> bool {
|
||||
return context.TODO(node_id, "KeywordNameBeforeParamsId");
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::BaseNameId node_id) -> bool {
|
||||
context.node_stack().Push(node_id, SemIR::NameId::Base);
|
||||
return true;
|
||||
@@ -188,7 +198,8 @@ auto HandleParseNode(Context& context,
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context,
|
||||
Parse::NameQualifierWithoutParamsId /*node_id*/) -> bool {
|
||||
Parse::IdentifierNameQualifierWithoutParamsId /*node_id*/)
|
||||
-> bool {
|
||||
context.decl_name_stack().ApplyNameQualifier(PopNameComponent(context));
|
||||
return true;
|
||||
}
|
||||
@@ -229,6 +240,12 @@ auto HandleParseNode(Context& context, Parse::DesignatorExprId node_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context,
|
||||
Parse::KeywordNameQualifierWithoutParamsId node_id)
|
||||
-> bool {
|
||||
return context.TODO(node_id, "KeywordNameQualifierWithoutParamsId");
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::PackageExprId node_id) -> bool {
|
||||
AddInstAndPush<SemIR::NameRef>(
|
||||
context, node_id,
|
||||
|
||||
@@ -57,8 +57,7 @@ auto PopNameComponent(Context& context, SemIR::InstId return_slot_pattern_id)
|
||||
}
|
||||
|
||||
auto [name_loc_id, name_id] =
|
||||
context.node_stack()
|
||||
.PopWithNodeId<Parse::NodeCategory::NonExprIdentifierName>();
|
||||
context.node_stack().PopWithNodeId<Parse::NodeCategory::NonExprName>();
|
||||
|
||||
return {
|
||||
.name_loc_id = name_loc_id,
|
||||
|
||||
@@ -377,9 +377,9 @@ class NodeStack {
|
||||
Id::KindFor<SemIR::InstId>());
|
||||
set_id_if_category_is(Parse::NodeCategory::Expr,
|
||||
Id::KindFor<SemIR::InstId>());
|
||||
set_id_if_category_is(Parse::NodeCategory::MemberName |
|
||||
Parse::NodeCategory::NonExprIdentifierName,
|
||||
Id::KindFor<SemIR::NameId>());
|
||||
set_id_if_category_is(
|
||||
Parse::NodeCategory::MemberName | Parse::NodeCategory::NonExprName,
|
||||
Id::KindFor<SemIR::NameId>());
|
||||
set_id_if_category_is(Parse::NodeCategory::ImplAs,
|
||||
Id::KindFor<SemIR::InstId>());
|
||||
set_id_if_category_is(Parse::NodeCategory::Decl |
|
||||
@@ -469,11 +469,13 @@ class NodeStack {
|
||||
case Parse::NodeKind::ForHeader:
|
||||
case Parse::NodeKind::ForHeaderStart:
|
||||
case Parse::NodeKind::ForIn:
|
||||
case Parse::NodeKind::IdentifierNameQualifierWithoutParams:
|
||||
case Parse::NodeKind::IdentifierPackageName:
|
||||
case Parse::NodeKind::IfConditionStart:
|
||||
case Parse::NodeKind::ImportIntroducer:
|
||||
case Parse::NodeKind::IndexExprStart:
|
||||
case Parse::NodeKind::InvalidParseStart:
|
||||
case Parse::NodeKind::KeywordNameQualifierWithoutParams:
|
||||
case Parse::NodeKind::LibraryIntroducer:
|
||||
case Parse::NodeKind::LibrarySpecifier:
|
||||
case Parse::NodeKind::MatchCase:
|
||||
@@ -494,7 +496,6 @@ class NodeStack {
|
||||
case Parse::NodeKind::NamedConstraintDefinitionStart:
|
||||
case Parse::NodeKind::NamedConstraintIntroducer:
|
||||
case Parse::NodeKind::NameQualifierWithParams:
|
||||
case Parse::NodeKind::NameQualifierWithoutParams:
|
||||
case Parse::NodeKind::NamespaceStart:
|
||||
case Parse::NodeKind::PackageIntroducer:
|
||||
case Parse::NodeKind::ParenExprStart:
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
// 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
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/no_prelude/destroy.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/no_prelude/destroy.carbon
|
||||
|
||||
// --- fail_todo_basic.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_todo_basic.carbon:[[@LINE+4]]:6: error: semantics TODO: `KeywordNameBeforeParamsId` [SemanticsTodo]
|
||||
// CHECK:STDERR: fn destroy[self: Self]();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy[self: Self]();
|
||||
}
|
||||
|
||||
// --- fail_todo_addr.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_todo_addr.carbon:[[@LINE+4]]:6: error: semantics TODO: `KeywordNameBeforeParamsId` [SemanticsTodo]
|
||||
// CHECK:STDERR: fn destroy[addr self: Self*]();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy[addr self: Self*]();
|
||||
}
|
||||
|
||||
// --- fail_todo_class_function.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_todo_class_function.carbon:[[@LINE+4]]:6: error: semantics TODO: `KeywordNameBeforeParamsId` [SemanticsTodo]
|
||||
// CHECK:STDERR: fn destroy();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy();
|
||||
}
|
||||
|
||||
// --- fail_todo_destroy_in_namespace.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
namespace NS;
|
||||
|
||||
// CHECK:STDERR: fail_todo_destroy_in_namespace.carbon:[[@LINE+4]]:7: error: semantics TODO: `KeywordNameBeforeParamsId` [SemanticsTodo]
|
||||
// CHECK:STDERR: fn NS.destroy();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn NS.destroy();
|
||||
|
||||
// --- fail_todo_missing_params.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_todo_missing_params.carbon:[[@LINE+4]]:6: error: semantics TODO: `KeywordNameNotBeforeParamsId` [SemanticsTodo]
|
||||
// CHECK:STDERR: fn destroy;
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy;
|
||||
}
|
||||
|
||||
fn C.destroy {}
|
||||
|
||||
// --- fail_todo_wrong_scope.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
|
||||
// CHECK:STDERR: fail_todo_wrong_scope.carbon:[[@LINE+4]]:4: error: semantics TODO: `KeywordNameBeforeParamsId` [SemanticsTodo]
|
||||
// CHECK:STDERR: fn destroy();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy();
|
||||
|
||||
// --- fail_invalid_qualifier.carbon
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_invalid_qualifier.carbon:[[@LINE+4]]:6: error: semantics TODO: `KeywordNameBeforeParamsId` [SemanticsTodo]
|
||||
// CHECK:STDERR: fn destroy();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy();
|
||||
}
|
||||
|
||||
fn C.destroy.destroy() {}
|
||||
|
||||
// CHECK:STDOUT: --- fail_todo_basic.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
// CHECK:STDOUT: complete_type_witness = invalid
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_addr.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
// CHECK:STDOUT: complete_type_witness = invalid
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_class_function.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
// CHECK:STDOUT: complete_type_witness = invalid
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_destroy_in_namespace.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_missing_params.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
// CHECK:STDOUT: complete_type_witness = invalid
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_wrong_scope.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_invalid_qualifier.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: class @C {
|
||||
// CHECK:STDOUT: complete_type_witness = invalid
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = constants.%C
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -179,7 +179,7 @@ CARBON_KEYWORD_TOKEN(Const, "const")
|
||||
CARBON_KEYWORD_TOKEN(Continue, "continue")
|
||||
CARBON_KEYWORD_TOKEN(Core, "Core")
|
||||
CARBON_KEYWORD_TOKEN(Default, "default")
|
||||
CARBON_KEYWORD_TOKEN(Destructor, "destructor")
|
||||
CARBON_KEYWORD_TOKEN(Destroy, "destroy")
|
||||
CARBON_KEYWORD_TOKEN(Else, "else")
|
||||
CARBON_KEYWORD_TOKEN(Extend, "extend")
|
||||
CARBON_KEYWORD_TOKEN(Extern, "extern")
|
||||
|
||||
@@ -110,6 +110,7 @@ cc_library(
|
||||
"//toolchain/base:shared_value_stores",
|
||||
"//toolchain/diagnostics:diagnostic_emitter",
|
||||
"//toolchain/diagnostics:format_providers",
|
||||
"//toolchain/lex:token_index",
|
||||
"//toolchain/lex:token_kind",
|
||||
"//toolchain/lex:tokenized_buffer",
|
||||
],
|
||||
|
||||
@@ -2,67 +2,87 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include "toolchain/lex/token_index.h"
|
||||
#include "toolchain/parse/context.h"
|
||||
#include "toolchain/parse/handle.h"
|
||||
|
||||
namespace Carbon::Parse {
|
||||
|
||||
auto HandleDeclNameAndParams(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
auto identifier = context.ConsumeIf(Lex::TokenKind::Identifier);
|
||||
if (!identifier) {
|
||||
Lex::TokenIndex token = *context.position();
|
||||
if (context.tokens().GetKind(token) == Lex::TokenKind::FileEnd) {
|
||||
// The end of file is an unhelpful diagnostic location. Instead, use the
|
||||
// introducer token.
|
||||
token = state.token;
|
||||
}
|
||||
if (state.token == *context.position()) {
|
||||
CARBON_DIAGNOSTIC(ExpectedDeclNameAfterPeriod, Error,
|
||||
"`.` should be followed by a name");
|
||||
context.emitter().Emit(token, ExpectedDeclNameAfterPeriod);
|
||||
} else {
|
||||
CARBON_DIAGNOSTIC(ExpectedDeclName, Error,
|
||||
"`{0}` introducer should be followed by a name",
|
||||
Lex::TokenKind);
|
||||
context.emitter().Emit(token, ExpectedDeclName,
|
||||
context.tokens().GetKind(state.token));
|
||||
}
|
||||
context.ReturnErrorOnState();
|
||||
context.AddInvalidParse(*context.position());
|
||||
return;
|
||||
}
|
||||
|
||||
// Adds a leaf node for the name, and updates the state stack for parameter
|
||||
// handling.
|
||||
static auto HandleName(Context& context, Context::StateStackEntry state,
|
||||
Lex::TokenIndex name_token,
|
||||
NodeKind not_before_params_kind,
|
||||
NodeKind not_before_params_qualifier_kind,
|
||||
NodeKind before_params_kind) -> void {
|
||||
switch (context.PositionKind()) {
|
||||
case Lex::TokenKind::Period:
|
||||
context.AddLeafNode(NodeKind::IdentifierNameNotBeforeParams, *identifier);
|
||||
context.AddNode(NodeKind::NameQualifierWithoutParams,
|
||||
context.AddLeafNode(not_before_params_kind, name_token);
|
||||
context.AddNode(not_before_params_qualifier_kind,
|
||||
context.ConsumeChecked(Lex::TokenKind::Period),
|
||||
state.has_error);
|
||||
context.PushState(State::DeclNameAndParams);
|
||||
break;
|
||||
|
||||
case Lex::TokenKind::OpenSquareBracket:
|
||||
context.AddLeafNode(NodeKind::IdentifierNameBeforeParams, *identifier);
|
||||
context.AddLeafNode(before_params_kind, name_token);
|
||||
state.state = State::DeclNameAndParamsAfterImplicit;
|
||||
context.PushState(state);
|
||||
context.PushState(State::PatternListAsImplicit);
|
||||
break;
|
||||
|
||||
case Lex::TokenKind::OpenParen:
|
||||
context.AddLeafNode(NodeKind::IdentifierNameBeforeParams, *identifier);
|
||||
context.AddLeafNode(before_params_kind, name_token);
|
||||
state.state = State::DeclNameAndParamsAfterParams;
|
||||
context.PushState(state);
|
||||
context.PushState(State::PatternListAsExplicit);
|
||||
break;
|
||||
|
||||
default:
|
||||
context.AddLeafNode(NodeKind::IdentifierNameNotBeforeParams, *identifier);
|
||||
context.AddLeafNode(not_before_params_kind, name_token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto HandleDeclNameAndParams(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
if (auto identifier = context.ConsumeIf(Lex::TokenKind::Identifier)) {
|
||||
HandleName(context, state, *identifier,
|
||||
NodeKind::IdentifierNameNotBeforeParams,
|
||||
NodeKind::IdentifierNameQualifierWithoutParams,
|
||||
NodeKind::IdentifierNameBeforeParams);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto keyword = context.ConsumeIf(Lex::TokenKind::Destroy)) {
|
||||
HandleName(context, state, *keyword, NodeKind::KeywordNameNotBeforeParams,
|
||||
NodeKind::KeywordNameQualifierWithoutParams,
|
||||
NodeKind::KeywordNameBeforeParams);
|
||||
return;
|
||||
}
|
||||
|
||||
Lex::TokenIndex token = *context.position();
|
||||
if (context.tokens().GetKind(token) == Lex::TokenKind::FileEnd) {
|
||||
// The end of file is an unhelpful diagnostic location. Instead, use the
|
||||
// introducer token.
|
||||
token = state.token;
|
||||
}
|
||||
if (state.token == *context.position()) {
|
||||
CARBON_DIAGNOSTIC(ExpectedDeclNameAfterPeriod, Error,
|
||||
"`.` should be followed by a name");
|
||||
context.emitter().Emit(token, ExpectedDeclNameAfterPeriod);
|
||||
} else {
|
||||
CARBON_DIAGNOSTIC(ExpectedDeclName, Error,
|
||||
"`{0}` introducer should be followed by a name",
|
||||
Lex::TokenKind);
|
||||
context.emitter().Emit(token, ExpectedDeclName,
|
||||
context.tokens().GetKind(state.token));
|
||||
}
|
||||
context.ReturnErrorOnState();
|
||||
context.AddInvalidParse(*context.position());
|
||||
}
|
||||
|
||||
auto HandleDeclNameAndParamsAfterImplicit(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
|
||||
X(MemberExpr) \
|
||||
X(MemberName) \
|
||||
X(Modifier) \
|
||||
X(NonExprIdentifierName) \
|
||||
X(NonExprName) \
|
||||
X(PackageName) \
|
||||
X(Pattern) \
|
||||
X(Requirement) \
|
||||
|
||||
@@ -79,8 +79,7 @@ using AnyPatternId = NodeIdInCategory<NodeCategory::Pattern>;
|
||||
using AnyStatementId =
|
||||
NodeIdInCategory<NodeCategory::Statement | NodeCategory::Decl>;
|
||||
using AnyRequirementId = NodeIdInCategory<NodeCategory::Requirement>;
|
||||
using AnyNonExprIdentifierNameId =
|
||||
NodeIdInCategory<NodeCategory::NonExprIdentifierName>;
|
||||
using AnyNonExprNameId = NodeIdInCategory<NodeCategory::NonExprName>;
|
||||
using AnyPackageNameId = NodeIdInCategory<NodeCategory::PackageName>;
|
||||
|
||||
// NodeId with kind that matches one of the `T::Kind`s.
|
||||
|
||||
@@ -98,6 +98,9 @@ CARBON_PARSE_NODE_KIND(EmptyDecl)
|
||||
CARBON_PARSE_NODE_KIND(IdentifierNameNotBeforeParams)
|
||||
CARBON_PARSE_NODE_KIND(IdentifierNameBeforeParams)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(KeywordNameNotBeforeParams)
|
||||
CARBON_PARSE_NODE_KIND(KeywordNameBeforeParams)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(IdentifierNameExpr)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(SelfValueName)
|
||||
@@ -124,7 +127,8 @@ CARBON_PARSE_NODE_KIND(LibraryDecl)
|
||||
CARBON_PARSE_NODE_KIND(LibrarySpecifier)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(NameQualifierWithParams)
|
||||
CARBON_PARSE_NODE_KIND(NameQualifierWithoutParams)
|
||||
CARBON_PARSE_NODE_KIND(IdentifierNameQualifierWithoutParams)
|
||||
CARBON_PARSE_NODE_KIND(KeywordNameQualifierWithoutParams)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(ExportIntroducer)
|
||||
CARBON_PARSE_NODE_KIND(ExportDecl)
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ fn F() {
|
||||
// CHECK:STDOUT: {kind: 'Alias', text: ';', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'AliasIntroducer', text: 'alias'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'NS'},
|
||||
// CHECK:STDOUT: {kind: 'NameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'ns'},
|
||||
// CHECK:STDOUT: {kind: 'AliasInitializer', text: '='},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'foo'},
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ fn F() {
|
||||
// CHECK:STDOUT: {kind: 'ClassDefinition', text: '}', subtree_size: 15},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'C'},
|
||||
// CHECK:STDOUT: {kind: 'NameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'H'},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
|
||||
@@ -36,6 +36,22 @@ fn foo(a: i32, b: i32);
|
||||
|
||||
fn foo() -> u32;
|
||||
|
||||
// --- keyword.carbon
|
||||
|
||||
fn destroy() {}
|
||||
|
||||
// --- keyword_no_params.carbon
|
||||
|
||||
fn destroy {}
|
||||
|
||||
// --- keyword_in_qualified.carbon
|
||||
|
||||
fn MyClass.destroy() {}
|
||||
|
||||
// --- keyword_decl.carbon
|
||||
|
||||
fn destroy.destroy() {}
|
||||
|
||||
// --- impl_fn.carbon
|
||||
|
||||
impl fn F();
|
||||
@@ -256,6 +272,52 @@ fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z);
|
||||
// CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: keyword.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameBeforeParams', text: 'destroy'},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: keyword_no_params.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameNotBeforeParams', text: 'destroy'},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: keyword_in_qualified.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'MyClass'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameBeforeParams', text: 'destroy'},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 8},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: keyword_decl.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameNotBeforeParams', text: 'destroy'},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameBeforeParams', text: 'destroy'},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 8},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: impl_fn.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
|
||||
@@ -79,7 +79,7 @@ fn C.(Self as Interface).F() {}
|
||||
// CHECK:STDOUT: {kind: 'ClassDefinition', text: '}', subtree_size: 15},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'C'},
|
||||
// CHECK:STDOUT: {kind: 'NameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: '(', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDecl', text: '}', has_error: yes, subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Foo.;
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Foo'},
|
||||
// CHECK:STDOUT: {kind: 'NameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'Namespace', text: ';', has_error: yes, subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
|
||||
+3
-3
@@ -23,14 +23,14 @@ fn Foo.Bar.Baz() {
|
||||
// CHECK:STDOUT: {kind: 'Namespace', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Foo'},
|
||||
// CHECK:STDOUT: {kind: 'NameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Bar'},
|
||||
// CHECK:STDOUT: {kind: 'Namespace', text: ';', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Foo'},
|
||||
// CHECK:STDOUT: {kind: 'NameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Bar'},
|
||||
// CHECK:STDOUT: {kind: 'NameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'Baz'},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
|
||||
+2
-2
@@ -162,7 +162,7 @@ export Foo;
|
||||
// CHECK:STDOUT: {kind: 'PackageDecl', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ExportIntroducer', text: 'export'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Foo'},
|
||||
// CHECK:STDOUT: {kind: 'NameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Bar'},
|
||||
// CHECK:STDOUT: {kind: 'ExportDecl', text: ';', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
@@ -230,7 +230,7 @@ export Foo;
|
||||
// CHECK:STDOUT: {kind: 'PackageDecl', text: ';', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ExportIntroducer', text: 'export'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Foo'},
|
||||
// CHECK:STDOUT: {kind: 'NameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'ExportDecl', text: ';', has_error: yes, subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
|
||||
@@ -131,13 +131,19 @@ using EmptyDecl =
|
||||
// to be followed by parameters.
|
||||
using IdentifierNameBeforeParams =
|
||||
LeafNode<NodeKind::IdentifierNameBeforeParams, Lex::IdentifierTokenIndex,
|
||||
NodeCategory::MemberName | NodeCategory::NonExprIdentifierName>;
|
||||
NodeCategory::MemberName | NodeCategory::NonExprName>;
|
||||
using KeywordNameBeforeParams =
|
||||
LeafNode<NodeKind::KeywordNameBeforeParams, Lex::TokenIndex,
|
||||
NodeCategory::MemberName | NodeCategory::NonExprName>;
|
||||
|
||||
// A name in a non-expression context, such as a declaration, that is known
|
||||
// to not be followed by parameters.
|
||||
using IdentifierNameNotBeforeParams =
|
||||
LeafNode<NodeKind::IdentifierNameNotBeforeParams, Lex::IdentifierTokenIndex,
|
||||
NodeCategory::MemberName | NodeCategory::NonExprIdentifierName>;
|
||||
NodeCategory::MemberName | NodeCategory::NonExprName>;
|
||||
using KeywordNameNotBeforeParams =
|
||||
LeafNode<NodeKind::KeywordNameNotBeforeParams, Lex::TokenIndex,
|
||||
NodeCategory::MemberName | NodeCategory::NonExprName>;
|
||||
|
||||
// A name in an expression context.
|
||||
using IdentifierNameExpr =
|
||||
@@ -174,21 +180,31 @@ struct NameQualifierWithParams {
|
||||
};
|
||||
|
||||
// A name qualifier without parameters, such as `A.`.
|
||||
struct NameQualifierWithoutParams {
|
||||
static constexpr auto Kind = NodeKind::NameQualifierWithoutParams.Define(
|
||||
{.bracketed_by = IdentifierNameNotBeforeParams::Kind});
|
||||
struct IdentifierNameQualifierWithoutParams {
|
||||
static constexpr auto Kind =
|
||||
NodeKind::IdentifierNameQualifierWithoutParams.Define(
|
||||
{.bracketed_by = IdentifierNameNotBeforeParams::Kind});
|
||||
|
||||
IdentifierNameNotBeforeParamsId name;
|
||||
Lex::PeriodTokenIndex token;
|
||||
};
|
||||
struct KeywordNameQualifierWithoutParams {
|
||||
static constexpr auto Kind =
|
||||
NodeKind::KeywordNameQualifierWithoutParams.Define(
|
||||
{.bracketed_by = KeywordNameNotBeforeParams::Kind});
|
||||
|
||||
KeywordNameNotBeforeParamsId name;
|
||||
Lex::PeriodTokenIndex token;
|
||||
};
|
||||
|
||||
// A complete name in a declaration: `A.C(T:! type).F(n: i32)`.
|
||||
// Note that this includes the parameters of the entity itself.
|
||||
struct DeclName {
|
||||
llvm::SmallVector<
|
||||
NodeIdOneOf<NameQualifierWithParams, NameQualifierWithoutParams>>
|
||||
NodeIdOneOf<NameQualifierWithParams, IdentifierNameQualifierWithoutParams,
|
||||
KeywordNameQualifierWithoutParams>>
|
||||
qualifiers;
|
||||
AnyNonExprIdentifierNameId name;
|
||||
AnyNonExprNameId name;
|
||||
std::optional<ImplicitParamListId> implicit_params;
|
||||
std::optional<ExplicitParamListId> params;
|
||||
};
|
||||
@@ -1157,7 +1173,7 @@ struct ChoiceDefinition {
|
||||
|
||||
ChoiceDefinitionStartId signature;
|
||||
struct Alternative {
|
||||
AnyNonExprIdentifierNameId name;
|
||||
AnyNonExprNameId name;
|
||||
std::optional<ExplicitParamListId> parameters;
|
||||
};
|
||||
CommaSeparatedList<Alternative, ChoiceAlternativeListCommaId> alternatives;
|
||||
|
||||
@@ -290,10 +290,10 @@ Optional [^:]*: found
|
||||
Optional [^:]*: begin
|
||||
NodeIdForKind error: wrong kind IdentifierNameBeforeParams, expected ImplicitParamList
|
||||
Optional [^:]*: missing
|
||||
NodeIdInCategory NonExprIdentifierName: kind IdentifierNameBeforeParams consumed
|
||||
NodeIdInCategory NonExprName: kind IdentifierNameBeforeParams consumed
|
||||
Vector: begin
|
||||
NodeIdOneOf NameQualifierWithParams or NameQualifierWithoutParams: NameQualifierWithoutParams consumed
|
||||
NodeIdOneOf error: wrong kind AbstractModifier, expected NameQualifierWithParams or NameQualifierWithoutParams
|
||||
NodeIdOneOf NameQualifierWithParams or IdentifierNameQualifierWithoutParams or KeywordNameQualifierWithoutParams: IdentifierNameQualifierWithoutParams consumed
|
||||
NodeIdOneOf error: wrong kind AbstractModifier, expected NameQualifierWithParams or IdentifierNameQualifierWithoutParams or KeywordNameQualifierWithoutParams
|
||||
Vector: end
|
||||
Aggregate [^:]*: success
|
||||
Vector: begin
|
||||
|
||||
Reference in New Issue
Block a user