|
@@ -362,6 +362,7 @@ typedef struct {
|
|
|
T_VAR,
|
|
|
T_LET,
|
|
|
T_CONST,
|
|
|
+ T_ENUM,
|
|
|
T_IF,
|
|
|
T_ELSE,
|
|
|
T_ELIF,
|
|
@@ -868,6 +869,8 @@ token_t *next_token(char *source, size_t *pos) {
|
|
|
return TK(LET);
|
|
|
else if (strcmp(name, "const") == 0)
|
|
|
return TK(CONST);
|
|
|
+ else if (strcmp(name, "enum") == 0)
|
|
|
+ return TK(ENUM);
|
|
|
else if (strcmp(name, "if") == 0)
|
|
|
return TK(IF);
|
|
|
else if (strcmp(name, "else") == 0)
|
|
@@ -1170,6 +1173,7 @@ struct _node_t {
|
|
|
N_VARUNPACK,
|
|
|
N_LETUNPACK,
|
|
|
N_CONST,
|
|
|
+ N_ENUM,
|
|
|
N_IF,
|
|
|
N_SWITCH,
|
|
|
N_FOR,
|
|
@@ -2492,6 +2496,36 @@ node_t *_parse_stmt(list_t *tokens, size_t *pos, int allow_comma) {
|
|
|
} while (MATCH(COMMA));
|
|
|
|
|
|
return NODEH(CONST, h);
|
|
|
+ } else if (MATCH(ENUM)) {
|
|
|
+ table_t *h = table_new();
|
|
|
+
|
|
|
+ EXPECT(LCB, "{");
|
|
|
+
|
|
|
+ do {
|
|
|
+ if (!AT(NAME))
|
|
|
+ PARSE_ERROR("expected identifier");
|
|
|
+
|
|
|
+ char *k = ((token_t *)tokens->data[(*pos)++])->text;
|
|
|
+
|
|
|
+ if (k[0] != '_' && !(k[0] >= 'A' && k[0] <= 'Z'))
|
|
|
+ PARSE_ERROR("compile-time constant identifiers must begin with an "
|
|
|
+ "uppercase letter or with an underscore, but '%s' does not",
|
|
|
+ k);
|
|
|
+
|
|
|
+ if (table_get(h, k))
|
|
|
+ PARSE_ERROR("duplicated compile-time constant definition: '%s'", k);
|
|
|
+
|
|
|
+ node_t *v = NULL;
|
|
|
+
|
|
|
+ if (MATCH(ASSIGN))
|
|
|
+ v = parse_expr(tokens, pos);
|
|
|
+
|
|
|
+ table_set(h, k, v);
|
|
|
+ } while (MATCH(COMMA));
|
|
|
+
|
|
|
+ EXPECT(RCB, "}");
|
|
|
+
|
|
|
+ return NODEH(ENUM, h);
|
|
|
} else if (MATCH(IF))
|
|
|
return parse_if(tokens, pos);
|
|
|
else if (MATCH(SWITCH)) {
|
|
@@ -3664,6 +3698,23 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
|
if (!const_set(name, entry.value))
|
|
|
COMPILE_ERROR("redeclaration of compile-time constant: '%s'", name);
|
|
|
});
|
|
|
+ } else if (node->tag == N_ENUM) {
|
|
|
+ size_t k = 0;
|
|
|
+
|
|
|
+ table_iterate(node->h, {
|
|
|
+ char *name = entry.key;
|
|
|
+
|
|
|
+ node_t *v = entry.value;
|
|
|
+ if (!v) {
|
|
|
+ char buf[128];
|
|
|
+ snprintf(buf, sizeof(buf), "%zu", k++);
|
|
|
+
|
|
|
+ v = nodet(N_LITERAL, token(T_NUMBER, strdup(buf)));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!const_set(name, v))
|
|
|
+ COMPILE_ERROR("redeclaration of compile-time constant: '%s'", name);
|
|
|
+ });
|
|
|
} else if (node->tag == N_FUNCDEF) {
|
|
|
compile_func(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node, NULL);
|
|
|
|
|
@@ -3761,7 +3812,7 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
|
|
|
|
for (size_t i = 0; i < block->length; i++) {
|
|
|
node_t *n = block->data[i];
|
|
|
- if (n->tag == N_CONST || n->tag == N_FUNCDEF || n->tag == N_CLASS ||
|
|
|
+ if (n->tag == N_CONST || n->tag == N_ENUM || n->tag == N_FUNCDEF || n->tag == N_CLASS ||
|
|
|
n->tag == N_PASS)
|
|
|
continue;
|
|
|
|
|
@@ -5939,7 +5990,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
|
node->l->data[i], varname, i);
|
|
|
} break;
|
|
|
|
|
|
- case N_CONST:
|
|
|
+ case N_CONST: case N_ENUM:
|
|
|
break;
|
|
|
|
|
|
case N_IF:
|