ht htglobals;
ht *typedefs;
+ /* same as above but for the spelling corrector */
+ ht *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;
size_t *_blocklocals;
}
else
{
+ size_t i;
+ char *correct = NULL;
+
/*
* sometimes people use preprocessing predefs without enabling them
* i've done this thousands of times already myself. Lets check for
* it in the predef table. And diagnose it better :)
*/
if (!OPTS_FLAG(FTEPP_PREDEFS)) {
- size_t i;
for (i = 0; i < sizeof(ftepp_predefs)/sizeof(*ftepp_predefs); i++) {
if (!strcmp(ftepp_predefs[i].name, parser_tokval(parser))) {
parseerror(parser, "unexpected ident: %s (use -fftepp-predef to enable pre-defined macros)", parser_tokval(parser));
}
}
- parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
+ /*
+ * 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.
+ */
+ 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 (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));
+ }
+
goto onerr;
}
}
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, util_htnew(PARSER_HT_SIZE));
+ vec_push(parser->correct_variables_score, NULL);
}
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;
vec_pop(parser->typedefs);
vec_pop(parser->_block_ctx);
+
return rv;
}
{
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 ast_expression* process_condition(parser_t *parser, ast_expression *cond, bool *_ifnot)
}
/* 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;
vec_push(parser->globals, (ast_expression*)thinkfunc);
util_htset(parser->htglobals, thinkfunc->name, thinkfunc);
+
nextthink = (ast_expression*)thinkfunc;
} else {
/* 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);
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);
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]);
+ }
+ 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);
+
+
for (i = 0; i < vec_size(parser->_typedefs); ++i)
ast_delete(parser->_typedefs[i]);
vec_free(parser->_typedefs);