diff options
author | Charlie Brej <cbrej@cs.man.ac.uk> | 2009-10-04 17:36:22 +0100 |
---|---|---|
committer | root <cbrej@cs.man.ac.uk> | 2009-10-04 17:36:22 +0100 |
commit | 9ca46671bbb21ed3cd56becf555229d553bc6a56 (patch) | |
tree | 58dbb26ec2df4335c44c26a5e77dc6d0c8cc5e75 | |
parent | a29f25bc6c67e87f38f323e8739f06249205d766 (diff) |
[script] Add do-while loops
Format is:
do {operations} while (condition);
or
do operation; while (condition);
Like in C, the semicolon at the end is necessary.
-rw-r--r-- | src/plugins/splash/script/script-execute.c | 18 | ||||
-rw-r--r-- | src/plugins/splash/script/script-parse.c | 54 | ||||
-rw-r--r-- | src/plugins/splash/script/script.h | 1 |
3 files changed, 68 insertions, 5 deletions
diff --git a/src/plugins/splash/script/script-execute.c b/src/plugins/splash/script/script-execute.c index 0ab15cf4..161186f1 100644 --- a/src/plugins/splash/script/script-execute.c +++ b/src/plugins/splash/script/script-execute.c @@ -658,18 +658,26 @@ script_return_t script_execute (script_state_t *state, break; } + case SCRIPT_OP_TYPE_DO_WHILE: case SCRIPT_OP_TYPE_WHILE: case SCRIPT_OP_TYPE_FOR: { - script_obj_t *obj; + script_obj_t *obj = NULL; + bool cond = false; + if (op->type == SCRIPT_OP_TYPE_DO_WHILE) cond = true; while (1) { - obj = script_evaluate (state, op->data.cond_op.cond); - if (script_obj_as_bool (obj)) + if (!cond) + { + obj = script_evaluate (state, op->data.cond_op.cond); + cond = script_obj_as_bool (obj); + script_obj_unref (obj); + } + + if (cond) { script_obj_unref (reply.object); reply = script_execute (state, op->data.cond_op.op1); - script_obj_unref (obj); switch (reply.type) { case SCRIPT_RETURN_TYPE_NORMAL: @@ -693,9 +701,9 @@ script_return_t script_execute (script_state_t *state, } else { - script_obj_unref (obj); break; } + cond = false; } break; } diff --git a/src/plugins/splash/script/script-parse.c b/src/plugins/splash/script/script-parse.c index 8e9a3559..1e02ac5d 100644 --- a/src/plugins/splash/script/script-parse.c +++ b/src/plugins/splash/script/script-parse.c @@ -592,6 +592,57 @@ static script_op_t *script_parse_if_while (script_scan_t *scan) return op; } +static script_op_t *script_parse_do_while (script_scan_t *scan) +{ + script_scan_token_t *curtoken = script_scan_get_current_token (scan); + + if (!script_scan_token_is_identifier_of_value (curtoken, "do")) + return NULL; + script_debug_location_t location = curtoken->location; + curtoken = script_scan_get_next_token (scan); + script_op_t *cond_op = script_parse_op (scan); + curtoken = script_scan_get_current_token (scan); + + if (!script_scan_token_is_identifier_of_value (curtoken, "while")) + { + script_parse_error (&curtoken->location, + "Expected a 'while' after a 'do' block"); + return NULL; + } + curtoken = script_scan_get_next_token (scan); + + if (!script_scan_token_is_symbol_of_value (curtoken, '(')) + { + script_parse_error (&curtoken->location, + "Expected a '(' at the start of a do-while condition block"); + return NULL; + } + curtoken = script_scan_get_next_token (scan); + script_exp_t *cond = script_parse_exp (scan); + curtoken = script_scan_get_current_token (scan); + if (!cond) + { + script_parse_error (&curtoken->location, "Expected a valid condition expression"); + return NULL; + } + if (!script_scan_token_is_symbol_of_value (curtoken, ')')) + { + script_parse_error (&curtoken->location, + "Expected a ')' at the end of a condition block"); + return NULL; + } + curtoken = script_scan_get_next_token (scan); + if (!script_scan_token_is_symbol_of_value (curtoken, ';')) + { + script_parse_error (&curtoken->location, + "Expected a ';' after a do-whileexpression"); + return NULL; + } + script_scan_get_next_token (scan); + script_op_t *op = script_parse_new_op_cond (SCRIPT_OP_TYPE_DO_WHILE, cond, cond_op, NULL, &location); + return op; +} + static script_op_t *script_parse_for (script_scan_t *scan) { script_scan_token_t *curtoken = script_scan_get_current_token (scan); @@ -734,6 +785,8 @@ static script_op_t *script_parse_op (script_scan_t *scan) if (reply) return reply; reply = script_parse_if_while (scan); if (reply) return reply; + reply = script_parse_do_while (scan); + if (reply) return reply; reply = script_parse_for (scan); if (reply) return reply; reply = script_parse_return (scan); @@ -880,6 +933,7 @@ void script_parse_op_free (script_op_t *op) case SCRIPT_OP_TYPE_IF: case SCRIPT_OP_TYPE_WHILE: + case SCRIPT_OP_TYPE_DO_WHILE: case SCRIPT_OP_TYPE_FOR: script_parse_exp_free (op->data.cond_op.cond); script_parse_op_free (op->data.cond_op.op1); diff --git a/src/plugins/splash/script/script.h b/src/plugins/splash/script/script.h index 45254bd6..e4f6958b 100644 --- a/src/plugins/splash/script/script.h +++ b/src/plugins/splash/script/script.h @@ -191,6 +191,7 @@ typedef enum SCRIPT_OP_TYPE_OP_BLOCK, SCRIPT_OP_TYPE_IF, SCRIPT_OP_TYPE_WHILE, + SCRIPT_OP_TYPE_DO_WHILE, SCRIPT_OP_TYPE_FOR, SCRIPT_OP_TYPE_RETURN, SCRIPT_OP_TYPE_FAIL, |