diff options
author | Jo-Philipp Wich <jo@mein.io> | 2020-09-21 12:50:14 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-09-21 12:50:14 +0200 |
commit | 64d998474dc4e0c27b6f9ffa054a556d90ff7d36 (patch) | |
tree | bc779d2882db78591b9848e409a6ea93d640ba24 | |
parent | ff88195a710ec58190a75a2c71e90126e52a07ca (diff) |
syntax: introduce try/catch blocks
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | eval.c | 25 | ||||
-rw-r--r-- | lexer.c | 4 | ||||
-rw-r--r-- | lexer.h | 2 | ||||
-rw-r--r-- | parser.y | 9 |
4 files changed, 39 insertions, 1 deletions
@@ -1436,6 +1436,28 @@ ut_execute_this(struct ut_state *state, uint32_t off) } static struct json_object * +ut_execute_try_catch(struct ut_state *state, uint32_t off) +{ + struct ut_op *op = ut_get_op(state, off); + struct json_object *rv; + + rv = ut_execute_op_sequence(state, op->tree.operand[0]); + + if (ut_is_type(rv, T_EXCEPTION)) { + if (op->tree.operand[1]) + ut_putval(ut_setval(ut_getscope(state, 0), ut_get_child(state, off, 1)->val, + json_object_new_string(json_object_get_string(rv)))); + + memset(&state->error, 0, sizeof(state->error)); + + ut_putval(rv); + rv = ut_execute_op_sequence(state, op->tree.operand[2]); + } + + return rv; +} + +static struct json_object * ut_execute_op(struct ut_state *state, uint32_t off) { struct ut_op *op = ut_get_op(state, off); @@ -1594,6 +1616,9 @@ ut_execute_op(struct ut_state *state, uint32_t off) case T_CONTINUE: return ut_execute_break_cont(state, off); + case T_TRY: + return ut_execute_try_catch(state, off); + default: return ut_exception(state, off, "Runtime error: Unrecognized opcode %d", op->type); } @@ -132,12 +132,14 @@ static const struct token reserved_words[] = { { T_ENDIF, "endif", 5 }, { T_WHILE, "while", 5 }, { T_BREAK, "break", 5 }, + { T_CATCH, "catch", 5 }, { T_BOOL, "false", 5, parse_bool }, { T_BOOL, "true", 4, parse_bool }, { T_ELSE, "else", 4 }, { T_THIS, "this", 4 }, { T_NULL, "null", 4 }, { T_NUMBER, "NaN", 3, parse_number }, + { T_TRY, "try", 3 }, { T_FOR, "for", 3 }, { T_IN, "in", 2 }, }; @@ -214,6 +216,8 @@ const char *tokennames[__T_MAX] = { [T_CONTINUE] = "'continue'", [T_NULL] = "'null'", [T_THIS] = "'this'", + [T_TRY] = "'try'", + [T_CATCH] = "'catch'", //[T_LSTM] = "'{%'", //[T_RSTM] = "'%}'" }; @@ -19,7 +19,7 @@ #include "ast.h" -#define __T_MAX 73 +#define __T_MAX 75 #define T_EXCEPTION (__T_MAX + 0) #define T_CFUNC (__T_MAX + 1) #define T_RESSOURCE (__T_MAX + 2) @@ -114,6 +114,7 @@ stmt(A) ::= exp_stmt(B). { A = B; } stmt(A) ::= sel_stmt(B). { A = B; } stmt(A) ::= iter_stmt(B). { A = B; } stmt(A) ::= func_stmt(B). { A = B; } +stmt(A) ::= try_stmt(B). { A = B; } stmt(A) ::= ret_stmt(B). { A = B; } stmt(A) ::= break_stmt(B). { A = B; } stmt(A) ::= decl_stmt(B). { A = B; } @@ -165,6 +166,14 @@ func_stmt(A) ::= T_FUNC(B) T_LABEL(C) T_LPAREN args(D) T_RPAREN empty_object. func_stmt(A) ::= T_FUNC(B) T_LABEL(C) T_LPAREN args(D) T_RPAREN T_COLON chunks(E) T_ENDFUNC. { A = wrap_op(B, C, D, E); } +try_stmt(A) ::= T_TRY(B) try_catch_block(C) T_CATCH T_LPAREN T_LABEL(D) T_RPAREN try_catch_block(E). + { A = wrap_op(B, C, D, E); } +try_stmt(A) ::= T_TRY(B) try_catch_block(C) T_CATCH try_catch_block(D). + { A = wrap_op(B, C, 0, D); } + +try_catch_block(A) ::= cpd_stmt(B). { A = B; } +try_catch_block(A) ::= empty_object. { A = 0; } + args(A) ::= args(B) T_COMMA T_LABEL(C). { A = append_op(B, C); } args(A) ::= T_LABEL(B). { A = B; } |