diff --git a/lib/comp.c b/lib/comp.c index 36a5833..9b9f2c1 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -488,7 +488,8 @@ static int check_block_expression_as_body (hcl_t* hcl, hcl_cnode_t* c, const hcl /* there are special words that can't start a new expression */ if (HCL_CNODE_IS_TYPED(car, HCL_CNODE_ELIF) || - HCL_CNODE_IS_TYPED(car, HCL_CNODE_ELSE)) + HCL_CNODE_IS_TYPED(car, HCL_CNODE_ELSE) || + HCL_CNODE_IS_TYPED(car, HCL_CNODE_CATCH)) { goto no_block; } @@ -522,6 +523,7 @@ static int check_block_expression_as_body (hcl_t* hcl, hcl_cnode_t* c, const hcl } else if (for_what == FOR_TRY) { + if (HCL_CNODE_IS_TYPED(nxt, HCL_CNODE_CATCH)) goto ok; if (HCL_CNODE_IS_SYMBOL(nxt)) { int syncode = HCL_CNODE_SYMBOL_SYNCODE(nxt); @@ -3473,7 +3475,7 @@ static int compile_try (hcl_t* hcl, hcl_cnode_t* src) HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(src)); - HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_TRY)); + HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_TRY) || HCL_CNODE_IS_TYPED(HCL_CNODE_CONS_CAR(src), HCL_CNODE_TRY)); /* (try * (perform this) @@ -3571,7 +3573,7 @@ static HCL_INLINE int compile_catch (hcl_t* hcl) src = cf->operand; HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(src)); - HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_CATCH)); + HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_CATCH) || HCL_CNODE_IS_TYPED(HCL_CNODE_CONS_CAR(src), HCL_CNODE_CATCH)); cmd = HCL_CNODE_CONS_CAR(src); obj = HCL_CNODE_CONS_CDR(src); @@ -3704,7 +3706,7 @@ static int compile_throw (hcl_t* hcl, hcl_cnode_t* src) /*hcl_cframe_t* cf;*/ HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(src)); - HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_THROW)); + HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_THROW) || HCL_CNODE_IS_TYPED(HCL_CNODE_CONS_CAR(src), HCL_CNODE_THROW)); obj = HCL_CNODE_CONS_CDR(src); @@ -3913,6 +3915,19 @@ static int compile_cons_xlist_expression (hcl_t* hcl, hcl_cnode_t* obj, int nret hcl_setsynerrbfmt (hcl, HCL_SYNERR_ELIF, HCL_CNODE_GET_LOC(car), HCL_CNODE_GET_TOK(car), "elif without if"); return -1; } + else if (HCL_CNODE_IS_TYPED(car, HCL_CNODE_THROW)) + { + if (compile_throw(hcl, obj) <= -1) return -1; + } + else if (HCL_CNODE_IS_TYPED(car, HCL_CNODE_TRY)) + { + if (compile_try(hcl, obj) <= -1) return -1; + } + else if (HCL_CNODE_IS_TYPED(car, HCL_CNODE_CATCH)) + { + hcl_setsynerrbfmt (hcl, HCL_SYNERR_CATCH, HCL_CNODE_GET_LOC(car), HCL_CNODE_GET_TOK(car), "catch without try"); + return -1; + } else if (HCL_CNODE_IS_SYMBOL(car) && (syncode = HCL_CNODE_SYMBOL_SYNCODE(car))) { if (nrets > 0) @@ -4971,7 +4986,7 @@ static int compile_object_list (hcl_t* hcl) } else if (cop == COP_COMPILE_TRY_OBJECT_LIST || cop == COP_COMPILE_TRY_OBJECT_LIST_TAIL) { - if (HCL_CNODE_IS_SYMBOL_SYNCODED(car, HCL_SYNCODE_CATCH)) + if (HCL_CNODE_IS_SYMBOL_SYNCODED(car, HCL_SYNCODE_CATCH) || HCL_CNODE_IS_TYPED(car, HCL_CNODE_CATCH)) { SWITCH_TOP_CFRAME (hcl, COP_COMPILE_CATCH, oprnd); goto done; diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index 701ad9e..e30cc1a 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -304,6 +304,9 @@ enum hcl_tok_type_t HCL_TOK_IF, HCL_TOK_ELIF, HCL_TOK_ELSE, + HCL_TOK_THROW, + HCL_TOK_TRY, + HCL_TOK_CATCH, HCL_TOK_BINOP, HCL_TOK_IDENT, @@ -388,6 +391,9 @@ enum hcl_cnode_type_t HCL_CNODE_IF, HCL_CNODE_ELIF, HCL_CNODE_ELSE, + HCL_CNODE_THROW, + HCL_CNODE_TRY, + HCL_CNODE_CATCH, HCL_CNODE_ELLIPSIS, HCL_CNODE_TRPCOLONS, diff --git a/lib/read.c b/lib/read.c index bd7e0cd..73dbe4c 100644 --- a/lib/read.c +++ b/lib/read.c @@ -61,6 +61,9 @@ static struct voca_t { 2, { 'i','f' } }, { 4, { 'e','l','i','f' } }, { 4, { 'e','l','s','e' } }, + { 5, { 't','h','r','o','w' } }, + { 3, { 't','r','y' } }, + { 5, { 'c','a','t','c','h' } }, { 3, { 's','e','t' } }, { 5, { 's','e','t','-','r' } }, @@ -107,6 +110,9 @@ enum voca_id_t VOCA_KW_IF, VOCA_KW_ELIF, VOCA_KW_ELSE, + VOCA_KW_THROW, + VOCA_KW_TRY, + VOCA_KW_CATCH, VOCA_SYM_SET, VOCA_SYM_SET_R, @@ -419,7 +425,10 @@ static hcl_tok_type_t classify_ident_token (hcl_t* hcl, const hcl_oocs_t* v) { VOCA_KW_IF, HCL_TOK_IF }, { VOCA_KW_ELIF, HCL_TOK_ELIF }, - { VOCA_KW_ELSE, HCL_TOK_ELSE } + { VOCA_KW_ELSE, HCL_TOK_ELSE }, + { VOCA_KW_THROW, HCL_TOK_THROW }, + { VOCA_KW_TRY, HCL_TOK_TRY }, + { VOCA_KW_CATCH, HCL_TOK_CATCH } }; for (i = 0; i < HCL_COUNTOF(tab); i++) @@ -1239,6 +1248,9 @@ static hcl_cnode_type_t kw_to_cnode_type (int tok_type) HCL_CNODE_IF, HCL_CNODE_ELIF, HCL_CNODE_ELSE, + HCL_CNODE_THROW, + HCL_CNODE_TRY, + HCL_CNODE_CATCH, }; return mapping[tok_type - HCL_TOK_NIL]; @@ -1648,6 +1660,9 @@ static int feed_process_token (hcl_t* hcl) case HCL_TOK_IF: case HCL_TOK_ELIF: case HCL_TOK_ELSE: + case HCL_TOK_THROW: + case HCL_TOK_TRY: + case HCL_TOK_CATCH: frd->obj = hcl_makecnode(hcl, kw_to_cnode_type(TOKEN_TYPE(hcl)), 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); goto auto_xlist;