Browse Source

add enums

txlyre 1 week ago
parent
commit
2c6d648c53
1 changed files with 53 additions and 2 deletions
  1. 53 2
      qic.c

+ 53 - 2
qic.c

@@ -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: