From d8d78f61a76bffb96ff70c410312f1434fd98e5a Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Sat, 9 Mar 2013 05:07:14 +0000 Subject: [PATCH] Implemented "reverse" enum attribute, e.g enum : reverse { A, B, C, D } -> A,B,C,D = 3,2,1,0 --- parser.c | 32 ++++++++++++++++++++++++-------- tests/enum.qc | 15 ++++++++++++++- tests/enum.tmpl | 4 ++++ 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/parser.c b/parser.c index 970837f..a5c039a 100644 --- 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; diff --git a/tests/enum.qc b/tests/enum.qc index 1691661..42853d8 100644 --- a/tests/enum.qc +++ b/tests/enum.qc @@ -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"); }; diff --git a/tests/enum.tmpl b/tests/enum.tmpl index c39537a..7647683 100644 --- a/tests/enum.tmpl +++ b/tests/enum.tmpl @@ -19,3 +19,7 @@ M: 13 M: 2 M: 4 M: 8 +M: 3 +M: 2 +M: 1 +M: 0 -- 2.39.2