aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core-commands.c13
-rw-r--r--src/parser.h4
-rw-r--r--tests/testsuite.at7
3 files changed, 21 insertions, 3 deletions
diff --git a/src/core-commands.c b/src/core-commands.c
index abe5604..a390fa4 100644
--- a/src/core-commands.c
+++ b/src/core-commands.c
@@ -244,6 +244,7 @@ teco_state_start_loop_open(teco_machine_main_t *ctx, GError **error)
if (!teco_expressions_eval(FALSE, error) ||
!teco_expressions_pop_num_calc(&lctx.counter, -1, error))
return;
+ lctx.brace_level = teco_brace_level;
lctx.pass_through = teco_machine_main_eval_colon(ctx);
if (lctx.counter) {
@@ -283,6 +284,14 @@ teco_state_start_loop_close(teco_machine_main_t *ctx, GError **error)
teco_loop_context_t *lctx = &g_array_index(teco_loop_stack, teco_loop_context_t,
teco_loop_stack->len-1);
+
+ /* only non-pass-through loops increase the brace level */
+ if (teco_brace_level != lctx->brace_level + !lctx->pass_through) {
+ g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED,
+ "Brace left open at loop end command");
+ return;
+ }
+
gboolean colon_modified = teco_machine_main_eval_colon(ctx);
/*
@@ -351,7 +360,7 @@ teco_state_start_break(teco_machine_main_t *ctx, GError **error)
{
if (teco_loop_stack->len <= ctx->loop_stack_fp) {
g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED,
- "<;> only allowed in iterations");
+ "<;> only allowed in loops");
return;
}
@@ -376,7 +385,7 @@ teco_state_start_break(teco_machine_main_t *ctx, GError **error)
if (!teco_expressions_discard_args(error))
return;
if (!lctx.pass_through &&
- !teco_expressions_brace_close(error))
+ !teco_expressions_brace_return(lctx.brace_level, 0, error))
return;
undo__insert_val__teco_loop_stack(teco_loop_stack->len, lctx);
diff --git a/src/parser.h b/src/parser.h
index 3bf9050..29b96b6 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -36,7 +36,9 @@ typedef struct {
/** how many iterations are left */
teco_int_t counter;
/** Program counter of loop start command */
- gsize pc : sizeof(gsize)*8 - 1;
+ gsize pc;
+ /** Brace level at loop start */
+ guint brace_level : sizeof(guint)*8 - 1;
/**
* Whether the loop represents an argument
* barrier or not (it "passes through"
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 33f1bf5..676ca59 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -13,6 +13,8 @@ AT_COLOR_TESTS
# (translated to [ ... ]) in simple cases where balanced
# brackets are required in TECO code as well and
# quadrigraphs (@<:@ and @:>@) in all other cases.
+# Single round brackets also have to be replaced with the
+# quadrigraphs @{:@ and @:}@.
AT_BANNER([Features])
@@ -45,6 +47,11 @@ AT_SETUP([Closing loops at the correct macro level])
AT_CHECK([$SCITECO -e '@^Ua{>} <Ma'], 1, ignore, ignore)
AT_CLEANUP
+AT_SETUP([Braces in loops])
+AT_CHECK([$SCITECO -e "1<23@{:@42>"], 1, ignore, ignore)
+AT_CHECK([$SCITECO -e "1<23(1;)> \"~|(0/0)'"], 0, ignore, ignore)
+AT_CLEANUP
+
AT_SETUP([Pass-through loops])
# NOTE: This requires the <=>, so that values get consumed from the stack.
# More elegant would be a command for popping exactly one argument like <:$>.