summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkim Demaille <akim.demaille@gmail.com>2019-09-27 18:28:19 +0200
committerAkim Demaille <akim.demaille@gmail.com>2019-10-06 09:54:25 +0200
commitbe3cf406afcd68bbf1c113607f3362722f4418d1 (patch)
treeba19fa11dedeb8ba306533fa6c4c441ebc5f2de9 /src
parent126c4622de27197bbe4c6a713f28d114839e636f (diff)
downloadbison-be3cf406afcd68bbf1c113607f3362722f4418d1.tar.gz
diagnostics: suggest fixes for undeclared symbols
From input.y:1.17-19: warning: symbol baz is used, but is not defined as a token and has no rules [-Wother] 1 | %printer {} foo baz | ^~~ to input.y:1.17-19: warning: symbol 'baz' is used, but is not defined as a token and has no rules; did you mean 'bar'? [-Wother] 1 | %printer {} foo baz | ^~~ | bar * bootstrap.conf: We need fstrcmp. * src/symtab.c (symbol_from_uniqstr_fuzzy): New. (complain_symbol_undeclared): Use it. * tests/diagnostics.at (Suggestions): New. * data/bison-default.css (insertion): Rename as... (fixit-insert): this, as this is what GCC uses.
Diffstat (limited to 'src')
-rw-r--r--src/location.c2
-rw-r--r--src/symtab.c56
2 files changed, 49 insertions, 9 deletions
diff --git a/src/location.c b/src/location.c
index b36f49d3..e6406bd6 100644
--- a/src/location.c
+++ b/src/location.c
@@ -473,7 +473,7 @@ location_caret (location loc, const char *style, FILE *out)
void
location_caret_suggestion (location loc, const char *s, FILE *out)
{
- const char *style = "insertion";
+ const char *style = "fixit-insert";
fprintf (out, " | %*s",
loc.start.column - 1 - caret_info.skip + (caret_info.skip ? 3 : 0),
"");
diff --git a/src/symtab.c b/src/symtab.c
index c7d308ac..b3642e67 100644
--- a/src/symtab.c
+++ b/src/symtab.c
@@ -24,6 +24,7 @@
#include "system.h"
#include <assure.h>
+#include <fstrcmp.h>
#include <hash.h>
#include "complain.h"
@@ -32,6 +33,8 @@
#include "quote.h"
+static struct hash_table *symbol_table = NULL;
+static struct hash_table *semantic_type_table = NULL;
/*----------------------------------------------------------------.
| Symbols sorted by tag. Allocated by table_sort, after which no |
@@ -41,6 +44,7 @@
static symbol **symbols_sorted = NULL;
static semantic_type **semantic_types_sorted = NULL;
+
/*------------------------.
| Distinguished symbols. |
`------------------------*/
@@ -321,15 +325,54 @@ complain_class_redeclared (symbol *sym, symbol_class class, location second)
}
}
+static const symbol *
+symbol_from_uniqstr_fuzzy (const uniqstr key)
+{
+ aver (symbols_sorted);
+#define FSTRCMP_THRESHOLD 0.6
+ double best_similarity = FSTRCMP_THRESHOLD;
+ const symbol *res = NULL;
+ size_t count = hash_get_n_entries (symbol_table);
+ for (int i = 0; i < count; ++i)
+ {
+ symbol *sym = symbols_sorted[i];
+ if (STRNEQ (key, sym->tag)
+ && (sym->content->status == declared
+ || sym->content->status == undeclared))
+ {
+ double similarity = fstrcmp_bounded (key, sym->tag, best_similarity);
+ if (best_similarity < similarity)
+ {
+ res = sym;
+ best_similarity = similarity;
+ }
+ }
+ }
+ return res;
+}
+
static void
complain_symbol_undeclared (symbol *sym)
{
assert (sym->content->status != declared);
- complain (&sym->location,
- sym->content->status == needed ? complaint : Wother,
- _("symbol %s is used, but is not defined as a token"
- " and has no rules"),
- quote (sym->tag));
+ const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag);
+ if (best)
+ {
+ complain (&sym->location,
+ sym->content->status == needed ? complaint : Wother,
+ _("symbol %s is used, but is not defined as a token"
+ " and has no rules; did you mean %s?"),
+ quote_n (0, sym->tag),
+ quote_n (1, best->tag));
+ if (feature_flag & feature_caret)
+ location_caret_suggestion (sym->location, best->tag, stderr);
+ }
+ else
+ complain (&sym->location,
+ sym->content->status == needed ? complaint : Wother,
+ _("symbol %s is used, but is not defined as a token"
+ " and has no rules"),
+ quote (sym->tag));
}
void
@@ -694,9 +737,6 @@ symbol_translation (symbol *this)
/* Initial capacity of symbol and semantic type hash table. */
#define HT_INITIAL_CAPACITY 257
-static struct hash_table *symbol_table = NULL;
-static struct hash_table *semantic_type_table = NULL;
-
static inline bool
hash_compare_symbol (const symbol *m1, const symbol *m2)
{