summaryrefslogtreecommitdiffstats
path: root/parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'parser.y')
-rw-r--r--parser.y44
1 files changed, 43 insertions, 1 deletions
diff --git a/parser.y b/parser.y
index 44ae0096..72aad3ae 100644
--- a/parser.y
+++ b/parser.y
@@ -70,6 +70,10 @@ struct lexer_param;
%token OR "or"
%token TRY "try"
%token CATCH "catch"
+%token LABEL "label"
+%token BREAK "break"
+%token BREAK2 "break2"
+%token BREAK3 "break3"
%token SETPIPE "|="
%token SETPLUS "+="
%token SETMINUS "-="
@@ -149,6 +153,8 @@ int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, block* answer, int* errors,
return tok;
}
+static unsigned int next_label = 0;
+
static block gen_dictpair(block k, block v) {
return BLOCK(gen_subexp(k), gen_subexp(v), gen_op_simple(INSERT));
}
@@ -335,7 +341,7 @@ Term "as" '$' IDENT '|' Exp {
"try" Exp "catch" Exp {
//$$ = BLOCK(gen_op_target(FORK_OPT, $2), $2, $4);
- $$ = gen_try($2, $4);
+ $$ = gen_try($2, gen_try_handler($4));
} |
"try" Exp {
//$$ = BLOCK(gen_op_target(FORK_OPT, $2), $2, gen_op_simple(BACKTRACK));
@@ -346,6 +352,19 @@ Term "as" '$' IDENT '|' Exp {
$$ = $2;
} |
+"label" '|' Exp {
+ jv v = jv_string_fmt("*anonlabel%u", next_label++);
+ $$ = gen_location(@$, locations, gen_label(jv_string_value(v), $3));
+ jv_free(v);
+} |
+
+"label" '$' IDENT '|' Exp {
+ jv v = jv_string_fmt("*label-%s", jv_string_value($3));
+ $$ = gen_location(@$, locations, gen_label(jv_string_value(v), $5));
+ jv_free($3);
+ jv_free(v);
+} |
+
// This rule conflicts with all the other rules using the '?' operator.
// It doesn't matter which bison prefers: all of them result in the same
// syntax and semantics, but the more specific rules optimize better
@@ -570,6 +589,29 @@ Term:
REC {
$$ = gen_call("recurse", gen_noop());
} |
+BREAK {
+ $$ = gen_location(@$, locations,
+ BLOCK(gen_op_unbound(LOADV, "*1"), // impossible symbol
+ gen_call("error", gen_noop())));
+} |
+BREAK2 {
+ $$ = gen_location(@$, locations,
+ BLOCK(gen_op_unbound(LOADV, "*2"), // impossible symbol
+ gen_call("error", gen_noop())));
+} |
+BREAK3 {
+ $$ = gen_location(@$, locations,
+ BLOCK(gen_op_unbound(LOADV, "*3"), // impossible symbol
+ gen_call("error", gen_noop())));
+} |
+BREAK '$' IDENT {
+ jv v = jv_string_fmt("*label-%s", jv_string_value($3)); // impossible symbol
+ $$ = gen_location(@$, locations,
+ BLOCK(gen_op_unbound(LOADV, jv_string_value(v)),
+ gen_call("error", gen_noop())));
+ jv_free(v);
+ jv_free($3);
+} |
Term FIELD '?' {
$$ = gen_index_opt($1, gen_const($2));
} |