summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Brej <cbrej@cs.man.ac.uk>2009-10-04 17:36:22 +0100
committerroot <cbrej@cs.man.ac.uk>2009-10-04 17:36:22 +0100
commit9ca46671bbb21ed3cd56becf555229d553bc6a56 (patch)
tree58dbb26ec2df4335c44c26a5e77dc6d0c8cc5e75
parenta29f25bc6c67e87f38f323e8739f06249205d766 (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.c18
-rw-r--r--src/plugins/splash/script/script-parse.c54
-rw-r--r--src/plugins/splash/script/script.h1
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,