diff --git a/README.md b/README.md index 7238cd2..7b7effe 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ A HCL program is composed of expressions. - do - elif - else +- fun - if - lambda - or @@ -30,7 +31,7 @@ A HCL program is composed of expressions. ``` do; do 10; -do { | k | set k 20; printf "k=%d\n" k }; +do { | k | set k 20; printf "k=%d\n" k; }; ``` ## Literals diff --git a/lib/comp.c b/lib/comp.c index fb9de33..7f7ae5f 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -1822,7 +1822,9 @@ static int compile_break (hcl_t* hcl, hcl_cnode_t* src) } } - hcl_setsynerrbfmt (hcl, HCL_SYNERR_BREAK, HCL_CNODE_GET_LOC(src), HCL_NULL, "%.*js outside loop", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); + hcl_setsynerrbfmt ( + hcl, HCL_SYNERR_BREAK, HCL_CNODE_GET_LOC(src), HCL_NULL, + "%.*js outside loop", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); return -1; inside_loop: @@ -1860,7 +1862,9 @@ inside_loop: /* this part must no be reached. if a loop control block is found, * there must exist a COP_POST_UNTIL_BODY or COP_POST_WHILE_BODY frame */ - hcl_setsynerrbfmt (hcl, HCL_SYNERR_INTERN, HCL_CNODE_GET_LOC(src), HCL_NULL, "internal error in compiling %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); + hcl_setsynerrbfmt ( + hcl, HCL_SYNERR_INTERN, HCL_CNODE_GET_LOC(src), HCL_NULL, + "internal error in compiling %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); return -1; } diff --git a/lib/read.c b/lib/read.c index 725e217..5634a57 100644 --- a/lib/read.c +++ b/lib/read.c @@ -1251,7 +1251,7 @@ static int feed_process_token (hcl_t* hcl) } concode = LIST_FLAG_GET_CONCODE(rstl->flagv); - if (concode != HCL_CONCODE_XLIST) /* TODO: handle MLIST as weel if the other part is implemented */ + if (concode != HCL_CONCODE_XLIST) /* TODO: handle MLIST as well if the other part is implemented */ { hcl_setsynerr (hcl, HCL_SYNERR_UNBALPBB, TOKEN_LOC(hcl), HCL_NULL); goto oops; @@ -1270,6 +1270,7 @@ static int feed_process_token (hcl_t* hcl) { int oldflagv; int concode; + hcl_rstl_t* rstl; if (frd->level <= 0) { @@ -1277,6 +1278,17 @@ static int feed_process_token (hcl_t* hcl) goto oops; } + if (TOKEN_TYPE(hcl) == HCL_TOK_RBRACE) + { + rstl = hcl->c->r.st; /* check the parent, not the current */ + if (rstl && (rstl->flagv & AUTO_FORGED)) + { + /* the auto-forged list has not been terminated. it must be terminated closed first */ + hcl_setsynerrbfmt (hcl, HCL_SYNERR_SEMICOLON, TOKEN_LOC(hcl), TOKEN_NAME(hcl), "semicolon expected"); + goto oops; + } + } + concode = LIST_FLAG_GET_CONCODE(frd->flagv); if (concode == HCL_CONCODE_XLIST && (frd->flagv & AUTO_FORGED)) { diff --git a/t/do-02.err b/t/do-02.err new file mode 100644 index 0000000..928cdd7 --- /dev/null +++ b/t/do-02.err @@ -0,0 +1,8 @@ +## 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-01.err b/t/feed-01.err new file mode 100644 index 0000000..f5d6623 --- /dev/null +++ b/t/feed-01.err @@ -0,0 +1,6 @@ +## the left brace opens a list explicitly and doesn't auto-forge a container list. +## so the semicolon after it is a redundant one. `do {};` would work because the semicolon +## terminates the auto-forged list of `do` and `{}`. +{ + printf "hello, world\n"; +}; ##ERROR: syntax error - unexpected semicolon diff --git a/t/var-03.err b/t/var-03.err new file mode 100644 index 0000000..3f9baee --- /dev/null +++ b/t/var-03.err @@ -0,0 +1,3 @@ +defclass A | a | { + | j | ##ERROR: syntax error - variable declaration disallowed in class init scope +};