mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-03-22 10:41:43 +00:00
Implemented "reverse" enum attribute, e.g enum : reverse { A, B, C, D } -> A,B,C,D = 3,2,1,0
This commit is contained in:
parent
73c085a461
commit
d8d78f61a7
3 changed files with 42 additions and 9 deletions
32
parser.c
32
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
if (!parser_next(parser) || parser->tok != '{') {
|
||||
parseerror(parser, "expected `{` after enum attribute `flag`");
|
||||
parseerror(parser, "expected `{` after enum attribute ");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* flagged enumeration start from 1 */
|
||||
num = 1;
|
||||
flag = true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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");
|
||||
};
|
||||
|
|
|
@ -19,3 +19,7 @@ M: 13
|
|||
M: 2
|
||||
M: 4
|
||||
M: 8
|
||||
M: 3
|
||||
M: 2
|
||||
M: 1
|
||||
M: 0
|
||||
|
|
Loading…
Reference in a new issue