From 64d998474dc4e0c27b6f9ffa054a556d90ff7d36 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Mon, 21 Sep 2020 12:50:14 +0200 Subject: syntax: introduce try/catch blocks Signed-off-by: Jo-Philipp Wich --- eval.c | 25 +++++++++++++++++++++++++ lexer.c | 4 ++++ lexer.h | 2 +- parser.y | 9 +++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/eval.c b/eval.c index 13e5c21..0728ba2 100644 --- a/eval.c +++ b/eval.c @@ -1435,6 +1435,28 @@ ut_execute_this(struct ut_state *state, uint32_t off) return json_object_get(ut_getproto(ut_getscope(state, 0))); } +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) { @@ -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); } diff --git a/lexer.c b/lexer.c index 390a12e..5c1b759 100644 --- a/lexer.c +++ b/lexer.c @@ -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] = "'%}'" }; diff --git a/lexer.h b/lexer.h index cb6bca9..06a0ceb 100644 --- a/lexer.h +++ b/lexer.h @@ -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) diff --git a/parser.y b/parser.y index a3ba991..be59abb 100644 --- a/parser.y +++ b/parser.y @@ -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; } -- cgit v1.2.3