summaryrefslogtreecommitdiff
path: root/src/parser/parsers.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/parsers.h')
-rw-r--r--src/parser/parsers.h122
1 files changed, 113 insertions, 9 deletions
diff --git a/src/parser/parsers.h b/src/parser/parsers.h
index 5f9f23a2a..d162de58c 100644
--- a/src/parser/parsers.h
+++ b/src/parser/parsers.h
@@ -48,11 +48,14 @@ MaybeResult<typename Ctx::InstrT> unfoldedBlockinstr(Ctx&);
template<typename Ctx> MaybeResult<typename Ctx::InstrT> blockinstr(Ctx&);
template<typename Ctx> MaybeResult<typename Ctx::InstrT> plaininstr(Ctx&);
template<typename Ctx> MaybeResult<typename Ctx::InstrT> instr(Ctx&);
-template<typename Ctx> Result<typename Ctx::InstrsT> instrs(Ctx&);
+template<typename Ctx>
+Result<typename Ctx::InstrsT> instrs(Ctx&, bool requireFolded = false);
+template<typename Ctx> Result<typename Ctx::InstrsT> foldedinstrs(Ctx&);
template<typename Ctx> Result<typename Ctx::ExprT> expr(Ctx&);
template<typename Ctx> Result<typename Ctx::MemargT> memarg(Ctx&, uint32_t);
template<typename Ctx> Result<typename Ctx::BlockTypeT> blocktype(Ctx&);
template<typename Ctx> MaybeResult<typename Ctx::InstrT> block(Ctx&, bool);
+template<typename Ctx> MaybeResult<typename Ctx::InstrT> ifelse(Ctx&, bool);
template<typename Ctx>
Result<typename Ctx::InstrT> makeUnreachable(Ctx&, Index);
template<typename Ctx> Result<typename Ctx::InstrT> makeNop(Ctx&, Index);
@@ -594,6 +597,9 @@ MaybeResult<typename Ctx::InstrT> foldedBlockinstr(Ctx& ctx) {
if (auto i = block(ctx, true)) {
return i;
}
+ if (auto i = ifelse(ctx, true)) {
+ return i;
+ }
// TODO: Other block instructions
return {};
}
@@ -603,6 +609,9 @@ MaybeResult<typename Ctx::InstrT> unfoldedBlockinstr(Ctx& ctx) {
if (auto i = block(ctx, false)) {
return i;
}
+ if (auto i = ifelse(ctx, false)) {
+ return i;
+ }
// TODO: Other block instructions
return {};
}
@@ -635,7 +644,7 @@ template<typename Ctx> MaybeResult<typename Ctx::InstrT> instr(Ctx& ctx) {
// Check for valid strings that are not instructions.
if (auto tok = ctx.in.peek()) {
if (auto keyword = tok->getKeyword()) {
- if (keyword == "end"sv) {
+ if (keyword == "end"sv || keyword == "then"sv || keyword == "else"sv) {
return {};
}
}
@@ -650,13 +659,20 @@ template<typename Ctx> MaybeResult<typename Ctx::InstrT> instr(Ctx& ctx) {
return {};
}
-template<typename Ctx> Result<typename Ctx::InstrsT> instrs(Ctx& ctx) {
+template<typename Ctx>
+Result<typename Ctx::InstrsT> instrs(Ctx& ctx, bool requireFolded) {
auto insts = ctx.makeInstrs();
+ bool parsedFolded = false;
while (true) {
if (auto blockinst = foldedBlockinstr(ctx)) {
CHECK_ERR(blockinst);
ctx.appendInstr(insts, *blockinst);
+ parsedFolded = true;
+ if (requireFolded) {
+ // Do not continue to parse another sibling folded instruction.
+ break;
+ }
continue;
}
// Parse an arbitrary number of folded instructions.
@@ -686,6 +702,7 @@ template<typename Ctx> Result<typename Ctx::InstrsT> instrs(Ctx& ctx) {
if (auto blockinst = foldedBlockinstr(ctx)) {
CHECK_ERR(blockinst);
ctx.appendInstr(insts, *blockinst);
+ parsedFolded = true;
} else if (ctx.in.takeLParen()) {
foldedInstrs.push_back({ctx.in.getPos(), {}});
} else if (ctx.in.takeRParen()) {
@@ -697,6 +714,7 @@ template<typename Ctx> Result<typename Ctx::InstrsT> instrs(Ctx& ctx) {
if (auto inst = plaininstr(ctx)) {
CHECK_ERR(inst);
ctx.appendInstr(insts, *inst);
+ parsedFolded = true;
} else {
return ctx.in.err(start, "expected folded instruction");
}
@@ -708,9 +726,18 @@ template<typename Ctx> Result<typename Ctx::InstrsT> instrs(Ctx& ctx) {
WASM_UNREACHABLE("expected paren");
}
}
+ if (requireFolded) {
+ // Do not continue to parse another sibling folded instruction.
+ break;
+ }
continue;
}
+ if (requireFolded) {
+ // Do not continue to parse a non-folded instruction.
+ break;
+ }
+
// A non-folded instruction.
if (auto inst = instr(ctx)) {
CHECK_ERR(inst);
@@ -720,9 +747,17 @@ template<typename Ctx> Result<typename Ctx::InstrsT> instrs(Ctx& ctx) {
}
}
+ if (requireFolded && !parsedFolded) {
+ return ctx.in.err("expected folded instructions");
+ }
+
return ctx.finishInstrs(insts);
}
+template<typename Ctx> Result<typename Ctx::InstrsT> foldedinstrs(Ctx& ctx) {
+ return instrs(ctx, true);
+}
+
template<typename Ctx> Result<typename Ctx::ExprT> expr(Ctx& ctx) {
auto insts = instrs(ctx);
CHECK_ERR(insts);
@@ -807,7 +842,81 @@ MaybeResult<typename Ctx::InstrT> block(Ctx& ctx, bool folded) {
}
}
- return ctx.finishBlock(pos, std::move(*insts));
+ return ctx.visitEnd(pos, std::move(*insts));
+}
+
+// if ::= 'if' label blocktype instr1* ('else' id1? instr2*)? 'end' id2?
+// | '(' 'if' label blocktype instr* '(' 'then' instr1* ')'
+// ('(' 'else' instr2* ')')? ')'
+template<typename Ctx>
+MaybeResult<typename Ctx::InstrT> ifelse(Ctx& ctx, bool folded) {
+ auto pos = ctx.in.getPos();
+
+ if (folded) {
+ if (!ctx.in.takeSExprStart("if"sv)) {
+ return {};
+ }
+ } else {
+ if (!ctx.in.takeKeyword("if"sv)) {
+ return {};
+ }
+ }
+
+ auto label = ctx.in.takeID();
+
+ auto type = blocktype(ctx);
+ CHECK_ERR(type);
+
+ if (folded) {
+ CHECK_ERR(foldedinstrs(ctx));
+ }
+
+ ctx.makeIf(pos, label, *type);
+
+ if (folded && !ctx.in.takeSExprStart("then"sv)) {
+ return ctx.in.err("expected 'then' before if instructions");
+ }
+
+ auto insts = instrs(ctx);
+ CHECK_ERR(insts);
+
+ if (folded && !ctx.in.takeRParen()) {
+ return ctx.in.err("expected ')' at end of then block");
+ }
+
+ if ((folded && ctx.in.takeSExprStart("else"sv)) ||
+ (!folded && ctx.in.takeKeyword("else"sv))) {
+ auto id1 = ctx.in.takeID();
+ if (id1 && id1 != label) {
+ return ctx.in.err("else label does not match if label");
+ }
+
+ ctx.visitElse(pos);
+
+ auto elseInsts = instrs(ctx);
+ CHECK_ERR(elseInsts);
+
+ if (folded && !ctx.in.takeRParen()) {
+ return ctx.in.err("expected ')' at end of else block");
+ }
+ }
+
+ if (folded) {
+ if (!ctx.in.takeRParen()) {
+ return ctx.in.err("expected ')' at end of if");
+ }
+ } else {
+ if (!ctx.in.takeKeyword("end"sv)) {
+ return ctx.in.err("expected 'end' at end of if");
+ }
+ }
+
+ auto id2 = ctx.in.takeID();
+ if (id2 && id2 != label) {
+ return ctx.in.err("end label does not match if label");
+ }
+
+ return ctx.visitEnd(pos, std::move(*insts));
}
template<typename Ctx>
@@ -897,11 +1006,6 @@ Result<typename Ctx::InstrT> makeBlock(Ctx& ctx, Index pos) {
}
template<typename Ctx>
-Result<typename Ctx::InstrT> makeThenOrElse(Ctx& ctx, Index pos) {
- return ctx.in.err("unimplemented instruction");
-}
-
-template<typename Ctx>
Result<typename Ctx::InstrT> makeConst(Ctx& ctx, Index pos, Type type) {
assert(type.isBasic());
switch (type.getBasic()) {