Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/parser/context-decls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include "contexts.h"
#include "parsers.h"

namespace wasm::WATParser {

Expand Down Expand Up @@ -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
2 changes: 2 additions & 0 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,8 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
recTypeDefs.push_back({{}, pos, Index(recTypeDefs.size()), {}});
}

bool skipFunctionBody();

Limits makeLimits(uint64_t n, std::optional<uint64_t> m) {
return Limits{n, m};
}
Expand Down
18 changes: 9 additions & 9 deletions src/parser/lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ struct Lexer {
advance();
}

// Consume the next `n` characters.
void take(size_t n) { pos += n; }
void takeAll() { pos = buffer.size(); }

Copy link
Copy Markdown
Contributor

@MaxGraey MaxGraey Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor proposal for API:

template<typename F>
inline void takeWhile(F&& pred, size_t n = 1) {
  while (pred()) {
    pos += n;
  }
}

template<typename F>
inline void takeUntil(F&& pred, size_t n = 1) {
  while (!pred()) {
    pos += n;
  }
}

This may simplify some code like this into

takeWhile(idchar);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are few enough places where this pattern would apply and they are already simple enough that we probably don't need this abstraction right now. But it's a good idea to keep in mind if we parser more repetitive patterns in the future.

// Whether the unlexed input starts with prefix `sv`.
size_t startsWith(std::string_view sv) const {
return next().starts_with(sv);
}

std::optional<char> peekChar() const;

bool peekLParen() { return !empty() && peek() == '('; }
Expand Down Expand Up @@ -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<int> getDigit(char c);

std::optional<int> getHexDigit(char c);
Expand Down
6 changes: 4 additions & 2 deletions src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -3491,6 +3491,7 @@ template<typename Ctx> MaybeResult<> func(Ctx& ctx) {
typename Ctx::TypeUseT type;
Exactness exact = Exact;
std::optional<typename Ctx::LocalsT> localVars;
bool skipped = false;

if (import) {
auto use = exacttypeuse(ctx);
Expand All @@ -3505,13 +3506,14 @@ template<typename Ctx> 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");
}

Expand Down
Loading