diff --git a/src/parser/context-decls.cpp b/src/parser/context-decls.cpp index 252185d6634..73327bd1640 100644 --- a/src/parser/context-decls.cpp +++ b/src/parser/context-decls.cpp @@ -15,6 +15,7 @@ */ #include "contexts.h" +#include "parsers.h" namespace wasm::WATParser { @@ -302,4 +303,36 @@ Result<> ParseDeclsCtx::addTag(Name name, return Ok{}; } +bool ParseDeclsCtx::skipFunctionBody() { + using namespace std::string_view_literals; + size_t depth = 1; + while (depth > 0 && !in.empty()) { + if (in.takeLParen()) { + ++depth; + continue; + } + if (in.takeRParen()) { + --depth; + continue; + } + if (auto kw = in.takeKeyword()) { + if (*kw == "block"sv || *kw == "loop"sv || *kw == "if"sv || + *kw == "try"sv || *kw == "try_table"sv) { + in.takeID(); + (void)typeuse(*this); + continue; + } + if (*kw == "call_indirect"sv || *kw == "return_call_indirect"sv) { + (void)maybeTableidx(*this); + (void)typeuse(*this, false); + continue; + } + continue; + } + in.take(1); + in.advance(); + } + return true; +} + } // namespace wasm::WATParser diff --git a/src/parser/contexts.h b/src/parser/contexts.h index eb09a0bb3b0..88b7d8a941c 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -1074,6 +1074,8 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx { recTypeDefs.push_back({{}, pos, Index(recTypeDefs.size()), {}}); } + bool skipFunctionBody(); + Limits makeLimits(uint64_t n, std::optional m) { return Limits{n, m}; } diff --git a/src/parser/lexer.h b/src/parser/lexer.h index 3a9fd74e27a..2f5cb7a0291 100644 --- a/src/parser/lexer.h +++ b/src/parser/lexer.h @@ -82,6 +82,15 @@ struct Lexer { advance(); } + // Consume the next `n` characters. + void take(size_t n) { pos += n; } + void takeAll() { pos = buffer.size(); } + + // Whether the unlexed input starts with prefix `sv`. + size_t startsWith(std::string_view sv) const { + return next().starts_with(sv); + } + std::optional peekChar() const; bool peekLParen() { return !empty() && peek() == '('; } @@ -155,15 +164,6 @@ struct Lexer { } private: - // Whether the unlexed input starts with prefix `sv`. - size_t startsWith(std::string_view sv) const { - return next().starts_with(sv); - } - - // Consume the next `n` characters. - void take(size_t n) { pos += n; } - void takeAll() { pos = buffer.size(); } - std::optional getDigit(char c); std::optional getHexDigit(char c); diff --git a/src/parser/parsers.h b/src/parser/parsers.h index db41a2534cc..4a5fb71b771 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -3491,6 +3491,7 @@ template MaybeResult<> func(Ctx& ctx) { typename Ctx::TypeUseT type; Exactness exact = Exact; std::optional localVars; + bool skipped = false; if (import) { auto use = exacttypeuse(ctx); @@ -3505,13 +3506,14 @@ template MaybeResult<> func(Ctx& ctx) { CHECK_ERR(l); localVars = *l; } - if (!ctx.skipFunctionBody()) { + skipped = ctx.skipFunctionBody(); + if (!skipped) { CHECK_ERR(instrs(ctx)); ctx.setSrcLoc(ctx.in.takeAnnotations()); } } - if (!ctx.skipFunctionBody() && !ctx.in.takeRParen()) { + if ((import || !skipped) && !ctx.in.takeRParen()) { return ctx.in.err("expected end of function"); }