summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstrap.conf3
-rw-r--r--data/bison-default.css3
-rw-r--r--lib/.gitignore5
-rw-r--r--lib/glthread/.gitignore2
-rw-r--r--m4/.gitignore5
-rw-r--r--src/location.c2
-rw-r--r--src/symtab.c56
-rw-r--r--tests/diagnostics.at36
8 files changed, 95 insertions, 17 deletions
diff --git a/bootstrap.conf b/bootstrap.conf
index 4f6ef94f..22816271 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -22,7 +22,8 @@ gnulib_modules='
calloc-posix close closeout config-h c-strcase
configmake
dirname
- error extensions fdl fopen-safer
+ error extensions
+ fdl fopen-safer fstrcmp
getopt-gnu
gettext-h git-version-gen gitlog-to-changelog
gpl-3.0 intprops inttypes isnan javacomp-script
diff --git a/data/bison-default.css b/data/bison-default.css
index 41304a2b..68df166a 100644
--- a/data/bison-default.css
+++ b/data/bison-default.css
@@ -21,7 +21,8 @@
.warning { color: purple; }
.error { color: red; }
.note { color: cyan; }
-.insertion { color: green; }
+
+.fixit-insert { color: green; }
/* Semantic values in Bison's own parser traces. */
.value { color: green; }
diff --git a/lib/.gitignore b/lib/.gitignore
index 0f007442..dc8934d5 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -53,6 +53,7 @@
/config.h
/config.in.h
/configmake.h
+/diffseq.h
/dirname-lgpl.c
/dirname.c
/dirname.h
@@ -91,6 +92,8 @@
/fseterr.c
/fseterr.h
/fstat.c
+/fstrcmp.c
+/fstrcmp.h
/fsync.c
/getdtablesize.c
/gethrxtime.c
@@ -324,6 +327,8 @@
/windows-recmutex.h
/windows-rwlock.c
/windows-rwlock.h
+/windows-tls.c
+/windows-tls.h
/xalloc-die.c
/xalloc-oversized.h
/xalloc.h
diff --git a/lib/glthread/.gitignore b/lib/glthread/.gitignore
index e0605e15..b854214e 100644
--- a/lib/glthread/.gitignore
+++ b/lib/glthread/.gitignore
@@ -1,3 +1,5 @@
/lock.c
/lock.h
/threadlib.c
+/tls.c
+/tls.h
diff --git a/m4/.gitignore b/m4/.gitignore
index 45f05270..f661f375 100644
--- a/m4/.gitignore
+++ b/m4/.gitignore
@@ -71,6 +71,8 @@
/iswblank.m4
/javacomp.m4
/javaexec.m4
+/jm-winsz1.m4
+/jm-winsz2.m4
/largefile.m4
/lcmessage.m4
/ldexp.m4
@@ -179,6 +181,7 @@
/threadlib.m4
/time_h.m4
/timespec.m4
+/tls.m4
/uintmax_t.m4
/unistd-safer.m4
/unistd_h.m4
@@ -202,5 +205,3 @@
/xalloc.m4
/xsize.m4
/xstrndup.m4
-/jm-winsz1.m4
-/jm-winsz2.m4
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)
{
diff --git a/tests/diagnostics.at b/tests/diagnostics.at
index 4042a815..bd01c15d 100644
--- a/tests/diagnostics.at
+++ b/tests/diagnostics.at
@@ -46,7 +46,7 @@ AT_DATA([experr], [$4])
AT_CHECK([LC_ALL=en_US.UTF-8 $5 bison -fcaret --color=debug -Wall input.y], [$3], [], [experr])
# When no style, same messages, but without style.
-AT_CHECK([perl -pi -e 's{(</?\w+>)}{ $[]1 eq "<tag>" ? $[]1 : "" }ge' experr])
+AT_CHECK([perl -pi -e 's{(</?(-|\w)+>)}{ $[]1 eq "<tag>" ? $[]1 : "" }ge' experr])
# Cannot use AT_BISON_CHECK easily as we need to change the
# environment.
@@ -344,7 +344,7 @@ input.y:9.8-33: previous declaration
input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>]
10 | <warning>%error-verbose</warning>
| <warning>^~~~~~~~~~~~~~</warning>
- | <insertion>%define parse.error verbose</insertion>
+ | <fixit-insert>%define parse.error verbose</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]],
[[COLUMNS=200]])
@@ -377,7 +377,7 @@ input.y:9.8-33: previous declaration
input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>]
10 | <warning>%error-verbose</warning>
| <warning>^~~~~~~~~~~~~~</warning>
- | <insertion>%define parse.error verbose</insertion>
+ | <fixit-insert>%define parse.error verbose</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]],
[[COLUMNS=80]])
@@ -410,11 +410,39 @@ input.y:9.8-33: previous declaration
input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>]
10 | ... <warning>%error-verbose</warning>
| <warning>^~~~~~~~~~~~~~</warning>
- | <insertion>%define parse.error verbose</insertion>
+ | <fixit-insert>%define parse.error verbose</fixit-insert>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]],
[[COLUMNS=60]])
+
+## ------------- ##
+## Suggestions. ##
+## ------------- ##
+
+# Don't suggest to fix QUX with QUUX and QUUX with QUX...
+AT_TEST([[Suggestions]],
+[[%%
+res: QUX baz
+bar: QUUX
+]],
+[1],
+[[input.y:11.6-9: <error>error:</error> symbol 'QUUX' is used, but is not defined as a token and has no rules
+ 11 | bar: <error>QUUX</error>
+ | <error>^~~~</error>
+input.y:10.6-8: <error>error:</error> symbol 'QUX' is used, but is not defined as a token and has no rules
+ 10 | res: <error>QUX</error> baz
+ | <error>^~~</error>
+input.y:10.10-12: <error>error:</error> symbol 'baz' is used, but is not defined as a token and has no rules; did you mean 'bar'?
+ 10 | res: QUX <error>baz</error>
+ | <error>^~~</error>
+ | <fixit-insert>bar</fixit-insert>
+]])
+
+
+
+
+
m4_popdef([AT_TEST])