|
@@ -417,6 +417,7 @@ typedef struct {
|
|
T_MINUSMINUS,
|
|
T_MINUSMINUS,
|
|
T_SLASHSLASH,
|
|
T_SLASHSLASH,
|
|
T_COLONASSIGN,
|
|
T_COLONASSIGN,
|
|
|
|
+ T_ARROW,
|
|
|
|
|
|
T_PLUS,
|
|
T_PLUS,
|
|
T_MINUS,
|
|
T_MINUS,
|
|
@@ -932,6 +933,8 @@ token_t *next_token(char *source, size_t *pos) {
|
|
return TK(GE);
|
|
return TK(GE);
|
|
else if (strncmp(&source[*pos], ":=", 2) == 0 && ++(*pos) && ++(*pos))
|
|
else if (strncmp(&source[*pos], ":=", 2) == 0 && ++(*pos) && ++(*pos))
|
|
return TK(COLONASSIGN);
|
|
return TK(COLONASSIGN);
|
|
|
|
+ else if (strncmp(&source[*pos], "=>", 2) == 0 && ++(*pos) && ++(*pos))
|
|
|
|
+ return TK(ARROW);
|
|
else if (source[*pos] == '(' && ++(*pos))
|
|
else if (source[*pos] == '(' && ++(*pos))
|
|
return TK(LPAR);
|
|
return TK(LPAR);
|
|
else if (source[*pos] == ')' && ++(*pos))
|
|
else if (source[*pos] == ')' && ++(*pos))
|
|
@@ -1092,6 +1095,7 @@ struct _node_t {
|
|
|
|
|
|
N_IFEXPR,
|
|
N_IFEXPR,
|
|
N_FUNCEXPR,
|
|
N_FUNCEXPR,
|
|
|
|
+ N_SWITCHEXPR,
|
|
|
|
|
|
N_LOGOR,
|
|
N_LOGOR,
|
|
N_LOGAND,
|
|
N_LOGAND,
|
|
@@ -1780,6 +1784,42 @@ node_t *parse_postfix(list_t *tokens, size_t *pos) {
|
|
return NODE1(INC, a);
|
|
return NODE1(INC, a);
|
|
else if (MATCH(MINUSMINUS))
|
|
else if (MATCH(MINUSMINUS))
|
|
return NODE1(DEC, a);
|
|
return NODE1(DEC, a);
|
|
|
|
+ else if (MATCH(SWITCH)) {
|
|
|
|
+ EXPECT(LCB, "{");
|
|
|
|
+
|
|
|
|
+ list_t *cases = list_new();
|
|
|
|
+ node_t *default_case = NULL;
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ if (MATCH(DEFAULT)) {
|
|
|
|
+ MATCH(ARROW);
|
|
|
|
+
|
|
|
|
+ default_case = parse_expr(tokens, pos);
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (AT(RCB))
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ node_t *expr = parse_expr(tokens, pos);
|
|
|
|
+
|
|
|
|
+ MATCH(ARROW);
|
|
|
|
+
|
|
|
|
+ list_t *pair = list_new();
|
|
|
|
+ list_push(pair, expr);
|
|
|
|
+ list_push(pair, parse_expr(tokens, pos));
|
|
|
|
+
|
|
|
|
+ list_push(cases, pair);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ EXPECT(RCB, "}");
|
|
|
|
+
|
|
|
|
+ if (!cases->length && !default_case)
|
|
|
|
+ PARSE_ERROR("empty switch expression");
|
|
|
|
+
|
|
|
|
+ return NODE2l(SWITCHEXPR, a, default_case, cases);
|
|
|
|
+ }
|
|
|
|
|
|
return a;
|
|
return a;
|
|
}
|
|
}
|
|
@@ -6407,6 +6447,46 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
EMIT(")");
|
|
EMIT(")");
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case N_SWITCHEXPR: {
|
|
|
|
+ NEWGID();
|
|
|
|
+
|
|
|
|
+ buffer_t *tbuf = buffer_new();
|
|
|
|
+ char *varname1 = tempvar();
|
|
|
|
+ char *varname2 = tempvar();
|
|
|
|
+ char *labelname = tempvar();
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "qi_value_t *__%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
|
+ buffer_fmt(tbuf, "qi_value_t *%s = state->nil;\n", varname1);
|
|
|
|
+ buffer_fmt(tbuf, "qi_value_t *%s = ", varname2);
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
|
|
+ buffer_fmt(tbuf, ";\n");
|
|
|
|
+
|
|
|
|
+ for (size_t i = 0; i < node->l->length; i++) {
|
|
|
|
+ list_t *pair = node->l->data[i];
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "if (_qi_equals(state, %s, ", varname2);
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, pair->data[0]);
|
|
|
|
+ buffer_fmt(tbuf, ")) {\n");
|
|
|
|
+ buffer_fmt(tbuf, "%s = ", varname1);
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, pair->data[1]);
|
|
|
|
+ buffer_fmt(tbuf, ";\n");
|
|
|
|
+ buffer_fmt(tbuf, "goto %s;\n}\n", labelname);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (node->b) {
|
|
|
|
+ buffer_fmt(tbuf, "%s = ", varname1);
|
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
|
|
+ buffer_fmt(tbuf, ";\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ buffer_fmt(tbuf, "%s: return %s;\n", labelname, varname1);
|
|
|
|
+ buffer_fmt(tbuf, "}\n");
|
|
|
|
+
|
|
|
|
+ buffer_appendb(gbuf, tbuf);
|
|
|
|
+
|
|
|
|
+ EMIT("__%s%d(state)", PREFIX, gid);
|
|
|
|
+ } break;
|
|
|
|
+
|
|
case N_FUNCEXPR:
|
|
case N_FUNCEXPR:
|
|
compile_func(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node, NULL);
|
|
compile_func(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node, NULL);
|
|
break;
|
|
break;
|