X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=parser.c;h=b15280b8d993ee9f33441463a700762f1ed460fb;hp=7c6854b6c14dd8db480ca30c9e0ec0d80eba219b;hb=428453a132f4099d1ff8f61598166bff9d1d3bb4;hpb=18b9473cf823e9e69f0557f125ac5d255236a899 diff --git a/parser.c b/parser.c index 7c6854b..b15280b 100644 --- a/parser.c +++ b/parser.c @@ -75,8 +75,8 @@ typedef struct { ht *typedefs; /* same as above but for the spelling corrector */ - ht *correct_variables; - size_t ***correct_variables_score; /* vector of vector of size_t* */ + correct_trie_t **correct_variables; + size_t ***correct_variables_score; /* vector of vector of size_t* */ /* not to be used directly, we use the hash table */ ast_expression **_locals; @@ -109,6 +109,7 @@ static const ast_expression *intrinsic_debug_typestring = (ast_expression*)0x10; static void parser_enterblock(parser_t *parser); static bool parser_leaveblock(parser_t *parser); static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e); +static void parser_addglobal(parser_t *parser, const char *name, ast_expression *e); static bool parse_typedef(parser_t *parser); static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring); static ast_block* parse_block(parser_t *parser); @@ -928,14 +929,21 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) exprs[0], exprs[1]); break; case opid1('^'): - parseerror(parser, "TODO: bitxor"); + compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor via ^"); return false; case opid2('<','<'): case opid2('>','>'): + if (CanConstFold(exprs[0], exprs[1]) && ! NotSameType(TYPE_FLOAT)) { + if (op->id == opid2('<','<')) + out = (ast_expression*)parser_const_float(parser, (double)((int)(ConstF(0)) << (int)(ConstF(1)))); + else + out = (ast_expression*)parser_const_float(parser, (double)((int)(ConstF(0)) >> (int)(ConstF(1)))); + break; + } case opid3('<','<','='): case opid3('>','>','='): - parseerror(parser, "TODO: shifts"); + compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-shifts"); return false; case opid2('|','|'): @@ -1642,22 +1650,28 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma * We should also consider adding correction tables for * other things as well. */ - for (i = 0; i < vec_size(parser->correct_variables); i++) { - correct = correct_str(parser->correct_variables[i], "ello"); - if (strcmp(correct, parser_tokval(parser))) { - break; - } else if (correct) { - mem_d(correct); + if (OPTS_FLAG(ENHANCED_DIAGNOSTICS)) { + 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 if (correct) { + mem_d(correct); + correct = NULL; + } } - } + correct_free(&corr); - if (correct) { - parseerror(parser, "unexpected ident: %s (did you mean %s?)", parser_tokval(parser), correct); - /*mem_d(correct);*/ - } else { - parseerror(parser, "unexpected ident: %s", parser_tokval(parser)); + if (correct) { + parseerror(parser, "unexpected ident: %s (did you mean %s?)", parser_tokval(parser), correct); + mem_d(correct); + goto onerr; + } } - + parseerror(parser, "unexpected ident: %s", parser_tokval(parser)); goto onerr; } } @@ -1998,7 +2012,7 @@ static void parser_enterblock(parser_t *parser) vec_push(parser->_block_ctx, parser_ctx(parser)); /* corrector */ - vec_push(parser->correct_variables, util_htnew(PARSER_HT_SIZE)); + vec_push(parser->correct_variables, correct_trie_new()); vec_push(parser->correct_variables_score, NULL); } @@ -2013,11 +2027,11 @@ static bool parser_leaveblock(parser_t *parser) } util_htdel(vec_last(parser->variables)); - util_htdel(vec_last(parser->correct_variables)); /* corrector */ - vec_free(vec_last(parser->correct_variables_score)); /* corrector */ + correct_del(vec_last(parser->correct_variables), vec_last(parser->correct_variables_score)); vec_pop(parser->variables); - vec_pop(parser->correct_variables); /* corrector */ + 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; @@ -2061,6 +2075,19 @@ static void parser_addlocal(parser_t *parser, const char *name, ast_expression * ); } +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) { bool ifnot = false; @@ -2164,6 +2191,8 @@ static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out) ast_delete(cond); return false; } + if (!ontrue) + ontrue = (ast_expression*)ast_block_new(parser_ctx(parser)); /* check for an else */ if (!strcmp(parser_tokval(parser), "else")) { /* parse into the 'else' branch */ @@ -2641,6 +2670,13 @@ static bool parse_break_continue(parser_t *parser, ast_block *block, ast_express return false; } + if (!vec_size(loops)) { + if (is_continue) + parseerror(parser, "`continue` can only be used inside loops"); + else + parseerror(parser, "`break` can only be used inside loops or switches"); + } + if (parser->tok == TOKEN_IDENT) { if (!OPTS_FLAG(LOOP_LABELS)) parseerror(parser, "labeled loops not activated, try using -floop-labels"); @@ -3043,28 +3079,35 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * } /* parse computed goto sides */ -static ast_expression *parse_goto_computed(parser_t *parser, ast_expression *side) { +static ast_expression *parse_goto_computed(parser_t *parser, ast_expression **side) { ast_expression *on_true; ast_expression *on_false; + ast_expression *cond; - if (!side) + if (!*side) return NULL; - if (ast_istype(side, ast_ternary)) { - on_true = parse_goto_computed(parser, ((ast_ternary*)side)->on_true); - on_false = parse_goto_computed(parser, ((ast_ternary*)side)->on_false); + if (ast_istype(*side, ast_ternary)) { + ast_ternary *tern = (ast_ternary*)*side; + on_true = parse_goto_computed(parser, &tern->on_true); + on_false = parse_goto_computed(parser, &tern->on_false); if (!on_true || !on_false) { parseerror(parser, "expected label or expression in ternary"); - if (((ast_ternary*)side)->on_false) ast_unref(((ast_ternary*)side)->on_false); - if (((ast_ternary*)side)->on_true) ast_unref(((ast_ternary*)side)->on_true); + if (on_true) ast_unref(on_true); + if (on_false) ast_unref(on_false); return NULL; } - return (ast_expression*)ast_ifthen_new(parser_ctx(parser), ((ast_ternary*)side)->cond, on_true, on_false); - } else if (ast_istype(side, ast_label)) { - ast_goto *gt = ast_goto_new(parser_ctx(parser), ((ast_label*)side)->name); - ast_goto_set_label(gt, ((ast_label*)side)); + cond = tern->cond; + tern->cond = NULL; + ast_delete(tern); + *side = NULL; + return (ast_expression*)ast_ifthen_new(parser_ctx(parser), cond, on_true, on_false); + } else if (ast_istype(*side, ast_label)) { + ast_goto *gt = ast_goto_new(parser_ctx(parser), ((ast_label*)*side)->name); + ast_goto_set_label(gt, ((ast_label*)*side)); + *side = NULL; return (ast_expression*)gt; } return NULL; @@ -3089,7 +3132,7 @@ static bool parse_goto(parser_t *parser, ast_expression **out) /* failed to parse expression for goto */ if (!(expression = parse_expression(parser, false, true)) || - !(*out = parse_goto_computed(parser, expression))) { + !(*out = parse_goto_computed(parser, &expression))) { parseerror(parser, "invalid goto expression"); ast_unref(expression); return false; @@ -3584,8 +3627,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) return false; } - vec_push(parser->globals, (ast_expression*)thinkfunc); - util_htset(parser->htglobals, thinkfunc->name, thinkfunc); + parser_addglobal(parser, thinkfunc->name, (ast_expression*)thinkfunc); nextthink = (ast_expression*)thinkfunc; @@ -4802,12 +4844,10 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } } else { - vec_push(parser->globals, (ast_expression*)var); - util_htset(parser->htglobals, var->name, var); + parser_addglobal(parser, var->name, (ast_expression*)var); if (isvector) { for (i = 0; i < 3; ++i) { - vec_push(parser->globals, (ast_expression*)me[i]); - util_htset(parser->htglobals, me[i]->name, me[i]); + parser_addglobal(parser, me[i]->name, (ast_expression*)me[i]); } } } @@ -5301,6 +5341,10 @@ bool parser_init() vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE)); vec_push(parser->_blocktypedefs, 0); + /* corrector */ + vec_push(parser->correct_variables, correct_trie_new()); + vec_push(parser->correct_variables_score, NULL); + empty_ctx.file = ""; empty_ctx.line = 0; parser->nil = ast_value_new(empty_ctx, "nil", TYPE_NIL); @@ -5406,9 +5450,6 @@ void parser_cleanup() for (i = 0; i < vec_size(parser->correct_variables); ++i) { correct_del(parser->correct_variables[i], parser->correct_variables_score[i]); } - for (i = 0; i < vec_size(parser->correct_variables_score); ++i) { - vec_free(parser->correct_variables_score[i]); - } vec_free(parser->correct_variables); vec_free(parser->correct_variables_score);