Skip to content

Commit 66824fd

Browse files
authored
Decouple parser errors with parser (#425)
* Pass parse errors to Translator through ProgramNodeContainer Instead of storing them in the Parser. * Rename ProgramNodeContainer to ParseResult
1 parent 8bc62fc commit 66824fd

File tree

5 files changed

+30
-27
lines changed

5 files changed

+30
-27
lines changed

main/pipeline/pipeline.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,13 @@ unique_ptr<parser::Node> runPrismParser(core::GlobalState &gs, core::FileRef fil
138138
core::UnfreezeNameTable nameTableAccess(gs);
139139

140140
Prism::Parser parser{source};
141-
Prism::ProgramNodeContainer root = parser.parse_root();
141+
Prism::ParseResult parseResult = parser.parse_root();
142142

143143
if (stopAfterParser) {
144144
return std::unique_ptr<parser::Node>();
145145
}
146146

147-
// Needs to be called after `parse_root()` otherwise there will be no errors to collect
148-
parser.collectErrors();
149-
auto nodes = Prism::Translator(parser, gs, file).translate(std::move(root));
147+
auto nodes = Prism::Translator(parser, gs, file).translate(std::move(parseResult));
150148

151149
if (print.ParseTree.enabled) {
152150
print.ParseTree.fmt("{}\n", nodes->toStringWithTabs(gs, 0));

parser/prism/Parser.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ pm_parser_t *Parser::getRawParserPointer() {
66
return &storage->parser;
77
}
88

9-
ProgramNodeContainer Parser::parse_root() {
9+
ParseResult Parser::parse_root() {
1010
pm_node_t *root = pm_parse(getRawParserPointer());
11-
return ProgramNodeContainer{*this, root};
11+
return ParseResult{*this, root, collectErrors()};
1212
};
1313

1414
core::LocOffsets Parser::translateLocation(pm_location_t location) {
@@ -28,7 +28,8 @@ std::string_view Parser::extractString(pm_string_t *string) {
2828
return std::string_view(reinterpret_cast<const char *>(pm_string_source(string)), pm_string_length(string));
2929
}
3030

31-
void Parser::collectErrors() {
31+
std::vector<ParseError> Parser::collectErrors() {
32+
std::vector<ParseError> parseErrors;
3233
parseErrors.reserve(storage->parser.error_list.size);
3334

3435
auto error_list = storage->parser.error_list;
@@ -42,5 +43,7 @@ void Parser::collectErrors() {
4243

4344
parseErrors.push_back(parseError);
4445
}
46+
47+
return parseErrors;
4548
}
4649
}; // namespace sorbet::parser::Prism

parser/prism/Parser.h

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ extern "C" {
1313

1414
namespace sorbet::parser::Prism {
1515

16-
class ProgramNodeContainer;
16+
class ParseResult;
1717

1818
class ParseError {
1919
public:
@@ -51,33 +51,28 @@ struct ParserStorage {
5151
};
5252

5353
class Parser final {
54-
friend class ProgramNodeContainer;
54+
friend class ParseResult;
5555
friend struct NodeDeleter;
5656

5757
std::shared_ptr<ParserStorage> storage;
5858

5959
public:
60-
std::vector<ParseError> parseErrors;
61-
6260
Parser(std::string_view source_code) : storage(std::make_shared<ParserStorage>(source_code)) {}
6361

6462
Parser(const Parser &) = default;
6563
Parser &operator=(const Parser &) = default;
6664

67-
ProgramNodeContainer parse_root();
65+
ParseResult parse_root();
6866
core::LocOffsets translateLocation(pm_location_t location);
6967
std::string_view resolveConstant(pm_constant_id_t constant_id);
7068
std::string_view extractString(pm_string_t *string);
7169

72-
void collectErrors();
73-
7470
private:
71+
std::vector<ParseError> collectErrors();
7572
pm_parser_t *getRawParserPointer();
7673
};
7774

78-
// This class holds a pointer to the parser and a pointer to the root node of Prism's AST
79-
// It's main purpose is to provide a way to clean up the AST nodes
80-
class ProgramNodeContainer final {
75+
class ParseResult final {
8176
struct NodeDeleter {
8277
Parser parser;
8378

@@ -91,11 +86,13 @@ class ProgramNodeContainer final {
9186

9287
Parser parser;
9388
std::unique_ptr<pm_node_t, NodeDeleter> node;
89+
std::vector<ParseError> parseErrors;
9490

95-
ProgramNodeContainer(Parser parser, pm_node_t *node) : parser{parser}, node{node, NodeDeleter{parser}} {}
91+
ParseResult(Parser parser, pm_node_t *node, std::vector<ParseError> parseErrors)
92+
: parser{parser}, node{node, NodeDeleter{parser}}, parseErrors{parseErrors} {}
9693

97-
ProgramNodeContainer(const ProgramNodeContainer &) = delete; // Copy constructor
98-
ProgramNodeContainer &operator=(const ProgramNodeContainer &) = delete; // Copy assignment
94+
ParseResult(const ParseResult &) = delete; // Copy constructor
95+
ParseResult &operator=(const ParseResult &) = delete; // Copy assignment
9996

10097
pm_node_t *getRawNodePointer() const {
10198
return node.get();

parser/prism/Translator.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,7 +1339,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node) {
13391339
// For now, we only report errors when we hit a missing node because we don't want to always report dynamic
13401340
// constant assignment errors
13411341
// TODO: We will improve this in the future when we handle more errored cases
1342-
for (auto &error : parser.parseErrors) {
1342+
for (auto &error : parseErrors) {
13431343
// EOF error is always pointed to the very last line of the file, which can't be expressed in Sorbet's
13441344
// error comments
13451345
if (error.id != PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT) {
@@ -1350,8 +1350,9 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node) {
13501350
}
13511351
}
13521352

1353-
unique_ptr<parser::Node> Translator::translate(const ProgramNodeContainer &container) {
1354-
return translate(container.getRawNodePointer());
1353+
unique_ptr<parser::Node> Translator::translate(const ParseResult &parseResult) {
1354+
this->parseErrors = parseResult.parseErrors;
1355+
return translate(parseResult.getRawNodePointer());
13551356
}
13561357

13571358
core::LocOffsets Translator::translateLoc(pm_location_t loc) {
@@ -1969,7 +1970,7 @@ template <typename PrismNode> std::unique_ptr<parser::Mlhs> Translator::translat
19691970
// Context management methods
19701971
Translator Translator::enterMethodDef() {
19711972
auto isInMethodDef = true;
1972-
return Translator(parser, gs, file, isInMethodDef, uniqueCounter);
1973+
return Translator(parser, gs, file, parseErrors, isInMethodDef, uniqueCounter);
19731974
}
19741975

19751976
void Translator::reportError(core::LocOffsets loc, const std::string &message) {

parser/prism/Translator.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ class Translator final {
2323
// Needed for reporting diagnostics
2424
core::FileRef file;
2525

26+
// The parse errors that occurred while parsing the root node
27+
std::vector<ParseError> parseErrors;
28+
2629
// Context variables
2730
bool isInMethodDef = false;
2831

@@ -47,13 +50,14 @@ class Translator final {
4750

4851
// Translates the given AST from Prism's node types into the equivalent AST in Sorbet's legacy parser node types.
4952
std::unique_ptr<parser::Node> translate(pm_node_t *node);
50-
std::unique_ptr<parser::Node> translate(const ProgramNodeContainer &container);
53+
std::unique_ptr<parser::Node> translate(const ParseResult &parseResult);
5154

5255
private:
5356
// Private constructor used only for creating child translators
5457
// uniqueCounterStorage is passed as the minimum integer value and is never used
55-
Translator(Parser parser, core::GlobalState &gs, core::FileRef file, bool isInMethodDef, int *uniqueCounter)
56-
: parser(parser), gs(gs), file(file), isInMethodDef(isInMethodDef),
58+
Translator(Parser parser, core::GlobalState &gs, core::FileRef file, std::vector<ParseError> parseErrors,
59+
bool isInMethodDef, int *uniqueCounter)
60+
: parser(parser), gs(gs), file(file), parseErrors(parseErrors), isInMethodDef(isInMethodDef),
5761
uniqueCounterStorage(std::numeric_limits<int>::min()), uniqueCounter(uniqueCounter) {}
5862
void reportError(core::LocOffsets loc, const std::string &message);
5963

0 commit comments

Comments
 (0)