From 8345e2f949100b57e8d28ed91c4ce527d287b679 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 9 Mar 2024 17:10:51 +0900 Subject: [PATCH] enhanced the binop expression check in leave_list() in read.c fixed the issue of the lost line terminator after the comment text which caused the next line to be treated as the same line --- lib/read.c | 40 +++++++++++++++++++++++++++++++++------- t/Makefile.am | 1 - t/Makefile.in | 1 - t/do-5001.err | 10 ++++++++++ t/do-5002.err | 8 -------- t/feed-5001.err | 4 ++++ t/fun-01.hcl | 9 +++------ 7 files changed, 50 insertions(+), 23 deletions(-) delete mode 100644 t/do-5002.err diff --git a/lib/read.c b/lib/read.c index dc384ca..80db364 100644 --- a/lib/read.c +++ b/lib/read.c @@ -541,7 +541,7 @@ static HCL_INLINE int enter_list (hcl_t* hcl, const hcl_loc_t* loc, int flagv) static HCL_INLINE hcl_cnode_t* leave_list (hcl_t* hcl, hcl_loc_t* list_loc, int* flagv, int* oldflagv) { hcl_rstl_t* rstl; - hcl_cnode_t* head; + hcl_cnode_t* head, * tail; hcl_oow_t count; hcl_loc_t loc; int fv, concode; @@ -551,6 +551,7 @@ static HCL_INLINE hcl_cnode_t* leave_list (hcl_t* hcl, hcl_loc_t* list_loc, int* rstl = hcl->c->r.st; /* get the stack top */ head = rstl->head; + tail = rstl->tail; count = rstl->count; fv = rstl->flagv; loc = rstl->loc; @@ -707,8 +708,21 @@ static HCL_INLINE hcl_cnode_t* leave_list (hcl_t* hcl, hcl_loc_t* list_loc, int* 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); +/* TODO: support multiple operators and operands .. like 1 + 2 - 3 +currently can_binop_list() disallows more operators. +but the check isn't complemete if more operands are added without an operator e.g. (1 + 2 3) +*/ + /*HCL_ASSERT (hcl, count == 3);*/ + if (count != 3) + { + /* Currently, the implementation supports two operands and a single binop in an expression. + * If the implementation is enhanced to support more than one binop and more operands, + * this check must be removed. */ + /* TODO: support more than two operands */ + hcl_setsynerrbfmt (hcl, HCL_SYNERR_ARGFLOOD, HCL_CNODE_GET_LOC(tail), HCL_CNODE_GET_TOK(tail), "too many operands"); + if (head) hcl_freecnode (hcl, head); + return HCL_NULL; + } HCL_CNODE_CONS_CDR(head) = HCL_CNODE_CONS_CDR(binop); HCL_CNODE_CONS_CDR(binop) = head; @@ -1542,9 +1556,12 @@ static int feed_process_token (hcl_t* hcl) } #endif frd->obj = leave_list(hcl, &frd->list_loc, &frd->flagv, &oldflagv); - frd->level--; - frd->flagv |= AT_BEGINNING; - list_loc = &frd->list_loc; + if (HCL_LIKELY(frd->obj)) + { + frd->level--; + frd->flagv |= AT_BEGINNING; + list_loc = &frd->list_loc; + } break; } @@ -2104,7 +2121,16 @@ static int flx_backslashed (hcl_t* hcl, hcl_ooci_t c) static int flx_comment (hcl_t* hcl, hcl_ooci_t c) { - if (is_linebreak(c)) FEED_CONTINUE (hcl, HCL_FLX_START); + if (is_linebreak(c)) + { + FEED_CONTINUE (hcl, HCL_FLX_START); + /* don't consume the line break together with the comment text + * if a comment text is located at the back of the line in the + * LANG_ENABLE_EOL mode. + * TODO: Consider removing this check because not consuming it + * in another mode doesn't cause a problem. */ + if ((hcl->option.trait & HCL_TRAIT_LANG_ENABLE_EOL)) return 0; /* not consumed */ + } return 1; /* consumed */ } diff --git a/t/Makefile.am b/t/Makefile.am index 2485e79..3a009e2 100644 --- a/t/Makefile.am +++ b/t/Makefile.am @@ -14,7 +14,6 @@ check_ERRORS = \ call-5001.err \ class-5001.err \ do-5001.err \ - do-5002.err \ feed-5001.err \ mlist-5001.err \ var-5001.err \ diff --git a/t/Makefile.in b/t/Makefile.in index e95b562..aca5de1 100644 --- a/t/Makefile.in +++ b/t/Makefile.in @@ -486,7 +486,6 @@ check_ERRORS = \ call-5001.err \ class-5001.err \ do-5001.err \ - do-5002.err \ feed-5001.err \ mlist-5001.err \ var-5001.err \ diff --git a/t/do-5001.err b/t/do-5001.err index ec5bd43..de68cc4 100644 --- a/t/do-5001.err +++ b/t/do-5001.err @@ -1,3 +1,13 @@ ## if `do` is not enclosed in `( )`, variable declaration is prohibited do { | k | set k 10 }; do | k | {set k 10;}; ##ERROR: syntax error - variable declaration disallowed + +--- + +## if `do` is not enclosed in `( )`, it supports only the limited number of expressions. + +do ; ## this is ok + +do 1; ## this is ok + +do { set k 10; printf "k=%d\n" k; } { set k 20; printf "k=%d\n" k; }; ##ERROR: syntax error - more than one expression after do diff --git a/t/do-5002.err b/t/do-5002.err deleted file mode 100644 index 928cdd7..0000000 --- a/t/do-5002.err +++ /dev/null @@ -1,8 +0,0 @@ -## if `do` is not enclosed in `( )`, it supports only the limited number of expressions. - -do ; ## this is ok - -do 1; ## this is ok - -do { set k 10; printf "k=%d\n" k; } ##ERROR: syntax error - more than one expression after do - { set k 20; printf "k=%d\n" k; }; diff --git a/t/feed-5001.err b/t/feed-5001.err index 6d70e01..89b00d2 100644 --- a/t/feed-5001.err +++ b/t/feed-5001.err @@ -86,3 +86,7 @@ defun :: fun1() { ##ERROR: syntax error - function name not symbol in defun defun :* fun1() { ##ERROR: syntax error - function name not symbol in defun return 10; }; + +--- + +(10 + 20 30) ##ERROR: syntax error - too many operands diff --git a/t/fun-01.hcl b/t/fun-01.hcl index 7bb3e99..802b400 100644 --- a/t/fun-01.hcl +++ b/t/fun-01.hcl @@ -23,8 +23,7 @@ defun mkfun(t) { defun mkfund(t) { return {fun(c) { return (fun(d) { - ##return (d + c t) ## this causes assertion failure. - return (d + c t) + return (+ d c t) }) }} } @@ -47,10 +46,8 @@ if (k = 50) { }; k := { - ## the return value of this expression is ignored - (mkfun 20) 30 ## having comment here cause an issue... - ## the return value of this expression is the return value of the block expression - (mkfun 20) 40 + (mkfun 20) 30 ## the return value of this expression is ignored + (mkfun 20) 40 ## the return value of this expression is the return value of the block expression } if (k = 60) { printf "OK - %d\n" k