X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=parser.c;h=f03057266d3c71bc37233ffc3e012086192f9451;hb=d9572e3e303929e1b6d7267d43c0904dac3078f5;hp=d913567d5e6db25d78cf1407bf00b9ee96f4255a;hpb=12a864abf5a5cc79f0a8f11535c26bb2009c0ad9;p=xonotic%2Fgmqcc.git diff --git a/parser.c b/parser.c index d913567..f030572 100644 --- a/parser.c +++ b/parser.c @@ -25,7 +25,6 @@ #include #include "parser.h" -#include "platform.h" #define PARSER_HT_LOCALS 2 #define PARSER_HT_SIZE 512 @@ -45,7 +44,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels); static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *array, const char *funcname); static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname); -static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef); +static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef, bool *is_vararg); static void parseerror(parser_t *parser, const char *fmt, ...) { @@ -373,6 +372,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) #define NotSameType(T) \ (exprs[0]->vtype != exprs[1]->vtype || \ exprs[0]->vtype != T) + switch (op->id) { default: @@ -469,13 +469,17 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid2('-','P'): if ((out = fold_op(parser->fold, op, exprs))) break; + if (exprs[0]->vtype != TYPE_FLOAT && exprs[0]->vtype != TYPE_VECTOR) { compile_error(ctx, "invalid types used in unary expression: cannot negate type %s", type_name[exprs[0]->vtype]); return false; } - out = (ast_expression*)ast_unary_new(ctx, (VINSTR_NEG_F-TYPE_FLOAT) + exprs[0]->vtype, exprs[0]); + if (exprs[0]->vtype == TYPE_FLOAT) + out = (ast_expression*)ast_unary_new(ctx, VINSTR_NEG_F, exprs[0]); + else + out = (ast_expression*)ast_unary_new(ctx, VINSTR_NEG_V, exprs[0]); break; case opid2('!','P'): @@ -520,10 +524,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (!(out = fold_op(parser->fold, op, exprs))) { switch (exprs[0]->vtype) { case TYPE_FLOAT: - out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]); + out = fold_binary(ctx, INSTR_ADD_F, exprs[0], exprs[1]); break; case TYPE_VECTOR: - out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]); + out = fold_binary(ctx, INSTR_ADD_V, exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot add type %s and %s", @@ -545,10 +549,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (!(out = fold_op(parser->fold, op, exprs))) { switch (exprs[0]->vtype) { case TYPE_FLOAT: - out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]); + out = fold_binary(ctx, INSTR_SUB_F, exprs[0], exprs[1]); break; case TYPE_VECTOR: - out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]); + out = fold_binary(ctx, INSTR_SUB_V, exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s", @@ -575,15 +579,15 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) switch (exprs[0]->vtype) { case TYPE_FLOAT: if (exprs[1]->vtype == TYPE_VECTOR) - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]); + out = fold_binary(ctx, INSTR_MUL_FV, exprs[0], exprs[1]); else - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]); + out = fold_binary(ctx, INSTR_MUL_F, exprs[0], exprs[1]); break; case TYPE_VECTOR: if (exprs[1]->vtype == TYPE_FLOAT) - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]); + out = fold_binary(ctx, INSTR_MUL_VF, exprs[0], exprs[1]); else - out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]); + out = fold_binary(ctx, INSTR_MUL_V, exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s", @@ -603,7 +607,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } if (!(out = fold_op(parser->fold, op, exprs))) { if (exprs[0]->vtype == TYPE_FLOAT) - out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]); + out = fold_binary(ctx, INSTR_DIV_F, exprs[0], exprs[1]); else { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); @@ -656,7 +660,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) * since scalar ^ vector is not allowed. */ if (exprs[0]->vtype == TYPE_FLOAT) { - out = (ast_expression*)ast_binary_new(ctx, + out = fold_binary(ctx, (op->id == opid1('^') ? VINSTR_BITXOR : op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND), exprs[0], exprs[1]); } else { @@ -669,11 +673,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) * Bitop all the values of the vector components against the * vectors components in question. */ - out = (ast_expression*)ast_binary_new(ctx, + out = fold_binary(ctx, (op->id == opid1('^') ? VINSTR_BITXOR_V : op->id == opid1('|') ? VINSTR_BITOR_V : VINSTR_BITAND_V), exprs[0], exprs[1]); } else { - out = (ast_expression*)ast_binary_new(ctx, + out = fold_binary(ctx, (op->id == opid1('^') ? VINSTR_BITXOR_VF : op->id == opid1('|') ? VINSTR_BITOR_VF : VINSTR_BITAND_VF), exprs[0], exprs[1]); } @@ -726,7 +730,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } } } - out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]); + out = fold_binary(ctx, generated_op, exprs[0], exprs[1]); } break; @@ -773,7 +777,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } if (!(out = fold_op(parser->fold, op, exprs))) { - out = (ast_expression*)ast_binary_new( + out = fold_binary( parser_ctx(parser), VINSTR_CROSS, exprs[0], @@ -794,6 +798,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } if (!(out = fold_op(parser->fold, op, exprs))) { + /* This whole block is NOT fold_binary safe */ ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]); eq->refs = AST_REF_NONE; @@ -834,7 +839,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } if (!(out = fold_op(parser->fold, op, exprs))) - out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]); + out = fold_binary(ctx, generated_op, exprs[0], exprs[1]); break; case opid2('!', '='): if (exprs[0]->vtype != exprs[1]->vtype) { @@ -844,7 +849,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } if (!(out = fold_op(parser->fold, op, exprs))) - out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]); + out = fold_binary(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]); break; case opid2('=', '='): if (exprs[0]->vtype != exprs[1]->vtype) { @@ -854,7 +859,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } if (!(out = fold_op(parser->fold, op, exprs))) - out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]); + out = fold_binary(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]); break; case opid1('='): @@ -968,9 +973,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } if (!out) return false; - out = (ast_expression*)ast_binary_new(ctx, subop, - out, - (ast_expression*)parser->fold->imm_float[1]); + out = fold_binary(ctx, subop, + out, + (ast_expression*)parser->fold->imm_float[1]); + break; case opid2('+','='): case opid2('-','='): @@ -1034,9 +1040,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF, exprs[0], exprs[1]); } else { - out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, - (ast_expression*)parser->fold->imm_float[1], - exprs[1]); + out = fold_binary(ctx, INSTR_DIV_F, + (ast_expression*)parser->fold->imm_float[1], + exprs[1]); if (!out) { compile_error(ctx, "internal error: failed to generate division"); return false; @@ -1093,9 +1099,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) else assignop = type_store_instr[exprs[0]->vtype]; if (exprs[0]->vtype == TYPE_FLOAT) - out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]); + out = fold_binary(ctx, INSTR_BITAND, exprs[0], exprs[1]); else - out = (ast_expression*)ast_binary_new(ctx, VINSTR_BITAND_V, exprs[0], exprs[1]); + out = fold_binary(ctx, VINSTR_BITAND_V, exprs[0], exprs[1]); if (!out) return false; (void)check_write_to(ctx, exprs[0]); @@ -1115,9 +1121,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } if (!(out = fold_op(parser->fold, op, exprs))) { if (exprs[0]->vtype == TYPE_FLOAT) { - out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser->fold->imm_float[2], exprs[0]); + out = fold_binary(ctx, INSTR_SUB_F, (ast_expression*)parser->fold->imm_float[2], exprs[0]); } else { - out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, (ast_expression*)parser->fold->imm_vector[1], exprs[0]); + out = fold_binary(ctx, INSTR_SUB_V, (ast_expression*)parser->fold->imm_vector[1], exprs[0]); } } break; @@ -1225,7 +1231,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) * sy->out should I be doing here? */ sy->out[fid] = syexp(foldval->node.context, foldval); - vec_shrinkby(sy->out, 1); + vec_shrinkby(sy->out, paramcount); vec_free(exprs); return true; @@ -1420,7 +1426,7 @@ static ast_expression* parse_vararg_do(parser_t *parser) return NULL; } - typevar = parse_typename(parser, NULL, NULL); + typevar = parse_typename(parser, NULL, NULL, NULL); if (!typevar) { ast_unref(idx); return NULL; @@ -2799,6 +2805,14 @@ static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool * return false; } } + else if (!strcmp(parser_tokval(parser), "accumulate")) { + flags |= AST_FLAG_ACCUMULATE; + if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) { + parseerror(parser, "`accumulate` attribute has no parameters, expected `]]`"); + *cvq = CV_WRONG; + return false; + } + } else if (!strcmp(parser_tokval(parser), "alias") && !(flags & AST_FLAG_ALIAS)) { flags |= AST_FLAG_ALIAS; *message = NULL; @@ -3336,7 +3350,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * if (parser->tok == TOKEN_IDENT) typevar = parser_find_typedef(parser, parser_tokval(parser), 0); - if (typevar || parser->tok == TOKEN_TYPENAME || parser->tok == '.') + if (typevar || parser->tok == TOKEN_TYPENAME || parser->tok == '.' || parser->tok == TOKEN_DOTS) { /* local variable */ if (!block) { @@ -3975,18 +3989,28 @@ static bool parse_function_body(parser_t *parser, ast_value *var) } if (var->hasvalue) { - parseerror(parser, "function `%s` declared with multiple bodies", var->name); - ast_block_delete(block); - goto enderr; - } + if (!(var->expression.flags & AST_FLAG_ACCUMULATE)) { + parseerror(parser, "function `%s` declared with multiple bodies", var->name); + ast_block_delete(block); + goto enderr; + } + func = var->constval.vfunc; - func = ast_function_new(ast_ctx(var), var->name, var); - if (!func) { - parseerror(parser, "failed to allocate function for `%s`", var->name); - ast_block_delete(block); - goto enderr; + if (!func) { + parseerror(parser, "internal error: NULL function: `%s`", var->name); + ast_block_delete(block); + goto enderr; + } + } else { + func = ast_function_new(ast_ctx(var), var->name, var); + + if (!func) { + parseerror(parser, "failed to allocate function for `%s`", var->name); + ast_block_delete(block); + goto enderr; + } + vec_push(parser->functions, func); } - vec_push(parser->functions, func); parser_enterblock(parser); @@ -4013,25 +4037,25 @@ static bool parse_function_body(parser_t *parser, ast_value *var) } } - if (var->argcounter) { + if (var->argcounter && !func->argc) { ast_value *argc = ast_value_new(ast_ctx(var), var->argcounter, TYPE_FLOAT); parser_addlocal(parser, argc->name, (ast_expression*)argc); func->argc = argc; } - if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) { + if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC && !func->varargs) { char name[1024]; ast_value *varargs = ast_value_new(ast_ctx(var), "reserved:va_args", TYPE_ARRAY); varargs->expression.flags |= AST_FLAG_IS_VARARG; varargs->expression.next = (ast_expression*)ast_value_new(ast_ctx(var), NULL, TYPE_VECTOR); varargs->expression.count = 0; - platform_snprintf(name, sizeof(name), "%s##va##SET", var->name); + util_snprintf(name, sizeof(name), "%s##va##SET", var->name); if (!parser_create_array_setter_proto(parser, varargs, name)) { ast_delete(varargs); ast_block_delete(block); goto enderrfn; } - platform_snprintf(name, sizeof(name), "%s##va##GET", var->name); + util_snprintf(name, sizeof(name), "%s##va##GET", var->name); if (!parser_create_array_getter_proto(parser, varargs, varargs->expression.next, name)) { ast_delete(varargs); ast_block_delete(block); @@ -4049,7 +4073,6 @@ static bool parse_function_body(parser_t *parser, ast_value *var) vec_push(func->blocks, block); - parser->function = old; if (!parser_leaveblock(parser)) retval = false; @@ -4486,7 +4509,6 @@ static bool parser_create_array_getter(parser_t *parser, ast_value *array, const return parser_create_array_getter_impl(parser, array); } -static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef); static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) { lex_ctx_t ctx; @@ -4512,6 +4534,8 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) /* parse variables until we hit a closing paren */ while (parser->tok != ')') { + bool is_varargs = false; + if (!first) { /* there must be commas between them */ if (parser->tok != ',') { @@ -4525,10 +4549,13 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) } first = false; - if (parser->tok == TOKEN_DOTS) { + param = parse_typename(parser, NULL, NULL, &is_varargs); + if (!param && !is_varargs) + goto on_error; + if (is_varargs) { /* '...' indicates a varargs function */ variadic = true; - if (!parser_next(parser) || (parser->tok != ')' && parser->tok != TOKEN_IDENT)) { + if (parser->tok != ')' && parser->tok != TOKEN_IDENT) { parseerror(parser, "`...` must be the last parameter of a variadic function declaration"); goto on_error; } @@ -4539,13 +4566,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) goto on_error; } } - } - else - { - /* for anything else just parse a typename */ - param = parse_typename(parser, NULL, NULL); - if (!param) - goto on_error; + } else { vec_push(params, param); if (param->expression.vtype >= TYPE_VARIANT) { char tname[1024]; /* typename is reserved in C++ */ @@ -4697,7 +4718,7 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var) * void() foo(), bar * then the type-information 'void()' can be stored in 'storebase' */ -static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef) +static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef, bool *is_vararg) { ast_value *var, *tmp; lex_ctx_t ctx; @@ -4707,11 +4728,15 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va bool wasarray = false; size_t morefields = 0; + bool vararg = (parser->tok == TOKEN_DOTS); + ctx = parser_ctx(parser); /* types may start with a dot */ - if (parser->tok == '.') { + if (parser->tok == '.' || parser->tok == TOKEN_DOTS) { isfield = true; + if (parser->tok == TOKEN_DOTS) + morefields += 2; /* if we parsed a dot we need a typename now */ if (!parser_next(parser)) { parseerror(parser, "expected typename for field definition"); @@ -4721,8 +4746,14 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* Further dots are handled seperately because they won't be part of the * basetype */ - while (parser->tok == '.') { - ++morefields; + while (true) { + if (parser->tok == '.') + ++morefields; + else if (parser->tok == TOKEN_DOTS) + morefields += 3; + else + break; + vararg = false; if (!parser_next(parser)) { parseerror(parser, "expected typename for field definition"); return NULL; @@ -4732,6 +4763,10 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va if (parser->tok == TOKEN_IDENT) cached_typedef = parser_find_typedef(parser, parser_tokval(parser), 0); if (!cached_typedef && parser->tok != TOKEN_TYPENAME) { + if (vararg && is_vararg) { + *is_vararg = true; + return NULL; + } parseerror(parser, "expected typename"); return NULL; } @@ -4783,8 +4818,14 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va } /* there may be a name now */ - if (parser->tok == TOKEN_IDENT) { + if (parser->tok == TOKEN_IDENT || parser->tok == TOKEN_KEYWORD) { + if (!strcmp(parser_tokval(parser), "break")) + (void)!parsewarning(parser, WARN_BREAKDEF, "break definition ignored (suggest removing it)"); + else if (parser->tok == TOKEN_KEYWORD) + goto leave; + name = util_strdup(parser_tokval(parser)); + /* parse on */ if (!parser_next(parser)) { ast_delete(var); @@ -4794,6 +4835,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va } } + leave: /* now this may be an array */ if (parser->tok == '[') { wasarray = true; @@ -4845,7 +4887,7 @@ static bool parse_typedef(parser_t *parser) ast_value *typevar, *oldtype; ast_expression *old; - typevar = parse_typename(parser, NULL, NULL); + typevar = parse_typename(parser, NULL, NULL, NULL); if (!typevar) return false; @@ -4928,10 +4970,10 @@ static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, cons static bool create_array_accessors(parser_t *parser, ast_value *var) { char name[1024]; - platform_snprintf(name, sizeof(name), "%s##SET", var->name); + util_snprintf(name, sizeof(name), "%s##SET", var->name); if (!parser_create_array_setter(parser, var, name)) return false; - platform_snprintf(name, sizeof(name), "%s##GET", var->name); + util_snprintf(name, sizeof(name), "%s##GET", var->name); if (!parser_create_array_getter(parser, var, var->expression.next, name)) return false; return true; @@ -5015,7 +5057,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield parseerror(parser, "`static` qualifier is not supported in global scope"); /* get the first complete variable */ - var = parse_typename(parser, &basetype, cached_typedef); + var = parse_typename(parser, &basetype, cached_typedef, NULL); if (!var) { if (basetype) ast_delete(basetype); @@ -5079,6 +5121,13 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield var->expression.flags & AST_FLAG_ALIAS) var->desc = vstring; + if (parser_find_global(parser, var->name) && var->expression.flags & AST_FLAG_ALIAS) { + parseerror(parser, "function aliases cannot be forward declared"); + retval = false; + goto cleanup; + } + + /* Part 1: * check for validity: (end_sys_..., multiple-definitions, prototypes, ...) * Also: if there was a prototype, `var` will be deleted and set to `proto` which @@ -5459,14 +5508,14 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield goto cleanup; } - platform_snprintf(name, sizeof(name), "%s##SETF", var->name); + util_snprintf(name, sizeof(name), "%s##SETF", var->name); if (!parser_create_array_field_setter(parser, array, name)) goto cleanup; telem = ast_type_copy(ast_ctx(var), array->expression.next); tfield = ast_value_new(ast_ctx(var), "<.type>", TYPE_FIELD); tfield->expression.next = telem; - platform_snprintf(name, sizeof(name), "%s##GETFP", var->name); + util_snprintf(name, sizeof(name), "%s##GETFP", var->name); if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) { ast_delete(tfield); goto cleanup; @@ -5506,16 +5555,8 @@ skipvar: if (parser->tok != '{' || var->expression.vtype != TYPE_FUNCTION) { if (parser->tok != '=') { - if (!strcmp(parser_tokval(parser), "break")) { - if (!parser_next(parser)) { - parseerror(parser, "error parsing break definition"); - break; - } - (void)!parsewarning(parser, WARN_BREAKDEF, "break definition ignored (suggest removing it)"); - } else { - parseerror(parser, "missing semicolon or initializer, got: `%s`", parser_tokval(parser)); - break; - } + parseerror(parser, "missing semicolon or initializer, got: `%s`", parser_tokval(parser)); + break; } if (!parser_next(parser)) { @@ -5768,7 +5809,7 @@ static bool parser_global_statement(parser_t *parser) if (parser->tok == TOKEN_IDENT) istype = parser_find_typedef(parser, parser_tokval(parser), 0); - if (istype || parser->tok == TOKEN_TYPENAME || parser->tok == '.') + if (istype || parser->tok == TOKEN_TYPENAME || parser->tok == '.' || parser->tok == TOKEN_DOTS) { return parse_variable(parser, NULL, false, CV_NONE, istype, false, false, 0, NULL); } @@ -5907,7 +5948,7 @@ parser_t *parser_create() } } if (!parser->assign_op) { - printf("internal error: initializing parser: failed to find assign operator\n"); + con_err("internal error: initializing parser: failed to find assign operator\n"); mem_d(parser); return NULL; }