|
@@ -300,6 +300,7 @@ typedef struct {
|
|
T_REQUIRE,
|
|
T_REQUIRE,
|
|
T_TRY,
|
|
T_TRY,
|
|
T_CATCH,
|
|
T_CATCH,
|
|
|
|
+ T_FINALLY,
|
|
T_THROW,
|
|
T_THROW,
|
|
T_GOTO,
|
|
T_GOTO,
|
|
T_CLASS,
|
|
T_CLASS,
|
|
@@ -634,6 +635,8 @@ token_t *next_token(char *source, size_t *pos) {
|
|
return TK(TRY);
|
|
return TK(TRY);
|
|
else if (strcmp(name, "catch") == 0)
|
|
else if (strcmp(name, "catch") == 0)
|
|
return TK(CATCH);
|
|
return TK(CATCH);
|
|
|
|
+ else if (strcmp(name, "finally") == 0)
|
|
|
|
+ return TK(FINALLY);
|
|
else if (strcmp(name, "throw") == 0)
|
|
else if (strcmp(name, "throw") == 0)
|
|
return TK(THROW);
|
|
return TK(THROW);
|
|
else if (strcmp(name, "goto") == 0)
|
|
else if (strcmp(name, "goto") == 0)
|
|
@@ -1042,6 +1045,20 @@ node_t *node3(int tag, node_t *a, node_t *b, node_t *c) {
|
|
|
|
|
|
#define NODE3(n, a, b, c) (node_pos(node3(N_##n, (a), (b), (c)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
|
|
#define NODE3(n, a, b, c) (node_pos(node3(N_##n, (a), (b), (c)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
|
|
|
|
|
|
|
|
+node_t *node3t(int tag, node_t *a, node_t *b, node_t *c, token_t *t) {
|
|
|
|
+ node_t *node = malloc(sizeof(node_t));
|
|
|
|
+
|
|
|
|
+ node->tag = tag;
|
|
|
|
+ node->a = a;
|
|
|
|
+ node->b = b;
|
|
|
|
+ node->c = c;
|
|
|
|
+ node->t = t;
|
|
|
|
+
|
|
|
|
+ return node;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#define NODE3t(n, a, b, c, d) (node_pos(node3t(N_##n, (a), (b), (c), (d)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
|
|
|
|
+
|
|
node_t *node4(int tag, node_t *a, node_t *b, node_t *c, node_t *d) {
|
|
node_t *node4(int tag, node_t *a, node_t *b, node_t *c, node_t *d) {
|
|
node_t *node = malloc(sizeof(node_t));
|
|
node_t *node = malloc(sizeof(node_t));
|
|
|
|
|
|
@@ -2038,8 +2055,12 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
|
|
}
|
|
}
|
|
|
|
|
|
node_t *b = BLOCK();
|
|
node_t *b = BLOCK();
|
|
|
|
+ node_t *c = NULL;
|
|
|
|
|
|
- return NODE2t(TRY, a, b, t);
|
|
|
|
|
|
+ if (MATCH(FINALLY))
|
|
|
|
+ c = BLOCK();
|
|
|
|
+
|
|
|
|
+ return NODE3t(TRY, a, b, c, t);
|
|
} else if (MATCH(THROW)) {
|
|
} else if (MATCH(THROW)) {
|
|
node_t *a = NULL;
|
|
node_t *a = NULL;
|
|
|
|
|
|
@@ -2417,7 +2438,7 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
- compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, table_new(), stack_new(), stack_new(), lbl, node->a);
|
|
|
|
|
|
CTXPOP();
|
|
CTXPOP();
|
|
CTXPOP();
|
|
CTXPOP();
|
|
@@ -4044,12 +4065,11 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
LBPUSH();
|
|
LBPUSH();
|
|
CTXPUSH("gap");
|
|
CTXPUSH("gap");
|
|
- compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, table_new(), stack_new(), stack_new(), lbl, node->a);
|
|
CTXPOP();
|
|
CTXPOP();
|
|
LBPOP();
|
|
LBPOP();
|
|
|
|
|
|
- buffer_fmt(tbuf, "\n");
|
|
|
|
- buffer_fmt(tbuf, "}\n");
|
|
|
|
|
|
+ buffer_fmt(tbuf, "\n}\n");
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
@@ -4081,14 +4101,42 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
case N_TRY:
|
|
case N_TRY:
|
|
EMIT("qi_try(state, {\n");
|
|
EMIT("qi_try(state, {\n");
|
|
- compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
|
|
|
|
+ LBPUSH();
|
|
|
|
+ CTXPUSH("gap");
|
|
|
|
+ CTXPUSH("trap");
|
|
|
|
+ compile_node(gbuf, buf, ctx, table_new(), stack_new(), stack_new(), lbl, node->a);
|
|
|
|
+ CTXPOP();
|
|
|
|
+ CTXPOP();
|
|
|
|
+ LBPOP();
|
|
EMIT("}, {\n");
|
|
EMIT("}, {\n");
|
|
if (node->t)
|
|
if (node->t)
|
|
EMIT("qi_decl(state, \"%s\", trap->value);\n", node->t->text);
|
|
EMIT("qi_decl(state, \"%s\", trap->value);\n", node->t->text);
|
|
- CTXPUSH("trap");
|
|
|
|
- compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
|
|
|
|
+ LBPUSH();
|
|
|
|
+ CTXPUSH("gap");
|
|
|
|
+ compile_node(gbuf, buf, ctx, table_new(), stack_new(), stack_new(), lbl, node->b);
|
|
CTXPOP();
|
|
CTXPOP();
|
|
- EMIT("}, NULL);\n");
|
|
|
|
|
|
+ LBPOP();
|
|
|
|
+
|
|
|
|
+ if (node->c) {
|
|
|
|
+ NEWGID();
|
|
|
|
+
|
|
|
|
+ buffer_t *tbuf = buffer_new();
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "void __finally%d(qi_state_t *state) {\n", gid);
|
|
|
|
+ LBPUSH();
|
|
|
|
+ CTXPUSH("gap");
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, table_new(), stack_new(), stack_new(), lbl, node->c);
|
|
|
|
+ CTXPOP();
|
|
|
|
+ LBPOP();
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "\n}\n");
|
|
|
|
+
|
|
|
|
+ buffer_appendb(gbuf, tbuf);
|
|
|
|
+
|
|
|
|
+ EMIT("}, __finally%d);\n", gid);
|
|
|
|
+ } else {
|
|
|
|
+ EMIT("}, NULL);\n");
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
|
|
|
|
case N_THROW:
|
|
case N_THROW:
|