diff --git a/src/parser/parse-1-decls.cpp b/src/parser/parse-1-decls.cpp index 1c753cc611a..7a4ad34ac23 100644 --- a/src/parser/parse-1-decls.cpp +++ b/src/parser/parse-1-decls.cpp @@ -18,6 +18,8 @@ namespace wasm::WATParser { -Result<> parseDecls(ParseDeclsCtx& decls) { return module(decls); } +Result<> parseModule(ParseDeclsCtx& decls) { return module(decls); } + +Result<> parseModuleBody(ParseDeclsCtx& decls) { return moduleBody(decls); } } // namespace wasm::WATParser diff --git a/src/parser/parsers.h b/src/parser/parsers.h index f18b8216c81..360878848c5 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -3882,6 +3882,15 @@ template MaybeResult<> modulefield(Ctx& ctx) { return ctx.in.err("unrecognized module field"); } +// (m:modulefield)* +template Result<> moduleBody(Ctx& ctx) { + while (auto field = modulefield(ctx)) { + CHECK_ERR(field); + } + + return Ok{}; +} + // module ::= '(' 'module' id? (m:modulefield)* ')' // | (m:modulefield)* eof template Result<> module(Ctx& ctx) { @@ -3893,9 +3902,7 @@ template Result<> module(Ctx& ctx) { } } - while (auto field = modulefield(ctx)) { - CHECK_ERR(field); - } + CHECK_ERR(moduleBody(ctx)); if (outer && !ctx.in.takeRParen()) { return ctx.in.err("expected end of module"); diff --git a/src/parser/wat-parser-internal.h b/src/parser/wat-parser-internal.h index 00c96abd42e..612fd0a4bc7 100644 --- a/src/parser/wat-parser-internal.h +++ b/src/parser/wat-parser-internal.h @@ -22,7 +22,9 @@ namespace wasm::WATParser { -Result<> parseDecls(ParseDeclsCtx& decls); +Result<> parseModule(ParseDeclsCtx& decls); + +Result<> parseModuleBody(ParseDeclsCtx& decls); Result<> parseTypeDefs( ParseDeclsCtx& decls, diff --git a/src/parser/wat-parser.cpp b/src/parser/wat-parser.cpp index 26b2bbad06f..7f1f9fe16ce 100644 --- a/src/parser/wat-parser.cpp +++ b/src/parser/wat-parser.cpp @@ -83,58 +83,75 @@ void propagateDebugLocations(Module& wasm) { runner.run(); } -// Parse module-level declarations. - -// Parse type definitions. - -// Parse implicit type definitions and map typeuses without explicit types to -// the correct types. - -Result<> doParseModule(Module& wasm, Lexer& input, bool allowExtra) { - ParseDeclsCtx decls(input, wasm); - CHECK_ERR(parseDecls(decls)); - if (!allowExtra && !decls.in.empty()) { - return decls.in.err("Unexpected tokens after module"); - } - +// After doing the initial pass, parse types, imports, etc. +Result<> parseModuleWithDecls(ParseDeclsCtx& decls) { auto typeIndices = createIndexMap(decls.in, decls.typeDefs); CHECK_ERR(typeIndices); std::vector types; std::unordered_map> typeNames; - CHECK_ERR(parseTypeDefs(decls, input, *typeIndices, types, typeNames)); + CHECK_ERR(parseTypeDefs(decls, decls.in, *typeIndices, types, typeNames)); + // Parse implicit type definitions and map typeuses without explicit types to + // the correct types. std::unordered_map implicitTypes; CHECK_ERR( - parseImplicitTypeDefs(decls, input, *typeIndices, types, implicitTypes)); + parseImplicitTypeDefs(decls, decls.in, *typeIndices, types, implicitTypes)); - CHECK_ERR(parseModuleTypes(decls, input, *typeIndices, types, implicitTypes)); + CHECK_ERR( + parseModuleTypes(decls, decls.in, *typeIndices, types, implicitTypes)); CHECK_ERR(parseDefinitions( - decls, input, *typeIndices, types, implicitTypes, typeNames)); + decls, decls.in, *typeIndices, types, implicitTypes, typeNames)); - propagateDebugLocations(wasm); - input = decls.in; + propagateDebugLocations(decls.wasm); return Ok{}; } +Result<> doParseModule(Module& wasm, Lexer& input, bool allowExtra) { + ParseDeclsCtx decls(input, wasm); + CHECK_ERR(parseModule(decls)); + if (!allowExtra && !decls.in.empty()) { + return decls.in.err("Unexpected tokens after module"); + } + + CHECK_ERR(parseModuleWithDecls(decls)); + + // decls / parseModule made a copy of `input`. Advance `input` past the parsed + // module. + input = decls.in; + return Ok{}; +} + } // anonymous namespace Result<> parseModule(Module& wasm, std::string_view in, std::optional filename) { Lexer lexer(in, filename); - return doParseModule(wasm, lexer, false); + return doParseModule(wasm, lexer, /*allowExtra=*/false); } Result<> parseModule(Module& wasm, std::string_view in) { Lexer lexer(in); - return doParseModule(wasm, lexer, false); + return doParseModule(wasm, lexer, /*allowExtra=*/false); } Result<> parseModule(Module& wasm, Lexer& lexer) { - return doParseModule(wasm, lexer, true); + return doParseModule(wasm, lexer, /*allowExtra=*/true); +} + +Result<> parseModuleBody(Module& wasm, Lexer& lexer) { + ParseDeclsCtx decls(lexer, wasm); + CHECK_ERR(parseModuleBody(decls)); + CHECK_ERR(parseModuleWithDecls(decls)); + + // decls / parseModuleBody made a copy of `input`. Advance `input` past the + // parsed module. + lexer = decls.in; + + return Ok{}; } } // namespace wasm::WATParser diff --git a/src/parser/wat-parser.h b/src/parser/wat-parser.h index 34e9b69f8f0..6bbe8601a4c 100644 --- a/src/parser/wat-parser.h +++ b/src/parser/wat-parser.h @@ -34,6 +34,11 @@ Result<> parseModule(Module& wasm, // file. Result<> parseModule(Module& wasm, Lexer& lexer); +// Similar to `parseModule`, parse the fields of a single WAT module (after the +// initial module definition including its name) and stop at the ending right +// paren. +Result<> parseModuleBody(Module& wasm, Lexer& lexer); + Result parseConst(Lexer& lexer); #pragma GCC diagnostic push