Implemented "reverse" enum attribute, e.g enum : reverse { A, B, C, D } -> A,B,C...
authorDale Weiler <killfieldengine@gmail.com>
Sat, 9 Mar 2013 05:07:14 +0000 (05:07 +0000)
committerDale Weiler <killfieldengine@gmail.com>
Sat, 9 Mar 2013 05:07:14 +0000 (05:07 +0000)
parser.c
tests/enum.qc
tests/enum.tmpl

index 970837f..a5c039a 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -3960,6 +3960,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression *
 static bool parse_enum(parser_t *parser)
 {
     bool        flag = false;
+    bool        reverse = false;
     qcfloat     num = 0;
     ast_value **values = NULL;
     ast_value  *var = NULL;
@@ -3974,19 +3975,28 @@ static bool parse_enum(parser_t *parser)
 
     /* enumeration attributes (can add more later) */
     if (parser->tok == ':') {
-        if (!parser_next(parser) || parser->tok != TOKEN_IDENT || strcmp(parser_tokval(parser), "flag")) {
-            parseerror(parser, "expected `flag` after enumeration attribute ':'");
+        if (!parser_next(parser) || parser->tok != TOKEN_IDENT){
+            parseerror(parser, "expected `flag` or `reverse` for enumeration attribute");
             return false;
         }
 
-        if (!parser_next(parser) || parser->tok != '{') {
-            parseerror(parser, "expected `{` after enum attribute `flag`");
+        /* attributes? */
+        if (!strcmp(parser_tokval(parser), "flag")) {
+            num  = 1;
+            flag = true;
+        }
+        else if (!strcmp(parser_tokval(parser), "reverse")) {
+            reverse = true;
+        }
+        else {
+            parseerror(parser, "invalid attribute `%s` for enumeration", parser_tokval(parser));
             return false;
         }
 
-        /* flagged enumeration start from 1 */
-        num  = 1;
-        flag = true;
+        if (!parser_next(parser) || parser->tok != '{') {
+            parseerror(parser, "expected `{` after enum attribute ");
+            return false;
+        }
     }
 
     while (true) {
@@ -4015,7 +4025,6 @@ static bool parse_enum(parser_t *parser)
 
         /* for flagged enumerations increment in POTs of TWO */
         var->constval.vfloat = (flag) ? (num *= 2) : (num ++);
-
         parser_addglobal(parser, var->name, (ast_expression*)var);
 
         if (!parser_next(parser)) {
@@ -4054,6 +4063,13 @@ static bool parse_enum(parser_t *parser)
         }
     }
 
+    /* patch them all (for reversed attribute) */
+    if (reverse) {
+        size_t i;
+        for (i = 0; i < vec_size(values); i++)
+            values[i]->constval.vfloat = vec_size(values) - i - 1;
+    }
+
     if (parser->tok != '}') {
         parseerror(parser, "internal error: breaking without `}`");
         goto onerror;
index 1691661..42853d8 100644 (file)
@@ -1,4 +1,4 @@
-void(string, ...)   print  = #1;enum {
+enum {
     // this behaviour is confusing, but I like that
     // we support it.
     __ = (__ - 1),
@@ -33,6 +33,14 @@ enum : flag {
     F3  /* = 1 << 3 */
 };
 
+/* reversed enumeration */
+enum : reverse {
+    R1, // 3
+    R2, // 2
+    R3, // 1
+    R4  // 0
+};
+
 void main() {
     print(ftos(A), "\n");
     print(ftos(B), "\n");
@@ -52,4 +60,9 @@ void main() {
     print(ftos(F1), "\n");
     print(ftos(F2), "\n");
     print(ftos(F3), "\n");
+
+    print(ftos(R1), "\n");
+    print(ftos(R2), "\n");
+    print(ftos(R3), "\n");
+    print(ftos(R4), "\n");
 };
index c39537a..7647683 100644 (file)
@@ -19,3 +19,7 @@ M: 13
 M: 2
 M: 4
 M: 8
+M: 3
+M: 2
+M: 1
+M: 0