aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/stmt.zc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/stmt.zc')
-rw-r--r--src/compiler/stmt.zc12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/compiler/stmt.zc b/src/compiler/stmt.zc
index a67b931..622d96a 100644
--- a/src/compiler/stmt.zc
+++ b/src/compiler/stmt.zc
@@ -432,22 +432,26 @@ int kw_continue() {
// happen. a defer a branch never reached is not on the stack at an exit on
// another path, because the stack only holds the defers read so far in the
// blocks still open. the entries of an exit run newest first.
+// a block, or an if, while, for, switch, unchecked or unbounded statement, can end
+// at a } (blk); either way an else after the end of an if branch belongs to it.
word .u defer_tokens() {
- int n = 0, depth = 0, blk = is_op(s_lb), semi, bad = 0; word q;
+ int n = 0, depth = 0, blk = is_op(s_lb), semi, bad = 0, rb; word q;
+ if (tk == T_ID && (tv == intern("if") || tv == s_while || tv == intern("for") || tv == intern("switch") || tv == s_unchecked || tv == s_unbounded)) blk = 2;
while (1) {
if (tk == T_EOF) { bad = 1; break; }
- semi = 0;
+ semi = 0; rb = 0;
if (tk == T_OP) {
if (tv == s_lb || tv == s_lp || tv == s_lk) depth++;
- else if (tv == s_rb || tv == s_rp || tv == s_rk) depth--;
+ else if (tv == s_rb || tv == s_rp || tv == s_rk) { depth--; rb = tv == s_rb; }
else if (tv == s_semi && depth == 0) semi = 1;
}
if (depth < 0) { bad = 1; break; }
reserve_R_QBUF((n + 1) * 3);
R_QBUF[n * 3] = tk; R_QBUF[n * 3 + 1] = tv; R_QBUF[n * 3 + 2] = tpack(); n++;
next();
+ if ((semi || (blk && rb && depth == 0)) && blk == 2 && is_id(s_else)) continue;
if (semi) break;
- if (blk && depth == 0) { accept(s_semi); break; }
+ if (blk && rb && depth == 0) { if (blk == 1) accept(s_semi); break; }
}
if (bad) { die("missing ; after the deferred statement"); n = 0; }
q = rt.new(n * 3 + 1);