From b971ddec3a7bb56ac6c9bc094916828283838adf Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Fri, 8 Mar 2013 08:01:45 +0000 Subject: [PATCH] Implemented concept of enumeration attributes (can be further extended, but currently only "flag" is implemented as an attribute). An enumeration with a flag attribute will act as a "flagged enumeration", one that automatically handles exponentiation of the constants defined inside it, i.e enum : flag { A, B, C }, A,B,C will equal 2, 4, 8. --- parser.c | 26 +++++++++++++++++++++++--- tests/enum.qc | 10 ++++++++++ tests/enum.tmpl | 3 +++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/parser.c b/parser.c index 98c0c9f..bd4f1c1 100644 --- a/parser.c +++ b/parser.c @@ -3861,6 +3861,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * static bool parse_enum(parser_t *parser) { + bool flag = false; qcfloat num = 0; ast_value **values = NULL; ast_value *var = NULL; @@ -3868,11 +3869,28 @@ static bool parse_enum(parser_t *parser) ast_expression *old; - if (!parser_next(parser) || parser->tok != '{') { - parseerror(parser, "expected `{` after `enum` keyword"); + if (!parser_next(parser) || (parser->tok != '{' && parser->tok != ':')) { + parseerror(parser, "expected `{` or `:` after `enum` keyword"); return false; } + /* 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 ':'"); + return false; + } + + if (!parser_next(parser) || parser->tok != '{') { + parseerror(parser, "expected `{` after enum attribute `flag`"); + return false; + } + + /* flagged enumeration start from 1 */ + num = 1; + flag = true; + } + while (true) { if (!parser_next(parser) || parser->tok != TOKEN_IDENT) { if (parser->tok == '}') { @@ -3896,7 +3914,9 @@ static bool parse_enum(parser_t *parser) vec_push(values, var); var->cvq = CV_CONST; var->hasvalue = true; - var->constval.vfloat = num++; + + /* for flagged enumerations increment in POTs of TWO */ + var->constval.vfloat = (flag) ? (num *= 2) : (num ++); parser_addglobal(parser, var->name, (ast_expression*)var); diff --git a/tests/enum.qc b/tests/enum.qc index da08cee..1691661 100644 --- a/tests/enum.qc +++ b/tests/enum.qc @@ -27,6 +27,12 @@ enum { N }; +enum : flag { + F1, /* = 1 << 1 */ + F2, /* = 1 << 2 */ + F3 /* = 1 << 3 */ +}; + void main() { print(ftos(A), "\n"); print(ftos(B), "\n"); @@ -42,4 +48,8 @@ void main() { print(ftos(L), "\n"); print(ftos(M), "\n"); print(ftos(N), "\n"); + + print(ftos(F1), "\n"); + print(ftos(F2), "\n"); + print(ftos(F3), "\n"); }; diff --git a/tests/enum.tmpl b/tests/enum.tmpl index 28cbd57..c39537a 100644 --- a/tests/enum.tmpl +++ b/tests/enum.tmpl @@ -16,3 +16,6 @@ M: 10 M: 11 M: 12 M: 13 +M: 2 +M: 4 +M: 8 -- 2.39.2