implemented switch ... case .. default ..
This commit is contained in:
parent
846cbcf951
commit
fac4aa7af5
22
README.md
22
README.md
@ -476,7 +476,9 @@ The following words are reserved and cannot be used as a variable name, a parame
|
||||
- BEGIN
|
||||
- END
|
||||
- break
|
||||
- case
|
||||
- continue
|
||||
- default
|
||||
- delete
|
||||
- do
|
||||
- else
|
||||
@ -494,6 +496,7 @@ The following words are reserved and cannot be used as a variable name, a parame
|
||||
- printf
|
||||
- return
|
||||
- while
|
||||
- switch
|
||||
|
||||
However, some of these words not beginning with `@` can be used as normal names in the context of a module call. For example, `mymod::break`. In practice, the predefined names used for built-in commands, functions, and variables are treated as if they are reserved since you can't create another definition with the same name.
|
||||
|
||||
@ -633,7 +636,7 @@ BEGIN {
|
||||
|
||||
Hawk supports various control structures for flow control and iteration, similar to those found in awk.
|
||||
|
||||
The `if` statement in Hawk follows the same syntax as in awk and other programming languages. It allows you to execute a block of code conditionally based on a specified condition.
|
||||
The `if` statement follows the same syntax as in awk and other programming languages. It allows you to execute a block of code conditionally based on a specified condition.
|
||||
|
||||
```awk
|
||||
if (condition) {
|
||||
@ -645,7 +648,18 @@ if (condition) {
|
||||
}
|
||||
```
|
||||
|
||||
The `while` loop in Hawk is used to repeatedly execute a block of code as long as a specific condition is true.
|
||||
The `switch` statement allows the result of an expression to be tested against a list of values.
|
||||
```awk
|
||||
switch (expression) {
|
||||
case value:
|
||||
## statements
|
||||
...
|
||||
default:
|
||||
## statements
|
||||
}
|
||||
```
|
||||
|
||||
The `while` loop is used to repeatedly execute a block of code as long as a specific condition is true.
|
||||
```awk
|
||||
while (condition) {
|
||||
# statements
|
||||
@ -659,13 +673,13 @@ do {
|
||||
} while (condition)
|
||||
```
|
||||
|
||||
The `for` loop in Hawk follows the same syntax as in awk and allows you to iterate over a range of values or an array.
|
||||
The `for` loop follows the same syntax as in awk and allows you to iterate over a range of values or an array.
|
||||
```awk
|
||||
for (initialization; condition; increment/decrement) {
|
||||
## statements
|
||||
}
|
||||
```
|
||||
You can also use the for loop to iterate over the elements of an array:
|
||||
You can also use the `fo`r loop to iterate over the elements of an array:
|
||||
```awk
|
||||
for (index in array) {
|
||||
## statements using array[index]
|
||||
|
@ -539,6 +539,15 @@ static void print_usage (FILE* out, const hawk_bch_t* argv0, const hawk_bch_t* r
|
||||
{
|
||||
fprintf (out, " --%-18s on/off %s\n", opttab[j].name, opttab[j].desc);
|
||||
}
|
||||
|
||||
if (!real_argv0)
|
||||
{
|
||||
fprintf (out, "\n");
|
||||
fprintf (out, "Special mode switching options(must be specified first to take effect):\n");
|
||||
fprintf (out, " --hawk/--awk run in the hawk mode\n");
|
||||
fprintf (out, " --cut run in the cut mode\n");
|
||||
fprintf (out, " --sed run in the sed mode\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
@ -76,6 +76,7 @@ const hawk_ooch_t* hawk_dfl_errstr (hawk_errnum_t errnum)
|
||||
HAWK_T("left brace expected"),
|
||||
HAWK_T("left parenthesis expected"),
|
||||
HAWK_T("right parenthesis expected"),
|
||||
HAWK_T("right brace expected"),
|
||||
HAWK_T("right bracket expected"),
|
||||
HAWK_T("comma expected"),
|
||||
HAWK_T("semicolon expected"),
|
||||
@ -88,6 +89,8 @@ const hawk_ooch_t* hawk_dfl_errstr (hawk_errnum_t errnum)
|
||||
|
||||
HAWK_T("keyword 'function' expected"),
|
||||
HAWK_T("keyword 'while' expected"),
|
||||
HAWK_T("keyword 'case' expected"),
|
||||
HAWK_T("multiple 'default' labels"),
|
||||
HAWK_T("invalid assignment statement"),
|
||||
HAWK_T("identifier expected"),
|
||||
HAWK_T("not a valid function name"),
|
||||
|
@ -940,6 +940,7 @@ enum hawk_errnum_t
|
||||
HAWK_ELBRACE, /**< left brace expected */
|
||||
HAWK_ELPAREN, /**< left parenthesis expected */
|
||||
HAWK_ERPAREN, /**< right parenthesis expected */
|
||||
HAWK_ERBRACE, /**< right brace expected */
|
||||
HAWK_ERBRACK, /**< right bracket expected */
|
||||
HAWK_ECOMMA, /**< comma expected */
|
||||
HAWK_ESCOLON, /**< semicolon expected */
|
||||
@ -952,6 +953,8 @@ enum hawk_errnum_t
|
||||
|
||||
HAWK_EKWFNC, /**< keyword 'function' expected */
|
||||
HAWK_EKWWHL, /**< keyword 'while' expected */
|
||||
HAWK_EKWCASE, /**< keyword 'case' expected */
|
||||
HAWK_EMULDFL, /**< multiple 'default' labels */
|
||||
HAWK_EASSIGN, /**< assignment statement expected */
|
||||
HAWK_EIDENT, /**< identifier expected */
|
||||
HAWK_EFUNNAM, /**< not a valid function name */
|
||||
|
@ -278,6 +278,7 @@ struct hawk_t
|
||||
hawk_oow_t loop;
|
||||
hawk_oow_t expr; /* expression */
|
||||
hawk_oow_t incl;
|
||||
hawk_oow_t swtch; /* switch */
|
||||
} depth;
|
||||
|
||||
/* current pragma values */
|
||||
|
@ -398,6 +398,8 @@ enum hawk_nde_type_t
|
||||
/* statement */
|
||||
HAWK_NDE_BLK,
|
||||
HAWK_NDE_IF,
|
||||
HAWK_NDE_SWITCH,
|
||||
HAWK_NDE_CASE,
|
||||
HAWK_NDE_WHILE,
|
||||
HAWK_NDE_DOWHILE,
|
||||
HAWK_NDE_FOR,
|
||||
|
@ -41,7 +41,9 @@ enum hawk_kwid_t
|
||||
HAWK_KWID_BEGIN,
|
||||
HAWK_KWID_END,
|
||||
HAWK_KWID_BREAK,
|
||||
HAWK_KWID_CASE,
|
||||
HAWK_KWID_CONTINUE,
|
||||
HAWK_KWID_DEFAULT,
|
||||
HAWK_KWID_DELETE,
|
||||
HAWK_KWID_DO,
|
||||
HAWK_KWID_ELSE,
|
||||
@ -58,6 +60,7 @@ enum hawk_kwid_t
|
||||
HAWK_KWID_PRINT,
|
||||
HAWK_KWID_PRINTF,
|
||||
HAWK_KWID_RETURN,
|
||||
HAWK_KWID_SWITCH,
|
||||
HAWK_KWID_WHILE
|
||||
};
|
||||
|
||||
|
288
lib/parse.c
288
lib/parse.c
@ -35,10 +35,13 @@
|
||||
#define FMT_EKWFNC HAWK_T("keyword 'function' expected in place of '%.*js'")
|
||||
#define FMT_EKWIN HAWK_T("keyword 'in' expected in place of '%.*js'")
|
||||
#define FMT_EKWWHL HAWK_T("keyword 'while' expected in place of '%.*js'")
|
||||
#define FMT_EKWCASE HAWK_T("keyword 'case' expected in place of '%.*js'")
|
||||
#define FMT_EMULDFL HAWK_T("multiple '%.*js' labels")
|
||||
#define FMT_ELBRACE HAWK_T("left brace expected in place of '%.*js'")
|
||||
#define FMT_ELPAREN HAWK_T("left parenthesis expected in place of '%.*js'")
|
||||
#define FMT_ENOENT_GBL_HS HAWK_T("no such global variable - %.*hs")
|
||||
#define FMT_ENOENT_GBL_LS HAWK_T("no such global variable - %.*ls")
|
||||
#define FMT_ERBRACE HAWK_T("right brace expected in place of '%.*js'")
|
||||
#define FMT_ERBRACK HAWK_T("right bracket expected in place of '%.*js'")
|
||||
#define FMT_ERPAREN HAWK_T("right parenthesis expected in place of '%.*js'")
|
||||
#define FMT_ESCOLON HAWK_T("semicolon expected in place of '%.*js'")
|
||||
@ -48,6 +51,8 @@
|
||||
|
||||
#define TOK_FLAGS_LPAREN_CLOSER (1 << 0)
|
||||
|
||||
#define PARSE_BLOCK_FLAG_IS_TOP (1 << 0)
|
||||
|
||||
enum tok_t
|
||||
{
|
||||
TOK_EOF,
|
||||
@ -140,6 +145,9 @@ enum tok_t
|
||||
TOK_WHILE,
|
||||
TOK_FOR,
|
||||
TOK_DO,
|
||||
TOK_SWITCH,
|
||||
TOK_CASE,
|
||||
TOK_DEFAULT,
|
||||
TOK_BREAK,
|
||||
TOK_CONTINUE,
|
||||
TOK_RETURN,
|
||||
@ -200,17 +208,15 @@ static int parse_progunit (hawk_t* hawk);
|
||||
static hawk_t* collect_globals (hawk_t* hawk);
|
||||
static void adjust_static_globals (hawk_t* hawk);
|
||||
static hawk_oow_t find_global (hawk_t* hawk, const hawk_oocs_t* name);
|
||||
static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int istop);
|
||||
static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int flags);
|
||||
|
||||
static hawk_nde_t* parse_function (hawk_t* hawk);
|
||||
static hawk_nde_t* parse_begin (hawk_t* hawk);
|
||||
static hawk_nde_t* parse_end (hawk_t* hawk);
|
||||
static hawk_chain_t* parse_action_block (hawk_t* hawk, hawk_nde_t* ptn, int blockless);
|
||||
|
||||
static hawk_nde_t* parse_block_dc (hawk_t* hawk, const hawk_loc_t* xloc, int istop);
|
||||
|
||||
static hawk_nde_t* parse_block_dc (hawk_t* hawk, const hawk_loc_t* xloc, int flags);
|
||||
static hawk_nde_t* parse_statement (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||
|
||||
static hawk_nde_t* parse_expr_withdc (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||
|
||||
static hawk_nde_t* parse_logical_or (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||
@ -233,6 +239,7 @@ static hawk_nde_t* parse_unary_exp (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||
static hawk_nde_t* parse_increment (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||
static hawk_nde_t* parse_primary (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||
static hawk_nde_t* parse_primary_ident (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||
static hawk_nde_t* parse_primary_literal (hawk_t* hawk, const hawk_loc_t* xloc);
|
||||
static hawk_nde_t* parse_hashidx (hawk_t* hawk, const hawk_oocs_t* name, const hawk_loc_t* xloc);
|
||||
|
||||
#define FNCALL_FLAG_NOARG (1 << 0) /* no argument */
|
||||
@ -281,7 +288,9 @@ static kwent_t kwtab[] =
|
||||
{ { HAWK_T("BEGIN"), 5 }, TOK_BEGIN, HAWK_PABLOCK },
|
||||
{ { HAWK_T("END"), 3 }, TOK_END, HAWK_PABLOCK },
|
||||
{ { HAWK_T("break"), 5 }, TOK_BREAK, 0 },
|
||||
{ { HAWK_T("case"), 4 }, TOK_CASE, 0 },
|
||||
{ { HAWK_T("continue"), 8 }, TOK_CONTINUE, 0 },
|
||||
{ { HAWK_T("default"), 7 }, TOK_DEFAULT, 0 },
|
||||
{ { HAWK_T("delete"), 6 }, TOK_DELETE, 0 },
|
||||
{ { HAWK_T("do"), 2 }, TOK_DO, 0 },
|
||||
{ { HAWK_T("else"), 4 }, TOK_ELSE, 0 },
|
||||
@ -298,6 +307,7 @@ static kwent_t kwtab[] =
|
||||
{ { HAWK_T("print"), 5 }, TOK_PRINT, HAWK_RIO },
|
||||
{ { HAWK_T("printf"), 6 }, TOK_PRINTF, HAWK_RIO },
|
||||
{ { HAWK_T("return"), 6 }, TOK_RETURN, 0 },
|
||||
{ { HAWK_T("switch"), 6 }, TOK_SWITCH, 0 },
|
||||
{ { HAWK_T("while"), 5 }, TOK_WHILE, 0 }
|
||||
};
|
||||
|
||||
@ -1665,7 +1675,7 @@ static hawk_chain_t* parse_action_block (hawk_t* hawk, hawk_nde_t* ptn, int bloc
|
||||
return chain;
|
||||
}
|
||||
|
||||
static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
||||
static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int flags)
|
||||
{
|
||||
hawk_nde_t* head, * curr, * nde;
|
||||
hawk_nde_blk_t* block;
|
||||
@ -1715,7 +1725,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
if (collect_locals(hawk, nlcls_outer, istop) == HAWK_NULL)
|
||||
if (collect_locals(hawk, nlcls_outer, flags) == HAWK_NULL)
|
||||
{
|
||||
hawk_arr_delete (hawk->parse.lcls, nlcls_outer, HAWK_ARR_SIZE(hawk->parse.lcls) - nlcls_outer);
|
||||
return HAWK_NULL;
|
||||
@ -1761,8 +1771,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
||||
{
|
||||
int once;
|
||||
|
||||
if (hawk->opt.depth.s.incl > 0 &&
|
||||
hawk->parse.depth.incl >= hawk->opt.depth.s.incl)
|
||||
if (hawk->opt.depth.s.incl > 0 && hawk->parse.depth.incl >= hawk->opt.depth.s.incl)
|
||||
{
|
||||
hawk_seterrnum(hawk, &hawk->ptok.loc, HAWK_EINCLTD);
|
||||
return HAWK_NULL;
|
||||
@ -1845,7 +1854,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
||||
and merged to top-level block */
|
||||
|
||||
/* migrate all block-local variables to the outermost block */
|
||||
if (istop)
|
||||
if (flags & PARSE_BLOCK_FLAG_IS_TOP)
|
||||
{
|
||||
HAWK_ASSERT (nlcls_outer == 0 && nlcls_max == 0);
|
||||
block->nlcls = hawk->parse.nlcls_max - nlcls_outer;
|
||||
@ -1863,7 +1872,7 @@ static hawk_nde_t* parse_block (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
||||
return (hawk_nde_t*)block;
|
||||
}
|
||||
|
||||
static hawk_nde_t* parse_block_dc (hawk_t* hawk, const hawk_loc_t* xloc, int istop)
|
||||
static hawk_nde_t* parse_block_dc (hawk_t* hawk, const hawk_loc_t* xloc, int flags)
|
||||
{
|
||||
hawk_nde_t* nde;
|
||||
|
||||
@ -1876,7 +1885,7 @@ static hawk_nde_t* parse_block_dc (hawk_t* hawk, const hawk_loc_t* xloc, int ist
|
||||
}
|
||||
|
||||
hawk->parse.depth.block++;
|
||||
nde = parse_block(hawk, xloc, istop);
|
||||
nde = parse_block(hawk, xloc, flags);
|
||||
hawk->parse.depth.block--;
|
||||
|
||||
return nde;
|
||||
@ -2330,7 +2339,7 @@ static hawk_t* collect_globals (hawk_t* hawk)
|
||||
return hawk;
|
||||
}
|
||||
|
||||
static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int istop)
|
||||
static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int flags)
|
||||
{
|
||||
if (MATCH(hawk,TOK_NEWLINE))
|
||||
{
|
||||
@ -2361,7 +2370,7 @@ static hawk_t* collect_locals (hawk_t* hawk, hawk_oow_t nlcls, int istop)
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
if (istop)
|
||||
if (flags & PARSE_BLOCK_FLAG_IS_TOP)
|
||||
{
|
||||
/* check if it conflicts with a parameter name.
|
||||
* the first level declaration is treated as the same
|
||||
@ -2525,6 +2534,214 @@ oops:
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
static hawk_nde_case_t* alloc_nde_case (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||
{
|
||||
hawk_nde_case_t* nde;
|
||||
|
||||
nde = (hawk_nde_case_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
|
||||
if (HAWK_UNLIKELY(!nde))
|
||||
{
|
||||
ADJERR_LOC(hawk, xloc);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
nde->type = HAWK_NDE_CASE;
|
||||
nde->loc = *xloc;
|
||||
nde->val = HAWK_NULL;
|
||||
nde->action = HAWK_NULL;
|
||||
|
||||
return nde;
|
||||
|
||||
oops:
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
static hawk_nde_t* parse_switch (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||
{
|
||||
hawk_nde_switch_t* nde;
|
||||
hawk_nde_t* test = HAWK_NULL; /* test to switch */
|
||||
hawk_nde_t* case_val = HAWK_NULL; /* value after case */
|
||||
hawk_nde_t* case_first = HAWK_NULL;
|
||||
hawk_nde_t* case_last = HAWK_NULL;
|
||||
hawk_nde_t* default_part = HAWK_NULL;
|
||||
hawk_loc_t eloc;
|
||||
|
||||
if (!MATCH(hawk,TOK_LPAREN))
|
||||
{
|
||||
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_ELPAREN, FMT_ELPAREN, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||
return HAWK_NULL;
|
||||
}
|
||||
if (get_token(hawk) <= -1) return HAWK_NULL;
|
||||
|
||||
eloc = hawk->tok.loc;
|
||||
test = parse_expr_withdc(hawk, &eloc);
|
||||
if (HAWK_UNLIKELY(!test)) goto oops;
|
||||
|
||||
if (!MATCH(hawk,TOK_RPAREN))
|
||||
{
|
||||
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_ERPAREN, FMT_ERPAREN, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
|
||||
while (MATCH(hawk,TOK_NEWLINE))
|
||||
{
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
}
|
||||
if (!MATCH(hawk,TOK_LBRACE))
|
||||
{
|
||||
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_ELBRACE, FMT_ELBRACE, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
|
||||
while (!MATCH(hawk, TOK_RBRACE))
|
||||
{
|
||||
while (MATCH(hawk,TOK_NEWLINE))
|
||||
{
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
}
|
||||
|
||||
if (MATCH(hawk, TOK_CASE) || MATCH(hawk, TOK_DEFAULT))
|
||||
{
|
||||
hawk_nde_case_t* vv;
|
||||
hawk_nde_t* action_first = HAWK_NULL;
|
||||
hawk_nde_t* action_last = HAWK_NULL;
|
||||
|
||||
if (MATCH(hawk, TOK_CASE))
|
||||
{
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
eloc = hawk->tok.loc;
|
||||
case_val = parse_primary_literal(hawk, &eloc);
|
||||
if (HAWK_UNLIKELY(!case_val)) goto oops;
|
||||
}
|
||||
else /* MATCH(hawk, TOK_DEFAULT) */
|
||||
{
|
||||
if (default_part)
|
||||
{
|
||||
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_EMULDFL, FMT_EMULDFL, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||
goto oops;
|
||||
}
|
||||
case_val = HAWK_NULL;
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
}
|
||||
|
||||
if (!MATCH(hawk, TOK_COLON))
|
||||
{
|
||||
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_ECOLON, FMT_ECOLON, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||
goto oops;
|
||||
}
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
|
||||
while (MATCH(hawk,TOK_NEWLINE))
|
||||
{
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
}
|
||||
|
||||
while (!MATCH(hawk, TOK_CASE) && !MATCH(hawk, TOK_DEFAULT) && !MATCH(hawk, TOK_RBRACE))
|
||||
{
|
||||
hawk_nde_t* v;
|
||||
|
||||
eloc = hawk->tok.loc;
|
||||
hawk->parse.depth.swtch++;
|
||||
v = parse_statement(hawk, &eloc);
|
||||
hawk->parse.depth.swtch--;
|
||||
if (!v) {
|
||||
if (action_first) hawk_clrpt(hawk, action_first);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (!action_first)
|
||||
{
|
||||
action_first = v;
|
||||
action_last = v;
|
||||
}
|
||||
else if (v->type == HAWK_NDE_NULL && v->type == action_last->type)
|
||||
{
|
||||
/* skip a successive null statement */
|
||||
hawk_freemem(hawk, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
action_last->next = v;
|
||||
action_last = v;
|
||||
}
|
||||
|
||||
while (MATCH(hawk,TOK_NEWLINE))
|
||||
{
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
}
|
||||
}
|
||||
|
||||
vv = alloc_nde_case(hawk, &eloc);
|
||||
if (!vv)
|
||||
{
|
||||
if (action_first) hawk_clrpt(hawk, action_first);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
vv->val = case_val;
|
||||
vv->action = action_first;
|
||||
|
||||
if (!case_val) default_part = (hawk_nde_t*)vv;
|
||||
else case_val = HAWK_NULL;
|
||||
|
||||
if (!case_first)
|
||||
{
|
||||
case_first = (hawk_nde_t*)vv;
|
||||
case_last = (hawk_nde_t*)vv;
|
||||
}
|
||||
else
|
||||
{
|
||||
case_last->next = (hawk_nde_t*)vv;
|
||||
case_last = (hawk_nde_t*)vv;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_EKWCASE, FMT_EKWCASE, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||
goto oops;
|
||||
}
|
||||
}
|
||||
|
||||
while (MATCH(hawk,TOK_NEWLINE))
|
||||
{
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
}
|
||||
if (!MATCH(hawk, TOK_RBRACE))
|
||||
{
|
||||
hawk_seterrfmt(hawk, &hawk->tok.loc, HAWK_ERBRACE, FMT_ERBRACE, HAWK_OOECS_LEN(hawk->tok.name), HAWK_OOECS_PTR(hawk->tok.name));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (get_token(hawk) <= -1) goto oops;
|
||||
|
||||
|
||||
nde = (hawk_nde_switch_t*)hawk_callocmem(hawk, HAWK_SIZEOF(*nde));
|
||||
if (HAWK_UNLIKELY(!nde))
|
||||
{
|
||||
ADJERR_LOC(hawk, xloc);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
nde->type = HAWK_NDE_SWITCH;
|
||||
nde->loc = *xloc;
|
||||
nde->test = test;
|
||||
nde->case_part = case_first;
|
||||
nde->default_part = default_part;
|
||||
|
||||
return (hawk_nde_t*)nde;
|
||||
|
||||
oops:
|
||||
if (case_val) hawk_clrpt(hawk, case_val);
|
||||
if (case_first) hawk_clrpt(hawk, case_first);
|
||||
/*if (default_part) hawk_clrpt(hawk, default_part); no need to crear it as it is in the case_first chanin */
|
||||
if (test) hawk_clrpt(hawk, test);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
static hawk_nde_t* parse_while (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||
{
|
||||
hawk_nde_t* test = HAWK_NULL;
|
||||
@ -2676,7 +2893,6 @@ static hawk_nde_t* parse_for (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||
{
|
||||
{
|
||||
hawk_loc_t eloc;
|
||||
|
||||
eloc = hawk->tok.loc;
|
||||
incr = parse_expr_withdc(hawk, &eloc);
|
||||
if (HAWK_UNLIKELY(!incr)) goto oops;
|
||||
@ -2791,7 +3007,7 @@ static hawk_nde_t* parse_break (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||
hawk_nde_break_t* nde;
|
||||
|
||||
HAWK_ASSERT (hawk->ptok.type == TOK_BREAK);
|
||||
if (hawk->parse.depth.loop <= 0)
|
||||
if (hawk->parse.depth.loop <= 0 && hawk->parse.depth.swtch <= 0)
|
||||
{
|
||||
hawk_seterrnum(hawk, xloc, HAWK_EBREAK);
|
||||
return HAWK_NULL;
|
||||
@ -3256,8 +3472,7 @@ oops:
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
static hawk_nde_t* parse_statement_nb (
|
||||
hawk_t* hawk, const hawk_loc_t* xloc)
|
||||
static hawk_nde_t* parse_statement_nb (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||
{
|
||||
/* parse a non-block statement */
|
||||
hawk_nde_t* nde;
|
||||
@ -3268,6 +3483,11 @@ static hawk_nde_t* parse_statement_nb (
|
||||
if (get_token(hawk) <= -1) return HAWK_NULL;
|
||||
return parse_if(hawk, xloc);
|
||||
}
|
||||
else if (MATCH(hawk, TOK_SWITCH))
|
||||
{
|
||||
if (get_token(hawk) <= -1) return HAWK_NULL;
|
||||
return parse_switch(hawk, xloc);
|
||||
}
|
||||
else if (MATCH(hawk,TOK_WHILE))
|
||||
{
|
||||
if (get_token(hawk) <= -1) return HAWK_NULL;
|
||||
@ -3485,7 +3705,6 @@ static hawk_nde_t* parse_expr_basic (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||
nde = parse_logical_or(hawk, xloc);
|
||||
if (nde == HAWK_NULL) return HAWK_NULL;
|
||||
|
||||
if (MATCH(hawk,TOK_QUEST))
|
||||
if (MATCH(hawk,TOK_QUEST))
|
||||
{
|
||||
hawk_loc_t eloc;
|
||||
@ -5200,6 +5419,39 @@ oops:
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
static hawk_nde_t* parse_primary_literal (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||
{
|
||||
switch (hawk->tok.type)
|
||||
{
|
||||
case TOK_CHAR:
|
||||
return parse_primary_char(hawk, xloc);
|
||||
|
||||
case TOK_BCHR:
|
||||
return parse_primary_bchr(hawk, xloc);
|
||||
|
||||
case TOK_INT:
|
||||
return parse_primary_int(hawk, xloc);
|
||||
|
||||
case TOK_FLT:
|
||||
return parse_primary_flt(hawk, xloc);
|
||||
|
||||
case TOK_STR:
|
||||
return parse_primary_str(hawk, xloc);
|
||||
|
||||
case TOK_MBS:
|
||||
return parse_primary_mbs(hawk, xloc);
|
||||
|
||||
default:
|
||||
{
|
||||
hawk_tok_t* xtok;
|
||||
|
||||
xtok = MATCH(hawk,TOK_NEWLINE)? &hawk->ptok: &hawk->tok;
|
||||
hawk_seterrfmt(hawk, &xtok->loc, HAWK_EEXPRNR, HAWK_T("literal expression not recognized around '%.*js'"), HAWK_OOECS_LEN(xtok->name), HAWK_OOECS_PTR(xtok->name));
|
||||
return HAWK_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static hawk_nde_t* parse_primary_nopipe (hawk_t* hawk, const hawk_loc_t* xloc)
|
||||
{
|
||||
switch (hawk->tok.type)
|
||||
|
193
lib/run.c
193
lib/run.c
@ -78,7 +78,7 @@ static int init_rtx (hawk_rtx_t* rtx, hawk_t* hawk, hawk_rio_cbs_t* rio);
|
||||
static void fini_rtx (hawk_rtx_t* rtx, int fini_globals);
|
||||
|
||||
static int init_globals (hawk_rtx_t* rtx);
|
||||
static void refdown_globals (hawk_rtx_t* run, int pop);
|
||||
static void refdown_globals (hawk_rtx_t* rtx, int pop);
|
||||
|
||||
static int run_pblocks (hawk_rtx_t* rtx);
|
||||
static int run_pblock_chain (hawk_rtx_t* rtx, hawk_chain_t* cha);
|
||||
@ -86,6 +86,7 @@ static int run_pblock (hawk_rtx_t* rtx, hawk_chain_t* cha, hawk_oow_t bno);
|
||||
static int run_block (hawk_rtx_t* rtx, hawk_nde_blk_t* nde);
|
||||
static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde);
|
||||
static int run_if (hawk_rtx_t* rtx, hawk_nde_if_t* nde);
|
||||
static int run_switch (hawk_rtx_t* rtx, hawk_nde_switch_t* nde);
|
||||
static int run_while (hawk_rtx_t* rtx, hawk_nde_while_t* nde);
|
||||
static int run_for (hawk_rtx_t* rtx, hawk_nde_for_t* nde);
|
||||
static int run_forin (hawk_rtx_t* rtx, hawk_nde_forin_t* nde);
|
||||
@ -1979,7 +1980,7 @@ static int run_pblocks (hawk_rtx_t* rtx)
|
||||
{
|
||||
int n;
|
||||
|
||||
#define ADJUST_ERROR(run) \
|
||||
#define ADJUST_ERROR(rtx) \
|
||||
if (rtx->hawk->tree.chain != HAWK_NULL) \
|
||||
{ \
|
||||
if (rtx->hawk->tree.chain->pattern != HAWK_NULL) \
|
||||
@ -1989,7 +1990,7 @@ static int run_pblocks (hawk_rtx_t* rtx)
|
||||
} \
|
||||
else if (rtx->hawk->tree.end != HAWK_NULL) \
|
||||
{ \
|
||||
ADJERR_LOC (run, &rtx->hawk->tree.end->loc); \
|
||||
ADJERR_LOC(rtx, &rtx->hawk->tree.end->loc); \
|
||||
}
|
||||
|
||||
rtx->inrec.buf_pos = 0;
|
||||
@ -2279,6 +2280,17 @@ static int run_statement (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
xret = run_if(rtx, (hawk_nde_if_t*)nde);
|
||||
break;
|
||||
|
||||
case HAWK_NDE_SWITCH:
|
||||
xret = run_switch(rtx, (hawk_nde_switch_t*)nde);
|
||||
break;
|
||||
|
||||
case HAWK_NDE_CASE:
|
||||
/* this must never happen - run_swtich must handle this part */
|
||||
HAWK_ASSERT (!"should never happen - HAWK_NDE_CASE must not be fed to run_statement");
|
||||
hawk_rtx_seterrnum(rtx, &nde->loc, HAWK_EINTERN);
|
||||
xret = -1;
|
||||
break;
|
||||
|
||||
case HAWK_NDE_WHILE:
|
||||
case HAWK_NDE_DOWHILE:
|
||||
xret = run_while(rtx, (hawk_nde_while_t*)nde);
|
||||
@ -2378,6 +2390,119 @@ static int run_if (hawk_rtx_t* rtx, hawk_nde_if_t* nde)
|
||||
return n;
|
||||
}
|
||||
|
||||
static int run_switch (hawk_rtx_t* rtx, hawk_nde_switch_t* nde)
|
||||
{
|
||||
hawk_val_t* test;
|
||||
hawk_val_t* v;
|
||||
hawk_nde_case_t* case_part;
|
||||
hawk_nde_case_t* default_part;
|
||||
int eval_true = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* the test expression for the if statement cannot have
|
||||
* chained expressions. this should not be allowed by the
|
||||
* parser first of all */
|
||||
HAWK_ASSERT (nde->test->next == HAWK_NULL);
|
||||
|
||||
test = eval_expression(rtx, nde->test);
|
||||
if (HAWK_UNLIKELY(!test)) return -1;
|
||||
|
||||
hawk_rtx_refupval(rtx, test);
|
||||
|
||||
HAWK_ASSERT(nde->type == HAWK_NDE_CASE);
|
||||
case_part = (hawk_nde_case_t*)nde->case_part;
|
||||
default_part = (hawk_nde_case_t*)nde->default_part;
|
||||
|
||||
while (case_part)
|
||||
{
|
||||
int x;
|
||||
|
||||
if (eval_true) goto skip_eval;
|
||||
if (case_part->val) // skip the default part.
|
||||
{
|
||||
v = eval_expression(rtx, case_part->val);
|
||||
hawk_rtx_refupval(rtx, v);
|
||||
x = hawk_rtx_cmpval(rtx, test, v, &ret);
|
||||
hawk_rtx_refdownval(rtx, v);
|
||||
if (x <= -1)
|
||||
{
|
||||
hawk_rtx_refdownval(rtx, test);
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0)
|
||||
{
|
||||
skip_eval:
|
||||
eval_true = 1;
|
||||
if (case_part->action)
|
||||
{
|
||||
hawk_nde_t* action;
|
||||
|
||||
action = case_part->action;
|
||||
do
|
||||
{
|
||||
if (run_statement(rtx, action) <= -1)
|
||||
{
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (rtx->exit_level == EXIT_BREAK) /* if 'break' has been executed */
|
||||
{
|
||||
rtx->exit_level = EXIT_NONE;
|
||||
goto done;
|
||||
}
|
||||
else if (rtx->exit_level != EXIT_NONE) goto done;
|
||||
|
||||
action = action->next;
|
||||
}
|
||||
while(action);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case_part = (hawk_nde_case_t*)case_part->next;
|
||||
}
|
||||
|
||||
if (!eval_true && default_part)
|
||||
{
|
||||
case_part = default_part;
|
||||
do
|
||||
{
|
||||
if (case_part->action)
|
||||
{
|
||||
hawk_nde_t* action;
|
||||
|
||||
action = case_part->action;
|
||||
do
|
||||
{
|
||||
if (run_statement(rtx, action) <= -1)
|
||||
{
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (rtx->exit_level == EXIT_BREAK) /* if 'break' has been executed */
|
||||
{
|
||||
rtx->exit_level = EXIT_NONE;
|
||||
goto done;
|
||||
}
|
||||
else if (rtx->exit_level != EXIT_NONE) goto done;
|
||||
|
||||
action = action->next;
|
||||
}
|
||||
while (action);
|
||||
}
|
||||
case_part = (hawk_nde_case_t*)case_part->next;
|
||||
}
|
||||
while (case_part);
|
||||
}
|
||||
|
||||
done:
|
||||
hawk_rtx_refdownval(rtx, test);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int run_while (hawk_rtx_t* rtx, hawk_nde_while_t* nde)
|
||||
{
|
||||
hawk_val_t* test;
|
||||
@ -2749,9 +2874,9 @@ done1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int run_break (hawk_rtx_t* run, hawk_nde_break_t* nde)
|
||||
static int run_break (hawk_rtx_t* rtx, hawk_nde_break_t* nde)
|
||||
{
|
||||
run->exit_level = EXIT_BREAK;
|
||||
rtx->exit_level = EXIT_BREAK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -6200,60 +6325,60 @@ static hawk_val_t* eval_binop_match0 (
|
||||
return res;
|
||||
}
|
||||
|
||||
static hawk_val_t* eval_binop_ma (hawk_rtx_t* run, hawk_nde_t* left, hawk_nde_t* right)
|
||||
static hawk_val_t* eval_binop_ma (hawk_rtx_t* rtx, hawk_nde_t* left, hawk_nde_t* right)
|
||||
{
|
||||
hawk_val_t* lv, * rv, * res;
|
||||
|
||||
HAWK_ASSERT (left->next == HAWK_NULL);
|
||||
HAWK_ASSERT (right->next == HAWK_NULL);
|
||||
|
||||
lv = eval_expression(run, left);
|
||||
lv = eval_expression(rtx, left);
|
||||
if (HAWK_UNLIKELY(!lv)) return HAWK_NULL;
|
||||
|
||||
hawk_rtx_refupval(run, lv);
|
||||
hawk_rtx_refupval(rtx, lv);
|
||||
|
||||
rv = eval_expression0(run, right);
|
||||
rv = eval_expression0(rtx, right);
|
||||
if (HAWK_UNLIKELY(!rv))
|
||||
{
|
||||
hawk_rtx_refdownval(run, lv);
|
||||
hawk_rtx_refdownval(rtx, lv);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
hawk_rtx_refupval(run, rv);
|
||||
hawk_rtx_refupval(rtx, rv);
|
||||
|
||||
res = eval_binop_match0(run, lv, rv, &left->loc, &right->loc, 1);
|
||||
res = eval_binop_match0(rtx, lv, rv, &left->loc, &right->loc, 1);
|
||||
|
||||
hawk_rtx_refdownval(run, rv);
|
||||
hawk_rtx_refdownval(run, lv);
|
||||
hawk_rtx_refdownval(rtx, rv);
|
||||
hawk_rtx_refdownval(rtx, lv);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static hawk_val_t* eval_binop_nm (hawk_rtx_t* run, hawk_nde_t* left, hawk_nde_t* right)
|
||||
static hawk_val_t* eval_binop_nm (hawk_rtx_t* rtx, hawk_nde_t* left, hawk_nde_t* right)
|
||||
{
|
||||
hawk_val_t* lv, * rv, * res;
|
||||
|
||||
HAWK_ASSERT (left->next == HAWK_NULL);
|
||||
HAWK_ASSERT (right->next == HAWK_NULL);
|
||||
|
||||
lv = eval_expression(run, left);
|
||||
lv = eval_expression(rtx, left);
|
||||
if (HAWK_UNLIKELY(!lv)) return HAWK_NULL;
|
||||
|
||||
hawk_rtx_refupval(run, lv);
|
||||
hawk_rtx_refupval(rtx, lv);
|
||||
|
||||
rv = eval_expression0(run, right);
|
||||
rv = eval_expression0(rtx, right);
|
||||
if (HAWK_UNLIKELY(!rv))
|
||||
{
|
||||
hawk_rtx_refdownval(run, lv);
|
||||
hawk_rtx_refdownval(rtx, lv);
|
||||
return HAWK_NULL;
|
||||
}
|
||||
|
||||
hawk_rtx_refupval(run, rv);
|
||||
hawk_rtx_refupval(rtx, rv);
|
||||
|
||||
res = eval_binop_match0(run, lv, rv, &left->loc, &right->loc, 0);
|
||||
res = eval_binop_match0(rtx, lv, rv, &left->loc, &right->loc, 0);
|
||||
|
||||
hawk_rtx_refdownval(run, rv);
|
||||
hawk_rtx_refdownval(run, lv);
|
||||
hawk_rtx_refdownval(rtx, rv);
|
||||
hawk_rtx_refdownval(rtx, lv);
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -6613,22 +6738,22 @@ static hawk_val_t* eval_incpst (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
return res;
|
||||
}
|
||||
|
||||
static hawk_val_t* eval_cnd (hawk_rtx_t* run, hawk_nde_t* nde)
|
||||
static hawk_val_t* eval_cnd (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
{
|
||||
hawk_val_t* tv, * v;
|
||||
hawk_nde_cnd_t* cnd = (hawk_nde_cnd_t*)nde;
|
||||
|
||||
HAWK_ASSERT (cnd->test->next == HAWK_NULL);
|
||||
|
||||
tv = eval_expression(run, cnd->test);
|
||||
tv = eval_expression(rtx, cnd->test);
|
||||
if (HAWK_UNLIKELY(!tv)) return HAWK_NULL;
|
||||
|
||||
hawk_rtx_refupval(run, tv);
|
||||
hawk_rtx_refupval(rtx, tv);
|
||||
|
||||
HAWK_ASSERT (cnd->left->next == HAWK_NULL && cnd->right->next == HAWK_NULL);
|
||||
v = (hawk_rtx_valtobool(run, tv))? eval_expression(run, cnd->left): eval_expression(run, cnd->right);
|
||||
v = (hawk_rtx_valtobool(rtx, tv))? eval_expression(rtx, cnd->left): eval_expression(rtx, cnd->right);
|
||||
|
||||
hawk_rtx_refdownval(run, tv);
|
||||
hawk_rtx_refdownval(rtx, tv);
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -7984,20 +8109,20 @@ static hawk_val_t* eval_getline (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
return ((hawk_nde_getline_t*)nde)->mbs? __eval_getbline(rtx, nde): __eval_getline(rtx, nde);
|
||||
}
|
||||
|
||||
static hawk_val_t* eval_print (hawk_rtx_t* run, hawk_nde_t* nde)
|
||||
static hawk_val_t* eval_print (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
{
|
||||
int n = run_print(run, (hawk_nde_print_t*)nde);
|
||||
int n = run_print(rtx, (hawk_nde_print_t*)nde);
|
||||
if (n == PRINT_IOERR) n = -1; /* let print return -1 */
|
||||
else if (n <= -1) return HAWK_NULL;
|
||||
return hawk_rtx_makeintval(run, n);
|
||||
return hawk_rtx_makeintval(rtx, n);
|
||||
}
|
||||
|
||||
static hawk_val_t* eval_printf (hawk_rtx_t* run, hawk_nde_t* nde)
|
||||
static hawk_val_t* eval_printf (hawk_rtx_t* rtx, hawk_nde_t* nde)
|
||||
{
|
||||
int n = run_printf(run, (hawk_nde_print_t*)nde);
|
||||
int n = run_printf(rtx, (hawk_nde_print_t*)nde);
|
||||
if (n == PRINT_IOERR) n = -1; /* let print return -1 */
|
||||
else if (n <= -1) return HAWK_NULL;
|
||||
return hawk_rtx_makeintval(run, n);
|
||||
return hawk_rtx_makeintval(rtx, n);
|
||||
}
|
||||
|
||||
static int read_record (hawk_rtx_t* rtx)
|
||||
|
@ -75,6 +75,8 @@ typedef struct hawk_nde_fncall_t hawk_nde_fncall_t;
|
||||
typedef struct hawk_nde_getline_t hawk_nde_getline_t;
|
||||
|
||||
typedef struct hawk_nde_if_t hawk_nde_if_t;
|
||||
typedef struct hawk_nde_switch_t hawk_nde_switch_t;
|
||||
typedef struct hawk_nde_case_t hawk_nde_case_t;
|
||||
typedef struct hawk_nde_while_t hawk_nde_while_t;
|
||||
typedef struct hawk_nde_for_t hawk_nde_for_t;
|
||||
typedef struct hawk_nde_forin_t hawk_nde_forin_t;
|
||||
@ -280,6 +282,23 @@ struct hawk_nde_if_t
|
||||
hawk_nde_t* else_part; /* optional */
|
||||
};
|
||||
|
||||
/* HAWK_NDE_SWITCH */
|
||||
struct hawk_nde_switch_t
|
||||
{
|
||||
HAWK_NDE_HDR;
|
||||
hawk_nde_t* test;
|
||||
hawk_nde_t* case_part; /* optional */
|
||||
hawk_nde_t* default_part; /* optional */
|
||||
};
|
||||
|
||||
/* HAWK_NDE_CASE */
|
||||
struct hawk_nde_case_t
|
||||
{
|
||||
HAWK_NDE_HDR;
|
||||
hawk_nde_t* val;
|
||||
hawk_nde_t* action;
|
||||
};
|
||||
|
||||
/* HAWK_NDE_WHILE, HAWK_NDE_DOWHILE */
|
||||
struct hawk_nde_while_t
|
||||
{
|
||||
|
64
lib/tree.c
64
lib/tree.c
@ -969,6 +969,49 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth)
|
||||
break;
|
||||
}
|
||||
|
||||
case HAWK_NDE_SWITCH:
|
||||
{
|
||||
hawk_nde_switch_t* px = (hawk_nde_switch_t*)p;
|
||||
|
||||
PRINT_TABS(hawk, depth);
|
||||
hawk_getkwname(hawk, HAWK_KWID_SWITCH, &kw);
|
||||
PUT_SRCSTRN(hawk, kw.ptr, kw.len);
|
||||
PUT_SRCSTR(hawk, HAWK_T(" ("));
|
||||
PRINT_EXPR(hawk, px->test);
|
||||
PUT_SRCSTR(hawk, HAWK_T(")"));
|
||||
PUT_NL(hawk);
|
||||
PRINT_TABS(hawk, depth);
|
||||
PUT_SRCSTR(hawk, HAWK_T("{"));
|
||||
PUT_NL(hawk);
|
||||
if (px->case_part) PRINT_STMTS(hawk, px->case_part, depth);
|
||||
/* default_part is one of the case_parts. no explicit printing is needed */
|
||||
/*if (px->default_part) PRINT_STMTS(hawk, px->default_part, depth);*/
|
||||
PUT_NL(hawk);
|
||||
PRINT_TABS(hawk, depth);
|
||||
PUT_SRCSTR(hawk, HAWK_T("}"));
|
||||
PUT_NL(hawk);
|
||||
break;
|
||||
}
|
||||
|
||||
case HAWK_NDE_CASE:
|
||||
{
|
||||
/* this is not a real statement and is subject to the owning switch statement. */
|
||||
hawk_nde_case_t* px = (hawk_nde_case_t*)p;
|
||||
|
||||
PRINT_TABS(hawk, depth);
|
||||
hawk_getkwname(hawk, (px->val? HAWK_KWID_CASE: HAWK_KWID_DEFAULT), &kw);
|
||||
PUT_SRCSTRN(hawk, kw.ptr, kw.len);
|
||||
if (px->val)
|
||||
{
|
||||
PUT_SRCSTR(hawk, HAWK_T(" "));
|
||||
PRINT_EXPR(hawk, px->val);
|
||||
}
|
||||
PUT_SRCSTR(hawk, HAWK_T(":"));
|
||||
PUT_NL(hawk);
|
||||
if (px->action) PRINT_STMTS(hawk, px->action, depth + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case HAWK_NDE_WHILE:
|
||||
{
|
||||
hawk_nde_while_t* px = (hawk_nde_while_t*)p;
|
||||
@ -988,6 +1031,7 @@ static int print_stmt (hawk_t* hawk, hawk_nde_t* p, int depth)
|
||||
{
|
||||
PRINT_STMTS(hawk, px->body, depth + 1);
|
||||
}
|
||||
PUT_NL(hawk);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1288,6 +1332,26 @@ void hawk_clrpt (hawk_t* hawk, hawk_nde_t* tree)
|
||||
break;
|
||||
}
|
||||
|
||||
case HAWK_NDE_SWITCH:
|
||||
{
|
||||
hawk_nde_switch_t* px = (hawk_nde_switch_t*)p;
|
||||
hawk_clrpt(hawk, px->test);
|
||||
if (px->case_part) hawk_clrpt(hawk, px->case_part);
|
||||
/* px->default_part is one of the case parts. explicit clean up isn't required */
|
||||
/*if (px->default_part) hawk_clrpt(hawk, px->default_part);*/
|
||||
hawk_freemem(hawk, p);
|
||||
break;
|
||||
}
|
||||
|
||||
case HAWK_NDE_CASE:
|
||||
{
|
||||
hawk_nde_case_t* px = (hawk_nde_case_t*)p;
|
||||
if (px->val) hawk_clrpt(hawk, px->val);
|
||||
if (px->action) hawk_clrpt(hawk, px->action);
|
||||
hawk_freemem(hawk, p);
|
||||
break;
|
||||
}
|
||||
|
||||
case HAWK_NDE_WHILE:
|
||||
case HAWK_NDE_DOWHILE:
|
||||
{
|
||||
|
108
t/h-002.hawk
108
t/h-002.hawk
@ -665,6 +665,29 @@ function main()
|
||||
f = test10
|
||||
tap_ensure (f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 55, @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
tap_ensure(test12(2,5), -3, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test12(3,5), 8, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
tap_ensure(test13(1), 1, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test13(2), 2, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test13(3), 3, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test13(4), 4, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test13(5), 5, @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test13(6), 1005, @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
tap_ensure(test14("hello"), "world", @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test14("donkey"), "rankey", @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test14("speed"), "unknown", @SCRIPTNAME, @SCRIPTLINE);
|
||||
|
||||
tap_ensure(test15("hello"), "world", @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test15("donkey"), "[rankey012]", @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test15("skunk"), "stinks", @SCRIPTNAME, @SCRIPTLINE);
|
||||
tap_ensure(test15("speed"), "unknown", @SCRIPTNAME, @SCRIPTLINE);
|
||||
}
|
||||
|
||||
tap_end ();
|
||||
}
|
||||
|
||||
@ -709,3 +732,88 @@ function test10(...) {
|
||||
function test11(...) {
|
||||
return (3 in @argv);
|
||||
}
|
||||
|
||||
function test12(...) {
|
||||
switch(@argv[0] * @argv[1]) {
|
||||
case 10:
|
||||
return @argv[0] - @argv[1];
|
||||
|
||||
default:
|
||||
return @argv[0] + @argv[1];
|
||||
}
|
||||
}
|
||||
|
||||
function test13(x) {
|
||||
@local a;
|
||||
|
||||
a = 0;
|
||||
|
||||
switch(x) {
|
||||
default:
|
||||
a = 1000;
|
||||
|
||||
case 5:
|
||||
a++;
|
||||
|
||||
case 4:
|
||||
a++;
|
||||
|
||||
case 3:
|
||||
a++;
|
||||
|
||||
case 2:
|
||||
a++;
|
||||
|
||||
case 1:
|
||||
a++;
|
||||
break;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
function test14(x) {
|
||||
switch(x) {
|
||||
case "hello":
|
||||
return "world";
|
||||
|
||||
case "donkey":
|
||||
return "rankey";
|
||||
|
||||
default:
|
||||
return "unknown";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test15(x) {
|
||||
@local a, i;
|
||||
|
||||
switch(x) {
|
||||
case "hello":
|
||||
a = "world";
|
||||
break;
|
||||
|
||||
case "donkey":
|
||||
{
|
||||
@local l;
|
||||
a = "rankey";
|
||||
l = length(a);
|
||||
for (i = 0; i < l; i++) {
|
||||
if (i == 3) break;
|
||||
a = sprintf("%s%d", a, i);
|
||||
}
|
||||
a = sprintf("[%s]", a);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (x == "skunk") a = "stinks";
|
||||
else a = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user