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;
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);
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('|','|'):
* 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;
}
}
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);
}
}
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;
);
}
+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;
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 */
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");
}
/* 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;
/* 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;
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;
}
}
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]);
}
}
}
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 = "<internal>";
empty_ctx.line = 0;
parser->nil = ast_value_new(empty_ctx, "nil", TYPE_NIL);
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);