mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-25 07:40:10 +01:00
Note #3486 rewrites the macro behavior, and is already approved: so this PR is only for the changed enforcement during error. Also, #3493 already changed several things to allow any token while this PR was awaiting review, but this still changes enforcement for `For` and `If`. This was brought up on [#toolchain](https://discord.com/channels/655572317891461132/655578254970716160/1182066616456970251), and I think this any-on-error approach gets at least some support. We could try setting it to the introducer, but it's quite possible we want it to be something like the token which led to the parse error, rather than a static token. That leads to a conclusion that, most typically, we'll expect arbitrary tokens when error conditions may lead to tokens which aren't the expected token. A couple related, recent `CARBON_IF_ERROR` crash fixes can be found in #3404 and #3424. Something like #3404 would've been needed regardless because `namespace` didn't have `CARBON_IF_ERROR` before, although I might've missed the underlying issue with declarations because only `namespace` had a relevant test (that is, if #3404 had added `CARBON_ANY_TOKEN_ON_ERROR`, I wouldn't have had a crash in #3462). #3424 would've been avoided with this change because there was a `CARBON_IF_ERROR`, and it was just too restrictive.
98 lines
3.2 KiB
C++
98 lines
3.2 KiB
C++
// 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
|
|
|
|
#include "toolchain/parse/node_kind.h"
|
|
|
|
#include "common/check.h"
|
|
|
|
namespace Carbon::Parse {
|
|
|
|
CARBON_DEFINE_ENUM_CLASS_NAMES(NodeKind) = {
|
|
#define CARBON_PARSE_NODE_KIND(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)
|
|
#include "toolchain/parse/node_kind.def"
|
|
};
|
|
|
|
auto NodeKind::has_bracket() const -> bool {
|
|
static constexpr bool HasBracket[] = {
|
|
#define CARBON_PARSE_NODE_KIND_BRACKET(...) true,
|
|
#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(...) false,
|
|
#include "toolchain/parse/node_kind.def"
|
|
};
|
|
return HasBracket[AsInt()];
|
|
}
|
|
|
|
auto NodeKind::bracket() const -> NodeKind {
|
|
// Nodes are never self-bracketed, so we use that for nodes that instead set
|
|
// child_count.
|
|
static constexpr NodeKind Bracket[] = {
|
|
#define CARBON_PARSE_NODE_KIND_BRACKET(Name, BracketName, ...) \
|
|
NodeKind::BracketName,
|
|
#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, ...) NodeKind::Name,
|
|
#include "toolchain/parse/node_kind.def"
|
|
};
|
|
auto bracket = Bracket[AsInt()];
|
|
CARBON_CHECK(bracket != *this) << *this;
|
|
return bracket;
|
|
}
|
|
|
|
auto NodeKind::child_count() const -> int32_t {
|
|
static constexpr int32_t ChildCount[] = {
|
|
#define CARBON_PARSE_NODE_KIND_BRACKET(...) -1,
|
|
#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, Size, ...) Size,
|
|
#include "toolchain/parse/node_kind.def"
|
|
};
|
|
auto child_count = ChildCount[AsInt()];
|
|
CARBON_CHECK(child_count >= 0) << *this;
|
|
return child_count;
|
|
}
|
|
|
|
// NOLINTNEXTLINE(readability-function-size): It's hard to extract macros.
|
|
auto CheckNodeMatchesLexerToken(NodeKind node_kind, Lex::TokenKind token_kind,
|
|
bool has_error) -> void {
|
|
// As a special-case, a placeholder node may correspond to any lexer token.
|
|
if (node_kind == NodeKind::Placeholder) {
|
|
return;
|
|
}
|
|
|
|
switch (node_kind) {
|
|
// Use `CARBON_LOG CARBON_ANY_TOKEN` to discover which combinations happen
|
|
// in practice.
|
|
#define CARBON_LOG \
|
|
llvm::errs() << "ZZZ: Created parse node with NodeKind " << node_kind \
|
|
<< " and has_error " << has_error << " for lexical token " \
|
|
<< token_kind << "\n";
|
|
|
|
#define CARBON_TOKEN(Expected) \
|
|
if (token_kind == Lex::TokenKind::Expected) { \
|
|
return; \
|
|
}
|
|
|
|
#define CARBON_ANY_TOKEN_ON_ERROR \
|
|
if (has_error) { \
|
|
return; \
|
|
}
|
|
|
|
#define CARBON_CASE(Name, MatchActions) \
|
|
case NodeKind::Name: \
|
|
MatchActions; /* NOLINT(bugprone-macro-parentheses) */ \
|
|
break;
|
|
|
|
#define CARBON_PARSE_NODE_KIND_BRACKET(Name, BracketName, MatchActions) \
|
|
CARBON_CASE(Name, MatchActions)
|
|
|
|
#define CARBON_PARSE_NODE_KIND_CHILD_COUNT(Name, Size, MatchActions) \
|
|
CARBON_CASE(Name, MatchActions)
|
|
|
|
#include "toolchain/parse/node_kind.def"
|
|
|
|
#undef CARBON_LOG
|
|
#undef CARBON_CASE
|
|
}
|
|
CARBON_FATAL() << "Created parse node with NodeKind " << node_kind
|
|
<< " and has_error " << has_error
|
|
<< " for unexpected lexical token " << token_kind;
|
|
}
|
|
|
|
} // namespace Carbon::Parse
|