Files
carbon-lang/toolchain/parse/parse.cpp
T
Jon Ross-Perkins 57ef976802 Move dumping into the phase factory functions (#5747)
By moving dumping, we can have dumping occur before verification that
might CHECK-fail (e.g. parse tree and llvm IR verification).

I'm dropping vlogging of raw semir. It was only done when dumping, so
`-v` would print zero copies and `-v --dump-raw-sem-ir` would print two
copies. The lack of complaints about this suggests it's not needed.

I'm making a small change to drop newlines between textual and raw
semir. This is an edge case so I don't expect people to really notice in
general, but it seemed unusually aware of what's on a stream, and it
made it harder to do the dump_stream/raw_dump_stream approach, which I
felt would be decent in general, since check is the only phase that can
emit two different things (which I could also just drop -- we don't
really use raw semir anymore, it doesn't seem like a big need to be able
to print it with textual semir, but I'm assuming to just maintain
existing behavior).

In parse, we were previously dumping the tree on verification errors.
I'm removing that because now `--dump-parse-tree` should work fine,
where previously it wouldn't.
2025-07-01 15:51:41 +00:00

74 lines
2.4 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/parse.h"
#include "common/check.h"
#include "common/pretty_stack_trace_function.h"
#include "toolchain/parse/context.h"
#include "toolchain/parse/handle.h"
#include "toolchain/parse/node_kind.h"
#include "toolchain/parse/tree_and_subtrees.h"
namespace Carbon::Parse {
auto HandleInvalid(Context& context) -> void {
CARBON_FATAL("The Invalid state shouldn't be on the stack: {0}",
context.PopState());
}
auto Parse(Lex::TokenizedBuffer& tokens, ParseOptions options) -> Tree {
auto* consumer =
options.consumer ? options.consumer : &Diagnostics::ConsoleConsumer();
// Delegate to the parser.
Tree tree(tokens);
Context context(&tree, &tokens, consumer, options.vlog_stream);
PrettyStackTraceFunction context_dumper(
[&](llvm::raw_ostream& output) { context.PrintForStackDump(output); });
context.AddLeafNode(NodeKind::FileStart,
context.ConsumeChecked(Lex::TokenKind::FileStart));
context.PushState(StateKind::DeclScopeLoopAsNonClass);
while (!context.state_stack().empty()) {
switch (context.state_stack().back().kind) {
#define CARBON_PARSE_STATE(Name) \
case StateKind::Name: \
Handle##Name(context); \
break;
#include "toolchain/parse/state.def"
}
}
context.AddLeafNode(NodeKind::FileEnd, *context.position());
// Mark the tree as potentially having errors if there were errors coming in
// from the tokenized buffer or we diagnosed new errors.
tree.set_has_errors(tokens.has_errors() || context.has_errors());
if (options.vlog_stream || options.dump_stream) {
// Flush diagnostics before printing.
consumer->Flush();
}
CARBON_VLOG_TO(options.vlog_stream, "*** Parse::Tree ***\n{0}", tree);
if (options.dump_stream) {
Parse::TreeAndSubtrees tree_and_subtrees(tokens, tree);
if (options.dump_preorder_parse_tree) {
tree_and_subtrees.PrintPreorder(*options.dump_stream);
} else {
tree_and_subtrees.Print(*options.dump_stream);
}
}
if (auto verify = tree.Verify(); !verify.ok()) {
// TODO: Consider printing a subtree as part of the error.
CARBON_FATAL("Invalid tree returned by Parse(): {0}", verify.error());
}
return tree;
}
} // namespace Carbon::Parse