diff --git a/lib/read.c b/lib/read.c index 97a10e3..fc6cd52 100644 --- a/lib/read.c +++ b/lib/read.c @@ -120,10 +120,12 @@ enum list_flag_t { QUOTED = (1 << 0), DOTTED = (1 << 1), + COMMAED = (1 << 2), COLONED = (1 << 3), COLONEQED = (1 << 4), BINOPED = (1 << 5), + CLOSED = (1 << 6), JSON = (1 << 7), DATA_LIST = (1 << 8), @@ -594,7 +596,7 @@ static HCL_INLINE hcl_cnode_t* leave_list (hcl_t* hcl, hcl_loc_t* list_loc, int* /* HACK */ if (concode == HCL_CONCODE_ALIST) { - /* tranform (var := val) to (set var val) */ + /* tranform (var := val) to (set var val) - note ALIST doesn't contain the := symbol */ hcl_cnode_t* sym, * newhead, * lval; hcl_oocs_t fake_tok, * fake_tok_ptr = HCL_NULL; @@ -637,7 +639,6 @@ static HCL_INLINE hcl_cnode_t* leave_list (hcl_t* hcl, hcl_loc_t* list_loc, int* fake_tok_ptr = &fake_tok; } - HCL_ASSERT (hcl, count >= 2); /* the missing rvalue check has been done above */ if (count != 2) { @@ -660,7 +661,6 @@ static HCL_INLINE hcl_cnode_t* leave_list (hcl_t* hcl, hcl_loc_t* list_loc, int* return HCL_NULL; } - /* create a new head joined with set or set-r */ newhead = hcl_makecnodecons(hcl, 0, &loc, fake_tok_ptr, sym, head); if (HCL_UNLIKELY(!newhead)) @@ -675,6 +675,36 @@ static HCL_INLINE hcl_cnode_t* leave_list (hcl_t* hcl, hcl_loc_t* list_loc, int* head = newhead; concode = HCL_CONCODE_XLIST; /* switch back to XLIST */ } + else if (concode == HCL_CONCODE_BLIST) + { + /* x binop y -> binop x y - BLIST contains BINOP in it */ + hcl_cnode_t* x, * binop; + + x = HCL_CNODE_CONS_CAR(head); + if (x && HCL_CNODE_IS_ELIST(x)) + { + hcl_setsynerr (hcl, HCL_SYNERR_LVALUE, HCL_CNODE_GET_LOC(x), HCL_CNODE_GET_TOK(x)); + if (head) hcl_freecnode (hcl, head); + return HCL_NULL; + } + + /* swap x and binop */ + binop = HCL_CNODE_CONS_CDR(head); + if (!binop || !HCL_CNODE_IS_CONS(binop) || !HCL_CNODE_CONS_CDR(binop) || !HCL_CNODE_IS_CONS(HCL_CNODE_CONS_CDR(binop))) + { + hcl_setsynerrbfmt (hcl, HCL_SYNERR_NOVALUE, HCL_CNODE_GET_LOC(x), HCL_CNODE_GET_TOK(x), "no operand after binary operator"); + if (head) hcl_freecnode (hcl, head); + return HCL_NULL; + } + +/* TODO: support multiple operators and operands .. like 1 + 2 - 3.. -> currently can_binop_list() disallows more operators */ + HCL_ASSERT (hcl, count == 3); + + HCL_CNODE_CONS_CDR(head) = HCL_CNODE_CONS_CDR(binop); + HCL_CNODE_CONS_CDR(binop) = head; + head = binop; + concode = HCL_CONCODE_XLIST; + } /* END HACK */ HCL_CNODE_CONS_CONCODE(head) = concode; @@ -1339,7 +1369,7 @@ static int feed_process_token (hcl_t* hcl) int can = 0; if (frd->level <= 0 || !(can = can_binop_list(hcl))) { - hcl_setsynerr (hcl, HCL_SYNERR_BANNED, TOKEN_LOC(hcl), HCL_NULL); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, TOKEN_LOC(hcl), TOKEN_NAME(hcl), "prohibited binary operator"); goto oops; } if (can == 1) goto ident; /* if binop is the first in the list */ diff --git a/t/feed-5001.err b/t/feed-5001.err index 071df03..6d70e01 100644 --- a/t/feed-5001.err +++ b/t/feed-5001.err @@ -1,3 +1,22 @@ +## + +x := (+ 10 20) "aaaa"; ##ERROR: syntax error - too many rvalues + +--- + +## + +x := (10 +); ##ERROR: syntax error - no operand after binary operator + +--- + +## + +x := (10 + 20 * 4); ##ERROR: syntax error - prohibited binary operator + +--- + + ## you can't have another colon before the method.. (obj: :method) ##ERROR: syntax error - : disallowed diff --git a/t/insta-01.hcl b/t/insta-01.hcl index 4e6f874..7e7e3ac 100644 --- a/t/insta-01.hcl +++ b/t/insta-01.hcl @@ -34,24 +34,24 @@ defclass B :: A | d e f | { }; a := ((B:newInstance 1 2 3):sum); -if (/= a 18) { printf "ERROR: a must be 18\n"; } \ +if (a /= 18) { printf "ERROR: a must be 18\n"; } \ else { printf "OK %d\n" a; }; b := (B:newInstance 2 3 4); a := (b:get-a); -if (/= a 4) {printf "ERROR: a must be 4\n" } \ +if (a /= 4) {printf "ERROR: a must be 4\n" } \ else { printf "OK %d\n" a }; a := (b:get-b); -if (/= a 6) { printf "ERROR: a must be 6\n" } \ +if (a /= 6) { printf "ERROR: a must be 6\n" } \ else { printf "OK %d\n" a }; a := (b:get-c); -if (/= a 8) { printf "ERROR: a must be 8\n" } \ +if (a /= 8) { printf "ERROR: a must be 8\n" } \ else {printf "OK %d\n" a }; a := (b:sum); -if (/= a 27) { printf "ERROR: a must be 27\n" } \ +if (a /= 27) { printf "ERROR: a must be 27\n" } \ else { printf "OK %d\n" a }; ## super is equivalent to self unless a message is sent to it.