From 0f120354b623b10dc7e130f931348a030839cd75 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Fri, 19 Jun 2020 07:06:24 +0200 Subject: [PATCH] cex: don't display twice unifying examples if there is no color It makes no sense, and is actually confusing, to display twice the same example with no visible difference. * src/complain.h, src/complain.c (is_styled): New. * src/counterexample.c (print_counterexample): Display the unified example a second time only if it makes a difference. * tests/conflicts.at, tests/counterexample.at, tests/report.at: Adjust. * tests/diagnostics.at: Make sure we do display the unifying examples twice when colors are enabled. And check those colors. --- src/complain.c | 21 ++++++++++++++--- src/complain.h | 2 ++ src/counterexample.c | 13 ++++++++--- tests/conflicts.at | 6 +---- tests/counterexample.at | 12 ---------- tests/diagnostics.at | 50 ++++++++++++++++++++++++++++++++++++++--- tests/report.at | 8 ------- 7 files changed, 78 insertions(+), 34 deletions(-) diff --git a/src/complain.c b/src/complain.c index 92d5fc52..889f0ae6 100644 --- a/src/complain.c +++ b/src/complain.c @@ -104,6 +104,23 @@ flush (FILE *out) fflush (out); } +bool +is_styled (FILE *out) +{ + if (out != stderr) + return false; + if (color_debug) + return true; +#if HAVE_LIBTEXTSTYLE + return (color_mode == color_yes + || color_mode == color_html + || (color_mode == color_tty && isatty (STDERR_FILENO))); +#else + return false; +#endif +} + + /*------------------------. | --warnings's handling. | `------------------------*/ @@ -288,9 +305,7 @@ void complain_init_color (void) { #if HAVE_LIBTEXTSTYLE - if (color_mode == color_yes - || color_mode == color_html - || (color_mode == color_tty && isatty (STDERR_FILENO))) + if (is_styled (stderr)) { style_file_prepare ("BISON_STYLE", "BISON_STYLEDIR", pkgdatadir (), "bison-default.css"); diff --git a/src/complain.h b/src/complain.h index eab5720d..303d0a54 100644 --- a/src/complain.h +++ b/src/complain.h @@ -36,6 +36,8 @@ void end_use_class (const char *style, FILE *out); /** Flush \a out. */ void flush (FILE *out); +/** Whether there's styling on OUT. */ +bool is_styled (FILE *out); /*-------------. | --warnings. | diff --git a/src/counterexample.c b/src/counterexample.c index 01114fdf..e5b3a0af 100644 --- a/src/counterexample.c +++ b/src/counterexample.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "closure.h" @@ -109,9 +110,15 @@ print_counterexample (counterexample *cex, FILE *out, const char *prefix) prefix, _("First derivation")); derivation_print (cex->d1, out, prefix); - fprintf (out, " %s%-20s ", - prefix, cex->unifying ? _("Example") : _("Second example")); - derivation_print_leaves (cex->d2, out, prefix); + // If we output to the terminal (via stderr) and we have color + // support, display unifying examples a second time, as color allows + // to see the differences. + if (!cex->unifying || is_styled (stderr)) + { + fprintf (out, " %s%-20s ", + prefix, cex->unifying ? _("Example") : _("Second example")); + derivation_print_leaves (cex->d2, out, prefix); + } fprintf (out, " %s%-20s ", prefix, _("Second derivation")); derivation_print (cex->d2, out, prefix); diff --git a/tests/conflicts.at b/tests/conflicts.at index a3aadbff..95ab79df 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -763,7 +763,7 @@ AT_CLEANUP AT_SETUP([Unresolved SR Conflicts]) -AT_KEYWORDS([report]) +AT_KEYWORDS([cex report]) AT_DATA([input.y], [[%token NUM OP @@ -866,7 +866,6 @@ State 5 1 exp: exp . OP exp Example exp OP exp . OP exp First derivation exp ::=[ exp ::=[ exp OP exp . ] OP exp ] - Example exp OP exp . OP exp Second derivation exp ::=[ exp OP exp ::=[ exp . OP exp ] ] ]]) @@ -1209,7 +1208,6 @@ State 1 4 id: '0' . Example '0' . First derivation exp ::=[ num ::=[ '0' . ] ] - Example '0' . Second derivation exp ::=[ id ::=[ '0' . ] ] @@ -1776,7 +1774,6 @@ State 5 9 reported_conflicts: 'a' . Example 'a' . First derivation reported_conflicts ::=[ 'a' . ] - Example 'a' . Second derivation reported_conflicts ::=[ 'a' . ] @@ -1961,7 +1958,6 @@ AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0, 13 empty_c3: . %empty Example . 'c' First derivation start ::=[ empty_c2 ::=[ . ] 'c' ] - Example . 'c' Second derivation start ::=[ empty_c3 ::=[ . ] 'c' ] diff --git a/tests/counterexample.at b/tests/counterexample.at index 65dc03cc..48d5acf3 100644 --- a/tests/counterexample.at +++ b/tests/counterexample.at @@ -48,7 +48,6 @@ AT_BISON_CHECK_CEX([input.y], [], [], Shift/reduce conflict on token B: Example A . B C First derivation s ::=[ a ::=[ A . ] x ::=[ B C ] ] - Example A . B C Second derivation s ::=[ y ::=[ A . B ] c ::=[ C ] ] input.y:4.4: warning: rule useless in parser due to conflicts [-Wother] @@ -78,7 +77,6 @@ AT_BISON_CHECK_CEX([input.y], [], [], Shift/reduce conflict on token B: Example A . B C First derivation s ::=[ a ::=[ A . ] bc ::=[ B C ] ] - Example A . B C Second derivation s ::=[ ac ::=[ A ac ::=[ b ::=[ . B ] ] C ] ] input.y:6.4: warning: rule useless in parser due to conflicts [-Wother] @@ -109,7 +107,6 @@ AT_BISON_CHECK_CEX([input.y], [], [], Shift/reduce conflict on token B: Example A . B First derivation s ::=[ ax ::=[ A x ::=[ . ] ] by ::=[ B y ::=[ ] ] ] - Example A . B Second derivation s ::=[ A xby ::=[ . B ] ] Shift/reduce conflict on token B: @@ -208,7 +205,6 @@ AT_BISON_CHECK_CEX([input.y], [], [], Shift/reduce conflict on token A: Example b . A X X Y First derivation a ::=[ r ::=[ b . ] t ::=[ A x ::=[ X ] xy ::=[ X Y ] ] ] - Example b . A X X Y Second derivation a ::=[ s ::=[ b . xx ::=[ A X X ] y ::=[ Y ] ] ] Shift/reduce conflict on token X: @@ -242,7 +238,6 @@ AT_BISON_CHECK_CEX([input.y], [], [], Reduce/reduce conflict on token $end: Example A b . First derivation a ::=[ A b . ] - Example A b . Second derivation a ::=[ A b ::=[ b . ] ] input.y:4.9: warning: rule useless in parser due to conflicts [-Wother] @@ -331,7 +326,6 @@ AT_BISON_CHECK_CEX([input.y], [], [], Shift/reduce conflict on token B: Example N A . B C First derivation s ::=[ n ::=[ N a ::=[ A . ] B ] C ] - Example N A . B C Second derivation s ::=[ n ::=[ N b ::=[ A . B C ] ] ] input.y:5.4: warning: rule useless in parser due to conflicts [-Wother] @@ -364,13 +358,11 @@ AT_BISON_CHECK_CEX([input.y], [], [], Reduce/reduce conflict on tokens b, c: Example B . b c First derivation S ::=[ B ::=[ A ::=[ B . ] b A ::=[ ] ] C ::=[ A ::=[ ] c A ::=[ ] ] ] - Example B . b c Second derivation S ::=[ B C ::=[ A ::=[ B ::=[ A ::=[ . ] b A ::=[ ] ] ] c A ::=[ ] ] ] Reduce/reduce conflict on tokens b, c: Example C . c b First derivation S ::=[ C ::=[ A ::=[ C . ] c A ::=[ ] ] B ::=[ A ::=[ ] b A ::=[ ] ] ] - Example C . c b Second derivation S ::=[ C B ::=[ A ::=[ C ::=[ A ::=[ . ] c A ::=[ ] ] ] b A ::=[ ] ] ] ]]) @@ -438,13 +430,11 @@ Shift/reduce conflict on token A: Reduce/reduce conflict on token $end: Example b d . First derivation a ::=[ b d . ] - Example b d . Second derivation a ::=[ b d ::=[ d . ] ] Reduce/reduce conflict on token $end: Example c d . First derivation a ::=[ c d . ] - Example c d . Second derivation a ::=[ c d ::=[ d . ] ] input.y:5.4: warning: rule useless in parser due to conflicts [-Wother] @@ -476,7 +466,6 @@ AT_BISON_CHECK_CEX([input.y], [], [], Shift/reduce conflict on token J: Example H i J . J J First derivation s ::=[ a ::=[ H i ::=[ i J . ] J J ] ] - Example H i J . J J Second derivation s ::=[ a ::=[ H i J . J ] J ] input.y:5.13-15: warning: rule useless in parser due to conflicts [-Wother] @@ -509,7 +498,6 @@ AT_BISON_CHECK_CEX([input.y], [], [], Shift/reduce conflict on token D: Example A a . D First derivation s ::=[ A a a ::=[ b ::=[ c ::=[ . ] ] ] d ::=[ D ] ] - Example A a . D Second derivation s ::=[ A a d ::=[ . D ] ] ]]) diff --git a/tests/diagnostics.at b/tests/diagnostics.at index 035948c4..6d3ead97 100644 --- a/tests/diagnostics.at +++ b/tests/diagnostics.at @@ -49,15 +49,24 @@ if $EGREP ['\^M|\\[0-9][0-9][0-9]'] input.y experr >/dev/null; then AT_PERL_REQUIRE([-pi -e 's{\^M}{\r}g;s{\\(\d{3}|.)}{$v = $[]1; $v =~ /\A\d+\z/ ? chr($v) : $v}ge' input.y experr]) fi -AT_CHECK([LC_ALL="$locale" $5 bison -fcaret --color=debug -Wall input.y], [$3], [], [experr]) +AT_CHECK([LC_ALL="$locale" $5 bison -fcaret --color=debug -Wall,cex input.y], [$3], [], [experr]) # When no style, same messages, but without style. -AT_PERL_REQUIRE([-pi -e 's{()}{ $[]1 eq "" ? $[]1 : "" }ge' experr]) +# Except for the second display of the counterexample, +# which is not displayed at all. +AT_PERL_REQUIRE([-pi -e ' + s{()}{ $[]1 eq "" ? $[]1 : "" }ge; + if (/Example/) + { + ++$example; + $_ = "" if $example % 2 == 0; + } +' experr]) # Cannot use AT_BISON_CHECK easily as we need to change the # environment. # FIXME: Enhance AT_BISON_CHECK. -AT_CHECK([LC_ALL="$locale" $5 bison -fcaret -Wall input.y], [$3], [], [experr]) +AT_CHECK([LC_ALL="$locale" $5 bison -fcaret -Wall,cex input.y], [$3], [], [experr]) AT_BISON_OPTION_POPDEFS @@ -509,6 +518,41 @@ input.y:11.6-9: error: symbol 'QUUX' is used, but is not defined ]]) +## ----------------- ## +## Counterexamples. ## +## ----------------- ## + +AT_TEST([[Counterexamples]], +[[%expect 0 +%% +exp +: "if" exp "then" exp +| "if" exp "then" exp "else" exp +| exp "+" exp +| "num" +]], +[1], +[[input.y: error: shift/reduce conflicts: 4 found, 0 expected +Shift/reduce conflict on token "+": + Example exp "+" exp "+" exp + First derivation exp ::=[ exp ::=[ exp "+" exp ] "+" exp ] + Example exp "+" exp "+" exp + Second derivation exp ::=[ exp "+" exp ::=[ exp "+" exp ] ] + +Shift/reduce conflict on token "else": + Example "if" exp "then" "if" exp "then" exp "else" exp + First derivation exp ::=[ "if" exp "then" exp ::=[ "if" exp "then" exp ] "else" exp ] + Example "if" exp "then" "if" exp "then" exp "else" exp + Second derivation exp ::=[ "if" exp "then" exp ::=[ "if" exp "then" exp "else" exp ] ] + +Shift/reduce conflict on token "+": + Example "if" exp "then" exp "else" exp "+" exp + First derivation exp ::=[ exp ::=[ "if" exp "then" exp "else" exp ] "+" exp ] + Example "if" exp "then" exp "else" exp "+" exp + Second derivation exp ::=[ "if" exp "then" exp "else" exp ::=[ exp "+" exp ] ] + +]]) + diff --git a/tests/report.at b/tests/report.at index bc2e5dbb..1d93f9a5 100644 --- a/tests/report.at +++ b/tests/report.at @@ -1173,25 +1173,21 @@ input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr] Shift/reduce conflict on token "⊕": Example exp "+" exp • "⊕" exp First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ] - Example exp "+" exp • "⊕" exp Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ] Reduce/reduce conflict on tokens $end, "+", "⊕": Example exp "+" exp • First derivation exp ::=[ exp "+" exp • ] - Example exp "+" exp • Second derivation exp ::=[ exp "+" exp • ] Shift/reduce conflict on token "⊕": Example exp "+" exp • "⊕" exp First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ] - Example exp "+" exp • "⊕" exp Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ] Shift/reduce conflict on token "⊕": Example exp "⊕" exp • "⊕" exp First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "⊕" exp ] - Example exp "⊕" exp • "⊕" exp Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "⊕" exp ] ] input.y:6.3-13: warning: rule useless in parser due to conflicts [-Wother] @@ -1342,7 +1338,6 @@ State 7 1 exp: exp • "⊕" exp Example exp "+" exp • "⊕" exp First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ] - Example exp "+" exp • "⊕" exp Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ] Reduce/reduce conflict on tokens $end, "+", "⊕": @@ -1350,7 +1345,6 @@ State 7 3 exp: exp "+" exp • Example exp "+" exp • First derivation exp ::=[ exp "+" exp • ] - Example exp "+" exp • Second derivation exp ::=[ exp "+" exp • ] Shift/reduce conflict on token "⊕": @@ -1358,7 +1352,6 @@ State 7 1 exp: exp • "⊕" exp Example exp "+" exp • "⊕" exp First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ] - Example exp "+" exp • "⊕" exp Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ] @@ -1382,7 +1375,6 @@ State 8 1 exp: exp • "⊕" exp Example exp "⊕" exp • "⊕" exp First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "⊕" exp ] - Example exp "⊕" exp • "⊕" exp Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "⊕" exp ] ] ]])