diff options
author | Thomas Lively <tlively@google.com> | 2024-01-29 15:36:41 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-29 15:36:41 -0800 |
commit | 9a31d7e351910191af2c00a9834bcb2e81a28d12 (patch) | |
tree | 015dbbd8436df56b3bf43edcce6ca32e469c0ea7 /src | |
parent | 053b591652865ce7959602f73eef56e6c09666b5 (diff) | |
download | binaryen-9a31d7e351910191af2c00a9834bcb2e81a28d12.tar.gz binaryen-9a31d7e351910191af2c00a9834bcb2e81a28d12.tar.bz2 binaryen-9a31d7e351910191af2c00a9834bcb2e81a28d12.zip |
[Parser] Parse tuple types (#6249)
Use the new `(tuple ...)` syntax. Enforce that tuples have a valid number of
elements and are not nested to avoid assertion failures when parsing invalid
input.
Diffstat (limited to 'src')
-rw-r--r-- | src/parser/contexts.h | 13 | ||||
-rw-r--r-- | src/parser/parsers.h | 37 |
2 files changed, 45 insertions, 5 deletions
diff --git a/src/parser/contexts.h b/src/parser/contexts.h index fb9218cbc..73be5e46e 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -78,6 +78,7 @@ struct TypeUse { struct NullTypeParserCtx { using IndexT = Ok; using HeapTypeT = Ok; + using TupleElemListT = Ok; using TypeT = Ok; using ParamsT = Ok; using ResultsT = size_t; @@ -122,6 +123,10 @@ struct NullTypeParserCtx { TypeT makeRefType(HeapTypeT, Nullability) { return Ok{}; } + TupleElemListT makeTupleElemList() { return Ok{}; } + void appendTupleElem(TupleElemListT&, TypeT) {} + TypeT makeTupleType(TupleElemListT) { return Ok{}; } + ParamsT makeParams() { return Ok{}; } void appendParam(ParamsT&, Name, TypeT) {} @@ -219,7 +224,13 @@ template<typename Ctx> struct TypeParserCtx { return Type(ht, nullability); } - TypeT makeTupleType(const std::vector<Type> types) { return Tuple(types); } + std::vector<Type> makeTupleElemList() { return {}; } + void appendTupleElem(std::vector<Type>& elems, Type elem) { + elems.push_back(elem); + } + Result<TypeT> makeTupleType(const std::vector<Type>& types) { + return Tuple(types); + } ParamsT makeParams() { return {}; } void appendParam(ParamsT& params, Name id, TypeT type) { diff --git a/src/parser/parsers.h b/src/parser/parsers.h index 0c7c5550f..706c6525e 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -28,6 +28,7 @@ using namespace std::string_view_literals; // Types template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx&); template<typename Ctx> MaybeResult<typename Ctx::RefTypeT> reftype(Ctx&); +template<typename Ctx> MaybeResult<typename Ctx::TypeT> tupletype(Ctx&); template<typename Ctx> Result<typename Ctx::TypeT> valtype(Ctx&); template<typename Ctx> MaybeResult<typename Ctx::ParamsT> params(Ctx&); template<typename Ctx> MaybeResult<typename Ctx::ResultsT> results(Ctx&); @@ -365,15 +366,34 @@ template<typename Ctx> MaybeResult<typename Ctx::TypeT> reftype(Ctx& ctx) { return ctx.makeRefType(*type, nullability); } +// tupletype ::= '(' 'tuple' valtype* ')' +template<typename Ctx> MaybeResult<typename Ctx::TypeT> tupletype(Ctx& ctx) { + if (!ctx.in.takeSExprStart("tuple"sv)) { + return {}; + } + auto elems = ctx.makeTupleElemList(); + size_t numElems = 0; + while (!ctx.in.takeRParen()) { + auto elem = singlevaltype(ctx); + CHECK_ERR(elem); + ctx.appendTupleElem(elems, *elem); + ++numElems; + } + if (numElems < 2) { + return ctx.in.err("tuples must have at least two elements"); + } + return ctx.makeTupleType(elems); +} + // numtype ::= 'i32' => i32 // | 'i64' => i64 // | 'f32' => f32 // | 'f64' => f64 // vectype ::= 'v128' => v128 -// valtype ::= t:numtype => t -// | t:vectype => t -// | t:reftype => t -template<typename Ctx> Result<typename Ctx::TypeT> valtype(Ctx& ctx) { +// singlevaltype ::= t:numtype => t +// | t:vectype => t +// | t:reftype => t +template<typename Ctx> Result<typename Ctx::TypeT> singlevaltype(Ctx& ctx) { if (ctx.in.takeKeyword("i32"sv)) { return ctx.makeI32(); } else if (ctx.in.takeKeyword("i64"sv)) { @@ -392,6 +412,15 @@ template<typename Ctx> Result<typename Ctx::TypeT> valtype(Ctx& ctx) { } } +// valtype ::= singlevaltype | tupletype +template<typename Ctx> Result<typename Ctx::TypeT> valtype(Ctx& ctx) { + if (auto type = tupletype(ctx)) { + CHECK_ERR(type); + return *type; + } + return singlevaltype(ctx); +} + // param ::= '(' 'param id? t:valtype ')' => [t] // | '(' 'param t*:valtype* ')' => [t*] // params ::= param* |