X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=parser.c;h=75014cb23607ab581341a36aaf424ed3d9af1b2b;hp=f95a2315784c83c52d6aaad00d76c1a278120f74;hb=d8c09c200a681ae12d078559dac526aa2c8cc951;hpb=4c1c1bc0519b666c92ce7bcab4c02c292d7cbfe7 diff --git a/parser.c b/parser.c index f95a231..75014cb 100644 --- a/parser.c +++ b/parser.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013, 2014 + * Copyright (C) 2012, 2013, 2014, 2015 * Wolfgang Bumiller * Dale Weiler * @@ -953,6 +953,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } } (void)check_write_to(ctx, exprs[0]); + /* When we're a vector of part of an entity field we use STOREP */ + if (ast_istype(exprs[0], ast_member) && ast_istype(((ast_member*)exprs[0])->owner, ast_entfield)) + assignop = INSTR_STOREP_F; out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]); break; case opid3('+','+','P'): @@ -1145,6 +1148,22 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) out = (ast_expression*)asbinstore; break; + case opid3('l', 'e', 'n'): + if (exprs[0]->vtype != TYPE_STRING && exprs[0]->vtype != TYPE_ARRAY) { + ast_type_to_string(exprs[0], ty1, sizeof(ty1)); + compile_error(ast_ctx(exprs[0]), "invalid type for length operator: %s", ty1); + return false; + } + /* strings must be const, arrays are statically sized */ + if (exprs[0]->vtype == TYPE_STRING && + !(((ast_value*)exprs[0])->hasvalue && ((ast_value*)exprs[0])->cvq == CV_CONST)) + { + compile_error(ast_ctx(exprs[0]), "operand of length operator not a valid constant expression"); + return false; + } + out = fold_op(parser->fold, op, exprs); + break; + case opid2('~', 'P'): if (exprs[0]->vtype != TYPE_FLOAT && exprs[0]->vtype != TYPE_VECTOR) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); @@ -1634,9 +1653,6 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) if (!var) { - char *correct = NULL; - size_t i; - /* * sometimes people use preprocessing predefs without enabling them * i've done this thousands of times already myself. Lets check for @@ -1647,34 +1663,6 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) return false; } - /* - * TODO: determine the best score for the identifier: be it - * a variable, a field. - * - * We should also consider adding correction tables for - * other things as well. - */ - if (OPTS_OPTION_BOOL(OPTION_CORRECTION) && strlen(parser_tokval(parser)) <= 16) { - correction_t corr; - correct_init(&corr); - - for (i = 0; i < vec_size(parser->correct_variables); i++) { - correct = correct_str(&corr, parser->correct_variables[i], parser_tokval(parser)); - if (strcmp(correct, parser_tokval(parser))) { - break; - } else { - mem_d(correct); - correct = NULL; - } - } - correct_free(&corr); - - if (correct) { - parseerror(parser, "unexpected identifier: %s (did you mean %s?)", parser_tokval(parser), correct); - mem_d(correct); - return false; - } - } parseerror(parser, "unexpected identifier: %s", parser_tokval(parser)); return false; } @@ -2026,10 +2014,6 @@ static void parser_enterblock(parser_t *parser) vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE)); vec_push(parser->_blocktypedefs, vec_size(parser->_typedefs)); vec_push(parser->_block_ctx, parser_ctx(parser)); - - /* corrector */ - vec_push(parser->correct_variables, correct_trie_new()); - vec_push(parser->correct_variables_score, NULL); } static bool parser_leaveblock(parser_t *parser) @@ -2043,11 +2027,8 @@ static bool parser_leaveblock(parser_t *parser) } util_htdel(vec_last(parser->variables)); - correct_del(vec_last(parser->correct_variables), vec_last(parser->correct_variables_score)); vec_pop(parser->variables); - vec_pop(parser->correct_variables); - vec_pop(parser->correct_variables_score); if (!vec_size(parser->_blocklocals)) { parseerror(parser, "internal error: parser_leaveblock with no block (2)"); return false; @@ -2082,26 +2063,12 @@ static void parser_addlocal(parser_t *parser, const char *name, ast_expression * { vec_push(parser->_locals, e); util_htset(vec_last(parser->variables), name, (void*)e); - - /* corrector */ - correct_add ( - vec_last(parser->correct_variables), - &vec_last(parser->correct_variables_score), - name - ); } static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e) { vec_push(parser->globals, e); util_htset(parser->htglobals, name, e); - - /* corrector */ - correct_add ( - parser->correct_variables[0], - &parser->correct_variables_score[0], - name - ); } static ast_expression* process_condition(parser_t *parser, ast_expression *cond, bool *_ifnot) @@ -2569,16 +2536,17 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou initexpr = parse_expression_leave(parser, false, false, false); if (!initexpr) goto onerr; - } - /* move on to condition */ - if (parser->tok != ';') { - parseerror(parser, "expected semicolon after for-loop initializer"); - goto onerr; - } - if (!parser_next(parser)) { - parseerror(parser, "expected for-loop condition"); - goto onerr; + /* move on to condition */ + if (parser->tok != ';') { + parseerror(parser, "expected semicolon after for-loop initializer"); + goto onerr; + } + + if (!parser_next(parser)) { + parseerror(parser, "expected for-loop condition"); + goto onerr; + } } /* parse the condition */ @@ -3142,7 +3110,7 @@ static bool parse_switch_go(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) { - if (!parse_variable(parser, block, false, CV_NONE, typevar, false, false, 0, NULL)) { + if (!parse_variable(parser, block, true, CV_NONE, typevar, false, false, 0, NULL)) { ast_delete(switchnode); return false; } @@ -3154,7 +3122,7 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * ast_delete(switchnode); return false; } - if (!parse_variable(parser, block, false, cvq, NULL, noref, is_static, qflags, NULL)) { + if (!parse_variable(parser, block, true, cvq, NULL, noref, is_static, qflags, NULL)) { ast_delete(switchnode); return false; } @@ -3462,7 +3430,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * { if (cvq == CV_WRONG) return false; - return parse_variable(parser, block, true, cvq, NULL, noref, is_static, qflags, vstring); + return parse_variable(parser, block, false, cvq, NULL, noref, is_static, qflags, vstring); } else if (parser->tok == TOKEN_KEYWORD) { @@ -4675,10 +4643,6 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) } } } else { - if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_FTEQCC && param->name[0] == '<') { - parseerror(parser, "parameter name omitted"); - goto on_error; - } vec_push(params, param); if (param->expression.vtype >= TYPE_VARIANT) { char tname[1024]; /* typename is reserved in C++ */ @@ -4697,12 +4661,17 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) } if (parser->tok == TOKEN_IDENT) { argcounter = util_strdup(parser_tokval(parser)); + ast_value_set_name(param, argcounter); if (!parser_next(parser) || parser->tok != ')') { parseerror(parser, "`...` must be the last parameter of a variadic function declaration"); goto on_error; } } } + if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_FTEQCC && param->name[0] == '<') { + parseerror(parser, "parameter name omitted"); + goto on_error; + } } } @@ -5489,22 +5458,8 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield return false; } - /* - * add alias to aliases table and to corrector - * so corrections can apply for aliases as well. - */ util_htset(parser->aliases, var->name, find); - /* - * add to corrector so corrections can work - * even for aliases too. - */ - correct_add ( - vec_last(parser->correct_variables), - &vec_last(parser->correct_variables_score), - var->name - ); - /* generate aliases for vector components */ if (isvector) { char *buffer[3]; @@ -5520,26 +5475,6 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield mem_d(buffer[0]); mem_d(buffer[1]); mem_d(buffer[2]); - - /* - * add to corrector so corrections can work - * even for aliases too. - */ - correct_add ( - vec_last(parser->correct_variables), - &vec_last(parser->correct_variables_score), - me[0]->name - ); - correct_add ( - vec_last(parser->correct_variables), - &vec_last(parser->correct_variables_score), - me[1]->name - ); - correct_add ( - vec_last(parser->correct_variables), - &vec_last(parser->correct_variables_score), - me[2]->name - ); } } } @@ -5562,13 +5497,6 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield /* Add it to the local scope */ util_htset(vec_last(parser->variables), var->name, (void*)var); - /* corrector */ - correct_add ( - vec_last(parser->correct_variables), - &vec_last(parser->correct_variables_score), - var->name - ); - /* now rename the global */ ln = strlen(var->name); vec_append(defname, ln, var->name); @@ -5600,13 +5528,6 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield for (i = 0; i < 3; ++i) { util_htset(vec_last(parser->variables), me[i]->name, (void*)(me[i])); - /* corrector */ - correct_add( - vec_last(parser->correct_variables), - &vec_last(parser->correct_variables_score), - me[i]->name - ); - vec_shrinkto(defname, prefix_len); ln = strlen(me[i]->name); vec_append(defname, ln, me[i]->name); @@ -6000,7 +5921,7 @@ static bool parser_global_statement(parser_t *parser) { if (cvq == CV_WRONG) return false; - return parse_variable(parser, NULL, true, cvq, NULL, noref, is_static, qflags, vstring); + return parse_variable(parser, NULL, false, cvq, NULL, noref, is_static, qflags, vstring); } else if (parser->tok == TOKEN_IDENT && !strcmp(parser_tokval(parser), "enum")) { @@ -6143,10 +6064,6 @@ parser_t *parser_create() parser->aliases = util_htnew(PARSER_HT_SIZE); - /* corrector */ - vec_push(parser->correct_variables, correct_trie_new()); - vec_push(parser->correct_variables_score, NULL); - empty_ctx.file = ""; empty_ctx.line = 0; empty_ctx.column = 0; @@ -6259,13 +6176,6 @@ static void parser_remove_ast(parser_t *parser) vec_free(parser->_blocklocals); vec_free(parser->_locals); - /* corrector */ - for (i = 0; i < vec_size(parser->correct_variables); ++i) { - correct_del(parser->correct_variables[i], parser->correct_variables_score[i]); - } - vec_free(parser->correct_variables); - vec_free(parser->correct_variables_score); - for (i = 0; i < vec_size(parser->_typedefs); ++i) ast_delete(parser->_typedefs[i]); vec_free(parser->_typedefs);