diff --git a/frontends/p4/dontcareArgs.h b/frontends/p4/dontcareArgs.h index a1ff4842bb..2c572d8469 100644 --- a/frontends/p4/dontcareArgs.h +++ b/frontends/p4/dontcareArgs.h @@ -37,33 +37,41 @@ class DontcareArgs : public Transform, public ResolutionContext { } const IR::Node *postorder(IR::MethodCallExpression *expression) override; const IR::Node *postorder(IR::Function *function) override { - IR::IndexedVector body; - for (auto d : toAdd) body.push_back(d); - body.append(function->body->components); - function->body = - new IR::BlockStatement(function->body->srcInfo, function->body->annotations, body); - toAdd.clear(); + if (!toAdd.empty()) { + IR::IndexedVector body; + for (auto d : toAdd) body.push_back(d); + body.append(function->body->components); + function->body = + new IR::BlockStatement(function->body->srcInfo, function->body->annotations, body); + toAdd.clear(); + } return function; } const IR::Node *postorder(IR::P4Action *action) override { - IR::IndexedVector body; - for (auto d : toAdd) body.push_back(d); - body.append(action->body->components); - action->body = - new IR::BlockStatement(action->body->srcInfo, action->body->annotations, body); - toAdd.clear(); + if (!toAdd.empty()) { + IR::IndexedVector body; + for (auto d : toAdd) body.push_back(d); + body.append(action->body->components); + action->body = + new IR::BlockStatement(action->body->srcInfo, action->body->annotations, body); + toAdd.clear(); + } return action; } const IR::Node *postorder(IR::P4Parser *parser) override { - toAdd.append(parser->parserLocals); - parser->parserLocals = toAdd; - toAdd.clear(); + if (!toAdd.empty()) { + toAdd.append(parser->parserLocals); + parser->parserLocals = toAdd; + toAdd.clear(); + } return parser; } const IR::Node *postorder(IR::P4Control *control) override { - toAdd.append(control->controlLocals); - control->controlLocals = toAdd; - toAdd.clear(); + if (!toAdd.empty()) { + toAdd.append(control->controlLocals); + control->controlLocals = toAdd; + toAdd.clear(); + } return control; } profile_t init_apply(const IR::Node *node) override; diff --git a/frontends/parsers/p4/p4parser.ypp b/frontends/parsers/p4/p4parser.ypp index ce2f266bf6..bd4ed0395d 100644 --- a/frontends/parsers/p4/p4parser.ypp +++ b/frontends/parsers/p4/p4parser.ypp @@ -352,6 +352,7 @@ using namespace P4; %type*> intOrStrList %type*> strList %type intOrStr +%type input // %precedence COMMA %precedence QUESTION @@ -396,7 +397,7 @@ a syntax error causing a spurious error cascade, which isn't too bad. // Simulate multiple start symbols to allow the parser to be reused for // annotation bodies. start - : fragment END_ANNOTATION { driver.nodes->push_back($1->getNode()); YYACCEPT; } + : fragment END_ANNOTATION { driver.result = $1->getNode(); YYACCEPT; } | START_PROGRAM program ; @@ -484,9 +485,10 @@ p4rtControllerType program : input END { YYACCEPT; }; input - : %empty - | input declaration { if ($2) driver.nodes->push_back($2->getNode()); } - | input ";" {} // empty declaration + : %empty { driver.result = $$ = new IR::P4Program; } + | input declaration { if ($2) $1->objects.push_back($2->getNode()); + $$ = $1; } + | input ";" { $$ = $1; } // empty declaration ; declaration @@ -497,7 +499,7 @@ declaration | typeDeclaration { $$ = $1; } | controlDeclaration { $$ = $1; } | instantiation { $$ = $1; } - | errorDeclaration { driver.onReadErrorDeclaration($1); $$ = nullptr; } + | errorDeclaration { $$ = driver.onReadErrorDeclaration($1) ? $1 : nullptr; } | matchKindDeclaration { $$ = $1; } | functionDeclaration { $$ = $1; } ; diff --git a/frontends/parsers/parserDriver.cpp b/frontends/parsers/parserDriver.cpp index 5a97d8508f..a1be68ec4f 100644 --- a/frontends/parsers/parserDriver.cpp +++ b/frontends/parsers/parserDriver.cpp @@ -114,8 +114,7 @@ void AbstractParserDriver::onParseError(const Util::SourceInfo &location, } } -P4ParserDriver::P4ParserDriver() - : structure(new Util::ProgramStructure), nodes(new IR::Vector()) {} +P4ParserDriver::P4ParserDriver() : structure(new Util::ProgramStructure) {} bool P4ParserDriver::parse(AbstractP4Lexer &lexer, std::string_view sourceFile, unsigned sourceLine /* = 1 */) { @@ -144,7 +143,9 @@ bool P4ParserDriver::parse(AbstractP4Lexer &lexer, std::string_view sourceFile, P4ParserDriver driver; P4Lexer lexer(in); if (!driver.parse(lexer, sourceFile, sourceLine)) return nullptr; - return new IR::P4Program(driver.nodes->srcInfo, *driver.nodes); + IR::P4Program *rv = driver.result->to(); + BUG_CHECK(rv, "parse result is not a program?"); + return rv; } /* static */ const IR::P4Program *P4ParserDriver::parse(FILE *in, std::string_view sourceFile, @@ -162,7 +163,8 @@ P4ParserDriver::parseProgramSources(std::istream &in, std::string_view sourceFil return {nullptr, nullptr}; } - auto *program = new IR::P4Program(driver.nodes->srcInfo, *driver.nodes); + auto *program = driver.result->to(); + BUG_CHECK(program, "parse result is not a program?"); const Util::InputSources *sources = driver.sources; return {program, sources}; @@ -185,7 +187,7 @@ const T *P4ParserDriver::parse(P4AnnotationLexer::Type type, const Util::SourceI return nullptr; } - return nodes->front()->to(); + return result->to(); } /* static */ const IR::Vector *P4ParserDriver::parseExpressionList( @@ -295,13 +297,13 @@ const T *P4ParserDriver::parse(P4AnnotationLexer::Type type, const Util::SourceI srcInfo, body); } -void P4ParserDriver::onReadErrorDeclaration(IR::Type_Error *error) { +bool P4ParserDriver::onReadErrorDeclaration(IR::Type_Error *error) { if (allErrors == nullptr) { - nodes->push_back(error); allErrors = error; - return; + return true; } allErrors->members.append(error->members); + return false; } } // namespace P4 diff --git a/frontends/parsers/parserDriver.h b/frontends/parsers/parserDriver.h index 92d8041502..ca736b048a 100644 --- a/frontends/parsers/parserDriver.h +++ b/frontends/parsers/parserDriver.h @@ -188,7 +188,9 @@ class P4ParserDriver final : public AbstractParserDriver { friend class P4::P4Parser; /// Notify that the parser parsed a P4 `error` declaration. - void onReadErrorDeclaration(IR::Type_Error *error); + // @return true if this is the first error declaration, false if it has + // been combined into a previous one (and should be elided) + bool onReadErrorDeclaration(IR::Type_Error *error); //////////////////////////////////////////////////////////////////////////// // Shared state manipulated directly by the lexer and parser. @@ -197,9 +199,9 @@ class P4ParserDriver final : public AbstractParserDriver { /// Semantic information about the program being parsed. Util::ProgramStructure *structure = nullptr; - /// The top-level nodes that make up the P4 program (or program fragment) + /// The top-level object that makes up the P4 program (or program fragment) /// we're parsing. - IR::Vector *nodes = nullptr; + IR::Node *result = nullptr; /// A scratch buffer to hold the current string literal. (They're lexed /// incrementally, so we need to hold some state between tokens.)