Compare commits

...
58 Commits
Author SHA1 Message Date
Akim Demaille 6675d36e25 version 3.7
* NEWS: Record release date.
2020-07-23 19:58:16 +02:00
Akim Demaille d0bec3175f style: avoid warnings with GCC 4.6
With have a clash with the "max" function.

    src/counterexample.c: In function 'visited_hasher':
    src/counterexample.c:720:48: error: declaration of 'max' shadows a global declaration [-Werror=shadow]
    src/counterexample.c:116:12: error: shadowed declaration is here [-Werror=shadow]

* src/counterexample.c (visited_hasher): Alpha conversion.
2020-07-23 19:55:24 +02:00
Akim Demaille 79e68b6c4d doc: fix definition of -Wall
* doc/bison.texi (Diagnostics): here.
2020-07-23 09:17:18 +02:00
Akim Demaille 5cb74cacd8 gnulib: update
* bootstrap.conf: We need stpncpy.
2020-07-23 06:56:25 +02:00
Akim Demaille 9c8e6e05b6 tests: fixes
Fix 6b78e50cef, "cex: make "rerun with
'-Wcex'" a note instead of a warning"

* tests/conflicts.at (-W versus %expect and %expect-rr): Fix
expectations.
2020-07-23 06:33:30 +02:00
Akim Demaille 431774d1f6 cex: update NEWS for 3.7
* NEWS: Update to the current style of cex display.
2020-07-22 07:36:02 +02:00
Akim Demaille 7d5474e979 doc: catch up with the current display of cex
Unfortunately I found no way to use the ↳ glyph in Texinfo, so I used
@arrow{} instead, which has a different width, so we have to have all
the examples doubled, once for TeX, another for the rest of the world.

* doc/bison.texi: Use the current display in the examples.
* doc/calc.y, doc/ids.y, doc/if-then-else.y, doc/sequence.y: New.
2020-07-22 07:36:02 +02:00
Akim Demaille 6b78e50cef cex: make "rerun with '-Wcex'" a note instead of a warning
Currently the suggestion to rerun is a -Wother warning:

    warning: 2 shift/reduce conflicts [-Wconflicts-sr]
    warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother]

Instead, let's attach it as a subnote of the diagnostic (in the
current case, -Wconflicts-sr):

    warning: 2 shift/reduce conflicts [-Wconflicts-sr]
    note: rerun with option '-Wcounterexamples' to generate conflict counterexamples

* src/conflicts.c (conflicts_print): Do that.
Adjust the test suite.
2020-07-21 18:57:56 +02:00
Akim Demaille 28769d608e maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-07-20 07:58:03 +02:00
Akim Demaille a22588bcb9 version 3.6.93
* NEWS: Record release date.
2020-07-20 07:37:47 +02:00
Akim Demaille b8c5e5609f cex: label all the derivations by their initial action
From

    input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
      Example: A b .
      First derivation
        a
        `-> A b .
      Second derivation
        a
        `-> A b
              `-> b .

to

    input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
      Example: A b .
      First reduce derivation
        a
        `-> A b .
      Second reduce derivation
        a
        `-> A b
              `-> b .

* src/counterexample.c (print_counterexample): here.
Compute the width of the labels to properly align the values.
* tests/conflicts.at, tests/counterexample.at, tests/diagnostics.at,
* tests/report.at: Adjust.
2020-07-20 07:36:38 +02:00
Akim Demaille b81229e1f9 cex: improve readability of the subsections
Now that the derivation is no longer printed on one line, aligning the
example and the derivation is no longer useful.  It can actually be
harmful, as it makes the overall structure less clear.

* src/derivation.h, src/derivation.c (derivation_print_leaves): Remove
the `prefix` argument.
* src/counterexample.c (print_counterexample): Put the example next to
its label.
* tests/conflicts.at, tests/counterexample.at, tests/diagnostics.at,
* tests/report.at: Adjust.
2020-07-20 07:09:31 +02:00
Akim Demaille 815a76f558 cex: don't issue an empty line between counterexamples
Now that we use complain, the "sections" are clearer.

* src/counterexample.c (print_counterexample): Use the empty line only
in reports.
* tests/counterexample.at, tests/diagnostics.at, tests/report.at: Adjust.
2020-07-20 06:45:31 +02:00
Akim Demaille ea138cd1f1 cex: use usual routines for diagnostics about S/R conflicts
See previous commit.  We go from

    input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
    Shift/reduce conflict on token "⊕":
      Example              exp "+" exp • "⊕" exp
      Shift derivation
        exp
        ↳ exp "+" exp
                  ↳ exp • "⊕" exp

to

    input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
    input.y: warning: shift/reduce conflict on token "⊕" [-Wcounterexamples]
      Example              exp "+" exp • "⊕" exp
      Shift derivation
        exp
        ↳ exp "+" exp
                  ↳ exp • "⊕" exp

with an hyperlink on -Wcounterexamples.

* src/counterexample.c (counterexample_report_shift_reduce):
Use complain.
* tests/counterexample.at, tests/diagnostics.at, tests/report.at:
Adjust.
2020-07-20 06:45:27 +02:00
Akim Demaille 9922f1f877 cex: use usual routines for diagnostics about R/R conflicts
This is more consistent, and brings benefits: users know that these
diagnostics are attached to -Wcounterexamples, and they can also click
on the hyperlink if permitted by their terminal.

We go from

    warning: 1 reduce/reduce conflict [-Wconflicts-rr]
    Reduce/reduce conflict on token $end:
      Example              A b .
      First derivation     a -> [ A b . ]
      Second derivation    a -> [ A b -> [ b . ] ]

to

    warning: 1 reduce/reduce conflict [-Wconflicts-rr]
    input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
      Example              A b .
      First derivation     a -> [ A b . ]
      Second derivation    a -> [ A b -> [ b . ] ]

with an hyperlink on -Wcounterexamples.

* src/counterexample.c (counterexample_report_reduce_reduce):
Use complain.
* tests/counterexample.at, tests/diagnostics.at, tests/report.at:
Adjust.
2020-07-20 06:45:21 +02:00
Akim Demaille 1438b79e80 diagnostics: use hyperlinks to point to the only documentation
* src/complain.c (begin_hyperlink, end_hyperlink): New.
(warnings_print_categories): Use them.
* tests/local.at (AT_SET_ENV): Disable hyperlinks in the tests, they
contain random id's, and brackets (which is not so nice for M4).
2020-07-19 19:26:47 +02:00
Akim Demaille 01f3e2969b doc: add anchors for warnings
Unfortunately Texinfo somewhat mangles anchors such as `-Werror` into
`g_t_002dWerror`, so let's not include the dash.

* doc/bison.texi (Diagnostics): here.
2020-07-19 17:28:45 +02:00
Akim Demaille 744da03955 glyphs: fix types
The code was written on top of buffers of `char[26]`, and then was
changed to use `char *`, yet was still using `sizeof buf`, which
became `sizeof (char *)` instead of `sizeof (char[26])`.

Reported by Dagobert Michelsen.
https://lists.gnu.org/r/bug-bison/2020-07/msg00023.html

* src/glyphs.h, src/glyphs.c: Get rid of uses of `char *`, use only
glyph_buffer_t.
2020-07-19 17:09:01 +02:00
Akim Demaille b28d67b6b0 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-07-19 09:45:36 +02:00
Akim Demaille cf890692f1 version 3.6.92
* NEWS: Record release date.
2020-07-19 09:24:57 +02:00
Akim Demaille 6932023f4d style: avoid strncpy
syntax-check seems to dislike strncpy.  The GNU Coreutils replaced
their uses of strncpy with stpncpy.

strlcpy is not an option.
  http://sources.redhat.com/ml/libc-alpha/2002-01/msg00159.html
  http://sources.redhat.com/ml/libc-alpha/2002-01/msg00011.html
  http://lists.gnu.org/archive/html/bug-gnulib/2004-09/msg00181.html

* src/glyphs.c: Use stpncpy.
2020-07-19 09:23:42 +02:00
Akim Demaille fff17fe8fe cex: display derivations as trees
Sometimes, understanding the derivations is difficult, because they
are serialized to fit in one line.  For instance, the example taken
from the NEWS file:

    %token ID
    %%
    s: a ID
    a: expr
    expr: expr ID ',' | "expr"

gave

    First example        expr • ID ',' ID $end
    Shift derivation     $accept → [ s → [ a → [ expr → [ expr • ID ',' ] ] ID ] $end ]
    Second example       expr • ID $end
    Reduce derivation    $accept → [ s → [ a → [ expr • ] ID ] $end ]

Printing as trees, it gives:

    First example        expr • ID ',' ID $end
    Shift derivation
      $accept
      ↳ s                      $end
        ↳ a                 ID
          ↳ expr
            ↳ expr • ID ','
    Second example       expr • ID $end
    Reduce derivation
      $accept
      ↳ s             $end
        ↳ a        ID
          ↳ expr •

* src/glyphs.h, src/glyphs.c (down_arrow, empty, derivation_separator):
New.
* src/derivation.c (derivation_print, derivation_print_impl): Rename
as...
(derivation_print_flat, derivation_print_flat_impl): These.
(fputs_if, derivation_depth, derivation_width, derivation_print_tree)
(derivation_print_tree_impl, derivation_print): New.
* src/counterexample.c (print_counterexample): Adjust.
* tests/conflicts.at, tests/counterexample.at, tests/diagnostics.at,
* tests/report.at: Adjust.
2020-07-18 07:54:02 +02:00
Akim Demaille 5544615a59 cex: use the glyphs
* src/derivation.c: here.
* src/gram.h, src/gram.c (print_arrow, print_dot, print_fallback):
Remove.
2020-07-16 07:31:25 +02:00
Akim Demaille 346ba14f15 cex: factor the handling of graphical symbols
* src/glyphs.h, src/glyphs.c: New.
2020-07-16 07:31:24 +02:00
Akim Demaille 4d18195ebc cex: style changes
* src/counterexample.c: here.
2020-07-15 06:41:07 +02:00
Akim Demaille dd3e7b3895 cex: simplify tests
* tests/counterexample.at (AT_BISON_CHECK_CEX): Handle the keyword.
Simplify the signature.
2020-07-15 06:38:36 +02:00
Akim Demaille 64a3b6546a cex: more colors
Provided by Daniela Becker.

* data/bison-default.css: More colors.
2020-07-15 06:38:36 +02:00
Akim Demaille bad07a7f66 style: comments changes
* src/print.c: here.
2020-07-14 14:26:02 +02:00
Akim Demaille 88bd814bf1 doc: update GLR sections
Reported by Christian Schoenebeck.

* doc/bison.texi (GLR Parsers): Minor fixes.
(Compiler Requirements for GLR): Remove, quite useless today.
2020-07-14 06:56:15 +02:00
Akim Demaille 4f9ae5de07 cex: display shifts before reductions
When reporting counterexamples for s/r conflicts, put the shift first.
This is more natural, and displays the default resolution first, which
is also what happens for r/r conflicts where the smallest rule number
is displayed first, and "wins".

* src/counterexample.c (counterexample): Add a shift_reduce member.
(new_counterexample): Adjust.
Swap the derivations when this is a s/r conflict.
(print_counterexample): For s/r conflicts, prefer "Shift derivation"
and "Reduce derivation" rather than "First/Second derivation".

* tests/conflicts.at, tests/counterexample.at, tests/report.at: Adjust.
* NEWS, doc/bison.texi: Ditto.
2020-07-14 06:48:48 +02:00
Akim Demaille 78f72a4516 style: s/lookahead_tokens/lookaheads/g
Currently we use both names.  Let's stick to the short one.

* src/AnnotationList.c, src/conflicts.c, src/counterexample.c,
* src/getargs.c, src/getargs.h, src/graphviz.c, src/ielr.c,
* src/lalr.c, src/print-graph.c, src/print-xml.c, src/print.c,
* src/state-item.c, src/state.c, src/state.h, src/tables.c:
s/lookahead_token/lookahead/gi.
2020-07-14 06:48:48 +02:00
Akim Demaille c04693d651 cex: factor memory allocation
* src/counterexample.c (counterexample_report_state): Allocate once
per conflicted state, instead of once per r/r conflict.
2020-07-14 06:48:48 +02:00
Akim Demaille 12191911ba cex: use state_item_number consistently
* src/counterexample.c, src/state-item.c: here.
(counterexample_report_state): While at it, prefer c2 to j/k, to match
c1.
2020-07-14 06:48:48 +02:00
Akim Demaille d7f27477f4 cex: more consistent memory allocation/copy
* src/counterexample.c, src/parse-simulation.c: It is more usual in
Bison to use sizeof on expressions than on types, especially for
allocation.
Let the compiler do it's job instead of calling memcpy ourselves.
2020-07-14 06:48:48 +02:00
Akim Demaille 5bad15d7ea cex: minor renaming
* src/counterexample.c (has_common_prefix): Rename as...
(have_common_prefix): this.
2020-07-14 06:48:48 +02:00
Akim Demaille cd099edf2d cex: use better type names
There are too many gl_list_t in there, it's hard to understand what is
going on.  Introduce and use more precise types.  I sure can be wrong
in some places, it's hard to tell without proper tool support.

* src/counterexample.c, src/lssi.c, src/lssi.h, src/parse-simulation.c,
* src/parse-simulation.h, src/state-item.c, src/state-item.h
(si_bfs_node_list, search_state_list, ssb_list, lssi_list)
(state_item_list): New.
2020-07-14 06:48:48 +02:00
Akim Demaille 1e12219775 cex: minor style changes
* src/counterexample.h, src/derivation.h, src/derivation.c:
More comments.
Use `out` for FILE*, as elsewhere.
2020-07-14 06:48:48 +02:00
Akim Demaille d8c2af56c1 tests: beware of version numbers from git describe
* tests/report.at: Be robust to version numbers such as
3.6.4.133-fbac-dirty.
2020-07-14 06:48:48 +02:00
Akim Demaille cc11bb037c tests: fix expectations
Broken in ee86ea8839.

* tests/diagnostics.at: here.
2020-07-14 06:48:48 +02:00
Akim Demaille 121dd98508 doc: makeinfo wants @arrow{}, not @arrow
* doc/bison.texi: here.
2020-07-12 08:15:44 +02:00
Akim Demaille 2eddbd0ac4 gnulib: update 2020-07-11 19:11:19 +02:00
Akim Demaille ee86ea8839 cex: prefer → to ::=
It does not make a lot of sense to use ::= in our counterexamples,
that's not something that belongs to the Bison "vocabulary".  Using
the colon makes sense, but it's too discreet.  Let's use the arrow,
which we already use in some reports (HTML and Dot).

* src/gram.h (print_dot_fallback): Generalize into...
(print_fallback): this.
(print_arrow): New.
* src/derivation.c: Use it.

* NEWS, tests/conflicts.at, tests/counterexample.at,
* tests/diagnostics.at, tests/report.at: Adjust.
* doc/bison.texi: Ditto.
Unfortunately the literal `→` is output as `↦`.  So we need to use
@arrow.
2020-07-11 18:43:46 +02:00
Akim Demaille a2ad33dca6 style: cex: prefer the array notation
Prefer `&foos[i]` to `foos + i` when `foos` is an array.  IMHO, it
makes the semantics clearer.

* src/counterexample.c, src/lssi.c, src/parse-simulation.c,
* src/state-item.c: With arrays, prefer the array notation rather than
the pointer one.
2020-07-11 18:07:09 +02:00
Akim Demaille 5b2b7b1ffb style: cex: remove variables that don't make it simpler to read
* src/counterexample.c: With arrays, prefer the array notation rather
than the pointer one.
2020-07-11 18:07:09 +02:00
Akim Demaille dc72b3566d bistromathic: demonstrate caret-diagnostics
* examples/c/bistromathic/parse.y (user_context): We need the current
line.
(yyreport_syntax_error): Quote the guilty line, with squiggles.
* examples/c/bistromathic/bistromathic.test: Adjust.
2020-07-11 18:06:45 +02:00
Akim Demaille c47e1174d4 bistromathic: do not display parse errors on completion
Currently autocompletion on a line with errors leaks the error
messages.  It can be useful to let the user know, but GNU Readline
does not provide us with an nice way to display the error.  So we
actually break into the current line of the user.

So instead, do not show these errors.

* examples/c/bistromathic/parse.y (user_context): New.
Use %param to pass it to the parser and scanner.
Keep quiet when in computing autocompletion.
2020-07-11 18:05:50 +02:00
Akim Demaille 093eeb27e9 bistromathic: don't stupidly reset the location for each token
That quite defeats the whole point of locations...  But anyway, we
should not see these messages at all.

* examples/c/bistromathic/parse.y (expected_tokens): Fix (useless)
location tracking.
2020-07-11 18:05:41 +02:00
Akim Demaille dab23c4a21 bistromathic: promote yytoken_kind_t
* examples/c/bistromathic/parse.y: Use yytoken_kind_t rather than int.
2020-07-11 18:05:35 +02:00
Akim Demaille 38a169bec1 html: capitalize titles
* data/xslt/xml2xhtml.xsl: Use "State 0", not "state 0".
As we do in text reports.
2020-07-11 12:58:45 +02:00
Akim Demaille dc77d6500f html: don't define several times the same anchors
Currently when we output useless rules, they appear before the
grammar, but using the same invocation.  As a result, the anchor is
defined twice, and the wrong one, being first, is honored.

* data/xslt/xml2xhtml.xsl (rule): Take a new 'anchor' parameter to
decide whether being an anchor, or a target.
Let it be true when output the grammar.
* tests/report.at: Adjust.
2020-07-11 12:58:44 +02:00
Akim Demaille 8262c7dc22 html: simplify
* data/xslt/xml2xhtml.xsl: Merge two identical when-clauses.
2020-07-11 12:58:44 +02:00
Akim Demaille 44f28d10ee reports: let html reports catch up with --report and --graph
* data/xslt/xml2xhtml.xsl: Show the symbol types.
* tests/report.at: Adjust.
2020-07-11 12:58:44 +02:00
Akim Demaille 44ad466a32 reports: let xml reports catch up with --report and --graph
The text and Dot reports are expected to be identical when generated
directly (--report, --graph) or indirectly (via XML).  The xml
testsuite had not be run for ages, let it catch up a bit.

* src/print-xml.c: Pass the type of the symbols.
* data/xslt/xml2text.xsl
Catch up with the new layout.
Display the symbol types.
Use '•', not '.'
* tests/local.at: Smash '•' to '.' when matching against the direct
text report.
* tests/report.at: Adjust XML expectations.
2020-07-11 12:58:44 +02:00
Akim Demaille a839f4c461 reports: update html ouput
* data/xslt/xml2xhtml.xsl: Improve indentation.
Use ul/li rather that pre.
2020-07-11 12:58:44 +02:00
Akim Demaille 9a51c6a128 tests: check html
* tests/report.at: here.
2020-07-11 12:58:44 +02:00
Akim Demaille 2608b0cf12 style: factor complex expressions
* src/print-xml.c, src/print.c: Introduce a variable pointing to the
current symbol.
2020-07-11 12:58:44 +02:00
Akim Demaille aa766d1560 maint: make it easier to update expectations
* tests/local.mk (update-tests): New.
2020-07-11 12:58:44 +02:00
Akim Demaille a7ed13b25f maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2020-07-09 21:38:23 +02:00
63 changed files with 3044 additions and 978 deletions
+1 -1
View File
@@ -1 +1 @@
3.6.90 3.6.93
+119 -30
View File
@@ -1,13 +1,6 @@
GNU Bison NEWS GNU Bison NEWS
* Noteworthy changes in release 3.6.91 (2020-07-09) [beta] * Noteworthy changes in release 3.7 (2020-07-23) [stable]
** Bug fixes
Portability issues.
* Noteworthy changes in release 3.6.90 (2020-07-04) [beta]
** Deprecated features ** Deprecated features
@@ -25,35 +18,114 @@ GNU Bison NEWS
Contributed by Vincent Imbimbo. Contributed by Vincent Imbimbo.
When given `--report=counterexamples` or `-Wcounterexamples`, bison will When given `-Wcounterexamples`/`-Wcex`, bison will now output
now output counterexamples for conflicts in the grammar. These are counterexamples for conflicts.
strings in the grammar which can be parsed in two ways due to the
conflict. For example:
Example exp '+' exp • '/' exp **** Unifying Counterexamples
First derivation exp ::=[ exp ::=[ exp '+' exp • ] '/' exp ]
Second derivation exp ::=[ exp '+' exp ::=[ exp • '/' exp ] ]
When Bison is installed with text styling enabled, the example is actually Unifying counterexamples are strings which can be parsed in two ways due
shown twice, with colors highlighting the ambiguity. to the conflict. For example on a grammar that contains the usual
"dangling else" ambiguity:
This is a shift/reduce conflict caused by none of the operators having $ bison else.y
precedence, so the example can be parsed in the two ways shown. When else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
bison cannot find an example that can be derived in two ways, it instead else.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
generates two examples that are the same up until the dot:
First example expr • ID $end $ bison else.y -Wcex
First derivation $accept ::=[ s ::=[ a ::=[ expr • ] ID ] $end ] else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Second example expr • ID ',' ID $end else.y: warning: shift/reduce conflict on token "else" [-Wcounterexamples]
Second derivation $accept ::=[ s ::=[ a ::=[ expr ::=[ exprID ',' ] ] ID ] $end ] Example: "if" exp "then" "if" exp "then" exp • "else" exp
Shift derivation
exp
↳ "if" exp "then" exp
↳ "if" exp "then" exp • "else" exp
Example: "if" exp "then" "if" exp "then" exp • "else" exp
Reduce derivation
exp
↳ "if" exp "then" exp "else" exp
↳ "if" exp "then" exp •
When text styling is enabled, colors are used in the examples and the
derivations to highlight the structure of both analyses. In this case,
"if" exp "then" [ "if" exp "then" exp • ] "else" exp
vs.
"if" exp "then" [ "if" exp "then" exp • "else" exp ]
The counterexamples are "focused", in two different ways. First, they do
not clutter the output with all the derivations from the start symbol,
rather they start on the "conflicted nonterminal". They go straight to the
point. Second, they don't "expand" nonterminal symbols uselessly.
**** Nonunifying Counterexamples
In the case of the dangling else, Bison found an example that can be
parsed in two ways (therefore proving that the grammar is ambiguous).
When it cannot find such an example, it instead generates two examples
that are the same up until the dot:
$ bison foo.y
foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
foo.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
foo.y:4.4-7: warning: rule useless in parser due to conflicts [-Wother]
4 | a: expr
| ^~~~
$ bison -Wcex foo.y
foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
foo.y: warning: shift/reduce conflict on token ID [-Wcounterexamples]
First example: expr • ID ',' ID $end
Shift derivation
$accept
↳ s $end
↳ a ID
↳ expr
↳ expr • ID ','
Second example: expr • ID $end
Reduce derivation
$accept
↳ s $end
↳ a ID
↳ expr •
foo.y:4.4-7: warning: rule useless in parser due to conflicts [-Wother]
4 | a: expr
| ^~~~
In these cases, the parser usually doesn't have enough lookahead to In these cases, the parser usually doesn't have enough lookahead to
differentiate the two given examples. differentiate the two given examples.
The counterexamples are "focused": in two different ways. First, they do **** Reports
not clutter the output with all the derivations from the start symbol,
rather they start on the "conflicted nonterminal". They go straight to the Counterexamples are also included in the report when given
point. Second, they don't "expand" nonterminal symbols uselessly. `--report=counterexamples`/`-rcex` (or `--report=all`), with more
technical details:
State 7
1 exp: "if" exp "then" exp • [$end, "then", "else"]
2 | "if" exp "then" exp • "else" exp
"else" shift, and go to state 8
"else" [reduce using rule 1 (exp)]
$default reduce using rule 1 (exp)
shift/reduce conflict on token "else":
1 exp: "if" exp "then" exp •
2 exp: "if" exp "then" exp • "else" exp
Example: "if" exp "then" "if" exp "then" exp • "else" exp
Shift derivation
exp
↳ "if" exp "then" exp
↳ "if" exp "then" exp • "else" exp
Example: "if" exp "then" "if" exp "then" exp • "else" exp
Reduce derivation
exp
↳ "if" exp "then" exp "else" exp
↳ "if" exp "then" exp •
*** File prefix mapping *** File prefix mapping
@@ -67,6 +139,11 @@ GNU Bison NEWS
** Changes ** Changes
*** Diagnostics
When text styling is enabled and the terminal supports it, the warnings
now include hyperlinks to the documentation.
*** Relocatable installation *** Relocatable installation
When installed to be relocatable (via `configure --enable-relocatable`), When installed to be relocatable (via `configure --enable-relocatable`),
@@ -107,6 +184,18 @@ GNU Bison NEWS
Now the parser state can be examined when parsing is finished. The parser Now the parser state can be examined when parsing is finished. The parser
state is reset when starting a new parse. state is reset when starting a new parse.
** Documentation
*** Examples
The bistromathic demonstrates %param and how to quote sources in the error
messages:
> 123 456
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
1 | 123 456
| ^~~
** Bug fixes ** Bug fixes
*** Include the generated header (yacc.c) *** Include the generated header (yacc.c)
@@ -4372,7 +4461,7 @@ LocalWords: yysymbol yytnamerr yyreport ctx ARGMAX yysyntax stderr LPAREN
LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF
LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc
LocalWords: yytoken YYUNDEF YYerror basename Automake's UTF ifdef ffile LocalWords: yytoken YYUNDEF YYerror basename Automake's UTF ifdef ffile
LocalWords: gotos readline Imbimbo Wcounterexamples LocalWords: gotos readline Imbimbo Wcounterexamples Wcex Nonunifying rcex
Local Variables: Local Variables:
ispell-dictionary: "american" ispell-dictionary: "american"
+1 -1
View File
@@ -444,7 +444,7 @@ added the `[-Wother]` part to all the warnings). Part of the update can be
done with a crude tool: `build-aux/update-test`. done with a crude tool: `build-aux/update-test`.
Once you ran the test suite, and therefore have many `testsuite.log` files, Once you ran the test suite, and therefore have many `testsuite.log` files,
run, from the source tree: run `make update-tests`. Or, by hand, from the *source* tree:
$ ./build-aux/update-test $build/tests/testsuite.dir/*/testsuite.log $ ./build-aux/update-test $build/tests/testsuite.dir/*/testsuite.log
+1
View File
@@ -45,6 +45,7 @@ Csaba Raduly [email protected]
Dagobert Michelsen [email protected] Dagobert Michelsen [email protected]
Daniel Frużyński [email protected] Daniel Frużyński [email protected]
Daniel Galloway [email protected] Daniel Galloway [email protected]
Daniela Becker [email protected]
Daniel Hagerty [email protected] Daniel Hagerty [email protected]
David Barto [email protected] David Barto [email protected]
David J. MacKenzie [email protected] David J. MacKenzie [email protected]
-2
View File
@@ -36,8 +36,6 @@ Unless we play it dumb (little structure).
- How about not evaluating incomplete lines when the text is not finished - How about not evaluating incomplete lines when the text is not finished
(as shells do). (as shells do).
- Caret diagnostics
** Questions ** Questions
*** Java *** Java
- Should i18n be part of the Lexer? Currently it's a static method of - Should i18n be part of the Lexer? Currently it's a static method of
+1 -1
View File
@@ -44,7 +44,7 @@ gnulib_modules='
realloc-posix realloc-posix
relocatable-prog relocatable-script relocatable-prog relocatable-script
rename rename
spawn-pipe stdbool stpcpy strdup-posix strerror strverscmp spawn-pipe stdbool stpcpy stpncpy strdup-posix strerror strverscmp
timevar timevar
unicodeio unistd unistd-safer unlink unlocked-io unicodeio unistd unistd-safer unlink unlocked-io
update-copyright unsetenv verify update-copyright unsetenv verify
+4
View File
@@ -49,6 +49,10 @@
.cex-5 { color: orange; } .cex-5 { color: orange; }
.cex-6 { color: brown; } .cex-6 { color: brown; }
.cex-7 { color: mauve; } .cex-7 { color: mauve; }
.cex-8 { color: #013220; } /* Dark green. */
.cex-9 { color: #e75480; } /* Dark pink. */
.cex-10 { color: cyan; }
.cex-11 { color: orange; }
/* Cex: derivation rewriting steps. */ /* Cex: derivation rewriting steps. */
.cex-step { font-style: italic; } .cex-step { font-style: italic; }
+14 -6
View File
@@ -52,7 +52,7 @@
<xsl:if test="nonterminal[@usefulness='useless-in-grammar']"> <xsl:if test="nonterminal[@usefulness='useless-in-grammar']">
<xsl:text>Nonterminals useless in grammar&#10;&#10;</xsl:text> <xsl:text>Nonterminals useless in grammar&#10;&#10;</xsl:text>
<xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']"> <xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']">
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<xsl:value-of select="@name"/> <xsl:value-of select="@name"/>
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
</xsl:for-each> </xsl:for-each>
@@ -65,7 +65,7 @@
<xsl:text>Terminals unused in grammar&#10;&#10;</xsl:text> <xsl:text>Terminals unused in grammar&#10;&#10;</xsl:text>
<xsl:for-each select="terminal[@usefulness='unused-in-grammar']"> <xsl:for-each select="terminal[@usefulness='unused-in-grammar']">
<xsl:sort select="@symbol-number" data-type="number"/> <xsl:sort select="@symbol-number" data-type="number"/>
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<xsl:value-of select="@name"/> <xsl:value-of select="@name"/>
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
</xsl:for-each> </xsl:for-each>
@@ -136,6 +136,7 @@
</xsl:template> </xsl:template>
<xsl:template match="terminal"> <xsl:template match="terminal">
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/> <xsl:value-of select="@name"/>
<xsl:call-template name="line-wrap"> <xsl:call-template name="line-wrap">
<xsl:with-param name="first-line-length"> <xsl:with-param name="first-line-length">
@@ -148,6 +149,9 @@
</xsl:with-param> </xsl:with-param>
<xsl:with-param name="line-length" select="66" /> <xsl:with-param name="line-length" select="66" />
<xsl:with-param name="text"> <xsl:with-param name="text">
<xsl:if test="string-length(@type) != 0">
<xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
</xsl:if>
<xsl:value-of select="concat(' (', @token-number, ')')"/> <xsl:value-of select="concat(' (', @token-number, ')')"/>
<xsl:for-each select="key('bison:ruleByRhs', @name)"> <xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:value-of select="concat(' ', @number)"/> <xsl:value-of select="concat(' ', @number)"/>
@@ -157,14 +161,18 @@
</xsl:template> </xsl:template>
<xsl:template match="nonterminal"> <xsl:template match="nonterminal">
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/> <xsl:value-of select="@name"/>
<xsl:if test="string-length(@type) != 0">
<xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
</xsl:if>
<xsl:value-of select="concat(' (', @symbol-number, ')')"/> <xsl:value-of select="concat(' (', @symbol-number, ')')"/>
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
<xsl:variable name="output"> <xsl:variable name="output">
<xsl:call-template name="line-wrap"> <xsl:call-template name="line-wrap">
<xsl:with-param name="line-length" select="66" /> <xsl:with-param name="line-length" select="66" />
<xsl:with-param name="text"> <xsl:with-param name="text">
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<xsl:if test="key('bison:ruleByLhs', @name)"> <xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>on@left:</xsl:text> <xsl:text>on@left:</xsl:text>
<xsl:for-each select="key('bison:ruleByLhs', @name)"> <xsl:for-each select="key('bison:ruleByLhs', @name)">
@@ -173,7 +181,7 @@
</xsl:if> </xsl:if>
<xsl:if test="key('bison:ruleByRhs', @name)"> <xsl:if test="key('bison:ruleByRhs', @name)">
<xsl:if test="key('bison:ruleByLhs', @name)"> <xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>, </xsl:text> <xsl:text>&#10; </xsl:text>
</xsl:if> </xsl:if>
<xsl:text>on@right:</xsl:text> <xsl:text>on@right:</xsl:text>
<xsl:for-each select="key('bison:ruleByRhs', @name)"> <xsl:for-each select="key('bison:ruleByRhs', @name)">
@@ -348,11 +356,11 @@
<!-- RHS --> <!-- RHS -->
<xsl:for-each select="rhs/*"> <xsl:for-each select="rhs/*">
<xsl:if test="position() = $dot + 1"> <xsl:if test="position() = $dot + 1">
<xsl:text> .</xsl:text> <xsl:text> </xsl:text>
</xsl:if> </xsl:if>
<xsl:apply-templates select="."/> <xsl:apply-templates select="."/>
<xsl:if test="position() = last() and position() = $dot"> <xsl:if test="position() = last() and position() = $dot">
<xsl:text> .</xsl:text> <xsl:text> </xsl:text>
</xsl:if> </xsl:if>
</xsl:for-each> </xsl:for-each>
<xsl:if test="$lookaheads"> <xsl:if test="$lookaheads">
+72 -48
View File
@@ -227,6 +227,7 @@
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
<p class="pre"> <p class="pre">
<xsl:call-template name="style-rule-set"> <xsl:call-template name="style-rule-set">
<xsl:with-param name="anchor" select="'true'" />
<xsl:with-param <xsl:with-param
name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']" name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']"
/> />
@@ -238,9 +239,11 @@
</xsl:template> </xsl:template>
<xsl:template name="style-rule-set"> <xsl:template name="style-rule-set">
<xsl:param name="anchor"/>
<xsl:param name="rule-set"/> <xsl:param name="rule-set"/>
<xsl:for-each select="$rule-set"> <xsl:for-each select="$rule-set">
<xsl:apply-templates select="."> <xsl:apply-templates select=".">
<xsl:with-param name="anchor" select="$anchor"/>
<xsl:with-param name="pad" select="'3'"/> <xsl:with-param name="pad" select="'3'"/>
<xsl:with-param name="prev-lhs"> <xsl:with-param name="prev-lhs">
<xsl:if test="position()>1"> <xsl:if test="position()>1">
@@ -306,9 +309,10 @@
<xsl:text> Terminals, with rules where they appear</xsl:text> <xsl:text> Terminals, with rules where they appear</xsl:text>
</h3> </h3>
<xsl:text>&#10;&#10;</xsl:text> <xsl:text>&#10;&#10;</xsl:text>
<p class="pre"> <ul>
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="terminal"/> <xsl:apply-templates select="terminal"/>
</p> </ul>
<xsl:text>&#10;&#10;</xsl:text> <xsl:text>&#10;&#10;</xsl:text>
</xsl:template> </xsl:template>
@@ -318,41 +322,64 @@
<xsl:text> Nonterminals, with rules where they appear</xsl:text> <xsl:text> Nonterminals, with rules where they appear</xsl:text>
</h3> </h3>
<xsl:text>&#10;&#10;</xsl:text> <xsl:text>&#10;&#10;</xsl:text>
<p class="pre"> <ul>
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates <xsl:apply-templates
select="nonterminal[@usefulness!='useless-in-grammar']" select="nonterminal[@usefulness!='useless-in-grammar']"
/> />
</p> </ul>
</xsl:template> </xsl:template>
<xsl:template match="terminal"> <xsl:template match="terminal">
<b><xsl:value-of select="@name"/></b> <xsl:text> </xsl:text>
<xsl:value-of select="concat(' (', @token-number, ')')"/> <li>
<xsl:for-each select="key('bison:ruleByRhs', @name)"> <b><xsl:value-of select="@name"/></b>
<xsl:apply-templates select="." mode="number-link"/> <xsl:if test="string-length(@type) != 0">
</xsl:for-each> <xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
</xsl:if>
<xsl:value-of select="concat(' (', @token-number, ')')"/>
<xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</li>
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
</xsl:template> </xsl:template>
<xsl:template match="nonterminal"> <xsl:template match="nonterminal">
<b><xsl:value-of select="@name"/></b> <xsl:text> </xsl:text>
<xsl:value-of select="concat(' (', @symbol-number, ')')"/> <li>
<xsl:text>&#10; </xsl:text> <b><xsl:value-of select="@name"/></b>
<xsl:if test="key('bison:ruleByLhs', @name)"> <xsl:if test="string-length(@type) != 0">
<xsl:text>on left:</xsl:text> <xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
<xsl:for-each select="key('bison:ruleByLhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</xsl:if>
<xsl:if test="key('bison:ruleByRhs', @name)">
<xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>&#10; </xsl:text>
</xsl:if> </xsl:if>
<xsl:text>on right:</xsl:text> <xsl:value-of select="concat(' (', @symbol-number, ')')"/>
<xsl:for-each select="key('bison:ruleByRhs', @name)"> <xsl:text>&#10; </xsl:text>
<xsl:apply-templates select="." mode="number-link"/> <ul>
</xsl:for-each> <xsl:text>&#10;</xsl:text>
</xsl:if> <xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text> </xsl:text>
<li>
<xsl:text>on left:</xsl:text>
<xsl:for-each select="key('bison:ruleByLhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</li>
<xsl:text>&#10;</xsl:text>
</xsl:if>
<xsl:if test="key('bison:ruleByRhs', @name)">
<xsl:text> </xsl:text>
<li>
<xsl:text>on right:</xsl:text>
<xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</li>
<xsl:text>&#10;</xsl:text>
</xsl:if>
<xsl:text> </xsl:text>
</ul>
<xsl:text>&#10; </xsl:text>
</li>
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
</xsl:template> </xsl:template>
@@ -385,7 +412,7 @@
<xsl:value-of select="concat('state_', @number)"/> <xsl:value-of select="concat('state_', @number)"/>
</xsl:attribute> </xsl:attribute>
</a> </a>
<xsl:text>state </xsl:text> <xsl:text>State </xsl:text>
<xsl:value-of select="@number"/> <xsl:value-of select="@number"/>
</h3> </h3>
<xsl:text>&#10;&#10;</xsl:text> <xsl:text>&#10;&#10;</xsl:text>
@@ -464,7 +491,12 @@
</xsl:apply-templates> </xsl:apply-templates>
</xsl:template> </xsl:template>
<!--
anchor = 'true': define as an <a> anchor.
itemset = 'true': show the items.
-->
<xsl:template match="rule"> <xsl:template match="rule">
<xsl:param name="anchor"/>
<xsl:param name="itemset"/> <xsl:param name="itemset"/>
<xsl:param name="pad"/> <xsl:param name="pad"/>
<xsl:param name="prev-lhs"/> <xsl:param name="prev-lhs"/>
@@ -475,17 +507,21 @@
<xsl:text>&#10;</xsl:text> <xsl:text>&#10;</xsl:text>
</xsl:if> </xsl:if>
<xsl:if test="$itemset != 'true'">
<a>
<xsl:attribute name="name">
<xsl:value-of select="concat('rule_', @number)"/>
</xsl:attribute>
</a>
</xsl:if>
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<xsl:choose> <xsl:choose>
<xsl:when test="$itemset = 'true'"> <xsl:when test="$anchor = 'true'">
<a>
<xsl:attribute name="name">
<xsl:value-of select="concat('rule_', @number)"/>
</xsl:attribute>
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="string(@number)"/>
<xsl:with-param name="pad" select="number($pad)"/>
</xsl:call-template>
</a>
</xsl:when>
<xsl:otherwise>
<a> <a>
<xsl:attribute name="href"> <xsl:attribute name="href">
<xsl:value-of select="concat('#rule_', @number)"/> <xsl:value-of select="concat('#rule_', @number)"/>
@@ -495,25 +531,13 @@
<xsl:with-param name="pad" select="number($pad)"/> <xsl:with-param name="pad" select="number($pad)"/>
</xsl:call-template> </xsl:call-template>
</a> </a>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="string(@number)"/>
<xsl:with-param name="pad" select="number($pad)"/>
</xsl:call-template>
</xsl:otherwise> </xsl:otherwise>
</xsl:choose> </xsl:choose>
<xsl:text> </xsl:text> <xsl:text> </xsl:text>
<!-- LHS --> <!-- LHS -->
<xsl:choose> <xsl:choose>
<xsl:when test="$itemset != 'true' and $prev-lhs = lhs[text()]"> <xsl:when test="$prev-lhs = lhs[text()]">
<xsl:call-template name="lpad">
<xsl:with-param name="str" select="'|'"/>
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$itemset = 'true' and $prev-lhs = lhs[text()]">
<xsl:call-template name="lpad"> <xsl:call-template name="lpad">
<xsl:with-param name="str" select="'|'"/> <xsl:with-param name="str" select="'|'"/>
<xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/> <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 2"/>
+253 -113
View File
@@ -263,7 +263,6 @@ Writing GLR Parsers
* Merging GLR Parses:: Using GLR parsers to resolve ambiguities. * Merging GLR Parses:: Using GLR parsers to resolve ambiguities.
* GLR Semantic Actions:: Considerations for semantic values and deferred actions. * GLR Semantic Actions:: Considerations for semantic values and deferred actions.
* Semantic Predicates:: Controlling a parse with arbitrary computations. * Semantic Predicates:: Controlling a parse with arbitrary computations.
* Compiler Requirements for GLR:: GLR parsers require a modern C compiler.
Examples Examples
@@ -943,7 +942,6 @@ on the resulting values to produce an arbitrary merged result.
* Merging GLR Parses:: Using GLR parsers to resolve ambiguities. * Merging GLR Parses:: Using GLR parsers to resolve ambiguities.
* GLR Semantic Actions:: Considerations for semantic values and deferred actions. * GLR Semantic Actions:: Considerations for semantic values and deferred actions.
* Semantic Predicates:: Controlling a parse with arbitrary computations. * Semantic Predicates:: Controlling a parse with arbitrary computations.
* Compiler Requirements for GLR:: GLR parsers require a modern C compiler.
@end menu @end menu
@node Simple GLR Parsers @node Simple GLR Parsers
@@ -1372,14 +1370,14 @@ widget:
@noindent @noindent
is one way to allow the same parser to handle two different syntaxes for is one way to allow the same parser to handle two different syntaxes for
widgets. The clause preceded by @code{%?} is treated like an ordinary widgets. The clause preceded by @code{%?} is treated like an ordinary
action, except that its text is treated as an expression and is always midrule action, except that its text is handled as an expression and is always
evaluated immediately (even when in nondeterministic mode). If the evaluated immediately (even when in nondeterministic mode). If the
expression yields 0 (false), the clause is treated as a syntax error, expression yields 0 (false), the clause is treated as a syntax error,
which, in a nondeterministic parser, causes the stack in which it is reduced which, in a nondeterministic parser, causes the stack in which it is reduced
to die. In a deterministic parser, it acts like YYERROR. to die. In a deterministic parser, it acts like @code{YYERROR}.
As the example shows, predicates otherwise look like semantic actions, and As the example shows, predicates otherwise look like semantic actions, and
therefore you must be take them into account when determining the numbers therefore you must take them into account when determining the numbers
to use for denoting the semantic values of right-hand side symbols. to use for denoting the semantic values of right-hand side symbols.
Predicate actions, however, have no defined value, and may not be given Predicate actions, however, have no defined value, and may not be given
labels. labels.
@@ -1393,7 +1391,7 @@ widget:
@{ if (!new_syntax) YYERROR; @} @{ if (!new_syntax) YYERROR; @}
"widget" id new_args @{ $$ = f($3, $4); @} "widget" id new_args @{ $$ = f($3, $4); @}
| @{ if (new_syntax) YYERROR; @} | @{ if (new_syntax) YYERROR; @}
"widget" id old_args @{ $$ = f($3, $4); @} "widget" id old_args @{ $$ = f($3, $4); @}
; ;
@end example @end example
@@ -1411,36 +1409,6 @@ reports an error.
Finally, be careful in writing predicates: deferred actions have not been Finally, be careful in writing predicates: deferred actions have not been
evaluated, so that using them in a predicate will have undefined effects. evaluated, so that using them in a predicate will have undefined effects.
@node Compiler Requirements for GLR
@subsection Considerations when Compiling GLR Parsers
@cindex @code{inline}
@cindex GLR parsers and @code{inline}
The GLR parsers require a compiler for ISO C89 or
later. In addition, they use the @code{inline} keyword, which is not
C89, but is C99 and is a common extension in pre-C99 compilers. It is
up to the user of these parsers to handle
portability issues. For instance, if using Autoconf and the Autoconf
macro @code{AC_C_INLINE}, a mere
@example
%@{
#include <config.h>
%@}
@end example
@noindent
will suffice. Otherwise, we suggest
@example
%@{
#if (__STDC_VERSION__ < 199901 && ! defined __GNUC__ \
&& ! defined inline)
# define inline
#endif
%@}
@end example
@node Locations @node Locations
@section Locations @section Locations
@cindex location @cindex location
@@ -9921,10 +9889,11 @@ initially developed by Chinawat Isradisaikul and Andrew Myers
As a first example, see the example grammar of @ref{Shift/Reduce}, which As a first example, see the example grammar of @ref{Shift/Reduce}, which
features on shift/reduce conflict: features on shift/reduce conflict:
@c see doc/if-then-else.y
@example @example
$ @kbd{bison if-then-else.y} $ @kbd{bison if-then-else.y}
if-then-else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
if-then-else.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] if-then-else.y: @dnotice{note}: rerun with option '-Wcounterexamples' to generate conflict counterexamples
@end example @end example
@noindent @noindent
@@ -9932,32 +9901,46 @@ Let's rerun @command{bison} with the option
@option{-Wcex}/@option{-Wcounterexamples}@inlinefmt{info, (the following @option{-Wcex}/@option{-Wcounterexamples}@inlinefmt{info, (the following
output is actually in color)}: output is actually in color)}:
@ifhtml @ifnottex
@example @example
Shift/reduce conflict on token "else": if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
if-then-else.y: @dwarning{warning}: shift/reduce conflict on token "else" [@dwarning{-Wcounterexamples}]
@group @group
Example @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt} Example: @yellow{"if" expr "then"} "if" expr "then" stmt"else" stmt
First derivation @yellow{if_stmt ::=[ "if" expr "then"} @green{stmt ::=[} @blue{if_stmt ::=[ "if" expr "then" stmt} @red{•} @blue{]} @green{]} @yellow{"else" stmt ]} Shift derivation
Example @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @blue{"else" stmt} @yellow{if_stmt}
Second derivation @yellow{if_stmt ::=[ "if" expr "then"} @green{stmt ::=[} @blue{if_stmt ::=[ "if" expr "then" stmt} @red{•} @blue{"else" stmt ]} @green{]} @yellow{]} @yellow{↳ "if" expr "then"} @green{stmt}
@green{↳} @blue{if_stmt}
@blue{↳ "if" expr "then" stmt} @red{•} @blue{"else" stmt}
Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
Reduce derivation
@yellow{if_stmt}
@yellow{↳ "if" expr "then"} @green{stmt} @yellow{"else" stmt}
@green{↳} @blue{if_stmt}
@blue{↳ "if" expr "then" stmt} @red{•}
@end group @end group
@end example @end example
@end ifhtml @end ifnottex
@ifnothtml @iftex
@smallexample @example
Shift/reduce conflict on token "else": if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
if-then-else.y: @dwarning{warning}: shift/reduce conflict on token "else" [@dwarning{-Wcounterexamples}]
@group @group
Example Example: @yellow{"if" expr "then"} "if" expr "then" stmt • "else" stmt
@yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt} Shift derivation
First derivation @yellow{if_stmt}
@yellow{if_stmt ::=[ "if" expr "then"} @green{stmt ::=[} @blue{if_stmt ::=[ "if" expr "then" stmt} @red{•} @blue{]} @green{]} @yellow{"else" stmt ]} @yellow{@arrow{} "if" expr "then"} @green{stmt}
Example @green{@arrow{}} @blue{if_stmt}
@yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @blue{"else" stmt} @blue{@arrow{} "if" expr "then" stmt} @red{•} @blue{"else" stmt}
Second derivation Example: @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
@yellow{if_stmt ::=[ "if" expr "then"} @green{stmt ::=[} @blue{if_stmt ::=[ "if" expr "then" stmt} @red{•} @blue{"else" stmt ]} @green{]} @yellow{]} Reduce derivation
@yellow{if_stmt}
@yellow{@arrow{} "if" expr "then"} @green{stmt} @yellow{"else" stmt}
@green{@arrow{}} @blue{if_stmt}
@blue{@arrow{} "if" expr "then" stmt} @red{•}
@end group @end group
@end smallexample @end example
@end ifnothtml @end iftex
This shows two different derivations for one single expression. That This shows two different derivations for one single expression. That
demonstrates that the grammar is ambiguous. demonstrates that the grammar is ambiguous.
@@ -9967,6 +9950,7 @@ demonstrates that the grammar is ambiguous.
As a more delicate example, consider the example grammar of As a more delicate example, consider the example grammar of
@ref{Reduce/Reduce}, which features a reduce/reduce conflict: @ref{Reduce/Reduce}, which features a reduce/reduce conflict:
@c doc/sequence.y
@example @example
%% %%
sequence: sequence:
@@ -9982,32 +9966,112 @@ maybeword:
Bison generates the following counterexamples: Bison generates the following counterexamples:
@ifnottex
@example @example
@group
$ @kbd{bison -Wcex sequence.y} $ @kbd{bison -Wcex sequence.y}
sequence.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}] sequence.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
sequence.y: @dwarning{warning}: 2 reduce/reduce conflicts [@dwarning{-Wconflicts-rr}] sequence.y: @dwarning{warning}: 2 reduce/reduce conflicts [@dwarning{-Wconflicts-rr}]
Shift/reduce conflict on token "word": @end group
Example @red{•} @yellow{"word"} @group
First derivation @yellow{sequence ::=[} @green{sequence ::=[} @red{•} @green{]} @yellow{"word" ]} sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
Example @red{•} @green{"word"} Example: @red{•} @green{"word"}
Second derivation @yellow{sequence ::=[} @green{maybeword ::=[} @red{•} @green{"word" ]} @yellow{]} Shift derivation
@yellow{sequence}
Reduce/reduce conflict on tokens $end, "word": @yellow{↳} @green{maybeword}
Example @red{•} @green{↳} @red{•} @green{"word"}
First derivation @yellow{sequence ::=[} @red{•} @yellow{]} Example: @red{•} @yellow{"word"}
Example @red{•} Reduce derivation
Second derivation @yellow{sequence ::=[} @green{maybeword ::=[} @red{•} @green{]} @yellow{]} @yellow{sequence}
@yellow{↳} @green{sequence} @yellow{"word"}
Shift/reduce conflict on token "word": @green{↳} @red{•}
Example @red{•} @yellow{"word"} @end group
First derivation @yellow{sequence ::=[} @green{sequence ::=[} @blue{maybeword ::=[} @red{•} @blue{]} @green{]} @yellow{"word" ]} @group
Example @red{•} @green{"word"} sequence.y: @dwarning{warning}: reduce/reduce conflict on tokens $end, "word" [@dwarning{-Wcounterexamples}]
Second derivation @yellow{sequence ::=[} @green{maybeword ::=[} @red{•} @green{"word" ]} @yellow{]} Example: @red{•}
First reduce derivation
@yellow{sequence}
@yellow{↳} @red{•}
Example: @red{•}
Second reduce derivation
@yellow{sequence}
@yellow{↳} @green{maybeword}
@green{↳} @red{•}
@end group
@group
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
Example: @red{•} @green{"word"}
Shift derivation
@yellow{sequence}
@yellow{↳} @green{maybeword}
@green{↳} @red{•} @green{"word"}
Example: @red{•} @yellow{"word"}
Reduce derivation
@yellow{sequence}
@yellow{↳} @green{sequence} @yellow{"word"}
@green{↳} @blue{maybeword}
@blue{↳} @red{•}
@end group
@group
sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [@dwarning{-Wother}] sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [@dwarning{-Wother}]
8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}} 8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}}
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~} | @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
@end group
@end example @end example
@end ifnottex
@iftex
@example
@group
$ @kbd{bison -Wcex sequence.y}
sequence.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
sequence.y: @dwarning{warning}: 2 reduce/reduce conflicts [@dwarning{-Wconflicts-rr}]
@end group
@group
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
Example: @red{•} @green{"word"}
Shift derivation
@yellow{sequence}
@yellow{@arrow{}} @green{maybeword}
@green{@arrow{}} @red{•} @green{"word"}
Example: @red{•} @yellow{"word"}
Reduce derivation
@yellow{sequence}
@yellow{@arrow{}} @green{sequence} @yellow{"word"}
@green{@arrow{}} @red{•}
@end group
@group
sequence.y: @dwarning{warning}: reduce/reduce conflict on tokens $end, "word" [@dwarning{-Wcounterexamples}]
Example: @red{•}
First reduce derivation
@yellow{sequence}
@yellow{@arrow{}} @red{•}
Example: @red{•}
Second reduce derivation
@yellow{sequence}
@yellow{@arrow{}} @green{maybeword}
@green{@arrow{}} @red{•}
@end group
@group
sequence.y: @dwarning{warning}: shift/reduce conflict on token "word" [@dwarning{-Wcounterexamples}]
Example: @red{•} @green{"word"}
Shift derivation
@yellow{sequence}
@yellow{@arrow{}} @green{maybeword}
@green{@arrow{}} @red{•} @green{"word"}
Example: @red{•} @yellow{"word"}
Reduce derivation
@yellow{sequence}
@yellow{@arrow{}} @green{sequence} @yellow{"word"}
@green{@arrow{}} @blue{maybeword}
@blue{@arrow{}} @red{•}
@end group
@group
sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [@dwarning{-Wother}]
8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}}
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
@end group
@end example
@end iftex
Each of these three conflicts, again, prove that the grammar is ambiguous. Each of these three conflicts, again, prove that the grammar is ambiguous.
For instance, the second conflict (the reduce/reduce one) shows that the For instance, the second conflict (the reduce/reduce one) shows that the
@@ -10021,6 +10085,7 @@ that are the same up until the dot. Most notably, this will happen when
your grammar requires a stronger parser (more lookahead, LR instead of your grammar requires a stronger parser (more lookahead, LR instead of
LALR). The following example isn't LR(1): LALR). The following example isn't LR(1):
@c doc/ids.y
@example @example
%token ID %token ID
%% %%
@@ -10031,13 +10096,58 @@ expr: %empty | expr ID ','
@command{bison} reports: @command{bison} reports:
@smallexample @ifnottex
Shift/reduce conflict on token ID: @example
First example @blue{expr} @red{•} @green{ID} @yellow{$end} ids.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
First derivation @yellow{$accept ::=[} @green{s ::=[} @blue{a ::=[ expr} @red{•} @blue{]} @green{ID ]} @yellow{$end ]} ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounterexamples}]
Second example @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end} @group
Second derivation @yellow{$accept ::=[} @green{s ::=[} @blue{a ::=[} @purple{expr ::=[ expr} @red{•} @purple{ID ',' ]} @blue{]} @green{ID ]} @yellow{$end ]} First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
@end smallexample Shift derivation
@yellow{$accept}
@yellow{↳} @green{s} @yellow{$end}
@green{↳} @blue{a} @green{ID}
@blue{↳} @purple{expr}
@purple{↳ expr} @red{•} @purple{ID ','}
Second example: @blue{expr} @red{•} @green{ID} @yellow{$end}
Reduce derivation
@yellow{$accept}
@yellow{↳} @green{s} @yellow{$end}
@green{↳} @blue{a} @green{ID}
@blue{↳ expr} @red{•}
@end group
@group
ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarning{-Wother}]
4 | a: expr
| ^~~~
@end group
@end example
@end ifnottex
@iftex
@example
ids.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
ids.y: @dwarning{warning}: shift/reduce conflict on token ID [@dwarning{-Wcounterexamples}]
@group
First example: @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
Shift derivation
@yellow{$accept}
@yellow{@arrow{}} @green{s} @yellow{$end}
@green{@arrow{}} @blue{a} @green{ID}
@blue{@arrow{}} @purple{expr}
@purple{@arrow{} expr} @red{•} @purple{ID ','}
Second example: @blue{expr} @red{•} @green{ID} @yellow{$end}
Reduce derivation
@yellow{$accept}
@yellow{@arrow{}} @green{s} @yellow{$end}
@green{@arrow{}} @blue{a} @green{ID}
@blue{@arrow{} expr} @red{•}
@end group
@group
ids.y:4.4-7: @dwarning{warning}: rule useless in parser due to conflicts [@dwarning{-Wother}]
4 | a: expr
| ^~~~
@end group
@end example
@end iftex
This conflict is caused by the parser not having enough information to know This conflict is caused by the parser not having enough information to know
the difference between these two examples. The parser would need an the difference between these two examples. The parser would need an
@@ -10073,6 +10183,7 @@ by default. As a consequence, the verbose output file is called
The following grammar file, @file{calc.y}, will be used in the sequel: The following grammar file, @file{calc.y}, will be used in the sequel:
@c doc/calc.y
@example @example
@group @group
%union %union
@@ -10116,7 +10227,7 @@ calc.y:19.1-7: @dwarning{warning}: nonterminal useless in grammar: useless [@dwa
19 | @dwarning{useless: STR;} 19 | @dwarning{useless: STR;}
| @dwarning{^~~~~~~} | @dwarning{^~~~~~~}
calc.y: @dwarning{warning}: 7 shift/reduce conflicts [@dwarning{-Wconflicts-sr}] calc.y: @dwarning{warning}: 7 shift/reduce conflicts [@dwarning{-Wconflicts-sr}]
calc.y: @dwarning{warning}: rerun with option '-Wcounterexamples' to generate conflict counterexamples [@dwarning{-Wother}] calc.y: @dnotice{note}: rerun with option '-Wcounterexamples' to generate conflict counterexamples
@end smallexample @end smallexample
Going back to the calc example, when given @option{--report=state}, Going back to the calc example, when given @option{--report=state},
@@ -10428,15 +10539,44 @@ When given @option{--report=counterexamples}, @command{bison} will generate
counterexamples within the report, augmented with the corresponding items counterexamples within the report, augmented with the corresponding items
(@pxref{Counterexamples}). (@pxref{Counterexamples}).
@ifnottex
@example @example
Shift/reduce conflict on token '/': shift/reduce conflict on token '/':
1 exp: exp '+' exp • 1 exp: exp '+' exp •
4 exp: exp • '/' exp 4 exp: exp • '/' exp
Example @green{exp '+' exp} @red{•} @yellow{'/' exp} @group
First derivation @yellow{exp ::=[} @green{exp ::=[ exp '+' exp} @red{•} @green{]} @yellow{'/' exp ]} Example: exp '+' exp • '/' exp
Example @yellow{exp '+'} @green{exp} @red{•} @green{'/' exp} Shift derivation
Second derivation @yellow{exp ::=[ exp '+'} @green{exp ::=[ exp} @red{•} @green{'/' exp ]} @yellow{]} exp
↳ exp '+' exp
↳ exp • '/' exp
Example: exp '+' exp • '/' exp
Reduce derivation
exp
↳ exp '/' exp
↳ exp '+' exp •
@end group
@end example @end example
@end ifnottex
@iftex
@example
shift/reduce conflict on token '/':
1 exp: exp '+' exp •
4 exp: exp • '/' exp
@group
Example: exp '+' exp • '/' exp
Shift derivation
exp
@arrow{} exp '+' exp
@arrow{} exp • '/' exp
Example: exp '+' exp • '/' exp
Reduce derivation
exp
@arrow{} exp '/' exp
@arrow{} exp '+' exp •
@end group
@end example
@end iftex
This shows two separate derivations in the grammar for the same @code{exp}: This shows two separate derivations in the grammar for the same @code{exp}:
@samp{e1 + e2 / e3}. The derivations show how your rules would parse the @samp{e1 + e2 / e3}. The derivations show how your rules would parse the
@@ -11047,7 +11187,7 @@ The exit status of @command{bison} is:
@item 0 (success) @item 0 (success)
when there were no errors. Warnings, which are diagnostics about dubious when there were no errors. Warnings, which are diagnostics about dubious
constructs, do not change the exit status, unless they are turned into constructs, do not change the exit status, unless they are turned into
errors (@pxref{-Werror,,@option{-Werror}}). errors (@pxref{Werror,,@option{-Werror}}).
@item 1 (failure) @item 1 (failure)
when there were errors. No file was generated (except the reports generated when there were errors. No file was generated (except the reports generated
@@ -11284,22 +11424,22 @@ Options controlling the diagnostics.
Output warnings falling in @var{category}. @var{category} can be one Output warnings falling in @var{category}. @var{category} can be one
of: of:
@table @code @table @code
@item conflicts-sr @item @anchor{Wconflicts-sr}conflicts-sr
@itemx conflicts-rr @itemx @anchor{Wconflicts-rr}conflicts-rr
S/R and R/R conflicts. These warnings are enabled by default. However, if S/R and R/R conflicts. These warnings are enabled by default. However, if
the @code{%expect} or @code{%expect-rr} directive is specified, an the @code{%expect} or @code{%expect-rr} directive is specified, an
unexpected number of conflicts is an error, and an expected number of unexpected number of conflicts is an error, and an expected number of
conflicts is not reported, so @option{-W} and @option{--warning} then have conflicts is not reported, so @option{-W} and @option{--warning} then have
no effect on the conflict report. no effect on the conflict report.
@item counterexamples @item @anchor{Wcounterexamples}counterexamples
@itemx cex @itemx cex
Provide counterexamples for conflicts. @xref{Counterexamples}. Provide counterexamples for conflicts. @xref{Counterexamples}.
Counterexamples take time to compute. The option @option{-Wcex} should be Counterexamples take time to compute. The option @option{-Wcex} should be
used by the developer when working on the grammar; it hardly makes sense to used by the developer when working on the grammar; it hardly makes sense to
use it in a CI. use it in a CI.
@item dangling-alias @item @anchor{Wdangling-alias}dangling-alias
Report string literals that are not bound to a token symbol. Report string literals that are not bound to a token symbol.
String literals, which allow for better error messages, are (too) liberally String literals, which allow for better error messages, are (too) liberally
@@ -11345,16 +11485,16 @@ foo: "baz" @{@}
| @dwarning{^~~~~} | @dwarning{^~~~~}
@end example @end example
@item deprecated @item @anchor{Wdeprecated}deprecated
Deprecated constructs whose support will be removed in future versions of Deprecated constructs whose support will be removed in future versions of
Bison. Bison.
@item empty-rule @item @anchor{Wempty-rule}empty-rule
Empty rules without @code{%empty}. @xref{Empty Rules}. Disabled by Empty rules without @code{%empty}. @xref{Empty Rules}. Disabled by
default, but enabled by uses of @code{%empty}, unless default, but enabled by uses of @code{%empty}, unless
@option{-Wno-empty-rule} was specified. @option{-Wno-empty-rule} was specified.
@item midrule-values @item @anchor{Wmidrule-values}midrule-values
Warn about midrule values that are set but not used within any of the actions Warn about midrule values that are set but not used within any of the actions
of the parent rule. of the parent rule.
For example, warn about unused @code{$2} in: For example, warn about unused @code{$2} in:
@@ -11374,7 +11514,7 @@ These warnings are not enabled by default since they sometimes prove to
be false alarms in existing grammars employing the Yacc constructs be false alarms in existing grammars employing the Yacc constructs
@code{$0} or @code{$-@var{n}} (where @var{n} is some positive integer). @code{$0} or @code{$-@var{n}} (where @var{n} is some positive integer).
@item precedence @item @anchor{Wprecedence}precedence
Useless precedence and associativity directives. Disabled by default. Useless precedence and associativity directives. Disabled by default.
Consider for instance the following grammar: Consider for instance the following grammar:
@@ -11435,20 +11575,21 @@ One would get the exact same parser with the following directives instead:
@end group @end group
@end example @end example
@item yacc @item @anchor{Wyacc}yacc
Incompatibilities with POSIX Yacc. Incompatibilities with POSIX Yacc.
@item other @item @anchor{Wother}other
All warnings not categorized above. These warnings are enabled by default. All warnings not categorized above. These warnings are enabled by default.
This category is provided merely for the sake of completeness. Future This category is provided merely for the sake of completeness. Future
releases of Bison may move warnings from this category to new, more specific releases of Bison may move warnings from this category to new, more specific
categories. categories.
@item all @item @anchor{Wall}all
All the warnings except @code{dangling-alias} and @code{yacc}. All the warnings except @code{counterexamples}, @code{dangling-alias} and
@code{yacc}.
@item none @item @anchor{Wnone}none
Turn off all the warnings. Turn off all the warnings.
@item error @item error
@@ -11459,8 +11600,7 @@ A category can be turned off by prefixing its name with @samp{no-}. For
instance, @option{-Wno-yacc} will hide the warnings about instance, @option{-Wno-yacc} will hide the warnings about
POSIX Yacc incompatibilities. POSIX Yacc incompatibilities.
@item -Werror @item @anchor{Werror}-Werror
@anchor{-Werror}
Turn enabled warnings for every @var{category} into errors, unless they are Turn enabled warnings for every @var{category} into errors, unless they are
explicitly disabled by @option{-Wno-error=@var{category}}. explicitly disabled by @option{-Wno-error=@var{category}}.
@@ -14824,13 +14964,13 @@ Bison. See the file @file{ABOUT-NLS} for more information.
I can't build Bison because my C compiler is too old. I can't build Bison because my C compiler is too old.
@end quotation @end quotation
Except for GLR parsers (@pxref{Compiler Requirements for GLR}), the C Except for GLR parsers (which require C99), the C code that Bison generates
code that Bison generates requires only C89 or later. However, Bison requires only C89 or later. However, Bison itself requires common C99
itself requires common C99 features such as declarations after features such as declarations after statements. Bison's @code{configure}
statements. Bison's @code{configure} script attempts to enable C99 (or script attempts to enable C99 (or later) support on compilers that default
later) support on compilers that default to pre-C99. If your compiler to pre-C99. If your compiler lacks these C99 features entirely, GCC may
lacks these C99 features entirely, GCC may well be a better choice; or well be a better choice; or you can try upgrading to your compiler's latest
you can try upgrading to your compiler's latest version. version.
@node Where can I find help? @node Where can I find help?
@section Where can I find help? @section Where can I find help?
@@ -15887,7 +16027,7 @@ London, Department of Computer Science, TR-00-12 (December 2000).
@c LocalWords: TokenKind Automake's rtti Wcounterexamples Chinawat PLDI @c LocalWords: TokenKind Automake's rtti Wcounterexamples Chinawat PLDI
@c LocalWords: Isradisaikul tcite pcite rgbGreen colorGreen rgbYellow Wcex @c LocalWords: Isradisaikul tcite pcite rgbGreen colorGreen rgbYellow Wcex
@c LocalWords: colorYellow rgbRed colorRed rgbBlue colorBlue rgbPurple @c LocalWords: colorYellow rgbRed colorRed rgbBlue colorBlue rgbPurple
@c LocalWords: colorPurple ifhtml ifnothtml situ rcex @c LocalWords: colorPurple ifhtml ifnothtml situ rcex MERCHANTABILITY Wnone
@c Local Variables: @c Local Variables:
@c ispell-dictionary: "american" @c ispell-dictionary: "american"
+23
View File
@@ -0,0 +1,23 @@
%union
{
int ival;
const char *sval;
}
%token <ival> NUM
%nterm <ival> exp
%token <sval> STR
%nterm <sval> useless
%left '+' '-'
%left '*'
%%
exp:
exp '+' exp
| exp '-' exp
| exp '*' exp
| exp '/' exp
| NUM
;
useless: STR;
+5
View File
@@ -0,0 +1,5 @@
%token ID
%%
s: a ID
a: expr
expr: %empty | expr ID ','
+13
View File
@@ -0,0 +1,13 @@
%%
stmt:
expr
| if_stmt
;
if_stmt:
"if" expr "then" stmt
| "if" expr "then" stmt "else" stmt
;
expr:
"identifier"
+10
View File
@@ -0,0 +1,10 @@
%%
sequence:
%empty
| maybeword
| sequence "word"
;
maybeword:
%empty
| "word"
;
+10 -1
View File
@@ -53,7 +53,9 @@ push-parser model.
This example demonstrates best practices when using Bison. This example demonstrates best practices when using Bison.
- Its hand-written scanner tracks locations. - Its hand-written scanner tracks locations.
- Its interface is pure. - Its interface is pure.
- It uses the `error` token to get error recovery. - It uses %params to pass user information to the parser and scanner.
- Its scanner uses the `error` token to signal lexical errors and enter
error recovery.
- Its interface is "incremental", well suited for interaction: it uses the - Its interface is "incremental", well suited for interaction: it uses the
push-parser API to feed the parser with the incoming tokens. push-parser API to feed the parser with the incoming tokens.
- It features an interactive command line with completion based on the - It features an interactive command line with completion based on the
@@ -62,6 +64,13 @@ This example demonstrates best practices when using Bison.
messages. messages.
- It uses a custom syntax error with location, lookahead correction and - It uses a custom syntax error with location, lookahead correction and
token internationalization. token internationalization.
- Error messages quote the source with squiggles that underline the error:
```
> 123 456
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
1 | 123 456
| ^~~
```
- It supports debug traces with semantic values. - It supports debug traces with semantic values.
- It uses named references instead of the traditional $1, $2, etc. - It uses named references instead of the traditional $1, $2, etc.
+10 -1
View File
@@ -2,7 +2,9 @@
This example demonstrates best practices when using Bison. This example demonstrates best practices when using Bison.
- Its hand-written scanner tracks locations. - Its hand-written scanner tracks locations.
- Its interface is pure. - Its interface is pure.
- It uses the `error` token to get error recovery. - It uses %params to pass user information to the parser and scanner.
- Its scanner uses the `error` token to signal lexical errors and enter
error recovery.
- Its interface is "incremental", well suited for interaction: it uses the - Its interface is "incremental", well suited for interaction: it uses the
push-parser API to feed the parser with the incoming tokens. push-parser API to feed the parser with the incoming tokens.
- It features an interactive command line with completion based on the - It features an interactive command line with completion based on the
@@ -11,6 +13,13 @@ This example demonstrates best practices when using Bison.
messages. messages.
- It uses a custom syntax error with location, lookahead correction and - It uses a custom syntax error with location, lookahead correction and
token internationalization. token internationalization.
- Error messages quote the source with squiggles that underline the error:
```
> 123 456
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
1 | 123 456
| ^~~
```
- It supports debug traces with semantic values. - It supports debug traces with semantic values.
- It uses named references instead of the traditional $1, $2, etc. - It uses named references instead of the traditional $1, $2, etc.
+40 -9
View File
@@ -101,14 +101,28 @@ cat >input <<EOF
EOF EOF
run 0 '> * run 0 '> *
> '' > ''
err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *' err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *
err: 1 | *
err: | ^'
# Underline long errors.
cat >input <<EOF
123 123456
EOF
run 0 '> 123 123456
> ''
err: 1.5-10: syntax error: expected end of file or + or - or * or / or ^ before number
err: 1 | 123 123456
err: | ^~~~~~'
cat >input <<EOF cat >input <<EOF
1 + 2 * * 3 1 + 2 * * 3
EOF EOF
run 0 '> 1 + 2 * * 3 run 0 '> 1 + 2 * * 3
> '' > ''
err: 1.9: syntax error: expected - or ( or number or function or variable before *' err: 1.9: syntax error: expected - or ( or number or function or variable before *
err: 1 | 1 + 2 * * 3
err: | ^'
cat >input <<EOF cat >input <<EOF
1 / 0 1 / 0
@@ -132,8 +146,14 @@ run 0 '> ((1 ++ 2) ** 3)
1332 1332
> '' > ''
err: 1.6: syntax error: expected - or ( or number or function or variable before + err: 1.6: syntax error: expected - or ( or number or function or variable before +
err: 1 | ((1 ++ 2) ** 3)
err: | ^
err: 2.5: syntax error: expected - or ( or number or function or variable before + err: 2.5: syntax error: expected - or ( or number or function or variable before +
err: 2.16: syntax error: expected - or ( or number or function or variable before *' err: 2 | (1 ++ 2) + (3 ** 4)
err: | ^
err: 2.16: syntax error: expected - or ( or number or function or variable before *
err: 2 | (1 ++ 2) + (3 ** 4)
err: | ^'
# The rule "( error )" should work even if there are no tokens between "(" and ")". # The rule "( error )" should work even if there are no tokens between "(" and ")".
cat >input <<EOF cat >input <<EOF
@@ -142,7 +162,9 @@ EOF
run 0 '> () run 0 '> ()
666 666
> '' > ''
err: 1.2: syntax error: expected - or ( or number or function or variable before )' err: 1.2: syntax error: expected - or ( or number or function or variable before )
err: 1 | ()
err: | ^'
cat >input <<EOF cat >input <<EOF
@@ -189,6 +211,8 @@ err: LAC: checking lookahead function: S5
err: LAC: checking lookahead variable: S6 err: LAC: checking lookahead variable: S6
err: LAC: checking lookahead NEG: Err err: LAC: checking lookahead NEG: Err
err: 1.2: syntax error: expected - or ( or number or function or variable before + err: 1.2: syntax error: expected - or ( or number or function or variable before +
err: 1 | (+_)
err: | ^
err: LAC: initial context discarded due to error recovery err: LAC: initial context discarded due to error recovery
err: Shifting token error (1.2: ) err: Shifting token error (1.2: )
err: Entering state 10 err: Entering state 10
@@ -286,7 +310,9 @@ run 0 '> (1+
( - atan cos exp ln number sin sqrt ( - atan cos exp ln number sin sqrt
> (1+ > (1+
> '' > ''
err: 1.4: syntax error: expected - or ( or number or function or variable before end of file' err: 1.4: syntax error: expected - or ( or number or function or variable before end of file
err: 1 | (1+
err: | ^'
# Check the completion of a word. # Check the completion of a word.
sed -e 's/\\t/ /g' >input <<EOF sed -e 's/\\t/ /g' >input <<EOF
@@ -294,7 +320,9 @@ sed -e 's/\\t/ /g' >input <<EOF
EOF EOF
run 0 '> (atan ( '' run 0 '> (atan ( ''
> '' > ''
err: 1.9: syntax error: expected - or ( or number or function or variable before end of file' err: 1.9: syntax error: expected - or ( or number or function or variable before end of file
err: 1 | (atan ( ''
err: | ^'
# Check the completion at the very beginning. # Check the completion at the very beginning.
sed -e 's/\\t/ /g' >input <<EOF sed -e 's/\\t/ /g' >input <<EOF
@@ -313,8 +341,9 @@ sed -e 's/\\t/ /g' >input <<EOF
EOF EOF
run -n 0 '> 1++ '' run -n 0 '> 1++ ''
> '' > ''
err: 1.1: syntax error: expected - or ( or number or function or variable before +
err: 1.3: syntax error: expected - or ( or number or function or variable before + err: 1.3: syntax error: expected - or ( or number or function or variable before +
err: 1 | 1++ ''
err: | ^
' '
# And even when the error was recovered from. # And even when the error was recovered from.
@@ -323,8 +352,10 @@ sed -e 's/\\t/ /g' >input <<EOF
EOF EOF
run -n 0 '> (1++2) + 3 + '' run -n 0 '> (1++2) + 3 + ''
> '' > ''
err: 1.1: syntax error: expected - or ( or number or function or variable before +
err: 1.1: syntax error: expected - or ( or number or function or variable before +
err: 1.4: syntax error: expected - or ( or number or function or variable before + err: 1.4: syntax error: expected - or ( or number or function or variable before +
err: 1 | (1++2) + 3 + ''
err: | ^
err: 1.15: syntax error: expected - or ( or number or function or variable before end of file err: 1.15: syntax error: expected - or ( or number or function or variable before end of file
err: 1 | (1++2) + 3 + ''
err: | ^
' '
+51 -15
View File
@@ -65,6 +65,15 @@
symrec *putsym (char const *name, int sym_type); symrec *putsym (char const *name, int sym_type);
symrec *getsym (char const *name); symrec *getsym (char const *name);
// Exchanging information with the parser.
typedef struct
{
// Whether to not emit error messages.
int silent;
// The current input line.
const char *line;
} user_context;
} }
// Emitted in the header file, after the definition of YYSTYPE. // Emitted in the header file, after the definition of YYSTYPE.
@@ -74,9 +83,13 @@
# define __attribute__(Spec) /* empty */ # define __attribute__(Spec) /* empty */
# endif # endif
# endif # endif
int yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc);
void yyerror (YYLTYPE *loc, char const *format, ...) yytoken_kind_t
__attribute__ ((__format__ (__printf__, 2, 3))); yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc,
const user_context *uctx);
void yyerror (YYLTYPE *loc, const user_context *uctx,
char const *format, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
} }
// Emitted in the implementation file. // Emitted in the implementation file.
@@ -116,6 +129,9 @@
// Generate the parser description file (calc.output). // Generate the parser description file (calc.output).
%verbose %verbose
// User information exchanged with the parser and scanner.
%param {const user_context *uctx}
// Generate YYSTYPE from the types assigned to symbols. // Generate YYSTYPE from the types assigned to symbols.
%define api.value.type union %define api.value.type union
%token %token
@@ -171,7 +187,7 @@ exp:
{ {
if ($r == 0) if ($r == 0)
{ {
yyerror (&@$, "error: division by zero"); yyerror (&@$, uctx, "error: division by zero");
YYERROR; YYERROR;
} }
else else
@@ -257,8 +273,9 @@ symbol_count (void)
| Scanner. | | Scanner. |
`----------*/ `----------*/
int yytoken_kind_t
yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc) yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc,
const user_context *uctx)
{ {
int c; int c;
@@ -328,7 +345,7 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
// Stray characters. // Stray characters.
default: default:
yyerror (yylloc, "syntax error: invalid character: %c", c); yyerror (yylloc, uctx, "syntax error: invalid character: %c", c);
return TOK_YYerror; return TOK_YYerror;
} }
} }
@@ -366,8 +383,11 @@ error_format_string (int argc)
int int
yyreport_syntax_error (const yypcontext_t *ctx) yyreport_syntax_error (const yypcontext_t *ctx, const user_context *uctx)
{ {
if (uctx->silent)
return 0;
enum { ARGS_MAX = 6 }; enum { ARGS_MAX = 6 };
yysymbol_kind_t arg[ARGS_MAX]; yysymbol_kind_t arg[ARGS_MAX];
int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX); int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX);
@@ -378,11 +398,12 @@ yyreport_syntax_error (const yypcontext_t *ctx)
argsize = ARGS_MAX; argsize = ARGS_MAX;
const char *format = error_format_string (1 + argsize + too_many_expected_tokens); const char *format = error_format_string (1 + argsize + too_many_expected_tokens);
const YYLTYPE *loc = yypcontext_location (ctx);
while (*format) while (*format)
// %@: location. // %@: location.
if (format[0] == '%' && format[1] == '@') if (format[0] == '%' && format[1] == '@')
{ {
YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx)); YY_LOCATION_PRINT (stderr, *loc);
format += 2; format += 2;
} }
// %u: unexpected token. // %u: unexpected token.
@@ -407,13 +428,25 @@ yyreport_syntax_error (const yypcontext_t *ctx)
++format; ++format;
} }
fputc ('\n', stderr); fputc ('\n', stderr);
// Quote the source line.
{
fprintf (stderr, "%5d | %s\n", loc->first_line, uctx->line);
fprintf (stderr, "%5s | %*s", "", loc->first_column, "^");
for (int i = loc->last_column - loc->first_column - 1; 0 < i; --i)
putc ('~', stderr);
putc ('\n', stderr);
}
return 0; return 0;
} }
// Called by yyparse on error. // Called by yyparse on error.
void yyerror (YYLTYPE *loc, char const *format, ...) void yyerror (YYLTYPE *loc, const user_context *uctx, char const *format, ...)
{ {
if (uctx->silent)
return;
YY_LOCATION_PRINT (stderr, *loc); YY_LOCATION_PRINT (stderr, *loc);
fputs (": ", stderr); fputs (": ", stderr);
va_list args; va_list args;
@@ -449,11 +482,13 @@ xstrndup (const char *string, size_t n)
static int static int
process_line (YYLTYPE *lloc, const char *line) process_line (YYLTYPE *lloc, const char *line)
{ {
user_context uctx = {0, line};
yypstate *ps = yypstate_new (); yypstate *ps = yypstate_new ();
int status = 0; int status = 0;
do { do {
YYSTYPE lval; YYSTYPE lval;
status = yypush_parse (ps, yylex (&line, &lval, lloc), &lval, lloc); yytoken_kind_t token = yylex (&line, &lval, lloc, &uctx);
status = yypush_parse (ps, token, &lval, lloc, &uctx);
} while (status == YYPUSH_MORE); } while (status == YYPUSH_MORE);
yypstate_delete (ps); yypstate_delete (ps);
lloc->last_line++; lloc->last_line++;
@@ -468,18 +503,19 @@ expected_tokens (const char *input,
int *tokens, int ntokens) int *tokens, int ntokens)
{ {
YYDPRINTF ((stderr, "expected_tokens (\"%s\")", input)); YYDPRINTF ((stderr, "expected_tokens (\"%s\")", input));
user_context uctx = {1, input};
// Parse the current state of the line. // Parse the current state of the line.
yypstate *ps = yypstate_new (); yypstate *ps = yypstate_new ();
int status = 0; int status = 0;
YYLTYPE lloc = { 1, 1, 1, 1 };
do { do {
YYLTYPE lloc = { 1, 1, 1, 1 };
YYSTYPE lval; YYSTYPE lval;
int token = yylex (&input, &lval, &lloc); yytoken_kind_t token = yylex (&input, &lval, &lloc, &uctx);
// Don't let the parse know when we reach the end of input. // Don't let the parse know when we reach the end of input.
if (!token) if (token == TOK_YYEOF)
break; break;
status = yypush_parse (ps, token, &lval, &lloc); status = yypush_parse (ps, token, &lval, &lloc, &uctx);
} while (status == YYPUSH_MORE); } while (status == YYPUSH_MORE);
int res = 0; int res = 0;
+1 -1
Submodule gnulib updated: 12c89745e3...ac34618e85
+1
View File
@@ -313,6 +313,7 @@
/stdlib.h /stdlib.h
/stdlib.in.h /stdlib.in.h
/stpcpy.c /stpcpy.c
/stpncpy.c
/strchrnul.c /strchrnul.c
/strchrnul.valgrind /strchrnul.valgrind
/strdup.c /strdup.c
+1
View File
@@ -175,6 +175,7 @@
/stdio_h.m4 /stdio_h.m4
/stdlib_h.m4 /stdlib_h.m4
/stpcpy.m4 /stpcpy.m4
/stpncpy.m4
/strchrnul.m4 /strchrnul.m4
/strdup.m4 /strdup.m4
/strerror.m4 /strerror.m4
+5 -5
View File
@@ -169,10 +169,10 @@ AnnotationList__compute_conflicted_tokens (bitset shift_tokens,
bitset_copy (tokens, shift_tokens); bitset_copy (tokens, shift_tokens);
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
{ {
bitset_and (conflicted_tokens_rule, tokens, reds->lookahead_tokens[i]); bitset_and (conflicted_tokens_rule, tokens, reds->lookaheads[i]);
bitset_or (conflicted_tokens, bitset_or (conflicted_tokens,
conflicted_tokens, conflicted_tokens_rule); conflicted_tokens, conflicted_tokens_rule);
bitset_or (tokens, tokens, reds->lookahead_tokens[i]); bitset_or (tokens, tokens, reds->lookaheads[i]);
/* Check that rules are sorted on rule number or the next step in /* Check that rules are sorted on rule number or the next step in
AnnotationList__compute_from_inadequacies will misbehave. */ AnnotationList__compute_from_inadequacies will misbehave. */
aver (i == 0 || reds->rules[i-1] < reds->rules[i]); aver (i == 0 || reds->rules[i-1] < reds->rules[i]);
@@ -401,7 +401,7 @@ AnnotationList__compute_from_inadequacies (
struct obstack *annotations_obstackp, struct obstack *annotations_obstackp,
InadequacyListNodeCount *inadequacy_list_node_count) InadequacyListNodeCount *inadequacy_list_node_count)
{ {
/* Return an empty list if s->lookahead_tokens = NULL. */ /* Return an empty list if s->lookaheads = NULL. */
if (s->consistent) if (s->consistent)
return; return;
@@ -422,7 +422,7 @@ AnnotationList__compute_from_inadequacies (
/* Allocate the annotation node. */ /* Allocate the annotation node. */
{ {
for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i) for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i)
if (bitset_test (s->reductions->lookahead_tokens[rule_i], if (bitset_test (s->reductions->lookaheads[rule_i],
conflicted_token)) conflicted_token))
++contribution_count; ++contribution_count;
if (bitset_test (shift_tokens, conflicted_token)) if (bitset_test (shift_tokens, conflicted_token))
@@ -445,7 +445,7 @@ AnnotationList__compute_from_inadequacies (
for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i) for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i)
{ {
rule *the_rule = s->reductions->rules[rule_i]; rule *the_rule = s->reductions->rules[rule_i];
if (bitset_test (s->reductions->lookahead_tokens[rule_i], if (bitset_test (s->reductions->lookaheads[rule_i],
conflicted_token)) conflicted_token))
{ {
bitset_set (actions, rule_i); bitset_set (actions, rule_i);
+35 -3
View File
@@ -35,6 +35,13 @@
#include "getargs.h" #include "getargs.h"
#include "quote.h" #include "quote.h"
// The URL of the manual page about diagnostics. Use the per-node
// manual, to avoid downloading repeatedly the whole manual over the
// Internet.
static const char *diagnostics_url
= "https://www.gnu.org/software/bison/manual/html_node/Diagnostics.html";
err_status complaint_status = status_none; err_status complaint_status = status_none;
bool warnings_are_errors = false; bool warnings_are_errors = false;
@@ -96,6 +103,20 @@ end_use_class (const char *s, FILE *out)
} }
} }
static void
begin_hyperlink (FILE *out, const char *ref)
{
if (out == stderr)
styled_ostream_set_hyperlink (errstream, ref, NULL);
}
static void
end_hyperlink (FILE *out)
{
if (out == stderr)
styled_ostream_set_hyperlink (errstream, NULL, NULL);
}
void void
flush (FILE *out) flush (FILE *out)
{ {
@@ -427,9 +448,20 @@ warnings_print_categories (warnings warn_flags, FILE *out)
const char* style = severity_style (s); const char* style = severity_style (s);
fputs (" [", out); fputs (" [", out);
begin_use_class (style, out); begin_use_class (style, out);
fprintf (out, "-W%s%s", // E.g., "counterexamples".
s == severity_error ? "error=" : "", const char *warning = argmatch_warning_argument (&w);
argmatch_warning_argument (&w)); char ref[200];
snprintf (ref, sizeof ref,
"%s#W%s", diagnostics_url, warning);
begin_hyperlink (out, ref);
ostream_printf (errstream,
"-W%s%s",
s == severity_error ? "error=" : "",
warning);
end_hyperlink (out);
// Because we mix stdio with ostream I/O, we need to flush
// here for sake of color == debug.
flush (out);
end_use_class (style, out); end_use_class (style, out);
fputc (']', out); fputc (']', out);
/* Display only the first match, the second is "-Wall". */ /* Display only the first match, the second is "-Wall". */
+29 -25
View File
@@ -250,9 +250,9 @@ flush_shift (state *s, int token)
`--------------------------------------------------------------------*/ `--------------------------------------------------------------------*/
static void static void
flush_reduce (bitset lookahead_tokens, int token) flush_reduce (bitset lookaheads, int token)
{ {
bitset_reset (lookahead_tokens, token); bitset_reset (lookaheads, token);
} }
@@ -275,10 +275,10 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
/* Find the rule to reduce by to get precedence of reduction. */ /* Find the rule to reduce by to get precedence of reduction. */
rule *redrule = reds->rules[ruleno]; rule *redrule = reds->rules[ruleno];
int redprec = redrule->prec->prec; int redprec = redrule->prec->prec;
bitset lookahead_tokens = reds->lookahead_tokens[ruleno]; bitset lookaheads = reds->lookaheads[ruleno];
for (symbol_number i = 0; i < ntokens; ++i) for (symbol_number i = 0; i < ntokens; ++i)
if (bitset_test (lookahead_tokens, i) if (bitset_test (lookaheads, i)
&& bitset_test (lookahead_set, i) && bitset_test (lookahead_set, i)
&& symbols[i]->content->prec) && symbols[i]->content->prec)
{ {
@@ -295,7 +295,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
{ {
register_precedence (i, redrule->prec->number); register_precedence (i, redrule->prec->number);
log_resolution (redrule, i, shift_resolution); log_resolution (redrule, i, shift_resolution);
flush_reduce (lookahead_tokens, i); flush_reduce (lookaheads, i);
} }
else else
/* Matching precedence levels. /* Matching precedence levels.
@@ -316,7 +316,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
case right_assoc: case right_assoc:
register_assoc (i, redrule->prec->number); register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, right_resolution); log_resolution (redrule, i, right_resolution);
flush_reduce (lookahead_tokens, i); flush_reduce (lookaheads, i);
break; break;
case left_assoc: case left_assoc:
@@ -329,7 +329,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
register_assoc (i, redrule->prec->number); register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, nonassoc_resolution); log_resolution (redrule, i, nonassoc_resolution);
flush_shift (s, i); flush_shift (s, i);
flush_reduce (lookahead_tokens, i); flush_reduce (lookaheads, i);
/* Record an explicit error for this token. */ /* Record an explicit error for this token. */
errors[(*nerrs)++] = symbols[i]; errors[(*nerrs)++] = symbols[i];
break; break;
@@ -369,7 +369,7 @@ set_conflicts (state *s, symbol **errors)
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
if (reds->rules[i]->prec if (reds->rules[i]->prec
&& reds->rules[i]->prec->prec && reds->rules[i]->prec->prec
&& !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set)) && !bitset_disjoint_p (reds->lookaheads[i], lookahead_set))
resolve_sr_conflict (s, i, errors, &nerrs); resolve_sr_conflict (s, i, errors, &nerrs);
if (nerrs) if (nerrs)
@@ -385,13 +385,13 @@ set_conflicts (state *s, symbol **errors)
/* Loop over all rules which require lookahead in this state. Check /* Loop over all rules which require lookahead in this state. Check
for conflicts not resolved above. for conflicts not resolved above.
reds->lookahead_tokens can be NULL if the LR type is LR(0). */ reds->lookaheads can be NULL if the LR type is LR(0). */
if (reds->lookahead_tokens) if (reds->lookaheads)
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
{ {
if (!bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set)) if (!bitset_disjoint_p (reds->lookaheads[i], lookahead_set))
conflicts[s->number] = true; conflicts[s->number] = true;
bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]); bitset_or (lookahead_set, lookahead_set, reds->lookaheads[i]);
} }
} }
@@ -460,7 +460,7 @@ count_state_sr_conflicts (const state *s)
} }
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]); bitset_or (lookahead_set, lookahead_set, reds->lookaheads[i]);
bitset_and (lookahead_set, lookahead_set, shift_set); bitset_and (lookahead_set, lookahead_set, shift_set);
@@ -499,7 +499,7 @@ count_state_rr_conflicts (const state *s)
{ {
int count = 0; int count = 0;
for (int j = 0; j < reds->num; ++j) for (int j = 0; j < reds->num; ++j)
count += bitset_test (reds->lookahead_tokens[j], i); count += bitset_test (reds->lookaheads[j], i);
if (2 <= count) if (2 <= count)
res += count-1; res += count-1;
} }
@@ -534,7 +534,7 @@ count_rule_state_sr_conflicts (rule *r, state *s)
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
if (reds->rules[i] == r) if (reds->rules[i] == r)
{ {
bitset lookaheads = reds->lookahead_tokens[i]; bitset lookaheads = reds->lookaheads[i];
int j; int j;
FOR_EACH_SHIFT (trans, j) FOR_EACH_SHIFT (trans, j)
res += bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j)); res += bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j));
@@ -576,8 +576,8 @@ count_rule_state_rr_conflicts (rule *r, state *s)
if (reds->rules[j] != r) if (reds->rules[j] != r)
{ {
bitset_and (lookaheads, bitset_and (lookaheads,
reds->lookahead_tokens[i], reds->lookaheads[i],
reds->lookahead_tokens[j]); reds->lookaheads[j]);
res += bitset_count (lookaheads); res += bitset_count (lookaheads);
} }
bitset_free (lookaheads); bitset_free (lookaheads);
@@ -686,7 +686,8 @@ conflicts_print (void)
expected_rr_conflicts = -1; expected_rr_conflicts = -1;
} }
bool has_unexpected_conflicts = false; // The warning flags used to emit a diagnostic, if we did.
warnings unexpected_conflicts_warning = Wnone;
/* The following two blocks scream for factoring, but i18n support /* The following two blocks scream for factoring, but i18n support
would make it ugly. */ would make it ugly. */
{ {
@@ -703,7 +704,8 @@ conflicts_print (void)
complain (NULL, complaint, complain (NULL, complaint,
_("shift/reduce conflicts: %d found, %d expected"), _("shift/reduce conflicts: %d found, %d expected"),
total, expected); total, expected);
has_unexpected_conflicts = true; if (total)
unexpected_conflicts_warning = complaint;
} }
} }
else if (total) else if (total)
@@ -713,7 +715,7 @@ conflicts_print (void)
"%d shift/reduce conflicts", "%d shift/reduce conflicts",
total), total),
total); total);
has_unexpected_conflicts = true; unexpected_conflicts_warning = Wconflicts_sr;
} }
} }
@@ -731,7 +733,8 @@ conflicts_print (void)
complain (NULL, complaint, complain (NULL, complaint,
_("reduce/reduce conflicts: %d found, %d expected"), _("reduce/reduce conflicts: %d found, %d expected"),
total, expected); total, expected);
has_unexpected_conflicts = true; if (total)
unexpected_conflicts_warning = complaint;
} }
} }
else if (total) else if (total)
@@ -741,15 +744,16 @@ conflicts_print (void)
"%d reduce/reduce conflicts", "%d reduce/reduce conflicts",
total), total),
total); total);
has_unexpected_conflicts = true; unexpected_conflicts_warning = Wconflicts_rr;
} }
} }
if (warning_is_enabled (Wcounterexamples)) if (warning_is_enabled (Wcounterexamples))
report_counterexamples (); report_counterexamples ();
else if (has_unexpected_conflicts) else if (unexpected_conflicts_warning != Wnone)
complain (NULL, Wother, subcomplain (NULL, unexpected_conflicts_warning,
_("rerun with option '-Wcounterexamples' to generate conflict counterexamples")); _("rerun with option '-Wcounterexamples'"
" to generate conflict counterexamples"));
} }
void void
+176 -103
View File
@@ -26,6 +26,7 @@
#include <gl_linked_list.h> #include <gl_linked_list.h>
#include <gl_rbtreehash_list.h> #include <gl_rbtreehash_list.h>
#include <hash.h> #include <hash.h>
#include <mbswidth.h>
#include <stdlib.h> #include <stdlib.h>
#include <textstyle.h> #include <textstyle.h>
#include <time.h> #include <time.h>
@@ -76,17 +77,29 @@ typedef struct
{ {
derivation *d1; derivation *d1;
derivation *d2; derivation *d2;
bool shift_reduce;
bool unifying; bool unifying;
bool timeout; bool timeout;
} counterexample; } counterexample;
static counterexample * static counterexample *
new_counterexample (derivation *d1, derivation *d2, new_counterexample (derivation *d1, derivation *d2,
bool shift_reduce,
bool u, bool t) bool u, bool t)
{ {
counterexample *res = xmalloc (sizeof (counterexample)); counterexample *res = xmalloc (sizeof *res);
res->d1 = d1; res->shift_reduce = shift_reduce;
res->d2 = d2; if (shift_reduce)
{
// Display the shift first.
res->d1 = d2;
res->d2 = d1;
}
else
{
res->d1 = d1;
res->d2 = d2;
}
res->unifying = u; res->unifying = u;
res->timeout = t; res->timeout = t;
return res; return res;
@@ -100,14 +113,37 @@ free_counterexample (counterexample *cex)
free (cex); free (cex);
} }
static void static int max (int a, int b)
print_counterexample (counterexample *cex, FILE *out, const char *prefix)
{ {
fprintf (out, " %s%-20s ", return a < b ? b : a;
prefix, cex->unifying ? _("Example") : _("First example")); }
derivation_print_leaves (cex->d1, out, prefix);
fprintf (out, " %s%-20s ", static void
prefix, _("First derivation")); print_counterexample (const counterexample *cex, FILE *out, const char *prefix)
{
const bool flat = getenv ("YYFLAT");
const char *example1_label
= cex->unifying ? _("Example") : _("First example");
const char *example2_label
= cex->unifying ? _("Example") : _("Second example");
const char *deriv1_label
= cex->shift_reduce ? _("Shift derivation") : _("First reduce derivation");
const char *deriv2_label
= cex->shift_reduce ? _("Reduce derivation") : _("Second reduce derivation");
const int width =
max (max (mbswidth (example1_label, 0), mbswidth (example2_label, 0)),
max (mbswidth (deriv1_label, 0), mbswidth (deriv2_label, 0)));
if (flat)
fprintf (out, " %s%s%*s ", prefix,
example1_label, width - mbswidth (example1_label, 0), "");
else
fprintf (out, " %s%s: ", prefix, example1_label);
derivation_print_leaves (cex->d1, out);
if (flat)
fprintf (out, " %s%s%*s ", prefix,
deriv1_label, width - mbswidth (deriv1_label, 0), "");
else
fprintf (out, " %s%s", prefix, deriv1_label);
derivation_print (cex->d1, out, prefix); derivation_print (cex->d1, out, prefix);
// If we output to the terminal (via stderr) and we have color // If we output to the terminal (via stderr) and we have color
@@ -115,15 +151,22 @@ print_counterexample (counterexample *cex, FILE *out, const char *prefix)
// to see the differences. // to see the differences.
if (!cex->unifying || is_styled (stderr)) if (!cex->unifying || is_styled (stderr))
{ {
fprintf (out, " %s%-20s ", if (flat)
prefix, cex->unifying ? _("Example") : _("Second example")); fprintf (out, " %s%s%*s ", prefix,
derivation_print_leaves (cex->d2, out, prefix); example2_label, width - mbswidth (example2_label, 0), "");
else
fprintf (out, " %s%s: ", prefix, example2_label);
derivation_print_leaves (cex->d2, out);
} }
fprintf (out, " %s%-20s ", if (flat)
prefix, _("Second derivation")); fprintf (out, " %s%s%*s ", prefix,
deriv2_label, width - mbswidth (deriv2_label, 0), "");
else
fprintf (out, " %s%s", prefix, deriv2_label);
derivation_print (cex->d2, out, prefix); derivation_print (cex->d2, out, prefix);
fputc ('\n', out); if (out != stderr)
putc ('\n', out);
} }
/* /*
@@ -144,7 +187,7 @@ typedef struct si_bfs_node
static si_bfs_node * static si_bfs_node *
si_bfs_new (state_item_number si, si_bfs_node *parent) si_bfs_new (state_item_number si, si_bfs_node *parent)
{ {
si_bfs_node *res = xcalloc (1, sizeof (si_bfs_node)); si_bfs_node *res = xcalloc (1, sizeof *res);
res->si = si; res->si = si;
res->parent = parent; res->parent = parent;
res->reference_count = 1; res->reference_count = 1;
@@ -175,6 +218,8 @@ si_bfs_free (si_bfs_node *n)
} }
} }
typedef gl_list_t si_bfs_node_list;
/** /**
* start is a state_item such that conflict_sym is an element of FIRSTS of the * start is a state_item such that conflict_sym is an element of FIRSTS of the
* nonterminal after the dot in start. Because of this, we should be able to * nonterminal after the dot in start. Because of this, we should be able to
@@ -188,15 +233,16 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
{ {
si_bfs_node *init = si_bfs_new (start, NULL); si_bfs_node *init = si_bfs_new (start, NULL);
gl_list_t queue = gl_list_create (GL_LINKED_LIST, NULL, NULL, si_bfs_node_list queue
(gl_listelement_dispose_fn) si_bfs_free, = gl_list_create (GL_LINKED_LIST, NULL, NULL,
true, 1, (const void **) &init); (gl_listelement_dispose_fn) si_bfs_free,
true, 1, (const void **) &init);
si_bfs_node *node = NULL; si_bfs_node *node = NULL;
// breadth-first search for a path of productions to the conflict symbol // breadth-first search for a path of productions to the conflict symbol
while (gl_list_size (queue) > 0) while (gl_list_size (queue) > 0)
{ {
node = (si_bfs_node *) gl_list_get_at (queue, 0); node = (si_bfs_node *) gl_list_get_at (queue, 0);
state_item *silast = state_items + node->si; state_item *silast = &state_items[node->si];
symbol_number sym = item_number_as_symbol_number (*silast->item); symbol_number sym = item_number_as_symbol_number (*silast->item);
if (sym == conflict_sym) if (sym == conflict_sym)
break; break;
@@ -238,7 +284,7 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
for (si_bfs_node *n = node; n != NULL; n = n->parent) for (si_bfs_node *n = node; n != NULL; n = n->parent)
{ {
state_item *si = state_items + n->si; state_item *si = &state_items[n->si];
item_number *pos = si->item; item_number *pos = si->item;
if (SI_PRODUCTION (si)) if (SI_PRODUCTION (si))
{ {
@@ -274,7 +320,7 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
*/ */
static derivation * static derivation *
complete_diverging_example (symbol_number conflict_sym, complete_diverging_example (symbol_number conflict_sym,
gl_list_t path, derivation_list derivs) state_item_list path, derivation_list derivs)
{ {
// The idea is to transfer each pending symbol on the productions // The idea is to transfer each pending symbol on the productions
// associated with the given StateItems to the resulting derivation. // associated with the given StateItems to the resulting derivation.
@@ -395,15 +441,15 @@ complete_diverging_example (symbol_number conflict_sym,
/* Iterate backwards through the shifts of the path in the reduce /* Iterate backwards through the shifts of the path in the reduce
conflict, and find a path of shifts from the shift conflict that conflict, and find a path of shifts from the shift conflict that
goes through the same states. */ goes through the same states. */
static gl_list_t static state_item_list
nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict) nonunifying_shift_path (state_item_list reduce_path, state_item *shift_conflict)
{ {
gl_list_node_t tmp = gl_list_add_last (reduce_path, NULL); gl_list_node_t tmp = gl_list_add_last (reduce_path, NULL);
gl_list_node_t next_node = gl_list_previous_node (reduce_path, tmp); gl_list_node_t next_node = gl_list_previous_node (reduce_path, tmp);
gl_list_node_t node = gl_list_previous_node (reduce_path, next_node); gl_list_node_t node = gl_list_previous_node (reduce_path, next_node);
gl_list_remove_node (reduce_path, tmp); gl_list_remove_node (reduce_path, tmp);
state_item *si = shift_conflict; state_item *si = shift_conflict;
gl_list_t result = state_item_list result =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
// FIXME: bool paths_merged; // FIXME: bool paths_merged;
for (; node != NULL; next_node = node, for (; node != NULL; next_node = node,
@@ -425,10 +471,10 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
// bfs to find a shift to the right state // bfs to find a shift to the right state
si_bfs_node *init = si_bfs_new (si - state_items, NULL); si_bfs_node *init = si_bfs_new (si - state_items, NULL);
gl_list_t queue = si_bfs_node_list queue
gl_list_create (GL_LINKED_LIST, NULL, NULL, = gl_list_create (GL_LINKED_LIST, NULL, NULL,
(gl_listelement_dispose_fn) si_bfs_free, (gl_listelement_dispose_fn) si_bfs_free,
true, 1, (const void **) &init); true, 1, (const void **) &init);
si_bfs_node *sis = NULL; si_bfs_node *sis = NULL;
state_item *prevsi = NULL; state_item *prevsi = NULL;
while (gl_list_size (queue) > 0) while (gl_list_size (queue) > 0)
@@ -438,7 +484,7 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
if (sis->si == 0) if (sis->si == 0)
break; break;
state_item *search_si = state_items + sis->si; state_item *search_si = &state_items[sis->si];
// if the current state-item is a production item, // if the current state-item is a production item,
// its reverse production items get added to the queue. // its reverse production items get added to the queue.
// Otherwise, look for a reverse transition to the target state. // Otherwise, look for a reverse transition to the target state.
@@ -447,7 +493,7 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
state_item_number sin; state_item_number sin;
BITSET_FOR_EACH (biter, rsi, sin, 0) BITSET_FOR_EACH (biter, rsi, sin, 0)
{ {
prevsi = state_items + sin; prevsi = &state_items[sin];
if (SI_TRANSITION (search_si)) if (SI_TRANSITION (search_si))
{ {
if (prevsi->state == refsi->state) if (prevsi->state == refsi->state)
@@ -465,9 +511,9 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
// prepend path to shift we found // prepend path to shift we found
if (sis) if (sis)
{ {
gl_list_node_t ln = gl_list_add_first (result, state_items + sis->si); gl_list_node_t ln = gl_list_add_first (result, &state_items[sis->si]);
for (si_bfs_node *n = sis->parent; n; n = n->parent) for (si_bfs_node *n = sis->parent; n; n = n->parent)
ln = gl_list_add_after (result, ln, state_items + n->si); ln = gl_list_add_after (result, ln, &state_items[n->si]);
} }
si = prevsi; si = prevsi;
@@ -493,17 +539,17 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
static counterexample * static counterexample *
example_from_path (bool shift_reduce, example_from_path (bool shift_reduce,
state_item_number itm2, state_item_number itm2,
gl_list_t shortest_path, symbol_number next_sym) state_item_list shortest_path, symbol_number next_sym)
{ {
derivation *deriv1 = derivation *deriv1 =
complete_diverging_example (next_sym, shortest_path, NULL); complete_diverging_example (next_sym, shortest_path, NULL);
gl_list_t path_2 state_item_list path_2
= shift_reduce = shift_reduce
? nonunifying_shift_path (shortest_path, &state_items [itm2]) ? nonunifying_shift_path (shortest_path, &state_items [itm2])
: shortest_path_from_start (itm2, next_sym); : shortest_path_from_start (itm2, next_sym);
derivation *deriv2 = complete_diverging_example (next_sym, path_2, NULL); derivation *deriv2 = complete_diverging_example (next_sym, path_2, NULL);
gl_list_free (path_2); gl_list_free (path_2);
return new_counterexample (deriv1, deriv2, false, true); return new_counterexample (deriv1, deriv2, shift_reduce, false, true);
} }
/* /*
@@ -525,7 +571,7 @@ typedef struct
static search_state * static search_state *
initial_search_state (state_item *conflict1, state_item *conflict2) initial_search_state (state_item *conflict1, state_item *conflict2)
{ {
search_state *res = xmalloc (sizeof (search_state)); search_state *res = xmalloc (sizeof *res);
res->states[0] = new_parse_state (conflict1); res->states[0] = new_parse_state (conflict1);
res->states[1] = new_parse_state (conflict2); res->states[1] = new_parse_state (conflict2);
parse_state_retain (res->states[0]); parse_state_retain (res->states[0]);
@@ -537,7 +583,7 @@ initial_search_state (state_item *conflict1, state_item *conflict2)
static search_state * static search_state *
new_search_state (parse_state *ps1, parse_state *ps2, int complexity) new_search_state (parse_state *ps1, parse_state *ps2, int complexity)
{ {
search_state *res = xmalloc (sizeof (search_state)); search_state *res = xmalloc (sizeof *res);
res->states[0] = ps1; res->states[0] = ps1;
res->states[1] = ps2; res->states[1] = ps2;
parse_state_retain (res->states[0]); parse_state_retain (res->states[0]);
@@ -549,8 +595,8 @@ new_search_state (parse_state *ps1, parse_state *ps2, int complexity)
static search_state * static search_state *
copy_search_state (search_state *parent) copy_search_state (search_state *parent)
{ {
search_state *res = xmalloc (sizeof (search_state)); search_state *res = xmalloc (sizeof *res);
memcpy (res, parent, sizeof (search_state)); *res = *parent;
parse_state_retain (res->states[0]); parse_state_retain (res->states[0]);
parse_state_retain (res->states[1]); parse_state_retain (res->states[1]);
return res; return res;
@@ -583,6 +629,8 @@ search_state_print (search_state *ss)
putc ('\n', stderr); putc ('\n', stderr);
} }
typedef gl_list_t search_state_list;
static inline bool static inline bool
search_state_list_next (gl_list_iterator_t *it, search_state **ss) search_state_list_next (gl_list_iterator_t *it, search_state **ss)
{ {
@@ -614,18 +662,20 @@ ss_set_parse_state (search_state *ss, int idx, parse_state *ps)
*/ */
static counterexample * static counterexample *
complete_diverging_examples (search_state *ss, complete_diverging_examples (search_state *ss,
symbol_number next_sym) symbol_number next_sym,
bool shift_reduce)
{ {
derivation *new_derivs[2]; derivation *new_derivs[2];
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
gl_list_t sitems; state_item_list sitems;
derivation_list derivs; derivation_list derivs;
parse_state_lists (ss->states[i], &sitems, &derivs); parse_state_lists (ss->states[i], &sitems, &derivs);
new_derivs[i] = complete_diverging_example (next_sym, sitems, derivs); new_derivs[i] = complete_diverging_example (next_sym, sitems, derivs);
gl_list_free (sitems); gl_list_free (sitems);
} }
return new_counterexample (new_derivs[0], new_derivs[1], false, true); return new_counterexample (new_derivs[0], new_derivs[1],
shift_reduce, false, true);
} }
/* /*
@@ -635,7 +685,7 @@ complete_diverging_examples (search_state *ss,
*/ */
typedef struct typedef struct
{ {
gl_list_t states; search_state_list states;
int complexity; int complexity;
} search_state_bundle; } search_state_bundle;
@@ -664,11 +714,13 @@ ssb_equals (const search_state_bundle *s1, const search_state_bundle *s2)
return s1->complexity == s2->complexity; return s1->complexity == s2->complexity;
} }
typedef gl_list_t ssb_list;
static size_t static size_t
visited_hasher (const search_state *ss, size_t max) visited_hasher (const search_state *ss, size_t maximum)
{ {
return (parse_state_hasher (ss->states[0], max) return (parse_state_hasher (ss->states[0], maximum)
+ parse_state_hasher (ss->states[1], max)) % max; + parse_state_hasher (ss->states[1], maximum)) % maximum;
} }
static bool static bool
@@ -679,7 +731,7 @@ visited_comparator (const search_state *ss1, const search_state *ss2)
} }
/* Priority queue for search states with minimal complexity. */ /* Priority queue for search states with minimal complexity. */
static gl_list_t ssb_queue; static ssb_list ssb_queue;
static Hash_table *visited; static Hash_table *visited;
/* The set of parser states on the shortest lookahead-sensitive path. */ /* The set of parser states on the shortest lookahead-sensitive path. */
static bitset scp_set = NULL; static bitset scp_set = NULL;
@@ -702,7 +754,7 @@ ssb_append (search_state *ss)
parse_state_free_contents_early (ss->states[1]); parse_state_free_contents_early (ss->states[1]);
parse_state_retain (ss->states[0]); parse_state_retain (ss->states[0]);
parse_state_retain (ss->states[1]); parse_state_retain (ss->states[1]);
search_state_bundle *ssb = xmalloc (sizeof (search_state_bundle)); search_state_bundle *ssb = xmalloc (sizeof *ssb);
ssb->complexity = ss->complexity; ssb->complexity = ss->complexity;
gl_list_node_t n = gl_list_search (ssb_queue, ssb); gl_list_node_t n = gl_list_search (ssb_queue, ssb);
if (!n) if (!n)
@@ -756,12 +808,12 @@ reduction_cost (const parse_state *ps)
return SHIFT_COST * shifts + PRODUCTION_COST * productions; return SHIFT_COST * shifts + PRODUCTION_COST * productions;
} }
static gl_list_t static search_state_list
reduction_step (search_state *ss, const item_number *conflict_item, reduction_step (search_state *ss, const item_number *conflict_item,
int parser_state, int rule_len) int parser_state, int rule_len)
{ {
(void) conflict_item; // FIXME: Unused (void) conflict_item; // FIXME: Unused
gl_list_t result = search_state_list result =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, 1); gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, 1);
parse_state *ps = ss->states[parser_state]; parse_state *ps = ss->states[parser_state];
@@ -897,7 +949,7 @@ search_state_prepend (search_state *ss, symbol_number sym, bitset guide)
* the same prefix up to the dot. * the same prefix up to the dot.
*/ */
static bool static bool
has_common_prefix (const item_number *itm1, const item_number *itm2) have_common_prefix (const item_number *itm1, const item_number *itm2)
{ {
int i = 0; int i = 0;
for (; !item_number_is_rule_number (itm1[i]); ++i) for (; !item_number_is_rule_number (itm1[i]); ++i)
@@ -988,14 +1040,14 @@ generate_next_states (search_state *ss, state_item *conflict1,
// prepended further, reduce. // prepended further, reduce.
if (ready1 && ready2) if (ready1 && ready2)
{ {
gl_list_t reduced1 = reduction_step (ss, conflict1->item, 0, len1); search_state_list reduced1 = reduction_step (ss, conflict1->item, 0, len1);
gl_list_add_last (reduced1, ss); gl_list_add_last (reduced1, ss);
search_state *red1 = NULL; search_state *red1 = NULL;
for (gl_list_iterator_t iter = gl_list_iterator (reduced1); for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
search_state_list_next (&iter, &red1); search_state_list_next (&iter, &red1);
) )
{ {
gl_list_t reduced2 = search_state_list reduced2 =
reduction_step (red1, conflict2->item, 1, len2); reduction_step (red1, conflict2->item, 1, len2);
search_state *red2 = NULL; search_state *red2 = NULL;
for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2); for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
@@ -1011,7 +1063,7 @@ generate_next_states (search_state *ss, state_item *conflict1,
} }
else if (ready1) else if (ready1)
{ {
gl_list_t reduced1 = reduction_step (ss, conflict1->item, 0, len1); search_state_list reduced1 = reduction_step (ss, conflict1->item, 0, len1);
search_state *red1 = NULL; search_state *red1 = NULL;
for (gl_list_iterator_t iter = gl_list_iterator (reduced1); for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
search_state_list_next (&iter, &red1); search_state_list_next (&iter, &red1);
@@ -1021,7 +1073,7 @@ generate_next_states (search_state *ss, state_item *conflict1,
} }
else if (ready2) else if (ready2)
{ {
gl_list_t reduced2 = reduction_step (ss, conflict2->item, 1, len2); search_state_list reduced2 = reduction_step (ss, conflict2->item, 1, len2);
search_state *red2 = NULL; search_state *red2 = NULL;
for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2); for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
search_state_list_next (&iter2, &red2); search_state_list_next (&iter2, &red2);
@@ -1055,10 +1107,10 @@ static counterexample *
unifying_example (state_item_number itm1, unifying_example (state_item_number itm1,
state_item_number itm2, state_item_number itm2,
bool shift_reduce, bool shift_reduce,
gl_list_t reduce_path, symbol_number next_sym) state_item_list reduce_path, symbol_number next_sym)
{ {
state_item *conflict1 = state_items + itm1; state_item *conflict1 = &state_items[itm1];
state_item *conflict2 = state_items + itm2; state_item *conflict2 = &state_items[itm2];
search_state *initial = initial_search_state (conflict1, conflict2); search_state *initial = initial_search_state (conflict1, conflict2);
ssb_queue = gl_list_create_empty (GL_RBTREEHASH_LIST, ssb_queue = gl_list_create_empty (GL_RBTREEHASH_LIST,
(gl_listelement_equals_fn) ssb_equals, (gl_listelement_equals_fn) ssb_equals,
@@ -1094,7 +1146,7 @@ unifying_example (state_item_number itm1,
const state_item *si1src = parse_state_head (ps1); const state_item *si1src = parse_state_head (ps1);
const state_item *si2src = parse_state_head (ps2); const state_item *si2src = parse_state_head (ps2);
if (item_rule (si1src->item)->lhs == item_rule (si2src->item)->lhs if (item_rule (si1src->item)->lhs == item_rule (si2src->item)->lhs
&& has_common_prefix (si1src->item, si2src->item)) && have_common_prefix (si1src->item, si2src->item))
{ {
// Stage 4: both paths share a prefix // Stage 4: both paths share a prefix
derivation *d1 = parse_state_derivation (ps1); derivation *d1 = parse_state_derivation (ps1);
@@ -1104,7 +1156,7 @@ unifying_example (state_item_number itm1,
{ {
// Once we have two derivations for the same symbol, // Once we have two derivations for the same symbol,
// we've found a unifying counterexample. // we've found a unifying counterexample.
cex = new_counterexample (d1, d2, true, false); cex = new_counterexample (d1, d2, shift_reduce, true, false);
derivation_retain (d1); derivation_retain (d1);
derivation_retain (d2); derivation_retain (d2);
goto cex_search_end; goto cex_search_end;
@@ -1142,7 +1194,7 @@ cex_search_end:;
// If a search state from Stage 3 is available, use it // If a search state from Stage 3 is available, use it
// to construct a more compact nonunifying counterexample. // to construct a more compact nonunifying counterexample.
if (stage3result) if (stage3result)
cex = complete_diverging_examples (stage3result, next_sym); cex = complete_diverging_examples (stage3result, next_sym, shift_reduce);
// Otherwise, construct a nonunifying counterexample that // Otherwise, construct a nonunifying counterexample that
// begins from the start state using the shortest // begins from the start state using the shortest
// lookahead-sensitive path to the reduce item. // lookahead-sensitive path to the reduce item.
@@ -1190,7 +1242,7 @@ counterexample_report (state_item_number itm1, state_item_number itm2,
{ {
// Compute the shortest lookahead-sensitive path and associated sets of // Compute the shortest lookahead-sensitive path and associated sets of
// parser states. // parser states.
gl_list_t shortest_path = shortest_path_from_start (itm1, next_sym); state_item_list shortest_path = shortest_path_from_start (itm1, next_sym);
bool reduce_prod_reached = false; bool reduce_prod_reached = false;
const rule *reduce_rule = item_rule (state_items[itm1].item); const rule *reduce_rule = item_rule (state_items[itm1].item);
@@ -1219,14 +1271,24 @@ counterexample_report (state_item_number itm1, state_item_number itm2,
free_counterexample (cex); free_counterexample (cex);
} }
// ITM1 denotes a shift, ITM2 a reduce.
static void static void
counterexample_report_shift_reduce (state_item_number itm1, state_item_number itm2, counterexample_report_shift_reduce (state_item_number itm1, state_item_number itm2,
symbol_number next_sym, symbol_number next_sym,
FILE *out, const char *prefix) FILE *out, const char *prefix)
{ {
fputs (prefix, out); if (out == stderr)
fprintf (out, _("Shift/reduce conflict on token %s:\n"), symbols[next_sym]->tag); complain (NULL, Wcounterexamples,
if (*prefix) _("shift/reduce conflict on token %s"), symbols[next_sym]->tag);
else
{
fputs (prefix, out);
fprintf (out, _("shift/reduce conflict on token %s"), symbols[next_sym]->tag);
fprintf (out, "%s\n", _(":"));
}
// In the report, print the items.
if (out != stderr || trace_flag & trace_cex)
{ {
print_state_item (&state_items[itm1], out, prefix); print_state_item (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix); print_state_item (&state_items[itm2], out, prefix);
@@ -1240,32 +1302,49 @@ counterexample_report_reduce_reduce (state_item_number itm1, state_item_number i
FILE *out, const char *prefix) FILE *out, const char *prefix)
{ {
{ {
fputs (prefix, out); struct obstack obstack;
fputs (ngettext ("Reduce/reduce conflict on token", obstack_init (&obstack);
"Reduce/reduce conflict on tokens",
bitset_count (conflict_syms)), out);
bitset_iterator biter; bitset_iterator biter;
state_item_number sym; state_item_number sym;
const char *sep = " "; const char *sep = "";
BITSET_FOR_EACH (biter, conflict_syms, sym, 0) BITSET_FOR_EACH (biter, conflict_syms, sym, 0)
{ {
fprintf (out, "%s%s", sep, symbols[sym]->tag); obstack_printf (&obstack, "%s%s", sep, symbols[sym]->tag);
sep = ", "; sep = ", ";
} }
fputs (_(":\n"), out); char *tokens = obstack_finish0 (&obstack);
if (out == stderr)
complain (NULL, Wcounterexamples,
ngettext ("reduce/reduce conflict on token %s",
"reduce/reduce conflict on tokens %s",
bitset_count (conflict_syms)),
tokens);
else
{
fputs (prefix, out);
fprintf (out,
ngettext ("reduce/reduce conflict on token %s",
"reduce/reduce conflict on tokens %s",
bitset_count (conflict_syms)),
tokens);
fprintf (out, "%s\n", _(":"));
}
obstack_free (&obstack, NULL);
} }
if (*prefix) // In the report, print the items.
if (out != stderr || trace_flag & trace_cex)
{ {
print_state_item (&state_items[itm1], out, prefix); print_state_item (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix); print_state_item (&state_items[itm2], out, prefix);
} }
counterexample_report (itm1, itm2, bitset_first (conflict_syms), false, out, prefix); counterexample_report (itm1, itm2, bitset_first (conflict_syms),
false, out, prefix);
} }
static state_item_number static state_item_number
find_state_item_number (const rule *r, state_number sn) find_state_item_number (const rule *r, state_number sn)
{ {
for (int i = state_item_map[sn]; i < state_item_map[sn + 1]; ++i) for (state_item_number i = state_item_map[sn]; i < state_item_map[sn + 1]; ++i)
if (!SI_DISABLED (i) if (!SI_DISABLED (i)
&& item_number_as_rule_number (*state_items[i].item) == r->number) && item_number_as_rule_number (*state_items[i].item) == r->number)
return i; return i;
@@ -1277,41 +1356,35 @@ counterexample_report_state (const state *s, FILE *out, const char *prefix)
{ {
const state_number sn = s->number; const state_number sn = s->number;
const reductions *reds = s->reductions; const reductions *reds = s->reductions;
bitset lookaheads = bitset_create (ntokens, BITSET_FIXED);
for (int i = 0; i < reds->num; ++i) for (int i = 0; i < reds->num; ++i)
{ {
const rule *r1 = reds->rules[i]; const rule *r1 = reds->rules[i];
const state_item_number c1 = find_state_item_number (r1, sn); const state_item_number c1 = find_state_item_number (r1, sn);
for (int j = state_item_map[sn]; j < state_item_map[sn + 1]; ++j) for (state_item_number c2 = state_item_map[sn]; c2 < state_item_map[sn + 1]; ++c2)
if (!SI_DISABLED (j)) if (!SI_DISABLED (c2))
{ {
state_item *si = state_items + j; item_number conf = *state_items[c2].item;
item_number conf = *si->item;
if (item_number_is_symbol_number (conf) if (item_number_is_symbol_number (conf)
&& bitset_test (reds->lookahead_tokens[i], conf)) && bitset_test (reds->lookaheads[i], conf))
counterexample_report_shift_reduce (c1, j, conf, out, prefix); counterexample_report_shift_reduce (c1, c2, conf, out, prefix);
} }
for (int j = i+1; j < reds->num; ++j) for (int j = i+1; j < reds->num; ++j)
{ {
bitset conf = bitset_create (ntokens, BITSET_FIXED); const rule *r2 = reds->rules[j];
bitset_intersection (conf, // Conflicts: common lookaheads.
reds->lookahead_tokens[i], bitset_intersection (lookaheads,
reds->lookahead_tokens[j]); reds->lookaheads[i],
if (!bitset_empty_p (conf)) reds->lookaheads[j]);
{ if (!bitset_empty_p (lookaheads))
const rule *r2 = reds->rules[j]; for (state_item_number c2 = state_item_map[sn]; c2 < state_item_map[sn + 1]; ++c2)
for (int k = state_item_map[sn]; k < state_item_map[sn + 1]; ++k) if (!SI_DISABLED (c2)
if (!SI_DISABLED (k)) && item_rule (state_items[c2].item) == r2)
{ {
state_item *si = state_items + k; counterexample_report_reduce_reduce (c1, c2, lookaheads, out, prefix);
const rule *r = item_rule (si->item); break;
if (r == r2) }
{
counterexample_report_reduce_reduce (c1, k, conf, out, prefix);
break;
}
}
}
bitset_free (conf);
} }
} }
bitset_free (lookaheads);
} }
+8 -2
View File
@@ -20,11 +20,17 @@
#ifndef COUNTEREXAMPLE_H #ifndef COUNTEREXAMPLE_H
# define COUNTEREXAMPLE_H # define COUNTEREXAMPLE_H
# include "state-item.h" # include "state.h"
// Init/deinit this module.
void counterexample_init (void); void counterexample_init (void);
void counterexample_free (void); void counterexample_free (void);
void counterexample_report_state (const state *s, FILE *out, const char *prefix); // Print the counterexamples for the conflicts of state S.
//
// Used both for the warnings on the terminal (OUT = stderr, PREFIX =
// ""), and for the reports (OUT != stderr, PREFIX != "").
void
counterexample_report_state (const state *s, FILE *out, const char *prefix);
#endif /* COUNTEREXAMPLE_H */ #endif /* COUNTEREXAMPLE_H */
+272 -41
View File
@@ -20,8 +20,11 @@
#include <config.h> #include <config.h>
#include "derivation.h" #include "derivation.h"
#include "glyphs.h"
#include <c-ctype.h>
#include <gl_linked_list.h> #include <gl_linked_list.h>
#include <mbswidth.h>
#include "system.h" #include "system.h"
#include "complain.h" #include "complain.h"
@@ -29,11 +32,15 @@
struct derivation struct derivation
{ {
symbol_number sym; symbol_number sym;
gl_list_t children; derivation_list children;
int reference_count; int reference_count;
// Color assigned for styling. Guarantees that the derivation is
// always displayed with the same color, independently of the order
// in which the derivations are traversed.
int color;
}; };
static derivation d_dot = { -1, NULL, -1 }; static derivation d_dot = { -1, NULL, -1, -1 };
derivation * derivation *
derivation_dot (void) derivation_dot (void)
@@ -73,6 +80,7 @@ derivation_new (symbol_number sym, derivation_list children)
deriv->sym = sym; deriv->sym = sym;
deriv->children = children; deriv->children = children;
deriv->reference_count = 0; deriv->reference_count = 0;
deriv->color = -1;
return deriv; return deriv;
} }
@@ -126,27 +134,242 @@ derivation_size (const derivation *deriv)
return size; return size;
} }
/* Print DERIV, colored according to COUNTER.
Return false if nothing is printed. */ static int
max (int a, int b)
{
return a < b ? b : a;
}
// Longest distance from root to leaf.
static int
derivation_depth (const derivation *deriv)
{
if (deriv->children)
{
// Children's depth cannot be 0, even if there are no children
// (the case of a derivation with an empty RHS).
int res = 1;
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
res = max (res, derivation_depth (child));
return res + 1;
}
else
return 1;
}
static bool static bool
derivation_print_impl (const derivation *deriv, FILE *f, all_spaces (const char *s)
bool leaves_only, {
int *counter, const char *prefix) while (c_isspace (*s))
s++;
return *s == '\0';
}
// Printing the derivation as trees without trailing spaces is
// painful: we cannot simply pad one "column" before moving to the
// next:
//
// exp
// ↳ x1 e1 foo1 x1
// ↳ x2 ↳ ε ↳ foo2 ↳ x2
// ↳ x3 ↳ foo3 ↳ x3
// ↳ "X" • ↳ x1 foo4 ↳ "X"
// ↳ x2 ↳ "quuux"
// ↳ x3
// ↳ "X"
//
// It's hard for a column to know that it's "last" to decide whether
// to output the right-padding or not. So when we need to pad on the
// right to complete a column, we don't output the spaces, we
// accumulate the width of padding in *PADDING.
//
// Each time we actually print something (non space), we flush that
// padding. When we _don't_ print something, its width is added to
// the current padding.
//
// This function implements this.
//
// When COND is true, put S on OUT, preceded by *PADDING white spaces.
// Otherwise add the width to *PADDING. Return the width of S.
static int
fputs_if (bool cond, FILE *out, int *padding, const char *s)
{
int res = mbswidth (s, 0);
if (cond && !all_spaces (s))
{
fprintf (out, "%*s%s", *padding, "", s);
*padding = 0;
}
else
{
*padding += res;
}
return res;
}
// The width taken to report this derivation recursively down to its
// leaves.
static int
derivation_width (const derivation *deriv)
{ {
if (deriv->children)
{
const symbol *sym = symbols[deriv->sym];
int self_width = mbswidth (sym->tag, 0);
// Arrow and space.
int children_width = down_arrow_width;
if (gl_list_size (deriv->children) == 0)
// Empty rhs.
children_width += empty_width;
else
{
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
children_width
+= derivation_separator_width + derivation_width (child);
// No separator at the beginning.
children_width -= derivation_separator_width;
}
return max (self_width, children_width);
}
else if (deriv == &d_dot)
{
return dot_width;
}
else // leaf.
{
const symbol *sym = symbols[deriv->sym];
return mbswidth (sym->tag, 0);
}
}
// Print DERIV for DEPTH.
//
// The tree is printed from top to bottom with DEPTH ranging from 0 to
// the total depth of the tree. DERIV should only printed when we
// reach its depth, i.e., then DEPTH is 0.
//
// When DEPTH is 1 and we're on a subderivation, then we print the RHS
// of the derivation (in DEPTH 0 we printed its LHS).
//
// Return the "logical printed" width. We might have not have reached
// that width, in which case the missing spaces are in *PADDING.
static int
derivation_print_tree_impl (const derivation *deriv, FILE *out,
int depth, int *padding)
{
const int width = derivation_width (deriv);
int res = 0;
if (deriv->children) if (deriv->children)
{ {
const symbol *sym = symbols[deriv->sym]; const symbol *sym = symbols[deriv->sym];
char style[20]; char style[20];
snprintf (style, 20, "cex-%d", *counter); snprintf (style, 20, "cex-%d", deriv->color);
if (depth == 0 || depth == 1)
{
begin_use_class (style, out);
begin_use_class ("cex-step", out);
}
if (depth == 0)
{
res += fputs_if (true, out, padding, sym->tag);
}
else
{
res += fputs_if (depth == 1, out, padding, down_arrow);
if (gl_list_size (deriv->children) == 0)
// Empty rhs.
res += fputs_if (depth == 1, out, padding, empty);
else
{
bool first = true;
derivation *child;
for (gl_list_iterator_t it = gl_list_iterator (deriv->children);
derivation_list_next (&it, &child);
)
{
if (!first)
res += fputs_if (depth == 1, out, padding, derivation_separator);
res += derivation_print_tree_impl (child, out, depth - 1, padding);
first = false;
}
}
}
if (depth == 0 || depth == 1)
{
end_use_class ("cex-step", out);
end_use_class (style, out);
}
*padding += width - res;
res = width;
}
else if (deriv == &d_dot)
{
if (depth == 0)
begin_use_class ("cex-dot", out);
res += fputs_if (depth == 0, out, padding, dot);
if (depth == 0)
end_use_class ("cex-dot", out);
}
else // leaf.
{
const symbol *sym = symbols[deriv->sym];
if (depth == 0)
begin_use_class ("cex-leaf", out);
res += fputs_if (depth == 0, out, padding, sym->tag);
if (depth == 0)
end_use_class ("cex-leaf", out);
}
return res;
}
static void
derivation_print_tree (const derivation *deriv, FILE *out, const char *prefix)
{
fputc ('\n', out);
for (int depth = 0, max_depth = derivation_depth (deriv);
depth < max_depth; ++depth)
{
int padding = 0;
fprintf (out, " %s", prefix);
derivation_print_tree_impl (deriv, out, depth, &padding);
fputc ('\n', out);
}
}
/* Print DERIV, colored according to COUNTER.
Return false if nothing is printed. */
static bool
derivation_print_flat_impl (derivation *deriv, FILE *out,
bool leaves_only,
int *counter, const char *prefix)
{
if (deriv->children)
{
const symbol *sym = symbols[deriv->sym];
deriv->color = *counter;
++*counter; ++*counter;
begin_use_class (style, f); char style[20];
snprintf (style, 20, "cex-%d", deriv->color);
begin_use_class (style, out);
if (!leaves_only) if (!leaves_only)
{ {
fputs (prefix, f); fputs (prefix, out);
begin_use_class ("cex-step", f); begin_use_class ("cex-step", out);
fprintf (f, "%s ::=[ ", sym->tag); fprintf (out, "%s %s [ ", sym->tag, arrow);
end_use_class ("cex-step", f); end_use_class ("cex-step", out);
prefix = ""; prefix = "";
} }
bool res = false; bool res = false;
@@ -155,7 +378,8 @@ derivation_print_impl (const derivation *deriv, FILE *f,
derivation_list_next (&it, &child); derivation_list_next (&it, &child);
) )
{ {
if (derivation_print_impl (child, f, leaves_only, counter, prefix)) if (derivation_print_flat_impl (child, out,
leaves_only, counter, prefix))
{ {
prefix = " "; prefix = " ";
res = true; res = true;
@@ -165,49 +389,56 @@ derivation_print_impl (const derivation *deriv, FILE *f,
} }
if (!leaves_only) if (!leaves_only)
{ {
begin_use_class ("cex-step", f); begin_use_class ("cex-step", out);
if (res) if (res)
fputs (" ]", f); fputs (" ]", out);
else else
fputs ("]", f); fputs ("]", out);
end_use_class ("cex-step", f); end_use_class ("cex-step", out);
} }
end_use_class (style, f); end_use_class (style, out);
return res; return res;
} }
else if (deriv == &d_dot) else if (deriv == &d_dot)
{ {
fputs (prefix, f); fputs (prefix, out);
begin_use_class ("cex-dot", f); begin_use_class ("cex-dot", out);
print_dot (f); fputs (dot, out);
end_use_class ("cex-dot", f); end_use_class ("cex-dot", out);
} }
else // leaf. else // leaf.
{ {
fputs (prefix, f); fputs (prefix, out);
const symbol *sym = symbols[deriv->sym]; const symbol *sym = symbols[deriv->sym];
begin_use_class ("cex-leaf", f); begin_use_class ("cex-leaf", out);
fprintf (f, "%s", sym->tag); fprintf (out, "%s", sym->tag);
end_use_class ("cex-leaf", f); end_use_class ("cex-leaf", out);
} }
return true; return true;
} }
static void
derivation_print_flat (const derivation *deriv, FILE *out, const char *prefix)
{
int counter = 0;
fputs (prefix, out);
derivation_print_flat_impl ((derivation *)deriv, out, false, &counter, "");
fputc ('\n', out);
}
void
derivation_print_leaves (const derivation *deriv, FILE *out)
{
int counter = 0;
derivation_print_flat_impl ((derivation *)deriv, out, true, &counter, "");
fputc ('\n', out);
}
void void
derivation_print (const derivation *deriv, FILE *out, const char *prefix) derivation_print (const derivation *deriv, FILE *out, const char *prefix)
{ {
int counter = 0; if (getenv ("YYFLAT"))
fputs (prefix, out); derivation_print_flat (deriv, out, prefix);
derivation_print_impl (deriv, out, false, &counter, ""); else
fputc ('\n', out); derivation_print_tree (deriv, out, prefix);
}
void
derivation_print_leaves (const derivation *deriv, FILE *out, const char *prefix)
{
int counter = 0;
fputs (prefix, out);
derivation_print_impl (deriv, out, true, &counter, "");
fputc ('\n', out);
} }
+4 -1
View File
@@ -60,12 +60,15 @@ static inline derivation *derivation_new_leaf (symbol_number sym)
{ {
return derivation_new (sym, NULL); return derivation_new (sym, NULL);
} }
// Number of symbols.
size_t derivation_size (const derivation *deriv); size_t derivation_size (const derivation *deriv);
void derivation_print (const derivation *deriv, FILE *out, const char *prefix); void derivation_print (const derivation *deriv, FILE *out, const char *prefix);
void derivation_print_leaves (const derivation *deriv, FILE *out, const char *prefix); void derivation_print_leaves (const derivation *deriv, FILE *out);
void derivation_free (derivation *deriv); void derivation_free (derivation *deriv);
void derivation_retain (derivation *deriv); void derivation_retain (derivation *deriv);
// A derivation denoting the position of the dot.
derivation *derivation_dot (void); derivation *derivation_dot (void);
#endif /* DERIVATION_H */ #endif /* DERIVATION_H */
+1 -1
View File
@@ -221,7 +221,7 @@ static const argmatch_report_arg argmatch_report_args[] =
{ "none", report_none }, { "none", report_none },
{ "states", report_states }, { "states", report_states },
{ "itemsets", report_states | report_itemsets }, { "itemsets", report_states | report_itemsets },
{ "lookaheads", report_states | report_lookahead_tokens }, { "lookaheads", report_states | report_lookaheads },
{ "solved", report_states | report_solved_conflicts }, { "solved", report_states | report_solved_conflicts },
{ "counterexamples", report_cex }, { "counterexamples", report_cex },
{ "cex", report_cex }, { "cex", report_cex },
+1 -1
View File
@@ -77,7 +77,7 @@ enum report
report_none = 0, report_none = 0,
report_states = 1 << 0, report_states = 1 << 0,
report_itemsets = 1 << 1, report_itemsets = 1 << 1,
report_lookahead_tokens = 1 << 2, report_lookaheads = 1 << 2,
report_solved_conflicts = 1 << 3, report_solved_conflicts = 1 << 3,
report_cex = 1 << 4, report_cex = 1 << 4,
report_all = ~0 report_all = ~0
+93
View File
@@ -0,0 +1,93 @@
/* Graphical symbols.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "glyphs.h"
#include <assert.h>
#include <attribute.h>
#include <stdbool.h>
#include <string.h>
#include <mbswidth.h>
#include <unicodeio.h>
glyph_buffer_t arrow;
int arrow_width;
glyph_buffer_t down_arrow;
int down_arrow_width;
glyph_buffer_t dot;
int dot_width;
glyph_buffer_t empty;
int empty_width;
const char *derivation_separator = " ";
int derivation_separator_width = 1;
typedef struct
{
glyph_buffer_t *pbuf;
const char *fallback;
} callback_arg_t;
static long
on_success (const char *buf, size_t buflen, void *callback_arg)
{
callback_arg_t *arg = (callback_arg_t *) callback_arg;
assert (buflen + 1 < sizeof *arg->pbuf);
*stpncpy (*arg->pbuf, buf, buflen) = '\0';
return 1;
}
static long
on_failure (unsigned code MAYBE_UNUSED, const char *msg MAYBE_UNUSED,
void *callback_arg)
{
callback_arg_t *arg = (callback_arg_t *) callback_arg;
assert (strlen (arg->fallback) + 1 < sizeof *arg->pbuf);
strcpy (*arg->pbuf, arg->fallback);
return 0;
}
static bool
glyph_set (glyph_buffer_t *glyph, int *width,
unsigned code, const char *fallback)
{
callback_arg_t arg = { glyph, fallback };
int res = unicode_to_mb (code, on_success, on_failure, &arg);
*width = mbswidth (*glyph, 0);
return res;
}
void
glyphs_init (void)
{
glyph_set (&arrow, &arrow_width, 0x2192, "->");
glyph_set (&dot, &dot_width, 0x2022, ".");
glyph_set (&down_arrow, &down_arrow_width, 0x21b3, "`->");
glyph_set (&empty, &empty_width, 0x03b5, "%empty");
strncat (down_arrow, " ", sizeof down_arrow - strlen (down_arrow) - 1);
down_arrow_width += 1;
}
+50
View File
@@ -0,0 +1,50 @@
/* Graphical symbols.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef GLYPHS_H
# define GLYPHS_H
/* Initialize the following variables. */
void glyphs_init (void);
/* In gnulib/lib/unicodeio.h unicode_to_mb uses a buffer of 25 bytes.
In down_arrow, we append one space. */
typedef char glyph_buffer_t[26];
/* "→", separates the lhs of a rule from its rhs. */
extern glyph_buffer_t arrow;
extern int arrow_width;
/* "•", a point in an item (aka, a dotted rule). */
extern glyph_buffer_t dot;
extern int dot_width;
/* "↳ ", below an lhs to announce the rhs. */
extern glyph_buffer_t down_arrow;
extern int down_arrow_width;
/* "ε", an empty rhs. */
extern glyph_buffer_t empty;
extern int empty_width;
/* " ", separate symbols in the rhs of a derivation. */
extern const char *derivation_separator;
extern int derivation_separator_width;
#endif /* GLYPHS_H */
+2 -2
View File
@@ -23,6 +23,7 @@
#include "complain.h" #include "complain.h"
#include "getargs.h" #include "getargs.h"
#include "glyphs.h"
#include "gram.h" #include "gram.h"
#include "print-xml.h" #include "print-xml.h"
#include "reader.h" #include "reader.h"
@@ -56,8 +57,7 @@ item_print (item_number *item, rule const *previous_rule, FILE *out)
for (item_number *sp = r->rhs; sp < item; sp++) for (item_number *sp = r->rhs; sp < item; sp++)
fprintf (out, " %s", symbols[*sp]->tag); fprintf (out, " %s", symbols[*sp]->tag);
putc (' ', out); fprintf (out, " %s", dot);
print_dot (out);
if (0 <= *r->rhs) if (0 <= *r->rhs)
for (item_number *sp = item; 0 <= *sp; ++sp) for (item_number *sp = item; 0 <= *sp; ++sp)
fprintf (out, " %s", symbols[*sp]->tag); fprintf (out, " %s", symbols[*sp]->tag);
-21
View File
@@ -103,8 +103,6 @@
# include "system.h" # include "system.h"
# include <unicodeio.h>
# include "location.h" # include "location.h"
# include "symtab.h" # include "symtab.h"
@@ -217,25 +215,6 @@ typedef struct
extern rule *rules; extern rule *rules;
extern rule_number nrules; extern rule_number nrules;
/* Fallback in case we can't print "•". */
static inline long
print_dot_fallback (unsigned int code _GL_UNUSED,
const char *msg _GL_UNUSED,
void *callback_arg)
{
FILE *out = (FILE *) callback_arg;
putc ('.', out);
return -1;
}
/* Print "•", the symbol used to represent a point in an item (aka, a
dotted rule). */
static inline void
print_dot (FILE *out)
{
unicode_to_mb (0x2022, fwrite_success_callback, print_dot_fallback, out);
}
/* Get the rule associated to this item. ITEM points inside RITEM. */ /* Get the rule associated to this item. ITEM points inside RITEM. */
static inline rule const * static inline rule const *
item_rule (item_number const *item) item_rule (item_number const *item)
+2 -2
View File
@@ -184,9 +184,9 @@ output_red (state const *s, reductions const *reds, FILE *fout)
bool firste = true; bool firste = true;
rule_number ruleno = reds->rules[j]->number; rule_number ruleno = reds->rules[j]->number;
if (reds->lookahead_tokens) if (reds->lookaheads)
for (int i = 0; i < ntokens; i++) for (int i = 0; i < ntokens; i++)
if (bitset_test (reds->lookahead_tokens[j], i)) if (bitset_test (reds->lookaheads[j], i))
{ {
if (bitset_test (no_reduce_set, i)) if (bitset_test (no_reduce_set, i))
firstd = print_token (&dout, firstd, symbols[i]->tag); firstd = print_token (&dout, firstd, symbols[i]->tag);
+1 -1
View File
@@ -1025,7 +1025,7 @@ ielr_split_states (bitsetv follow_kernel_items, bitsetv always_follows,
{ {
rule *this_rule = node->state->reductions->rules[r]; rule *this_rule = node->state->reductions->rules[r];
bitset lookahead_set = bitset lookahead_set =
node->state->reductions->lookahead_tokens[r]; node->state->reductions->lookaheads[r];
if (item_number_is_rule_number (*this_rule->rhs)) if (item_number_is_rule_number (*this_rule->rhs))
ielr_compute_goto_follow_set (follow_kernel_items, ielr_compute_goto_follow_set (follow_kernel_items,
always_follows, node, always_follows, node,
+24 -27
View File
@@ -256,9 +256,9 @@ lookback_find_state (int lookback_index)
state *res = NULL; state *res = NULL;
for (int j = 0; j < nstates; ++j) for (int j = 0; j < nstates; ++j)
if (states[j]->reductions if (states[j]->reductions
&& states[j]->reductions->lookahead_tokens) && states[j]->reductions->lookaheads)
{ {
if (states[j]->reductions->lookahead_tokens - LA > lookback_index) if (states[j]->reductions->lookaheads - LA > lookback_index)
/* Went too far. */ /* Went too far. */
break; break;
else else
@@ -280,7 +280,7 @@ lookback_print (FILE *out)
{ {
fprintf (out, " %3d = ", i); fprintf (out, " %3d = ", i);
const state *s = lookback_find_state (i); const state *s = lookback_find_state (i);
int rnum = i - (s->reductions->lookahead_tokens - LA); int rnum = i - (s->reductions->lookaheads - LA);
const rule *r = s->reductions->rules[rnum]; const rule *r = s->reductions->rules[rnum];
fprintf (out, "(%3d, ", s->number); fprintf (out, "(%3d, ", s->number);
rule_print (r, NULL, out); rule_print (r, NULL, out);
@@ -305,7 +305,7 @@ static void
add_lookback_edge (state *s, rule const *r, goto_number gotono) add_lookback_edge (state *s, rule const *r, goto_number gotono)
{ {
int ri = state_reduction_find (s, r); int ri = state_reduction_find (s, r);
int idx = (s->reductions->lookahead_tokens - LA) + ri; int idx = (s->reductions->lookaheads - LA) + ri;
lookback[idx] = goto_list_new (gotono, lookback[idx]); lookback[idx] = goto_list_new (gotono, lookback[idx]);
} }
@@ -421,7 +421,7 @@ compute_follows (void)
static void static void
compute_lookahead_tokens (void) compute_lookaheads (void)
{ {
if (trace_flag & trace_automaton) if (trace_flag & trace_automaton)
lookback_print (stderr); lookback_print (stderr);
@@ -437,13 +437,12 @@ compute_lookahead_tokens (void)
} }
/*----------------------------------------------------. /*------------------------------------------------------.
| Count the number of lookahead tokens required for S | | Count the number of lookahead tokens required for S. |
| (N_LOOKAHEAD_TOKENS member). | `------------------------------------------------------*/
`----------------------------------------------------*/
static int static int
state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept) state_lookaheads_count (state *s, bool default_reduction_only_for_accept)
{ {
const reductions *reds = s->reductions; const reductions *reds = s->reductions;
const transitions *trans = s->transitions; const transitions *trans = s->transitions;
@@ -473,9 +472,9 @@ state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept)
} }
/*----------------------------------------------------. /*----------------------------------------------.
| Compute LA, NLA, and the lookahead_tokens members. | | Compute LA, NLA, and the lookaheads members. |
`----------------------------------------------------*/ `----------------------------------------------*/
void void
initialize_LA (void) initialize_LA (void)
@@ -491,25 +490,23 @@ initialize_LA (void)
/* Compute the total number of reductions requiring a lookahead. */ /* Compute the total number of reductions requiring a lookahead. */
nLA = 0; nLA = 0;
for (state_number i = 0; i < nstates; ++i) for (state_number i = 0; i < nstates; ++i)
nLA += nLA += state_lookaheads_count (states[i],
state_lookahead_tokens_count (states[i], default_reduction_only_for_accept);
default_reduction_only_for_accept);
/* Avoid having to special case 0. */ /* Avoid having to special case 0. */
if (!nLA) if (!nLA)
nLA = 1; nLA = 1;
bitsetv pLA = LA = bitsetv_create (nLA, ntokens, BITSET_FIXED); bitsetv pLA = LA = bitsetv_create (nLA, ntokens, BITSET_FIXED);
/* Initialize the members LOOKAHEAD_TOKENS for each state whose reductions /* Initialize the members LOOKAHEADS for each state whose reductions
require lookahead tokens. */ require lookahead tokens. */
for (state_number i = 0; i < nstates; ++i) for (state_number i = 0; i < nstates; ++i)
{ {
int count = int count = state_lookaheads_count (states[i],
state_lookahead_tokens_count (states[i], default_reduction_only_for_accept);
default_reduction_only_for_accept);
if (count) if (count)
{ {
states[i]->reductions->lookahead_tokens = pLA; states[i]->reductions->lookaheads = pLA;
pLA += count; pLA += count;
} }
} }
@@ -521,7 +518,7 @@ initialize_LA (void)
`---------------------------------------------*/ `---------------------------------------------*/
static void static void
lookahead_tokens_print (FILE *out) lookaheads_print (FILE *out)
{ {
fputs ("Lookaheads:\n", out); fputs ("Lookaheads:\n", out);
for (state_number i = 0; i < nstates; ++i) for (state_number i = 0; i < nstates; ++i)
@@ -533,11 +530,11 @@ lookahead_tokens_print (FILE *out)
for (int j = 0; j < reds->num; ++j) for (int j = 0; j < reds->num; ++j)
{ {
fprintf (out, " rule %d:", reds->rules[j]->number); fprintf (out, " rule %d:", reds->rules[j]->number);
if (reds->lookahead_tokens) if (reds->lookaheads)
{ {
bitset_iterator iter; bitset_iterator iter;
int k; int k;
BITSET_FOR_EACH (iter, reds->lookahead_tokens[j], k, 0) BITSET_FOR_EACH (iter, reds->lookaheads[j], k, 0)
fprintf (out, " %s", symbols[k]->tag); fprintf (out, " %s", symbols[k]->tag);
} }
fputc ('\n', out); fputc ('\n', out);
@@ -564,10 +561,10 @@ lalr (void)
lookback = xcalloc (nLA, sizeof *lookback); lookback = xcalloc (nLA, sizeof *lookback);
build_relations (); build_relations ();
compute_follows (); compute_follows ();
compute_lookahead_tokens (); compute_lookaheads ();
if (trace_flag & trace_sets) if (trace_flag & trace_sets)
lookahead_tokens_print (stderr); lookaheads_print (stderr);
if (trace_flag & trace_automaton) if (trace_flag & trace_automaton)
{ {
begin_use_class ("trace0", stderr); begin_use_class ("trace0", stderr);
@@ -614,6 +611,6 @@ void
lalr_free (void) lalr_free (void)
{ {
for (state_number s = 0; s < nstates; ++s) for (state_number s = 0; s < nstates; ++s)
states[s]->reductions->lookahead_tokens = NULL; states[s]->reductions->lookaheads = NULL;
bitsetv_free (LA); bitsetv_free (LA);
} }
+2
View File
@@ -53,6 +53,8 @@ src_bison_SOURCES = \
src/flex-scanner.h \ src/flex-scanner.h \
src/getargs.c \ src/getargs.c \
src/getargs.h \ src/getargs.h \
src/glyphs.c \
src/glyphs.h \
src/gram.c \ src/gram.c \
src/gram.h \ src/gram.h \
src/graphviz.c \ src/graphviz.c \
+13 -11
View File
@@ -82,8 +82,10 @@ lssi_comparator (lssi *s1, lssi *s2)
return false; return false;
} }
typedef gl_list_t lssi_list;
static inline bool static inline bool
append_lssi (lssi *sn, Hash_table *visited, gl_list_t queue) append_lssi (lssi *sn, Hash_table *visited, lssi_list queue)
{ {
if (hash_lookup (visited, sn)) if (hash_lookup (visited, sn))
{ {
@@ -100,7 +102,7 @@ append_lssi (lssi *sn, Hash_table *visited, gl_list_t queue)
static void static void
lssi_print (lssi *l) lssi_print (lssi *l)
{ {
print_state_item (state_items + l->si, stdout); print_state_item (&state_items[l->si], stdout);
if (l->lookahead) if (l->lookahead)
{ {
printf ("FOLLOWL = { "); printf ("FOLLOWL = { ");
@@ -121,7 +123,7 @@ static bitset
eligible_state_items (state_item *target) eligible_state_items (state_item *target)
{ {
bitset result = bitset_create (nstate_items, BITSET_FIXED); bitset result = bitset_create (nstate_items, BITSET_FIXED);
gl_list_t queue = state_item_list queue =
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
(const void **) &target); (const void **) &target);
while (gl_list_size (queue) > 0) while (gl_list_size (queue) > 0)
@@ -147,7 +149,7 @@ eligible_state_items (state_item *target)
* this conflict. If optimized is true, only consider parser states * this conflict. If optimized is true, only consider parser states
* that can reach the conflict state. * that can reach the conflict state.
*/ */
gl_list_t state_item_list
shortest_path_from_start (state_item_number target, symbol_number next_sym) shortest_path_from_start (state_item_number target, symbol_number next_sym)
{ {
bitset eligible = eligible_state_items (&state_items[target]); bitset eligible = eligible_state_items (&state_items[target]);
@@ -159,7 +161,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
bitset il = bitset_create (nsyms, BITSET_FIXED); bitset il = bitset_create (nsyms, BITSET_FIXED);
bitset_set (il, 0); bitset_set (il, 0);
lssi *init = new_lssi (0, NULL, il, true); lssi *init = new_lssi (0, NULL, il, true);
gl_list_t queue = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, lssi_list queue = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL,
NULL, true); NULL, true);
append_lssi (init, visited, queue); append_lssi (init, visited, queue);
// breadth-first search // breadth-first search
@@ -175,7 +177,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
finished = true; finished = true;
break; break;
} }
state_item *si = state_items + last; state_item *si = &state_items[last];
// Transitions don't change follow_L // Transitions don't change follow_L
if (si->trans >= 0) if (si->trans >= 0)
{ {
@@ -240,10 +242,10 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
fputs ("Cannot find shortest path to conflict state.", stderr); fputs ("Cannot find shortest path to conflict state.", stderr);
abort (); abort ();
} }
gl_list_t res = state_item_list res =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
for (lssi *sn = n; sn != NULL; sn = sn->parent) for (lssi *sn = n; sn != NULL; sn = sn->parent)
gl_list_add_first (res, state_items + sn->si); gl_list_add_first (res, &state_items[sn->si]);
hash_free (visited); hash_free (visited);
gl_list_free (queue); gl_list_free (queue);
@@ -306,10 +308,10 @@ intersect (bitset ts, bitset syms)
* Compute a list of state_items that have a production to n with respect * Compute a list of state_items that have a production to n with respect
* to its lookahead * to its lookahead
*/ */
gl_list_t state_item_list
lssi_reverse_production (const state_item *si, bitset lookahead) lssi_reverse_production (const state_item *si, bitset lookahead)
{ {
gl_list_t result = state_item_list result =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
if (SI_TRANSITION (si)) if (SI_TRANSITION (si))
return result; return result;
@@ -320,7 +322,7 @@ lssi_reverse_production (const state_item *si, bitset lookahead)
state_item_number sin; state_item_number sin;
BITSET_FOR_EACH (biter, si->revs, sin, 0) BITSET_FOR_EACH (biter, si->revs, sin, 0)
{ {
state_item *prevsi = state_items + sin; state_item *prevsi = &state_items[sin];
if (!production_allowed (prevsi, si)) if (!production_allowed (prevsi, si))
continue; continue;
bitset prev_lookahead = prevsi->lookahead; bitset prev_lookahead = prevsi->lookahead;
+3 -3
View File
@@ -32,8 +32,8 @@
* find shortest lookahead-sensitive path of state-items to target such that * find shortest lookahead-sensitive path of state-items to target such that
* next_sym is in the follow_L set of target in that position. * next_sym is in the follow_L set of target in that position.
*/ */
gl_list_t shortest_path_from_start (state_item_number target, state_item_list shortest_path_from_start (state_item_number target,
symbol_number next_sym); symbol_number next_sym);
/** /**
* Determine if the given terminal is in the given symbol set or can begin * Determine if the given terminal is in the given symbol set or can begin
@@ -52,6 +52,6 @@ bool intersect (bitset ts, bitset syms);
* to this state-item such that the resulting possible lookahead symbols are * to this state-item such that the resulting possible lookahead symbols are
* as given. * as given.
*/ */
gl_list_t lssi_reverse_production (const state_item *si, bitset lookahead); state_item_list lssi_reverse_production (const state_item *si, bitset lookahead);
#endif /* LSSI_H */ #endif /* LSSI_H */
+2
View File
@@ -38,6 +38,7 @@
#include "files.h" #include "files.h"
#include "fixits.h" #include "fixits.h"
#include "getargs.h" #include "getargs.h"
#include "glyphs.h"
#include "gram.h" #include "gram.h"
#include "ielr.h" #include "ielr.h"
#include "lalr.h" #include "lalr.h"
@@ -85,6 +86,7 @@ main (int argc, char *argv[])
atexit (close_stdout); atexit (close_stdout);
glyphs_init ();
uniqstrs_new (); uniqstrs_new ();
muscle_init (); muscle_init ();
complain_init (); complain_init ();
+32 -34
View File
@@ -34,7 +34,7 @@ typedef struct parse_state
struct si_chunk struct si_chunk
{ {
// elements newly added in this chunk // elements newly added in this chunk
gl_list_t contents; state_item_list contents;
// properties of the linked list this chunk represents // properties of the linked list this chunk represents
const state_item *head_elt; const state_item *head_elt;
const state_item *tail_elt; const state_item *tail_elt;
@@ -135,7 +135,7 @@ static parse_state *
copy_parse_state (bool prepend, parse_state *parent) copy_parse_state (bool prepend, parse_state *parent)
{ {
parse_state *res = xmalloc (sizeof *res); parse_state *res = xmalloc (sizeof *res);
memcpy (res, parent, sizeof *res); *res = *parent;
res->state_items.contents res->state_items.contents
= gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
res->derivs.contents = derivation_list_new (); res->derivs.contents = derivation_list_new ();
@@ -252,7 +252,7 @@ parse_state_completed_steps (const parse_state *ps, int *shifts, int *production
while (root_ps->parent) while (root_ps->parent)
root_ps = root_ps->parent; root_ps = root_ps->parent;
gl_list_t sis = root_ps->state_items.contents; state_item_list sis = root_ps->state_items.contents;
int count = 0; int count = 0;
state_item *last = NULL; state_item *last = NULL;
@@ -337,19 +337,17 @@ parser_pop (parse_state *ps, int deriv_index,
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
chunks[i] = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); chunks[i] = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
for (parse_state *pn = ps; pn != NULL; pn = pn->parent) for (parse_state *pn = ps; pn != NULL; pn = pn->parent)
{ if (pn->prepend)
if (pn->prepend) {
{ gl_list_add_last (chunks[0], pn->state_items.contents);
gl_list_add_last (chunks[0], pn->state_items.contents); gl_list_add_last (chunks[2], pn->derivs.contents);
gl_list_add_last (chunks[2], pn->derivs.contents); }
} else
else {
{ gl_list_add_first (chunks[1], pn->state_items.contents);
gl_list_add_first (chunks[1], pn->state_items.contents); gl_list_add_first (chunks[3], pn->derivs.contents);
gl_list_add_first (chunks[3], pn->derivs.contents); }
} derivation_list popped_derivs = derivation_list_new ();
}
gl_list_t popped_derivs = derivation_list_new ();
gl_list_t ret_chunks[4] = { ret->state_items.contents, NULL, gl_list_t ret_chunks[4] = { ret->state_items.contents, NULL,
ret->derivs.contents, popped_derivs ret->derivs.contents, popped_derivs
}; };
@@ -390,7 +388,7 @@ parser_pop (parse_state *ps, int deriv_index,
} }
void void
parse_state_lists (parse_state *ps, gl_list_t *sitems, parse_state_lists (parse_state *ps, state_item_list *sitems,
derivation_list *derivs) derivation_list *derivs)
{ {
parse_state *temp = empty_parse_state (); parse_state *temp = empty_parse_state ();
@@ -418,12 +416,12 @@ nullable_closure (parse_state *ps, state_item *si, parse_state_list state_list)
for (state_item_number sin = si->trans; sin != -1; for (state_item_number sin = si->trans; sin != -1;
prev_sin = sin, sin = state_items[sin].trans) prev_sin = sin, sin = state_items[sin].trans)
{ {
state_item *psi = state_items + prev_sin; state_item *psi = &state_items[prev_sin];
symbol_number sp = item_number_as_symbol_number (*psi->item); symbol_number sp = item_number_as_symbol_number (*psi->item);
if (ISTOKEN (sp) || !nullable[sp - ntokens]) if (ISTOKEN (sp) || !nullable[sp - ntokens])
break; break;
state_item *nsi = state_items + sin; state_item *nsi = &state_items[sin];
current_ps = copy_parse_state (false, current_ps); current_ps = copy_parse_state (false, current_ps);
ps_si_append (current_ps, nsi); ps_si_append (current_ps, nsi);
ps_derivs_append (current_ps, derivation_new (sp, derivation_list_new ())); ps_derivs_append (current_ps, derivation_new (sp, derivation_list_new ()));
@@ -431,14 +429,14 @@ nullable_closure (parse_state *ps, state_item *si, parse_state_list state_list)
} }
} }
gl_list_t parse_state_list
simulate_transition (parse_state *ps) simulate_transition (parse_state *ps)
{ {
const state_item *si = ps->state_items.tail_elt; const state_item *si = ps->state_items.tail_elt;
symbol_number sym = item_number_as_symbol_number (*si->item); symbol_number sym = item_number_as_symbol_number (*si->item);
// Transition on the same next symbol, taking nullable // Transition on the same next symbol, taking nullable
// symbols into account. // symbols into account.
gl_list_t result = parse_state_list_new (); parse_state_list result = parse_state_list_new ();
state_item_number si_next = si->trans; state_item_number si_next = si->trans;
// check for disabled transition, shouldn't happen // check for disabled transition, shouldn't happen
// as any state_items that lead to these should be // as any state_items that lead to these should be
@@ -446,11 +444,11 @@ simulate_transition (parse_state *ps)
if (si_next < 0) if (si_next < 0)
return result; return result;
parse_state *next_ps = copy_parse_state (false, ps); parse_state *next_ps = copy_parse_state (false, ps);
ps_si_append (next_ps, state_items + si_next); ps_si_append (next_ps, &state_items[si_next]);
ps_derivs_append (next_ps, derivation_new_leaf (sym)); ps_derivs_append (next_ps, derivation_new_leaf (sym));
parse_state_list_append (result, next_ps); parse_state_list_append (result, next_ps);
nullable_closure (next_ps, state_items + si_next, result); nullable_closure (next_ps, &state_items[si_next], result);
return result; return result;
} }
@@ -473,10 +471,10 @@ compatible (symbol_number sym1, symbol_number sym2)
return false; return false;
} }
gl_list_t parse_state_list
simulate_production (parse_state *ps, symbol_number compat_sym) simulate_production (parse_state *ps, symbol_number compat_sym)
{ {
gl_list_t result = parse_state_list_new (); parse_state_list result = parse_state_list_new ();
const state_item *si = parse_state_tail (ps); const state_item *si = parse_state_tail (ps);
if (si->prods) if (si->prods)
{ {
@@ -486,7 +484,7 @@ simulate_production (parse_state *ps, symbol_number compat_sym)
{ {
// Take production step only if lhs is not nullable and // Take production step only if lhs is not nullable and
// if first rhs symbol is compatible with compat_sym // if first rhs symbol is compatible with compat_sym
state_item *next = state_items + sin; state_item *next = &state_items[sin];
item_number *itm1 = next->item; item_number *itm1 = next->item;
if (!compatible (*itm1, compat_sym) || !production_allowed (si, next)) if (!compatible (*itm1, compat_sym) || !production_allowed (si, next))
continue; continue;
@@ -504,10 +502,10 @@ simulate_production (parse_state *ps, symbol_number compat_sym)
// simulates a reduction on the given parse state, conflict_item is the // simulates a reduction on the given parse state, conflict_item is the
// item associated with ps's conflict. symbol_set is a lookahead set this // item associated with ps's conflict. symbol_set is a lookahead set this
// reduction must be compatible with // reduction must be compatible with
gl_list_t parse_state_list
simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set) simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
{ {
gl_list_t result = parse_state_list_new (); parse_state_list result = parse_state_list_new ();
int s_size = ps->state_items.total_size; int s_size = ps->state_items.total_size;
int d_size = ps->derivs.total_size; int d_size = ps->derivs.total_size;
@@ -529,7 +527,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
if (s_size != rule_len + 1) if (s_size != rule_len + 1)
{ {
state_item *tail = (state_item *) new_root->state_items.tail_elt; state_item *tail = (state_item *) new_root->state_items.tail_elt;
ps_si_append (new_root, state_items + tail->trans); ps_si_append (new_root, &state_items[tail->trans]);
parse_state_list_append (result, new_root); parse_state_list_append (result, new_root);
} }
else else
@@ -537,7 +535,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
// The head state_item is a production item, so we need to prepend // The head state_item is a production item, so we need to prepend
// with possible source state-items. // with possible source state-items.
const state_item *head = ps->state_items.head_elt; const state_item *head = ps->state_items.head_elt;
gl_list_t prev = lssi_reverse_production (head, symbol_set); state_item_list prev = lssi_reverse_production (head, symbol_set);
// TODO: better understand what causes this case. // TODO: better understand what causes this case.
if (gl_list_size (prev) == 0) if (gl_list_size (prev) == 0)
{ {
@@ -560,7 +558,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
copy = copy_parse_state (false, copy); copy = copy_parse_state (false, copy);
struct si_chunk *sis = &copy->state_items; struct si_chunk *sis = &copy->state_items;
const state_item *tail = sis->tail_elt; const state_item *tail = sis->tail_elt;
ps_si_append (copy, state_items + tail->trans); ps_si_append (copy, &state_items[tail->trans]);
parse_state_list_append (result, copy); parse_state_list_append (result, copy);
nullable_closure (copy, (state_item *) sis->tail_elt, result); nullable_closure (copy, (state_item *) sis->tail_elt, result);
} }
@@ -570,10 +568,10 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
return result; return result;
} }
gl_list_t parse_state_list
parser_prepend (parse_state *ps) parser_prepend (parse_state *ps)
{ {
gl_list_t res = parse_state_list_new (); parse_state_list res = parse_state_list_new ();
const state_item *head = ps->state_items.head_elt; const state_item *head = ps->state_items.head_elt;
symbol_number prepend_sym = symbol_number prepend_sym =
item_number_as_symbol_number (*(head->item - 1)); item_number_as_symbol_number (*(head->item - 1));
@@ -582,7 +580,7 @@ parser_prepend (parse_state *ps)
BITSET_FOR_EACH (biter, head->revs, sin, 0) BITSET_FOR_EACH (biter, head->revs, sin, 0)
{ {
parse_state *copy = copy_parse_state (true, ps); parse_state *copy = copy_parse_state (true, ps);
ps_si_prepend (copy, state_items + sin); ps_si_prepend (copy, &state_items[sin]);
if (SI_TRANSITION (head)) if (SI_TRANSITION (head))
ps_derivs_prepend (copy, derivation_new_leaf (prepend_sym)); ps_derivs_prepend (copy, derivation_new_leaf (prepend_sym));
parse_state_list_append (res, copy); parse_state_list_append (res, copy);
+1 -1
View File
@@ -113,7 +113,7 @@ int parse_state_length (const parse_state *ps);
int parse_state_depth (const parse_state *ps); int parse_state_depth (const parse_state *ps);
/* returns the linked lists that the parse state is supposed to represent */ /* returns the linked lists that the parse state is supposed to represent */
void parse_state_lists (parse_state *ps, gl_list_t *state_items, void parse_state_lists (parse_state *ps, state_item_list *state_items,
derivation_list *derivs); derivation_list *derivs);
/* various functions that return a list of states based off of /* various functions that return a list of states based off of
+3 -3
View File
@@ -96,7 +96,7 @@ print_core (struct obstack *oout, state *s)
obstack_sgrow (oout, " %empty"); obstack_sgrow (oout, " %empty");
/* Experimental feature: display the lookahead tokens. */ /* Experimental feature: display the lookahead tokens. */
if (report_flag & report_lookahead_tokens if (report_flag & report_lookaheads
&& item_number_is_rule_number (*sp1)) && item_number_is_rule_number (*sp1))
{ {
/* Find the reduction we are handling. */ /* Find the reduction we are handling. */
@@ -104,13 +104,13 @@ print_core (struct obstack *oout, state *s)
int redno = state_reduction_find (s, r); int redno = state_reduction_find (s, r);
/* Print them if there are. */ /* Print them if there are. */
if (reds->lookahead_tokens && redno != -1) if (reds->lookaheads && redno != -1)
{ {
bitset_iterator biter; bitset_iterator biter;
int k; int k;
char const *sep = ""; char const *sep = "";
obstack_sgrow (oout, " ["); obstack_sgrow (oout, " [");
BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0) BITSET_FOR_EACH (biter, reds->lookaheads[redno], k, 0)
{ {
obstack_sgrow (oout, sep); obstack_sgrow (oout, sep);
obstack_backslash (oout, symbols[k]->tag); obstack_backslash (oout, symbols[k]->tag);
+29 -22
View File
@@ -86,12 +86,12 @@ print_core (FILE *out, int level, state *s)
reductions *reds = s->reductions; reductions *reds = s->reductions;
int red = state_reduction_find (s, r); int red = state_reduction_find (s, r);
/* Print item with lookaheads if there are. */ /* Print item with lookaheads if there are. */
if (reds->lookahead_tokens && red != -1) if (reds->lookaheads && red != -1)
{ {
xml_printf (out, level + 1, xml_printf (out, level + 1,
"<item rule-number=\"%d\" dot=\"%d\">", "<item rule-number=\"%d\" dot=\"%d\">",
r->number, sp1 - sp); r->number, sp1 - sp);
state_rule_lookahead_tokens_print_xml (s, r, state_rule_lookaheads_print_xml (s, r,
out, level + 2); out, level + 2);
xml_puts (out, level + 1, "</item>"); xml_puts (out, level + 1, "</item>");
printed = true; printed = true;
@@ -202,26 +202,26 @@ print_errs (FILE *out, int level, state *s)
} }
/*-------------------------------------------------------------------------. /*-------------------------------------------------------------------.
| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). | | Report a reduction of RULE on LOOKAHEAD (which can be 'default'). |
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
| R/R conflicts). | | R/R conflicts). |
`-------------------------------------------------------------------------*/ `-------------------------------------------------------------------*/
static void static void
print_reduction (FILE *out, int level, char const *lookahead_token, print_reduction (FILE *out, int level, char const *lookahead,
rule *r, bool enabled) rule *r, bool enabled)
{ {
if (r->number) if (r->number)
xml_printf (out, level, xml_printf (out, level,
"<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>", "<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>",
xml_escape (lookahead_token), xml_escape (lookahead),
r->number, r->number,
enabled ? "true" : "false"); enabled ? "true" : "false");
else else
xml_printf (out, level, xml_printf (out, level,
"<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>", "<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>",
xml_escape (lookahead_token), xml_escape (lookahead),
enabled ? "true" : "false"); enabled ? "true" : "false");
} }
@@ -258,13 +258,13 @@ print_reductions (FILE *out, int level, state *s)
if (default_reduction) if (default_reduction)
report = true; report = true;
if (reds->lookahead_tokens) if (reds->lookaheads)
for (i = 0; i < ntokens; i++) for (i = 0; i < ntokens; i++)
{ {
bool count = bitset_test (no_reduce_set, i); bool count = bitset_test (no_reduce_set, i);
for (j = 0; j < reds->num; ++j) for (j = 0; j < reds->num; ++j)
if (bitset_test (reds->lookahead_tokens[j], i)) if (bitset_test (reds->lookaheads[j], i))
{ {
if (! count) if (! count)
{ {
@@ -289,14 +289,14 @@ print_reductions (FILE *out, int level, state *s)
xml_puts (out, level, "<reductions>"); xml_puts (out, level, "<reductions>");
/* Report lookahead tokens (or $default) and reductions. */ /* Report lookahead tokens (or $default) and reductions. */
if (reds->lookahead_tokens) if (reds->lookaheads)
for (i = 0; i < ntokens; i++) for (i = 0; i < ntokens; i++)
{ {
bool defaulted = false; bool defaulted = false;
bool count = bitset_test (no_reduce_set, i); bool count = bitset_test (no_reduce_set, i);
for (j = 0; j < reds->num; ++j) for (j = 0; j < reds->num; ++j)
if (bitset_test (reds->lookahead_tokens[j], i)) if (bitset_test (reds->lookaheads[j], i))
{ {
if (! count) if (! count)
{ {
@@ -382,14 +382,17 @@ print_grammar (FILE *out, int level)
for (int i = 0; i < max_code + 1; i++) for (int i = 0; i < max_code + 1; i++)
if (token_translations[i] != undeftoken->content->number) if (token_translations[i] != undeftoken->content->number)
{ {
char const *tag = symbols[token_translations[i]]->tag; symbol const *sym = symbols[token_translations[i]];
int precedence = symbols[token_translations[i]]->content->prec; char const *tag = sym->tag;
assoc associativity = symbols[token_translations[i]]->content->assoc; char const *type = sym->content->type_name;
int precedence = sym->content->prec;
assoc associativity = sym->content->assoc;
xml_indent (out, level + 2); xml_indent (out, level + 2);
fprintf (out, fprintf (out,
"<terminal symbol-number=\"%d\" token-number=\"%d\"" "<terminal symbol-number=\"%d\" token-number=\"%d\""
" name=\"%s\" usefulness=\"%s\"", " name=\"%s\" type=\"%s\" usefulness=\"%s\"",
token_translations[i], i, xml_escape (tag), token_translations[i], i, xml_escape_n (0, tag),
type ? xml_escape_n (1, type) : "",
reduce_token_unused_in_grammar (token_translations[i]) reduce_token_unused_in_grammar (token_translations[i])
? "unused-in-grammar" : "useful"); ? "unused-in-grammar" : "useful");
if (precedence) if (precedence)
@@ -404,12 +407,16 @@ print_grammar (FILE *out, int level)
xml_puts (out, level + 1, "<nonterminals>"); xml_puts (out, level + 1, "<nonterminals>");
for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; i++) for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; i++)
{ {
char const *tag = symbols[i]->tag; symbol const *sym = symbols[i];
char const *tag = sym->tag;
char const *type = sym->content->type_name;
xml_printf (out, level + 2, xml_printf (out, level + 2,
"<nonterminal symbol-number=\"%d\" name=\"%s\"" "<nonterminal symbol-number=\"%d\" name=\"%s\""
" type=\"%s\""
" usefulness=\"%s\"/>", " usefulness=\"%s\"/>",
i, xml_escape (tag), i, xml_escape_n (0, tag),
reduce_nonterminal_useless_in_grammar (symbols[i]->content) type ? xml_escape_n (1, type) : "",
reduce_nonterminal_useless_in_grammar (sym->content)
? "useless-in-grammar" : "useful"); ? "useless-in-grammar" : "useful");
} }
xml_puts (out, level + 1, "</nonterminals>"); xml_puts (out, level + 1, "</nonterminals>");
+22 -21
View File
@@ -90,9 +90,9 @@ print_core (FILE *out, const state *s)
previous_rule = r; previous_rule = r;
/* Display the lookahead tokens? */ /* Display the lookahead tokens? */
if (report_flag & report_lookahead_tokens if (report_flag & report_lookaheads
&& item_number_is_rule_number (*sp1)) && item_number_is_rule_number (*sp1))
state_rule_lookahead_tokens_print (s, r, out); state_rule_lookaheads_print (s, r, out);
fputc ('\n', out); fputc ('\n', out);
} }
} }
@@ -180,19 +180,19 @@ print_errs (FILE *out, const state *s)
} }
/*-------------------------------------------------------------------------. /*-------------------------------------------------------------------.
| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). | | Report a reduction of RULE on LOOKAHEAD (which can be 'default'). |
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
| R/R conflicts). | | R/R conflicts). |
`-------------------------------------------------------------------------*/ `-------------------------------------------------------------------*/
static void static void
print_reduction (FILE *out, size_t width, print_reduction (FILE *out, size_t width,
const char *lookahead_token, const char *lookahead,
rule *r, bool enabled) rule *r, bool enabled)
{ {
fprintf (out, " %s", lookahead_token); fprintf (out, " %s", lookahead);
for (int j = width - mbswidth (lookahead_token, 0); j > 0; --j) for (int j = width - mbswidth (lookahead, 0); j > 0; --j)
fputc (' ', out); fputc (' ', out);
if (!enabled) if (!enabled)
fputc ('[', out); fputc ('[', out);
@@ -239,13 +239,13 @@ print_reductions (FILE *out, const state *s)
if (default_reduction) if (default_reduction)
width = mbswidth (_("$default"), 0); width = mbswidth (_("$default"), 0);
if (reds->lookahead_tokens) if (reds->lookaheads)
for (int i = 0; i < ntokens; i++) for (int i = 0; i < ntokens; i++)
{ {
bool count = bitset_test (no_reduce_set, i); bool count = bitset_test (no_reduce_set, i);
for (int j = 0; j < reds->num; ++j) for (int j = 0; j < reds->num; ++j)
if (bitset_test (reds->lookahead_tokens[j], i)) if (bitset_test (reds->lookaheads[j], i))
{ {
if (! count) if (! count)
{ {
@@ -268,7 +268,7 @@ print_reductions (FILE *out, const state *s)
bool default_reduction_only = true; bool default_reduction_only = true;
/* Report lookahead tokens (or $default) and reductions. */ /* Report lookahead tokens (or $default) and reductions. */
if (reds->lookahead_tokens) if (reds->lookaheads)
for (int i = 0; i < ntokens; i++) for (int i = 0; i < ntokens; i++)
{ {
bool defaulted = false; bool defaulted = false;
@@ -277,7 +277,7 @@ print_reductions (FILE *out, const state *s)
default_reduction_only = false; default_reduction_only = false;
for (int j = 0; j < reds->num; ++j) for (int j = 0; j < reds->num; ++j)
if (bitset_test (reds->lookahead_tokens[j], i)) if (bitset_test (reds->lookaheads[j], i))
{ {
if (! count) if (! count)
{ {
@@ -377,11 +377,11 @@ print_terminal_symbols (FILE *out)
for (int i = 0; i < max_code + 1; ++i) for (int i = 0; i < max_code + 1; ++i)
if (token_translations[i] != undeftoken->content->number) if (token_translations[i] != undeftoken->content->number)
{ {
const char *tag = symbols[token_translations[i]]->tag; const symbol *sym = symbols[token_translations[i]];
const char *tag = sym->tag;
fprintf (out, "%4s%s", "", tag); fprintf (out, "%4s%s", "", tag);
if (symbols[token_translations[i]]->content->type_name) if (sym->content->type_name)
fprintf (out, " <%s>", fprintf (out, " <%s>", sym->content->type_name);
symbols[token_translations[i]]->content->type_name);
fprintf (out, " (%d)", i); fprintf (out, " (%d)", i);
for (rule_number r = 0; r < nrules; r++) for (rule_number r = 0; r < nrules; r++)
@@ -403,7 +403,8 @@ print_nonterminal_symbols (FILE *out)
fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear")); fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear"));
for (symbol_number i = ntokens; i < nsyms; i++) for (symbol_number i = ntokens; i < nsyms; i++)
{ {
const char *tag = symbols[i]->tag; const symbol *sym = symbols[i];
const char *tag = sym->tag;
bool on_left = false; bool on_left = false;
bool on_right = false; bool on_right = false;
@@ -418,9 +419,9 @@ print_nonterminal_symbols (FILE *out)
int column = 4 + mbswidth (tag, 0); int column = 4 + mbswidth (tag, 0);
fprintf (out, "%4s%s", "", tag); fprintf (out, "%4s%s", "", tag);
if (symbols[i]->content->type_name) if (sym->content->type_name)
column += fprintf (out, " <%s>", column += fprintf (out, " <%s>",
symbols[i]->content->type_name); sym->content->type_name);
fprintf (out, " (%d)\n", i); fprintf (out, " (%d)\n", i);
if (on_left) if (on_left)
+32 -34
View File
@@ -144,13 +144,13 @@ init_state_items (void)
for (int j = 0; j < s->nitems; ++j) for (int j = 0; j < s->nitems; ++j)
{ {
state_item_set (sidx, s, s->items[j]); state_item_set (sidx, s, s->items[j]);
state_item *si = state_items + sidx; state_item *si = &state_items[sidx];
const rule *r = item_rule (si->item); const rule *r = item_rule (si->item);
if (rule_search_idx < red->num && red->rules[rule_search_idx] < r) if (rule_search_idx < red->num && red->rules[rule_search_idx] < r)
++rule_search_idx; ++rule_search_idx;
if (rule_search_idx < red->num && r == red->rules[rule_search_idx]) if (rule_search_idx < red->num && r == red->rules[rule_search_idx])
{ {
bitsetv lookahead = red->lookahead_tokens; bitsetv lookahead = red->lookaheads;
if (lookahead) if (lookahead)
si->lookahead = lookahead[rule_search_idx]; si->lookahead = lookahead[rule_search_idx];
} }
@@ -163,7 +163,7 @@ init_state_items (void)
state_item_set (sidx, s, off); state_item_set (sidx, s, off);
if (item_number_is_rule_number (ritem[off])) if (item_number_is_rule_number (ritem[off]))
{ {
bitsetv lookahead = red->lookahead_tokens; bitsetv lookahead = red->lookaheads;
if (lookahead) if (lookahead)
state_items[sidx].lookahead = lookahead[rule_search_idx]; state_items[sidx].lookahead = lookahead[rule_search_idx];
++rule_search_idx; ++rule_search_idx;
@@ -211,7 +211,7 @@ init_trans (void)
for (int j = 0; j < t->num; ++j) for (int j = 0; j < t->num; ++j)
if (!TRANSITION_IS_DISABLED (t, j)) if (!TRANSITION_IS_DISABLED (t, j))
hash_xinsert (transition_set, t->states[j]); hash_xinsert (transition_set, t->states[j]);
for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j) for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
{ {
item_number *item = state_items[j].item; item_number *item = state_items[j].item;
if (item_number_is_rule_number (*item)) if (item_number_is_rule_number (*item))
@@ -222,16 +222,14 @@ init_trans (void)
// find the item in the destination state that corresponds // find the item in the destination state that corresponds
// to the transition of item // to the transition of item
for (int k = 0; k < dst->nitems; ++k) for (int k = 0; k < dst->nitems; ++k)
{ if (item + 1 == ritem + dst->items[k])
if (item + 1 == ritem + dst->items[k]) {
{ state_item_number dstSI =
state_item_number dstSI = state_item_index_lookup (dst->number, k);
state_item_index_lookup (dst->number, k);
state_items[j].trans = dstSI; state_items[j].trans = dstSI;
bitset_set (state_items[dstSI].revs, j); bitset_set (state_items[dstSI].revs, j);
break; break;
}
} }
} }
hash_free (transition_set); hash_free (transition_set);
@@ -250,10 +248,10 @@ init_prods (void)
// Add the nitems of state to skip to the production portion // Add the nitems of state to skip to the production portion
// of that state's state_items // of that state's state_items
for (int j = state_item_map[i] + s->nitems; for (state_item_number j = state_item_map[i] + s->nitems;
j < state_item_map[i + 1]; ++j) j < state_item_map[i + 1]; ++j)
{ {
state_item *src = state_items + j; state_item *src = &state_items[j];
item_number *item = src->item; item_number *item = src->item;
symbol_number lhs = item_rule (item)->lhs->number; symbol_number lhs = item_rule (item)->lhs->number;
bitset itms = hash_pair_lookup (closure_map, lhs); bitset itms = hash_pair_lookup (closure_map, lhs);
@@ -266,9 +264,9 @@ init_prods (void)
} }
// For each item with a dot followed by a nonterminal, // For each item with a dot followed by a nonterminal,
// try to create a production edge. // try to create a production edge.
for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j) for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
{ {
state_item *src = state_items + j; state_item *src = &state_items[j];
item_number item = *(src->item); item_number item = *(src->item);
// Skip reduce items and items with terminals after the dot // Skip reduce items and items with terminals after the dot
if (item_number_is_rule_number (item) || ISTOKEN (item)) if (item_number_is_rule_number (item) || ISTOKEN (item))
@@ -301,12 +299,12 @@ gen_lookaheads (void)
{ {
for (state_item_number i = 0; i < nstate_items; ++i) for (state_item_number i = 0; i < nstate_items; ++i)
{ {
state_item *si = state_items + i; state_item *si = &state_items[i];
if (item_number_is_symbol_number (*(si->item)) || !si->lookahead) if (item_number_is_symbol_number (*(si->item)) || !si->lookahead)
continue; continue;
bitset lookahead = si->lookahead; bitset lookahead = si->lookahead;
gl_list_t queue = state_item_list queue =
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
(const void **) &si); (const void **) &si);
@@ -339,7 +337,7 @@ init_firsts (void)
firsts = bitsetv_create (nnterms, nsyms, BITSET_FIXED); firsts = bitsetv_create (nnterms, nsyms, BITSET_FIXED);
for (rule_number i = 0; i < nrules; ++i) for (rule_number i = 0; i < nrules; ++i)
{ {
rule *r = rules + i; rule *r = &rules[i];
item_number *n = r->rhs; item_number *n = r->rhs;
// Iterate through nullable nonterminals to try to find a terminal. // Iterate through nullable nonterminals to try to find a terminal.
while (item_number_is_symbol_number (*n) && ISVAR (*n) while (item_number_is_symbol_number (*n) && ISVAR (*n)
@@ -357,7 +355,7 @@ init_firsts (void)
change = false; change = false;
for (rule_number i = 0; i < nrules; ++i) for (rule_number i = 0; i < nrules; ++i)
{ {
rule *r = rules + i; rule *r = &rules[i];
symbol_number lhs = r->lhs->number; symbol_number lhs = r->lhs->number;
bitset f_lhs = FIRSTS (lhs); bitset f_lhs = FIRSTS (lhs);
for (item_number *n = r->rhs; for (item_number *n = r->rhs;
@@ -392,7 +390,7 @@ disable_state_item (state_item *si)
static void static void
prune_forward (const state_item *si) prune_forward (const state_item *si)
{ {
gl_list_t queue = state_item_list queue =
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
(const void **) &si); (const void **) &si);
@@ -401,7 +399,7 @@ prune_forward (const state_item *si)
state_item *dsi = (state_item *) gl_list_get_at (queue, 0); state_item *dsi = (state_item *) gl_list_get_at (queue, 0);
gl_list_remove_at (queue, 0); gl_list_remove_at (queue, 0);
if (dsi->trans >= 0) if (dsi->trans >= 0)
gl_list_add_last (queue, state_items + dsi->trans); gl_list_add_last (queue, &state_items[dsi->trans]);
if (dsi->prods) if (dsi->prods)
{ {
@@ -409,7 +407,7 @@ prune_forward (const state_item *si)
state_item_number sin; state_item_number sin;
BITSET_FOR_EACH (biter, dsi->prods, sin, 0) BITSET_FOR_EACH (biter, dsi->prods, sin, 0)
{ {
const state_item *prod = state_items + sin; const state_item *prod = &state_items[sin];
bitset_reset (prod->revs, dsi - state_items); bitset_reset (prod->revs, dsi - state_items);
if (bitset_empty_p (prod->revs)) if (bitset_empty_p (prod->revs))
gl_list_add_last (queue, prod); gl_list_add_last (queue, prod);
@@ -427,7 +425,7 @@ prune_forward (const state_item *si)
static void static void
prune_backward (const state_item *si) prune_backward (const state_item *si)
{ {
gl_list_t queue = state_item_list queue =
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
(const void **) &si); (const void **) &si);
@@ -441,7 +439,7 @@ prune_backward (const state_item *si)
{ {
if (SI_DISABLED (sin)) if (SI_DISABLED (sin))
continue; continue;
state_item *rev = state_items + sin; state_item *rev = &state_items[sin];
if (rev->prods) if (rev->prods)
{ {
bitset_reset (rev->prods, dsi - state_items); bitset_reset (rev->prods, dsi - state_items);
@@ -466,7 +464,7 @@ prune_disabled_paths (void)
{ {
for (int i = nstate_items - 1; i >= 0; --i) for (int i = nstate_items - 1; i >= 0; --i)
{ {
state_item *si = state_items + i; state_item *si = &state_items[i];
if (si->trans == -1 && item_number_is_symbol_number (*si->item)) if (si->trans == -1 && item_number_is_symbol_number (*si->item))
{ {
prune_forward (si); prune_forward (si);
@@ -494,9 +492,9 @@ state_items_report (void)
for (state_number i = 0; i < nstates; ++i) for (state_number i = 0; i < nstates; ++i)
{ {
printf ("State %d:\n", i); printf ("State %d:\n", i);
for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j) for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j)
{ {
state_item *si = state_items + j; state_item *si = &state_items[j];
item_print (si->item, NULL, stdout); item_print (si->item, NULL, stdout);
if (SI_DISABLED (j)) if (SI_DISABLED (j))
{ {
@@ -508,7 +506,7 @@ state_items_report (void)
if (si->trans >= 0) if (si->trans >= 0)
{ {
fputs (" -> ", stdout); fputs (" -> ", stdout);
print_state_item (state_items + si->trans, stdout, ""); print_state_item (&state_items[si->trans], stdout, "");
} }
bitset sets[2] = { si->prods, si->revs }; bitset sets[2] = { si->prods, si->revs };
@@ -523,7 +521,7 @@ state_items_report (void)
BITSET_FOR_EACH (biter, b, sin, 0) BITSET_FOR_EACH (biter, b, sin, 0)
{ {
fputs (txt[seti], stdout); fputs (txt[seti], stdout);
print_state_item (state_items + sin, stdout, ""); print_state_item (&state_items[sin], stdout, "");
} }
} }
} }
@@ -562,10 +560,10 @@ state_items_init (void)
void void
state_items_free (void) state_items_free (void)
{ {
for (int i = 0; i < nstate_items; ++i) for (state_item_number i = 0; i < nstate_items; ++i)
if (!SI_DISABLED (i)) if (!SI_DISABLED (i))
{ {
state_item *si = state_items + i; state_item *si = &state_items[i];
if (si->prods) if (si->prods)
bitset_free (si->prods); bitset_free (si->prods);
bitset_free (si->revs); bitset_free (si->revs);
@@ -594,5 +592,5 @@ production_allowed (const state_item *si, const state_item *next)
if (prec1 == prec2 && s1->assoc == left_assoc) if (prec1 == prec2 && s1->assoc == left_assoc)
return false; return false;
} }
return true; return true;
} }
+12 -8
View File
@@ -28,16 +28,16 @@
# include "state.h" # include "state.h"
/* Initializes a graph connecting (state, production item) pairs to /* Initializes a graph connecting (state, production item) pairs to
pairs they can make a transition or production step to. This graph pairs they can make a transition or production step to. This graph
is used to search for paths that represent counterexamples of some is used to search for paths that represent counterexamples of some
conflict. conflict.
state_items is an array of state state-item pairs ordered by state. state_items is an array of state state-item pairs ordered by state.
state_item_map maps state numbers to the first item which state_item_map maps state numbers to the first item which
corresponds to it in the array. A state's portion in state_items corresponds to it in the array. A state's portion in state_items
begins with its items in the same order as it was in the begins with its items in the same order as it was in the state.
state. This is then followed by productions from the closure of the This is then followed by productions from the closure of the state
state in order by rule. in order by rule.
There are two type of edges in this graph transitions and There are two type of edges in this graph transitions and
productions. Transitions are the same as transitions from the productions. Transitions are the same as transitions from the
@@ -53,9 +53,9 @@
production edges, and all others will have reverse transition production edges, and all others will have reverse transition
edges. */ edges. */
# define SI_DISABLED(sin) (state_items[sin].trans == -2) # define SI_DISABLED(Sin) (state_items[Sin].trans == -2)
# define SI_PRODUCTION(si) ((si) == state_items || *((si)->item - 1) < 0) # define SI_PRODUCTION(Si) ((Si) == state_items || *((Si)->item - 1) < 0)
# define SI_TRANSITION(si) ((si) != state_items && *((si)->item - 1) >= 0) # define SI_TRANSITION(Si) ((Si) != state_items && *((Si)->item - 1) >= 0)
typedef int state_item_number; typedef int state_item_number;
@@ -69,6 +69,9 @@ typedef struct
bitset lookahead; bitset lookahead;
} state_item; } state_item;
// A path of state-items.
typedef gl_list_t state_item_list;
extern bitsetv firsts; extern bitsetv firsts;
# define FIRSTS(sym) firsts[(sym) - ntokens] # define FIRSTS(sym) firsts[(sym) - ntokens]
@@ -92,6 +95,7 @@ void state_items_free (void);
bool production_allowed (const state_item *si, const state_item *next); bool production_allowed (const state_item *si, const state_item *next);
// Iterating on a state_item_list.
static inline bool static inline bool
state_item_list_next (gl_list_iterator_t *it, state_item **si) state_item_list_next (gl_list_iterator_t *it, state_item **si)
{ {
+7 -7
View File
@@ -101,7 +101,7 @@ reductions_new (int num, rule **reds)
size_t rules_size = num * sizeof *reds; size_t rules_size = num * sizeof *reds;
reductions *res = xmalloc (offsetof (reductions, rules) + rules_size); reductions *res = xmalloc (offsetof (reductions, rules) + rules_size);
res->num = num; res->num = num;
res->lookahead_tokens = NULL; res->lookaheads = NULL;
memcpy (res->rules, reds, rules_size); memcpy (res->rules, reds, rules_size);
return res; return res;
} }
@@ -260,20 +260,20 @@ state_errs_set (state *s, int num, symbol **tokens)
`--------------------------------------------------*/ `--------------------------------------------------*/
void void
state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out) state_rule_lookaheads_print (state const *s, rule const *r, FILE *out)
{ {
/* Find the reduction we are handling. */ /* Find the reduction we are handling. */
reductions *reds = s->reductions; reductions *reds = s->reductions;
int red = state_reduction_find (s, r); int red = state_reduction_find (s, r);
/* Print them if there are. */ /* Print them if there are. */
if (reds->lookahead_tokens && red != -1) if (reds->lookaheads && red != -1)
{ {
bitset_iterator biter; bitset_iterator biter;
int k; int k;
char const *sep = ""; char const *sep = "";
fprintf (out, " ["); fprintf (out, " [");
BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0) BITSET_FOR_EACH (biter, reds->lookaheads[red], k, 0)
{ {
fprintf (out, "%s%s", sep, symbols[k]->tag); fprintf (out, "%s%s", sep, symbols[k]->tag);
sep = ", "; sep = ", ";
@@ -283,7 +283,7 @@ state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out)
} }
void void
state_rule_lookahead_tokens_print_xml (state const *s, rule const *r, state_rule_lookaheads_print_xml (state const *s, rule const *r,
FILE *out, int level) FILE *out, int level)
{ {
/* Find the reduction we are handling. */ /* Find the reduction we are handling. */
@@ -291,12 +291,12 @@ state_rule_lookahead_tokens_print_xml (state const *s, rule const *r,
int red = state_reduction_find (s, r); int red = state_reduction_find (s, r);
/* Print them if there are. */ /* Print them if there are. */
if (reds->lookahead_tokens && red != -1) if (reds->lookaheads && red != -1)
{ {
bitset_iterator biter; bitset_iterator biter;
int k; int k;
xml_puts (out, level, "<lookaheads>"); xml_puts (out, level, "<lookaheads>");
BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0) BITSET_FOR_EACH (biter, reds->lookaheads[red], k, 0)
{ {
xml_printf (out, level + 1, "<symbol>%s</symbol>", xml_printf (out, level + 1, "<symbol>%s</symbol>",
xml_escape (symbols[k]->tag)); xml_escape (symbols[k]->tag));
+5 -5
View File
@@ -62,7 +62,7 @@
Each reductions structure describes the possible reductions at the Each reductions structure describes the possible reductions at the
state whose number is in the number field. rules is an array of state whose number is in the number field. rules is an array of
num rules. lookahead_tokens is an array of bitsets, one per rule. num rules. lookaheads is an array of bitsets, one per rule.
Conflict resolution can decide that certain tokens in certain Conflict resolution can decide that certain tokens in certain
states should explicitly be errors (for implementing %nonassoc). states should explicitly be errors (for implementing %nonassoc).
@@ -187,7 +187,7 @@ errs *errs_new (int num, symbol **tokens);
typedef struct typedef struct
{ {
int num; int num;
bitset *lookahead_tokens; bitset *lookaheads;
/* Sorted ascendingly on rule number. */ /* Sorted ascendingly on rule number. */
rule *rules[1]; rule *rules[1];
} reductions; } reductions;
@@ -254,9 +254,9 @@ void state_errs_set (state *s, int num, symbol **errors);
/* Print on OUT all the lookahead tokens such that this STATE wants to /* Print on OUT all the lookahead tokens such that this STATE wants to
reduce R. */ reduce R. */
void state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out); void state_rule_lookaheads_print (state const *s, rule const *r, FILE *out);
void state_rule_lookahead_tokens_print_xml (state const *s, rule const *r, void state_rule_lookaheads_print_xml (state const *s, rule const *r,
FILE *out, int level); FILE *out, int level);
/* Create/destroy the states hash table. */ /* Create/destroy the states hash table. */
void state_hash_new (void); void state_hash_new (void);
+4 -4
View File
@@ -200,7 +200,7 @@ conflict_row (state *s)
/* Find all reductions for token J, and record all that do not /* Find all reductions for token J, and record all that do not
match ACTROW[J]. */ match ACTROW[J]. */
for (int i = 0; i < reds->num; i += 1) for (int i = 0; i < reds->num; i += 1)
if (bitset_test (reds->lookahead_tokens[i], j) if (bitset_test (reds->lookaheads[i], j)
&& (actrow[j] && (actrow[j]
!= rule_number_as_item_number (reds->rules[i]->number))) != rule_number_as_item_number (reds->rules[i]->number)))
{ {
@@ -247,7 +247,7 @@ action_row (state *s)
reductions *reds = s->reductions; reductions *reds = s->reductions;
bool conflicted = false; bool conflicted = false;
if (reds->lookahead_tokens) if (reds->lookaheads)
/* loop over all the rules available here which require /* loop over all the rules available here which require
lookahead (in reverse order to give precedence to the first lookahead (in reverse order to give precedence to the first
rule) */ rule) */
@@ -257,7 +257,7 @@ action_row (state *s)
{ {
bitset_iterator biter; bitset_iterator biter;
int j; int j;
BITSET_FOR_EACH (biter, reds->lookahead_tokens[i], j, 0) BITSET_FOR_EACH (biter, reds->lookaheads[i], j, 0)
{ {
/* and record this rule as the rule to use if that /* and record this rule as the rule to use if that
token follows. */ token follows. */
@@ -308,7 +308,7 @@ action_row (state *s)
} }
/* Turn off default reductions where requested by the user. See /* Turn off default reductions where requested by the user. See
state_lookahead_tokens_count in lalr.c to understand when states are state_lookaheads_count in lalr.c to understand when states are
labeled as consistent. */ labeled as consistent. */
{ {
char *default_reductions = char *default_reductions =
+92 -44
View File
@@ -726,7 +726,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-Dlr.type=canonical-lr -o input.c input.y]], AT_BISON_CHECK([[-Dlr.type=canonical-lr -o input.c input.y]],
[[0]], [[]], [[0]], [[]],
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([[input]]) AT_COMPILE([[input]])
AT_PARSER_CHECK([[input]], [[1]], [[]], AT_PARSER_CHECK([[input]], [[1]], [[]],
@@ -737,7 +737,7 @@ AT_PARSER_CHECK([[input]], [[1]], [[]],
AT_BISON_CHECK([[-Dlr.type=canonical-lr -Dparse.lac=full \ AT_BISON_CHECK([[-Dlr.type=canonical-lr -Dparse.lac=full \
-o input.c input.y]], [[0]], [[]], -o input.c input.y]], [[0]], [[]],
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([[input]]) AT_COMPILE([[input]])
AT_PARSER_CHECK([[input]], [[1]], [[]], AT_PARSER_CHECK([[input]], [[1]], [[]],
@@ -748,7 +748,7 @@ AT_PARSER_CHECK([[input]], [[1]], [[]],
AT_BISON_CHECK([[-Dlr.type=ielr -Dparse.lac=full -o input.c input.y]], AT_BISON_CHECK([[-Dlr.type=ielr -Dparse.lac=full -o input.c input.y]],
[[0]], [[]], [[0]], [[]],
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([[input]]) AT_COMPILE([[input]])
AT_PARSER_CHECK([[input]], [[1]], [[]], AT_PARSER_CHECK([[input]], [[1]], [[]],
@@ -773,7 +773,7 @@ exp: exp OP exp | NUM;
AT_BISON_CHECK([-o input.c --report=all input.y], 0, [], AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
# Check the contents of the report. # Check the contents of the report.
@@ -861,12 +861,18 @@ State 5
OP [reduce using rule 1 (exp)] OP [reduce using rule 1 (exp)]
$default reduce using rule 1 (exp) $default reduce using rule 1 (exp)
Shift/reduce conflict on token OP: shift/reduce conflict on token OP:
1 exp: exp OP exp . 1 exp: exp OP exp .
1 exp: exp . OP exp 1 exp: exp . OP exp
Example exp OP exp . OP exp Example: exp OP exp . OP exp
First derivation exp ::=[ exp ::=[ exp OP exp . ] OP exp ] Shift derivation
Second derivation exp ::=[ exp OP exp ::=[ exp . OP exp ] ] exp
`-> exp OP exp
`-> exp . OP exp
Reduce derivation
exp
`-> exp OP exp
`-> exp OP exp .
]]) ]])
@@ -1026,7 +1032,7 @@ cond:
AT_BISON_CHECK([-o input.c input.y], 0, [], AT_BISON_CHECK([-o input.c input.y], 0, [],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
input.y:12.3-18: warning: rule useless in parser due to conflicts [-Wother] input.y:12.3-18: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -1119,7 +1125,7 @@ m4_popdef([AT_TEST])
# else. # else.
AT_SETUP([Defaulted Conflicted Reduction]) AT_SETUP([Defaulted Conflicted Reduction])
AT_KEYWORDS([report]) AT_KEYWORDS([cex report])
AT_DATA([input.y], AT_DATA([input.y],
[[%% [[%%
@@ -1131,7 +1137,7 @@ id : '0';
AT_BISON_CHECK([-o input.c --report=all input.y], 0, [], AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
input.y:4.6-8: warning: rule useless in parser due to conflicts [-Wother] input.y:4.6-8: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -1203,12 +1209,18 @@ State 1
$end [reduce using rule 4 (id)] $end [reduce using rule 4 (id)]
$default reduce using rule 3 (num) $default reduce using rule 3 (num)
Reduce/reduce conflict on token $end: reduce/reduce conflict on token $end:
3 num: '0' . 3 num: '0' .
4 id: '0' . 4 id: '0' .
Example '0' . Example: '0' .
First derivation exp ::=[ num ::=[ '0' . ] ] First reduce derivation
Second derivation exp ::=[ id ::=[ '0' . ] ] exp
`-> num
`-> '0' .
Second reduce derivation
exp
`-> id
`-> '0' .
@@ -1260,7 +1272,7 @@ exp: exp OP exp | NUM;
AT_BISON_CHECK([-o input.c input.y], 1, [], AT_BISON_CHECK([-o input.c input.y], 1, [],
[[input.y: error: shift/reduce conflicts: 1 found, 0 expected [[input.y: error: shift/reduce conflicts: 1 found, 0 expected
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -1297,7 +1309,7 @@ exp: exp OP exp | NUM;
AT_BISON_CHECK([-o input.c input.y], 1, [], AT_BISON_CHECK([-o input.c input.y], 1, [],
[[input.y: error: shift/reduce conflicts: 1 found, 2 expected [[input.y: error: shift/reduce conflicts: 1 found, 2 expected
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -1317,7 +1329,7 @@ a: 'a';
AT_BISON_CHECK([-o input.c input.y], 1, [], AT_BISON_CHECK([-o input.c input.y], 1, [],
[[input.y: error: reduce/reduce conflicts: 1 found, 0 expected [[input.y: error: reduce/reduce conflicts: 1 found, 0 expected
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -1518,7 +1530,7 @@ e: e '+' e
AT_BISON_CHECK([-Wall -o input.c input.y], 0, [], AT_BISON_CHECK([-Wall -o input.c input.y], 0, [],
[[input.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
input.y:1.1-5: warning: useless precedence and associativity for '+' [-Wprecedence] input.y:1.1-5: warning: useless precedence and associativity for '+' [-Wprecedence]
input.y:2.1-5: warning: useless precedence and associativity for '*' [-Wprecedence] input.y:2.1-5: warning: useless precedence and associativity for '*' [-Wprecedence]
]]) ]])
@@ -1579,6 +1591,8 @@ AT_CLEANUP
AT_SETUP([[Unreachable States After Conflict Resolution]]) AT_SETUP([[Unreachable States After Conflict Resolution]])
AT_KEYWORDS([cex report])
# If conflict resolution makes states unreachable, remove those states, report # If conflict resolution makes states unreachable, remove those states, report
# rules that are then unused, and don't report conflicts in those states. Test # rules that are then unused, and don't report conflicts in those states. Test
# what happens when a nonterminal becomes useless as a result of state removal # what happens when a nonterminal becomes useless as a result of state removal
@@ -1624,7 +1638,7 @@ reported_conflicts:
AT_BISON_CHECK([[--report=all input.y]], 0, [], AT_BISON_CHECK([[--report=all input.y]], 0, [],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
input.y:12.5-20: warning: rule useless in parser due to conflicts [-Wother] input.y:12.5-20: warning: rule useless in parser due to conflicts [-Wother]
input.y:20.5-20: warning: rule useless in parser due to conflicts [-Wother] input.y:20.5-20: warning: rule useless in parser due to conflicts [-Wother]
input.y:21.4: warning: rule useless in parser due to conflicts [-Wother] input.y:21.4: warning: rule useless in parser due to conflicts [-Wother]
@@ -1750,21 +1764,33 @@ State 4
reported_conflicts go to state 6 reported_conflicts go to state 6
Shift/reduce conflict on token 'a': shift/reduce conflict on token 'a':
10 reported_conflicts: . %empty 10 reported_conflicts: . %empty
8 reported_conflicts: . 'a' 8 reported_conflicts: . 'a'
First example resolved_conflict . 'a' First example: resolved_conflict . 'a' 'a'
First derivation start ::=[ resolved_conflict reported_conflicts ::=[ . ] 'a' ] Shift derivation
Second example resolved_conflict . 'a' 'a' start
Second derivation start ::=[ resolved_conflict reported_conflicts ::=[ . 'a' ] 'a' ] `-> resolved_conflict reported_conflicts 'a'
`-> . 'a'
Second example: resolved_conflict . 'a'
Reduce derivation
start
`-> resolved_conflict reported_conflicts 'a'
`-> .
Shift/reduce conflict on token 'a': shift/reduce conflict on token 'a':
10 reported_conflicts: . %empty 10 reported_conflicts: . %empty
9 reported_conflicts: . 'a' 9 reported_conflicts: . 'a'
First example resolved_conflict . 'a' First example: resolved_conflict . 'a' 'a'
First derivation start ::=[ resolved_conflict reported_conflicts ::=[ . ] 'a' ] Shift derivation
Second example resolved_conflict . 'a' 'a' start
Second derivation start ::=[ resolved_conflict reported_conflicts ::=[ . 'a' ] 'a' ] `-> resolved_conflict reported_conflicts 'a'
`-> . 'a'
Second example: resolved_conflict . 'a'
Reduce derivation
start
`-> resolved_conflict reported_conflicts 'a'
`-> .
@@ -1777,12 +1803,16 @@ State 5
'a' [reduce using rule 9 (reported_conflicts)] 'a' [reduce using rule 9 (reported_conflicts)]
$default reduce using rule 8 (reported_conflicts) $default reduce using rule 8 (reported_conflicts)
Reduce/reduce conflict on token 'a': reduce/reduce conflict on token 'a':
8 reported_conflicts: 'a' . 8 reported_conflicts: 'a' .
9 reported_conflicts: 'a' . 9 reported_conflicts: 'a' .
Example 'a' . Example: 'a' .
First derivation reported_conflicts ::=[ 'a' . ] First reduce derivation
Second derivation reported_conflicts ::=[ 'a' . ] reported_conflicts
`-> 'a' .
Second reduce derivation
reported_conflicts
`-> 'a' .
@@ -1808,7 +1838,7 @@ AT_CHECK([[cat input.y >> input-keep.y]])
AT_BISON_CHECK([[input-keep.y]], 0, [], AT_BISON_CHECK([[input-keep.y]], 0, [],
[[input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
input-keep.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] input-keep.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
input-keep.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input-keep.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
input-keep.y:22.4: warning: rule useless in parser due to conflicts [-Wother] input-keep.y:22.4: warning: rule useless in parser due to conflicts [-Wother]
input-keep.y:26.16: warning: rule useless in parser due to conflicts [-Wother] input-keep.y:26.16: warning: rule useless in parser due to conflicts [-Wother]
input-keep.y:32.5-7: warning: rule useless in parser due to conflicts [-Wother] input-keep.y:32.5-7: warning: rule useless in parser due to conflicts [-Wother]
@@ -1904,6 +1934,8 @@ AT_CLEANUP
AT_SETUP([[%nonassoc error actions for multiple reductions in a state]]) AT_SETUP([[%nonassoc error actions for multiple reductions in a state]])
AT_KEYWORDS([cex report])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%nonassoc 'a' 'b' 'c' [[%nonassoc 'a' 'b' 'c'
%% %%
@@ -1961,12 +1993,18 @@ AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
Conflict between rule 10 and token 'b' resolved as an error (%nonassoc 'b'). Conflict between rule 10 and token 'b' resolved as an error (%nonassoc 'b').
Conflict between rule 11 and token 'c' resolved as an error (%nonassoc 'c'). Conflict between rule 11 and token 'c' resolved as an error (%nonassoc 'c').
Reduce/reduce conflict on token 'c': reduce/reduce conflict on token 'c':
12 empty_c2: . %empty 12 empty_c2: . %empty
13 empty_c3: . %empty 13 empty_c3: . %empty
Example . 'c' Example: . 'c'
First derivation start ::=[ empty_c2 ::=[ . ] 'c' ] First reduce derivation
Second derivation start ::=[ empty_c3 ::=[ . ] 'c' ] start
`-> empty_c2 'c'
`-> .
Second reduce derivation
start
`-> empty_c3 'c'
`-> .
@@ -2000,7 +2038,7 @@ exp: 'a' | 'a';
AT_BISON_CHECK([[2.y]], [[0]], [], AT_BISON_CHECK([[2.y]], [[0]], [],
[[2.y: warning: %expect-rr applies only to GLR parsers [-Wother] [[2.y: warning: %expect-rr applies only to GLR parsers [-Wother]
2.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] 2.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
2.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] 2.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
2.y:3.12-14: warning: rule useless in parser due to conflicts [-Wother] 2.y:3.12-14: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -2037,15 +2075,14 @@ B: ;
AT_BISON_CHECK([[sr-rr.y]], [[0]], [[]], AT_BISON_CHECK([[sr-rr.y]], [[0]], [[]],
[[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
sr-rr.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] sr-rr.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
sr-rr.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] sr-rr.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_BISON_CHECK([[-Wno-conflicts-sr sr-rr.y]], [[0]], [[]], AT_BISON_CHECK([[-Wno-conflicts-sr sr-rr.y]], [[0]], [[]],
[[sr-rr.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[sr-rr.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
sr-rr.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] sr-rr.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_BISON_CHECK([[-Wno-conflicts-rr sr-rr.y]], [[0]], [[]], AT_BISON_CHECK([[-Wno-conflicts-rr sr-rr.y]], [[0]], [[]],
[[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
sr-rr.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother]
]]) ]])
[ [
@@ -2102,19 +2139,30 @@ for gram in sr-rr sr rr; do
]AT_BISON_CHECK([[-Werror $file]])[ ]AT_BISON_CHECK([[-Werror $file]])[
else else
{ {
issue_note=false
if test -z "$sr_exp_i" && test "$sr_count" -ne 0; then if test -z "$sr_exp_i" && test "$sr_count" -ne 0; then
echo "warning: $sr_count shift/reduce conflicts" echo "warning: $sr_count shift/reduce conflicts"
issue_note=true
elif test "$sr_exp_i" -ne "$sr_count"; then elif test "$sr_exp_i" -ne "$sr_count"; then
echo "error: shift/reduce conflicts: $sr_count found, $sr_exp_i expected" echo "error: shift/reduce conflicts: $sr_count found, $sr_exp_i expected"
if test "$sr_count" -ne 0; then
issue_note=true
fi
fi fi
if test -z "$rr_exp_i" && test "$rr_count" -ne 0; then if test -z "$rr_exp_i" && test "$rr_count" -ne 0; then
echo "warning: $rr_count reduce/reduce conflicts" echo "warning: $rr_count reduce/reduce conflicts"
issue_note=true
elif test "$rr_exp_i" -ne "$rr_count"; then elif test "$rr_exp_i" -ne "$rr_count"; then
echo "error: reduce/reduce conflicts: $rr_count found, $rr_exp_i expected" echo "error: reduce/reduce conflicts: $rr_count found, $rr_exp_i expected"
if test "$rr_count" -ne 0; then
issue_note=true
fi
fi
if $issue_note; then
echo "note: rerun with option '-Wcounterexamples' to generate conflict counterexamples"
fi fi
} | sed -e "s/^/$file: /" > experr } | sed -e "s/^/$file: /" > experr
]AT_BISON_CHECK([[-Wnone $file]], [[1]], [[]], [[experr]])[ ]AT_BISON_CHECK([[-Wnone $file]], [[1]], [[]], [[experr]])[
echo "$file: error: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Werror=other]" >> experr
]AT_BISON_CHECK([[-Werror $file]], [[1]], [[]], [[experr]])[ ]AT_BISON_CHECK([[-Werror $file]], [[1]], [[]], [[experr]])[
fi fi
done done
+559 -183
View File
@@ -17,13 +17,23 @@
AT_BANNER([[Counterexamples.]]) AT_BANNER([[Counterexamples.]])
# AT_BISON_CHECK_CEX(TREE, FLAT)
# ------------------------------
m4_define([AT_BISON_CHECK_CEX], m4_define([AT_BISON_CHECK_CEX],
[AT_DATA([experr], [$4]) [AT_KEYWORDS([cex])
sed -e ['s/time limit exceeded: [0-9][.0-9]*/time limit exceeded: XXX/g'] \
experr >expout AT_BISON_CHECK([-Wcounterexamples input.y], [0], [], [stderr])
AT_BISON_CHECK([-Wcounterexamples $1], [$2], [$3], [stderr]) # FIXME: Avoid trailing white spaces.
AT_CHECK([[sed -e 's/time limit exceeded: [0-9][.0-9]*/time limit exceeded: XXX/g;s/ *$//;' stderr]],
[], [$1])
m4_pushdef([AT_SET_ENV_IF],
[[YYFLAT=1; export YYFLAT;]]m4_defn([AT_SET_ENV_IF]))
AT_BISON_CHECK([-Wcounterexamples input.y], [0], [], [stderr])
AT_CHECK([[sed -e 's/time limit exceeded: [0-9][.0-9]*/time limit exceeded: XXX/g' stderr]], AT_CHECK([[sed -e 's/time limit exceeded: [0-9][.0-9]*/time limit exceeded: XXX/g' stderr]],
[], [expout]) [], [$2])
m4_popdef([AT_SET_ENV_IF])
]) ])
## --------------------- ## ## --------------------- ##
@@ -31,7 +41,6 @@ AT_CHECK([[sed -e 's/time limit exceeded: [0-9][.0-9]*/time limit exceeded: XXX/
## --------------------- ## ## --------------------- ##
AT_SETUP([Unifying S/R]) AT_SETUP([Unifying S/R])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A B C [[%token A B C
@@ -43,13 +52,25 @@ x: B | B C;
y: A | A B; y: A | A B;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token B: input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example A . B C Example: A . B C
First derivation s ::=[ a ::=[ A . ] x ::=[ B C ] ] Shift derivation
Second derivation s ::=[ y ::=[ A . B ] c ::=[ C ] ] s
`-> y c
`-> A . B `-> C
Reduce derivation
s
`-> a x
`-> A . `-> B C
input.y:4.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example A . B C
Shift derivation s -> [ y -> [ A . B ] c -> [ C ] ]
Reduce derivation s -> [ a -> [ A . ] x -> [ B C ] ]
input.y:4.4: warning: rule useless in parser due to conflicts [-Wother] input.y:4.4: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -60,7 +81,6 @@ AT_CLEANUP
## ------------------- ## ## ------------------- ##
AT_SETUP([Deep Unifying S/R]) AT_SETUP([Deep Unifying S/R])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A B C [[%token A B C
@@ -72,18 +92,46 @@ a: A | A a;
bc: B bc C | B C; bc: B bc C | B C;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token B: input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example A . B C Example: A . B C
First derivation s ::=[ a ::=[ A . ] bc ::=[ B C ] ] Shift derivation
Second derivation s ::=[ ac ::=[ A ac ::=[ b ::=[ . B ] ] C ] ] s
`-> ac
Shift/reduce conflict on token B: `-> A ac C
Example A A . B B C C `-> b
First derivation s ::=[ a ::=[ A a ::=[ A . ] ] bc ::=[ B bc ::=[ B C ] C ] ] `-> . B
Second derivation s ::=[ ac ::=[ A ac ::=[ A ac ::=[ b ::=[ . b ::=[ B B ] ] ] C ] C ] ] Reduce derivation
s
`-> a bc
`-> A . `-> B C
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example: A A . B B C C
Shift derivation
s
`-> ac
`-> A ac C
`-> A ac C
`-> b
`-> . b
`-> B B
Reduce derivation
s
`-> a bc
`-> A a `-> B bc C
`-> A . `-> B C
input.y:6.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example A . B C
Shift derivation s -> [ ac -> [ A ac -> [ b -> [ . B ] ] C ] ]
Reduce derivation s -> [ a -> [ A . ] bc -> [ B C ] ]
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example A A . B B C C
Shift derivation s -> [ ac -> [ A ac -> [ A ac -> [ b -> [ . b -> [ B B ] ] ] C ] C ] ]
Reduce derivation s -> [ a -> [ A a -> [ A . ] ] bc -> [ B bc -> [ B C ] C ] ]
input.y:6.4: warning: rule useless in parser due to conflicts [-Wother] input.y:6.4: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -94,7 +142,6 @@ AT_CLEANUP
## ------------------------------------ ## ## ------------------------------------ ##
AT_SETUP([S/R Conflict with Nullable Symbols]) AT_SETUP([S/R Conflict with Nullable Symbols])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A B X Y [[%token A B X Y
@@ -107,19 +154,47 @@ y: %empty | Y y;
xby: B | X xby Y; xby: B | X xby Y;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
Shift/reduce conflict on token B: input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example A . B Example: A . B
First derivation s ::=[ ax ::=[ A x ::=[ . ] ] by ::=[ B y ::=[ ] ] ] Shift derivation
Second derivation s ::=[ A xby ::=[ . B ] ] s
`-> A xby
Shift/reduce conflict on token B: `-> . B
First example A X . B y $end Reduce derivation
First derivation $accept ::=[ s ::=[ ax ::=[ A x ::=[ X x ::=[ . ] ] ] by ::=[ B y ] ] $end ] s
Second example A X . B Y $end `-> ax by
Second derivation $accept ::=[ s ::=[ A xby ::=[ X xby ::=[ . B ] Y ] ] $end ] `-> A x `-> B y
`-> . `-> %empty
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
First example: A X . B Y $end
Shift derivation
$accept
`-> s $end
`-> A xby
`-> X xby Y
`-> . B
Second example: A X . B y $end
Reduce derivation
$accept
`-> s $end
`-> ax by
`-> A x `-> B y
`-> X x
`-> .
input.y:5.4-9: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example A . B
Shift derivation s -> [ A xby -> [ . B ] ]
Reduce derivation s -> [ ax -> [ A x -> [ . ] ] by -> [ B y -> [ ] ] ]
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
First example A X . B Y $end
Shift derivation $accept -> [ s -> [ A xby -> [ X xby -> [ . B ] Y ] ] $end ]
Second example A X . B y $end
Reduce derivation $accept -> [ s -> [ ax -> [ A x -> [ X x -> [ . ] ] ] by -> [ B y ] ] $end ]
input.y:5.4-9: warning: rule useless in parser due to conflicts [-Wother] input.y:5.4-9: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -130,7 +205,6 @@ AT_CLEANUP
## ---------------------------- ## ## ---------------------------- ##
AT_SETUP([Non-unifying Ambiguous S/R]) AT_SETUP([Non-unifying Ambiguous S/R])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A B C D E [[%token A B C D E
@@ -143,14 +217,31 @@ cd: C D;
bc: B C; bc: B C;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token C: input.y: warning: shift/reduce conflict on token C [-Wcounterexamples]
First example B . C D $end First example: B . C $end
First derivation $accept ::=[ g ::=[ x ::=[ b ::=[ B . ] cd ::=[ C D ] ] ] $end ] Shift derivation
Second example B . C $end $accept
Second derivation $accept ::=[ g ::=[ x ::=[ bc ::=[ B . C ] ] ] $end ] `-> g $end
`-> x
`-> bc
`-> B . C
Second example: B . C D $end
Reduce derivation
$accept
`-> g $end
`-> x
`-> b cd
`-> B . `-> C D
input.y:6.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token C [-Wcounterexamples]
First example B . C $end
Shift derivation $accept -> [ g -> [ x -> [ bc -> [ B . C ] ] ] $end ]
Second example B . C D $end
Reduce derivation $accept -> [ g -> [ x -> [ b -> [ B . ] cd -> [ C D ] ] ] $end ]
input.y:6.4: warning: rule useless in parser due to conflicts [-Wother] input.y:6.4: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -161,7 +252,6 @@ AT_CLEANUP
## ------------------------------ ## ## ------------------------------ ##
AT_SETUP([Non-unifying Unambiguous S/R]) AT_SETUP([Non-unifying Unambiguous S/R])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A B [[%token A B
@@ -172,14 +262,31 @@ x: A;
y: A A B; y: A A B;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token A: input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
First example A . A $end First example: A . A B $end
First derivation $accept ::=[ s ::=[ s ::=[ t ::=[ x ::=[ A . ] ] ] t ::=[ x ::=[ A ] ] ] $end ] Shift derivation
Second example A . A B $end $accept
Second derivation $accept ::=[ s ::=[ t ::=[ y ::=[ A . A B ] ] ] $end ] `-> s $end
`-> t
`-> y
`-> A . A B
Second example: A . A $end
Reduce derivation
$accept
`-> s $end
`-> s t
`-> t `-> x
`-> x `-> A
`-> A .
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
First example A . A B $end
Shift derivation $accept -> [ s -> [ t -> [ y -> [ A . A B ] ] ] $end ]
Second example A . A $end
Reduce derivation $accept -> [ s -> [ s -> [ t -> [ x -> [ A . ] ] ] t -> [ x -> [ A ] ] ] $end ]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -189,7 +296,6 @@ AT_CLEANUP
## ----------------------- ## ## ----------------------- ##
AT_SETUP([S/R after first token]) AT_SETUP([S/R after first token])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A B X Y [[%token A B X Y
@@ -205,19 +311,45 @@ xy: X Y;
y: Y; y: Y;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
Shift/reduce conflict on token A: input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
Example b . A X X Y Example: b . A X X Y
First derivation a ::=[ r ::=[ b . ] t ::=[ A x ::=[ X ] xy ::=[ X Y ] ] ] Shift derivation
Second derivation a ::=[ s ::=[ b . xx ::=[ A X X ] y ::=[ Y ] ] ] a
`-> s
Shift/reduce conflict on token X: `-> b . xx y
First example X . X xy `-> A X X `-> Y
First derivation a ::=[ x ::=[ X . ] t ::=[ X xy ] ] Reduce derivation
Second example A X . X a
Second derivation a ::=[ t ::=[ A xx ::=[ X . X ] ] ] `-> r t
`-> b . `-> A x xy
`-> X `-> X Y
input.y: warning: shift/reduce conflict on token X [-Wcounterexamples]
First example: A X . X
Shift derivation
a
`-> t
`-> A xx
`-> X . X
Second example: X . X xy
Reduce derivation
a
`-> x t
`-> X . `-> X xy
input.y:4.4: warning: rule useless in parser due to conflicts [-Wother]
input.y:8.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
Example b . A X X Y
Shift derivation a -> [ s -> [ b . xx -> [ A X X ] y -> [ Y ] ] ]
Reduce derivation a -> [ r -> [ b . ] t -> [ A x -> [ X ] xy -> [ X Y ] ] ]
input.y: warning: shift/reduce conflict on token X [-Wcounterexamples]
First example A X . X
Shift derivation a -> [ t -> [ A xx -> [ X . X ] ] ]
Second example X . X xy
Reduce derivation a -> [ x -> [ X . ] t -> [ X xy ] ]
input.y:4.4: warning: rule useless in parser due to conflicts [-Wother] input.y:4.4: warning: rule useless in parser due to conflicts [-Wother]
input.y:8.4: warning: rule useless in parser due to conflicts [-Wother] input.y:8.4: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -229,7 +361,6 @@ AT_CLEANUP
## ----------------------------- ## ## ----------------------------- ##
AT_SETUP([Unifying R/R counterexample]) AT_SETUP([Unifying R/R counterexample])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A [[%token A
@@ -238,13 +369,24 @@ a : A b ;
b : A | b; b : A | b;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
Reduce/reduce conflict on token $end: input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
Example A b . Example: A b .
First derivation a ::=[ A b . ] First reduce derivation
Second derivation a ::=[ A b ::=[ b . ] ] a
`-> A b .
Second reduce derivation
a
`-> A b
`-> b .
input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
Example A b .
First reduce derivation a -> [ A b . ]
Second reduce derivation a -> [ A b -> [ b . ] ]
input.y:4.9: warning: rule useless in parser due to conflicts [-Wother] input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -255,7 +397,6 @@ AT_CLEANUP
## --------------------------------- ## ## --------------------------------- ##
AT_SETUP([Non-unifying R/R LR(1) conflict]) AT_SETUP([Non-unifying R/R LR(1) conflict])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A B C D [[%token A B C D
@@ -265,14 +406,29 @@ a: D;
b: D; b: D;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] [[input.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on tokens A, C: input.y: warning: reduce/reduce conflict on tokens A, C [-Wcounterexamples]
First example D . A $end First example: D . A $end
First derivation $accept ::=[ s ::=[ a ::=[ D . ] A ] $end ] First reduce derivation
Second example B D . A $end $accept
Second derivation $accept ::=[ s ::=[ B b ::=[ D . ] A ] $end ] `-> s $end
`-> a A
`-> D .
Second example: B D . A $end
Second reduce derivation
$accept
`-> s $end
`-> B b A
`-> D .
input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
input.y: warning: reduce/reduce conflict on tokens A, C [-Wcounterexamples]
First example D . A $end
First reduce derivation $accept -> [ s -> [ a -> [ D . ] A ] $end ]
Second example B D . A $end
Second reduce derivation $accept -> [ s -> [ B b -> [ D . ] A ] $end ]
input.y:5.4: warning: rule useless in parser due to conflicts [-Wother] input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -283,7 +439,6 @@ AT_CLEANUP
## --------------------------------- ## ## --------------------------------- ##
AT_SETUP([Non-unifying R/R LR(2) conflict]) AT_SETUP([Non-unifying R/R LR(2) conflict])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token H J K X [[%token H J K X
@@ -293,15 +448,31 @@ a: H i;
i: X | i J K; i: X | i J K;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token J: input.y: warning: shift/reduce conflict on token J [-Wcounterexamples]
time limit exceeded: XXX time limit exceeded: XXX
First example H i . J $end First example: H i . J K $end
First derivation $accept ::=[ s ::=[ a ::=[ H i . ] J ] $end ] Shift derivation
Second example H i . J K $end $accept
Second derivation $accept ::=[ a ::=[ H i ::=[ i . J K ] ] $end ] `-> a $end
`-> H i
`-> i . J K
Second example: H i . J $end
Reduce derivation
$accept
`-> s $end
`-> a J
`-> H i .
input.y:4.4-6: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token J [-Wcounterexamples]
time limit exceeded: XXX
First example H i . J K $end
Shift derivation $accept -> [ a -> [ H i -> [ i . J K ] ] $end ]
Second example H i . J $end
Reduce derivation $accept -> [ s -> [ a -> [ H i . ] J ] $end ]
input.y:4.4-6: warning: rule useless in parser due to conflicts [-Wother] input.y:4.4-6: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -315,7 +486,6 @@ AT_CLEANUP
# graph search # graph search
AT_SETUP([Cex Search Prepend]) AT_SETUP([Cex Search Prepend])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token N A B C D [[%token N A B C D
@@ -326,18 +496,45 @@ a: A;
b: A B C | A B D; b: A B C | A B D;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token B: input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example N A . B C Example: N A . B C
First derivation s ::=[ n ::=[ N a ::=[ A . ] B ] C ] Shift derivation
Second derivation s ::=[ n ::=[ N b ::=[ A . B C ] ] ] s
`-> n
Shift/reduce conflict on token B: `-> N b
Example N N A . B D C `-> A . B C
First derivation s ::=[ n ::=[ N n ::=[ N a ::=[ A . ] B ] D ] C ] Reduce derivation
Second derivation s ::=[ n ::=[ N n ::=[ N b ::=[ A . B D ] ] C ] ] s
`-> n C
`-> N a B
`-> A .
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example: N N A . B D C
Shift derivation
s
`-> n
`-> N n C
`-> N b
`-> A . B D
Reduce derivation
s
`-> n C
`-> N n D
`-> N a B
`-> A .
input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example N A . B C
Shift derivation s -> [ n -> [ N b -> [ A . B C ] ] ]
Reduce derivation s -> [ n -> [ N a -> [ A . ] B ] C ]
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example N N A . B D C
Shift derivation s -> [ n -> [ N n -> [ N b -> [ A . B D ] ] C ] ]
Reduce derivation s -> [ n -> [ N n -> [ N a -> [ A . ] B ] D ] C ]
input.y:5.4: warning: rule useless in parser due to conflicts [-Wother] input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -351,7 +548,6 @@ AT_CLEANUP
# precedence/associativity directives work. # precedence/associativity directives work.
AT_SETUP([R/R cex with prec]) AT_SETUP([R/R cex with prec])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%left b [[%left b
@@ -363,18 +559,46 @@ B : A b A;
C : A c A; C : A c A;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 4 reduce/reduce conflicts [-Wconflicts-rr] [[input.y: warning: 4 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on tokens b, c: input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
Example B . b c Example: B . b c
First derivation S ::=[ B ::=[ A ::=[ B . ] b A ::=[ ] ] C ::=[ A ::=[ ] c A ::=[ ] ] ] First reduce derivation
Second derivation S ::=[ B C ::=[ A ::=[ B ::=[ A ::=[ . ] b A ::=[ ] ] ] c A ::=[ ] ] ] S
`-> B C
Reduce/reduce conflict on tokens b, c: `-> A b A `-> A c A
Example C . c b `-> B . `-> %empty `-> %empty `-> %empty
First derivation S ::=[ C ::=[ A ::=[ C . ] c A ::=[ ] ] B ::=[ A ::=[ ] b A ::=[ ] ] ] Second reduce derivation
Second derivation S ::=[ C B ::=[ A ::=[ C ::=[ A ::=[ . ] c A ::=[ ] ] ] b A ::=[ ] ] ] S
`-> B C
`-> A c A
`-> B `-> %empty
`-> A b A
`-> . `-> %empty
input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
Example: C . c b
First reduce derivation
S
`-> C B
`-> A c A `-> A b A
`-> C . `-> %empty `-> %empty `-> %empty
Second reduce derivation
S
`-> C B
`-> A b A
`-> C `-> %empty
`-> A c A
`-> . `-> %empty
]],
[[input.y: warning: 4 reduce/reduce conflicts [-Wconflicts-rr]
input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
Example B . b c
First reduce derivation S -> [ B -> [ A -> [ B . ] b A -> [ ] ] C -> [ A -> [ ] c A -> [ ] ] ]
Second reduce derivation S -> [ B C -> [ A -> [ B -> [ A -> [ . ] b A -> [ ] ] ] c A -> [ ] ] ]
input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
Example C . c b
First reduce derivation S -> [ C -> [ A -> [ C . ] c A -> [ ] ] B -> [ A -> [ ] b A -> [ ] ] ]
Second reduce derivation S -> [ C B -> [ A -> [ C -> [ A -> [ . ] c A -> [ ] ] ] b A -> [ ] ] ]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -384,7 +608,6 @@ AT_CLEANUP
## ------------------- ## ## ------------------- ##
AT_SETUP([Null nonterminals]) AT_SETUP([Null nonterminals])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A [[%token A
@@ -395,58 +618,172 @@ c : ;
d : a | c A | d; d : a | c A | d;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: 6 reduce/reduce conflicts [-Wconflicts-rr] input.y: warning: 6 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on token A: input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
First example . c A A $end First example: . c A A $end
First derivation $accept ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] $end ] First reduce derivation
Second example . c A A $end $accept
Second derivation $accept ::=[ a ::=[ c ::=[ . ] d ::=[ c A A ] ] $end ] `-> a $end
`-> b d
Reduce/reduce conflict on token A: `-> . `-> c A A
Second example: . c A A $end
Second reduce derivation
$accept
`-> a $end
`-> c d
`-> . `-> c A A
input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
time limit exceeded: XXX time limit exceeded: XXX
First example b . c A A $end First example: b . c A A $end
First derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] ] ] $end ] First reduce derivation
Second example b . A $end $accept
Second derivation $accept ::=[ a ::=[ b d ::=[ c ::=[ . ] A ] ] $end ] `-> a $end
`-> b d
Reduce/reduce conflict on token A: `-> a
`-> b d
`-> . `-> c A A
Second example: b . A $end
Second reduce derivation
$accept
`-> a $end
`-> b d
`-> c A
`-> .
input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
time limit exceeded: XXX time limit exceeded: XXX
First example c . c A A $end First example: c . c A A $end
First derivation $accept ::=[ a ::=[ c d ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] ] ] $end ] First reduce derivation
Second example c . A $end $accept
Second derivation $accept ::=[ a ::=[ c d ::=[ c ::=[ . ] A ] ] $end ] `-> a $end
`-> c d
Shift/reduce conflict on token A: `-> a
`-> b d
`-> . `-> c A A
Second example: c . A $end
Second reduce derivation
$accept
`-> a $end
`-> c d
`-> c A
`-> .
input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
time limit exceeded: XXX time limit exceeded: XXX
First example b c . c A A $end First example: b c . A
First derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ c d ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] ] ] ] ] $end ] Shift derivation
Second example b c . A a
Second derivation a ::=[ b d ::=[ c . A ] ] `-> b d
`-> c . A
Reduce/reduce conflict on token A: Second example: b c . c A A $end
First example b c . c A A $end Reduce derivation
First derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ c d ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] ] ] ] ] $end ] $accept
Second example b c . A $end `-> a $end
Second derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ c d ::=[ c ::=[ . ] A ] ] ] ] $end ] `-> b d
`-> a
Shift/reduce conflict on token A: `-> c d
First example b c . A $end `-> a
First derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ c d ::=[ c ::=[ . ] A ] ] ] ] $end ] `-> b d
Second example b c . A `-> . `-> c A A
Second derivation a ::=[ b d ::=[ c . A ] ] input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
First example: b c . c A A $end
Reduce/reduce conflict on token $end: First reduce derivation
Example b d . $accept
First derivation a ::=[ b d . ] `-> a $end
Second derivation a ::=[ b d ::=[ d . ] ] `-> b d
`-> a
Reduce/reduce conflict on token $end: `-> c d
Example c d . `-> a
First derivation a ::=[ c d . ] `-> b d
Second derivation a ::=[ c d ::=[ d . ] ] `-> . `-> c A A
Second example: b c . A $end
Second reduce derivation
$accept
`-> a $end
`-> b d
`-> a
`-> c d
`-> c A
`-> .
input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
First example: b c . A
Shift derivation
a
`-> b d
`-> c . A
Second example: b c . A $end
Reduce derivation
$accept
`-> a $end
`-> b d
`-> a
`-> c d
`-> c A
`-> .
input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
Example: b d .
First reduce derivation
a
`-> b d .
Second reduce derivation
a
`-> b d
`-> d .
input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
Example: c d .
First reduce derivation
a
`-> c d .
Second reduce derivation
a
`-> c d
`-> d .
input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
input.y:6.15: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: 6 reduce/reduce conflicts [-Wconflicts-rr]
input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
First example . c A A $end
First reduce derivation $accept -> [ a -> [ b -> [ . ] d -> [ c A A ] ] $end ]
Second example . c A A $end
Second reduce derivation $accept -> [ a -> [ c -> [ . ] d -> [ c A A ] ] $end ]
input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
time limit exceeded: XXX
First example b . c A A $end
First reduce derivation $accept -> [ a -> [ b d -> [ a -> [ b -> [ . ] d -> [ c A A ] ] ] ] $end ]
Second example b . A $end
Second reduce derivation $accept -> [ a -> [ b d -> [ c -> [ . ] A ] ] $end ]
input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
time limit exceeded: XXX
First example c . c A A $end
First reduce derivation $accept -> [ a -> [ c d -> [ a -> [ b -> [ . ] d -> [ c A A ] ] ] ] $end ]
Second example c . A $end
Second reduce derivation $accept -> [ a -> [ c d -> [ c -> [ . ] A ] ] $end ]
input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
time limit exceeded: XXX
First example b c . A
Shift derivation a -> [ b d -> [ c . A ] ]
Second example b c . c A A $end
Reduce derivation $accept -> [ a -> [ b d -> [ a -> [ c d -> [ a -> [ b -> [ . ] d -> [ c A A ] ] ] ] ] ] $end ]
input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
First example b c . c A A $end
First reduce derivation $accept -> [ a -> [ b d -> [ a -> [ c d -> [ a -> [ b -> [ . ] d -> [ c A A ] ] ] ] ] ] $end ]
Second example b c . A $end
Second reduce derivation $accept -> [ a -> [ b d -> [ a -> [ c d -> [ c -> [ . ] A ] ] ] ] $end ]
input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
First example b c . A
Shift derivation a -> [ b d -> [ c . A ] ]
Second example b c . A $end
Reduce derivation $accept -> [ a -> [ b d -> [ a -> [ c d -> [ c -> [ . ] A ] ] ] ] $end ]
input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
Example b d .
First reduce derivation a -> [ b d . ]
Second reduce derivation a -> [ b d -> [ d . ] ]
input.y: warning: reduce/reduce conflict on token $end [-Wcounterexamples]
Example c d .
First reduce derivation a -> [ c d . ]
Second reduce derivation a -> [ c d -> [ d . ] ]
input.y:5.4: warning: rule useless in parser due to conflicts [-Wother] input.y:5.4: warning: rule useless in parser due to conflicts [-Wother]
input.y:6.15: warning: rule useless in parser due to conflicts [-Wother] input.y:6.15: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -458,7 +795,6 @@ AT_CLEANUP
## --------------------------- ## ## --------------------------- ##
AT_SETUP([Non-unifying Prefix Share]) AT_SETUP([Non-unifying Prefix Share])
AT_KEYWORDS([cex])
# Tests for a counterexample which should start its derivation # Tests for a counterexample which should start its derivation
# at a shared symbol rather than the start symbol. # at a shared symbol rather than the start symbol.
@@ -471,13 +807,26 @@ a: H i J J
i: %empty | i J; i: %empty | i J;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token J: input.y: warning: shift/reduce conflict on token J [-Wcounterexamples]
Example H i J . J J Example: H i J . J J
First derivation s ::=[ a ::=[ H i ::=[ i J . ] J J ] ] Shift derivation
Second derivation s ::=[ a ::=[ H i J . J ] J ] s
`-> a J
`-> H i J . J
Reduce derivation
s
`-> a
`-> H i J J
`-> i J .
input.y:5.13-15: warning: rule useless in parser due to conflicts [-Wother]
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token J [-Wcounterexamples]
Example H i J . J J
Shift derivation s -> [ a -> [ H i J . J ] J ]
Reduce derivation s -> [ a -> [ H i -> [ i J . ] J J ] ]
input.y:5.13-15: warning: rule useless in parser due to conflicts [-Wother] input.y:5.13-15: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
@@ -491,7 +840,6 @@ AT_CLEANUP
# are derived correctly. # are derived correctly.
AT_SETUP([Deep Null Unifying]) AT_SETUP([Deep Null Unifying])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A D [[%token A D
@@ -503,13 +851,26 @@ c: %empty
d: D; d: D;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token D: input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
Example A a . D Example: A a . D
First derivation s ::=[ A a a ::=[ b ::=[ c ::=[ . ] ] ] d ::=[ D ] ] Shift derivation
Second derivation s ::=[ A a d ::=[ . D ] ] s
`-> A a d
`-> . D
Reduce derivation
s
`-> A a a d
`-> b `-> D
`-> c
`-> .
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
Example A a . D
Shift derivation s -> [ A a d -> [ . D ] ]
Reduce derivation s -> [ A a a -> [ b -> [ c -> [ . ] ] ] d -> [ D ] ]
]]) ]])
AT_CLEANUP AT_CLEANUP
@@ -521,7 +882,6 @@ AT_CLEANUP
# Tests that expand_to_conflict works with nullable sybols # Tests that expand_to_conflict works with nullable sybols
AT_SETUP([Deep Null Non-unifying]) AT_SETUP([Deep Null Non-unifying])
AT_KEYWORDS([cex])
AT_DATA([[input.y]], AT_DATA([[input.y]],
[[%token A D E [[%token A D E
@@ -533,14 +893,30 @@ c: %empty
d: D; d: D;
]]) ]])
AT_BISON_CHECK_CEX([input.y], [], [], AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token D: input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
First example A a . D E $end First example: A a . D $end
First derivation $accept ::=[ s ::=[ A a a ::=[ b ::=[ c ::=[ . ] ] ] d ::=[ D ] E ] $end ] Shift derivation
Second example A a . D $end $accept
Second derivation $accept ::=[ s ::=[ A a d ::=[ . D ] ] $end ] `-> s $end
`-> A a d
`-> . D
Second example: A a . D E $end
Reduce derivation
$accept
`-> s $end
`-> A a a d E
`-> b `-> D
`-> c
`-> .
]],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
First example A a . D $end
Shift derivation $accept -> [ s -> [ A a d -> [ . D ] ] $end ]
Second example A a . D E $end
Reduce derivation $accept -> [ s -> [ A a a -> [ b -> [ c -> [ . ] ] ] d -> [ D ] E ] $end ]
]]) ]])
AT_CLEANUP AT_CLEANUP
+105 -26
View File
@@ -28,6 +28,8 @@ m4_pushdef([AT_TEST],
AT_SETUP([$1]) AT_SETUP([$1])
AT_KEYWORDS([diagnostics]) AT_KEYWORDS([diagnostics])
m4_if(m4_index([$1], [Counterexample]), [-1], [], [AT_KEYWORDS([cex])])
# We need UTF-8 support for correct screen-width computation of UTF-8 # We need UTF-8 support for correct screen-width computation of UTF-8
# characters. Skip the test if not available. # characters. Skip the test if not available.
locale=`locale -a | $EGREP '^en_US\.(UTF-8|utf8)$' | sed 1q` locale=`locale -a | $EGREP '^en_US\.(UTF-8|utf8)$' | sed 1q`
@@ -49,7 +51,7 @@ 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]) 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 fi
AT_CHECK([LC_ALL="$locale" $5 bison -fcaret --color=debug -Wall,cex input.y], [$3], [], [experr]) AT_CHECK(AT_SET_ENV [LC_ALL="$locale" $5 bison -fcaret --color=debug -Wall,cex input.y], [$3], [], [experr])
# When no style, same messages, but without style. # When no style, same messages, but without style.
# Except for the second display of the counterexample, # Except for the second display of the counterexample,
@@ -66,7 +68,7 @@ AT_PERL_REQUIRE([-pi -e '
# Cannot use AT_BISON_CHECK easily as we need to change the # Cannot use AT_BISON_CHECK easily as we need to change the
# environment. # environment.
# FIXME: Enhance AT_BISON_CHECK. # FIXME: Enhance AT_BISON_CHECK.
AT_CHECK([LC_ALL="$locale" $5 bison -fcaret -Wall,cex input.y], [$3], [], [experr]) AT_CHECK(AT_SET_ENV [LC_ALL="$locale" $5 bison -fcaret -Wall,cex input.y], [$3], [], [experr])
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
@@ -533,34 +535,111 @@ exp
]], ]],
[1], [1],
[[input.y: <error>error:</error> shift/reduce conflicts: 4 found, 0 expected [[input.y: <error>error:</error> shift/reduce conflicts: 4 found, 0 expected
Shift/reduce conflict on token "+": input.y: <warning>warning:</warning> shift/reduce conflict on token "+" [<warning>-Wcounterexamples</warning>]
Example <cex-0><cex-1><cex-leaf>exp</cex-leaf> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0> Example: <cex-0><cex-leaf>exp</cex-leaf> <cex-leaf>"+"</cex-leaf><cex-1> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0>
First derivation <cex-0><cex-step>exp ::=[ </cex-step><cex-1><cex-step>exp ::=[ </cex-step><cex-leaf>exp</cex-leaf> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot><cex-step> ]</cex-step></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-0> Shift derivation
Example <cex-0><cex-leaf>exp</cex-leaf> <cex-leaf>"+"</cex-leaf><cex-1> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0> <cex-0><cex-step>exp</cex-step></cex-0>
Second derivation <cex-0><cex-step>exp ::=[ </cex-step><cex-leaf>exp</cex-leaf> <cex-leaf>"+"</cex-leaf><cex-1> <cex-step>exp ::=[ </cex-step><cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-1><cex-step> ]</cex-step></cex-0> <cex-0><cex-step><cex-leaf>exp</cex-leaf><cex-leaf> "+"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
<cex-1><cex-step> ↳ <cex-leaf>exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
Shift/reduce conflict on token "else": Example: <cex-0><cex-1><cex-leaf>exp</cex-leaf> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0>
Example <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0> Reduce derivation
First derivation <cex-0><cex-step>exp ::=[ </cex-step><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-step>exp ::=[ </cex-step><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot><cex-step> ]</cex-step></cex-1> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-0> <cex-0><cex-step>exp</cex-step></cex-0>
Example <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0> <cex-0><cex-step>↳ <cex-1><cex-step>exp</cex-step></cex-1><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
Second derivation <cex-0><cex-step>exp ::=[ </cex-step><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-step>exp ::=[ </cex-step><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-1><cex-step> ]</cex-step></cex-0> <cex-1><cex-step> <cex-leaf>exp</cex-leaf><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
input.y: <warning>warning:</warning> shift/reduce conflict on token "else" [<warning>-Wcounterexamples</warning>]
Shift/reduce conflict on token "+": Example: <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0>
Example <cex-0><cex-1><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0> Shift derivation
First derivation <cex-0><cex-step>exp ::=[ </cex-step><cex-1><cex-step>exp ::=[ </cex-step><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot><cex-step> ]</cex-step></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-0> <cex-0><cex-step>exp</cex-step></cex-0>
Example <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0> <cex-0><cex-step>↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
Second derivation <cex-0><cex-step>exp ::=[ </cex-step><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-step>exp ::=[ </cex-step><cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-1><cex-step> ]</cex-step></cex-0> <cex-1><cex-step><cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "else"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
Example: <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0>
Shift/reduce conflict on token "+": Reduce derivation
Example <cex-0><cex-1><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0> <cex-0><cex-step>exp</cex-step></cex-0>
First derivation <cex-0><cex-step>exp ::=[ </cex-step><cex-1><cex-step>exp ::=[ </cex-step><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot><cex-step> ]</cex-step></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-0> <cex-0><cex-step><cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1><cex-leaf> "else"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
Example <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"else"</cex-leaf><cex-1> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0> <cex-1><cex-step> <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
Second derivation <cex-0><cex-step>exp ::=[ </cex-step><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"else"</cex-leaf><cex-1> <cex-step>exp ::=[ </cex-step><cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf><cex-step> ]</cex-step></cex-1><cex-step> ]</cex-step></cex-0> input.y: <warning>warning:</warning> shift/reduce conflict on token "+" [<warning>-Wcounterexamples</warning>]
Example: <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf><cex-1> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0>
Shift derivation
<cex-0><cex-step>exp</cex-step></cex-0>
<cex-0><cex-step>↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
<cex-1><cex-step> ↳ <cex-leaf>exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
Example: <cex-0><cex-1><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0>
Reduce derivation
<cex-0><cex-step>exp</cex-step></cex-0>
<cex-0><cex-step>↳ <cex-1><cex-step>exp</cex-step></cex-1><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
<cex-1><cex-step> ↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
input.y: <warning>warning:</warning> shift/reduce conflict on token "+" [<warning>-Wcounterexamples</warning>]
Example: <cex-0><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"else"</cex-leaf><cex-1> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-1></cex-0>
Shift derivation
<cex-0><cex-step>exp</cex-step></cex-0>
<cex-0><cex-step>↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "else"</cex-leaf><cex-1><cex-step> exp</cex-step></cex-1></cex-step></cex-0>
<cex-1><cex-step> ↳ <cex-leaf>exp</cex-leaf><cex-dot> •</cex-dot><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-1>
Example: <cex-0><cex-1><cex-leaf>"if"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"then"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-leaf>"else"</cex-leaf> <cex-leaf>exp</cex-leaf> <cex-dot>•</cex-dot></cex-1> <cex-leaf>"+"</cex-leaf> <cex-leaf>exp</cex-leaf></cex-0>
Reduce derivation
<cex-0><cex-step>exp</cex-step></cex-0>
<cex-0><cex-step>↳ <cex-1><cex-step>exp</cex-step></cex-1><cex-leaf> "+"</cex-leaf><cex-leaf> exp</cex-leaf></cex-step></cex-0>
<cex-1><cex-step> ↳ <cex-leaf>"if"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "then"</cex-leaf><cex-leaf> exp</cex-leaf><cex-leaf> "else"</cex-leaf><cex-leaf> exp</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-1>
]]) ]])
AT_TEST([[Deep Counterexamples]],
[[%expect 0
%%
exp: x1 e1 foo1 x1 | y1 e2 bar1 y1
foo1: foo2
foo2: foo3
foo3: x1 foo4
foo4: "quuux"
bar1: bar2
bar2: bar3
bar3: y1 bar4
bar4: "quuux"
x1: x2
x2: x3
x3: "X"
y1: y2
y2: y3
y3: "X"
e1:
e2:
]],
[1],
[[input.y:30.4: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
30 | e1:
| <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y:31.4: <warning>warning:</warning> empty rule without %empty [<warning>-Wempty-rule</warning>]
31 | e2:
| <warning>^</warning>
| <fixit-insert>%empty</fixit-insert>
input.y: <error>error:</error> reduce/reduce conflicts: 1 found, 0 expected
input.y: <warning>warning:</warning> reduce/reduce conflict on token "X" [<warning>-Wcounterexamples</warning>]
Example: <cex-0><cex-1><cex-2><cex-3><cex-leaf>"X"</cex-leaf> <cex-dot>•</cex-dot></cex-3></cex-2></cex-1><cex-4></cex-4><cex-5><cex-6><cex-7><cex-8><cex-9><cex-10> <cex-leaf>"X"</cex-leaf></cex-10></cex-9></cex-8><cex-11> <cex-leaf>"quuux"</cex-leaf></cex-11></cex-7></cex-6></cex-5><cex-12><cex-13><cex-14> <cex-leaf>"X"</cex-leaf></cex-14></cex-13></cex-12></cex-0>
First reduce derivation
<cex-0><cex-step>exp</cex-step></cex-0>
<cex-0><cex-step>↳ <cex-1><cex-step>x1</cex-step></cex-1><cex-4><cex-step> e1</cex-step></cex-4><cex-5><cex-step> foo1</cex-step></cex-5><cex-12><cex-step> x1</cex-step></cex-12></cex-step></cex-0>
<cex-1><cex-step> ↳ <cex-2><cex-step>x2</cex-step></cex-2></cex-step></cex-1><cex-4><cex-step> ↳ ε</cex-step></cex-4><cex-5><cex-step> ↳ <cex-6><cex-step>foo2</cex-step></cex-6></cex-step></cex-5><cex-12><cex-step> ↳ <cex-13><cex-step>x2</cex-step></cex-13></cex-step></cex-12>
<cex-2><cex-step> ↳ <cex-3><cex-step>x3</cex-step></cex-3></cex-step></cex-2><cex-6><cex-step> ↳ <cex-7><cex-step>foo3</cex-step></cex-7></cex-step></cex-6><cex-13><cex-step> ↳ <cex-14><cex-step>x3</cex-step></cex-14></cex-step></cex-13>
<cex-3><cex-step> ↳ <cex-leaf>"X"</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-3><cex-7><cex-step> ↳ <cex-8><cex-step>x1</cex-step></cex-8><cex-11><cex-step> foo4</cex-step></cex-11></cex-step></cex-7><cex-14><cex-step> ↳ <cex-leaf>"X"</cex-leaf></cex-step></cex-14>
<cex-8><cex-step> ↳ <cex-9><cex-step>x2</cex-step></cex-9></cex-step></cex-8><cex-11><cex-step> ↳ <cex-leaf>"quuux"</cex-leaf></cex-step></cex-11>
<cex-9><cex-step> ↳ <cex-10><cex-step>x3</cex-step></cex-10></cex-step></cex-9>
<cex-10><cex-step> ↳ <cex-leaf>"X"</cex-leaf></cex-step></cex-10>
Example: <cex-0><cex-1><cex-2><cex-3><cex-leaf>"X"</cex-leaf> <cex-dot>•</cex-dot></cex-3></cex-2></cex-1><cex-4></cex-4><cex-5><cex-6><cex-7><cex-8><cex-9><cex-10> <cex-leaf>"X"</cex-leaf></cex-10></cex-9></cex-8><cex-11> <cex-leaf>"quuux"</cex-leaf></cex-11></cex-7></cex-6></cex-5><cex-12><cex-13><cex-14> <cex-leaf>"X"</cex-leaf></cex-14></cex-13></cex-12></cex-0>
Second reduce derivation
<cex-0><cex-step>exp</cex-step></cex-0>
<cex-0><cex-step>↳ <cex-1><cex-step>y1</cex-step></cex-1><cex-4><cex-step> e2</cex-step></cex-4><cex-5><cex-step> bar1</cex-step></cex-5><cex-12><cex-step> y1</cex-step></cex-12></cex-step></cex-0>
<cex-1><cex-step> ↳ <cex-2><cex-step>y2</cex-step></cex-2></cex-step></cex-1><cex-4><cex-step> ↳ ε</cex-step></cex-4><cex-5><cex-step> ↳ <cex-6><cex-step>bar2</cex-step></cex-6></cex-step></cex-5><cex-12><cex-step> ↳ <cex-13><cex-step>y2</cex-step></cex-13></cex-step></cex-12>
<cex-2><cex-step> ↳ <cex-3><cex-step>y3</cex-step></cex-3></cex-step></cex-2><cex-6><cex-step> ↳ <cex-7><cex-step>bar3</cex-step></cex-7></cex-step></cex-6><cex-13><cex-step> ↳ <cex-14><cex-step>y3</cex-step></cex-14></cex-step></cex-13>
<cex-3><cex-step> ↳ <cex-leaf>"X"</cex-leaf><cex-dot> •</cex-dot></cex-step></cex-3><cex-7><cex-step> ↳ <cex-8><cex-step>y1</cex-step></cex-8><cex-11><cex-step> bar4</cex-step></cex-11></cex-step></cex-7><cex-14><cex-step> ↳ <cex-leaf>"X"</cex-leaf></cex-step></cex-14>
<cex-8><cex-step> ↳ <cex-9><cex-step>y2</cex-step></cex-9></cex-step></cex-8><cex-11><cex-step> ↳ <cex-leaf>"quuux"</cex-leaf></cex-step></cex-11>
<cex-9><cex-step> ↳ <cex-10><cex-step>y3</cex-step></cex-10></cex-step></cex-9>
<cex-10><cex-step> ↳ <cex-leaf>"X"</cex-leaf></cex-step></cex-10>
input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>]
]])
m4_popdef([AT_TEST]) m4_popdef([AT_TEST])
+2 -2
View File
@@ -434,7 +434,7 @@ input.y:323.10: warning: empty rule without %empty [-Wempty-rule]
]AT_COND_CASE([[canonical LR]], ]AT_COND_CASE([[canonical LR]],
[[input.y: warning: 265 shift/reduce conflicts [-Wconflicts-sr]]], [[input.y: warning: 265 shift/reduce conflicts [-Wconflicts-sr]]],
[[input.y: warning: 65 shift/reduce conflicts [-Wconflicts-sr]]])[ [[input.y: warning: 65 shift/reduce conflicts [-Wconflicts-sr]]])[
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
input.y:39.1-5: warning: useless associativity for FUNC_CALL, use %precedence [-Wprecedence] input.y:39.1-5: warning: useless associativity for FUNC_CALL, use %precedence [-Wprecedence]
input.y:44.1-5: warning: useless associativity for YNUMBER, use %precedence [-Wprecedence] input.y:44.1-5: warning: useless associativity for YNUMBER, use %precedence [-Wprecedence]
input.y:44.1-5: warning: useless associativity for YSTRING, use %precedence [-Wprecedence] input.y:44.1-5: warning: useless associativity for YSTRING, use %precedence [-Wprecedence]
@@ -1419,7 +1419,7 @@ input.y:591.18: warning: empty rule without %empty [-Wempty-rule]
input.y: warning: 144 reduce/reduce conflicts [-Wconflicts-rr]]], input.y: warning: 144 reduce/reduce conflicts [-Wconflicts-rr]]],
[[input.y: warning: 78 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 78 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: 10 reduce/reduce conflicts [-Wconflicts-rr]]])[ input.y: warning: 10 reduce/reduce conflicts [-Wconflicts-rr]]])[
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
input.y:72.1-5: warning: useless associativity for HQUA, use %precedence [-Wprecedence] input.y:72.1-5: warning: useless associativity for HQUA, use %precedence [-Wprecedence]
input.y:53.1-6: warning: useless associativity for HASSIGN, use %precedence [-Wprecedence] input.y:53.1-6: warning: useless associativity for HASSIGN, use %precedence [-Wprecedence]
input.y:54.1-5: warning: useless associativity for HORELSE, use %precedence [-Wprecedence] input.y:54.1-5: warning: useless associativity for HORELSE, use %precedence [-Wprecedence]
+17 -17
View File
@@ -89,7 +89,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr1.c -rall glr-regr1.y]], 0, [], AT_BISON_CHECK([[-o glr-regr1.c -rall glr-regr1.y]], 0, [],
[[glr-regr1.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[glr-regr1.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
glr-regr1.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr1.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr1]) AT_COMPILE([glr-regr1])
AT_PARSER_CHECK([[glr-regr1 BPBPB]], 0, AT_PARSER_CHECK([[glr-regr1 BPBPB]], 0,
@@ -214,7 +214,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr2a.c -rall glr-regr2a.y]], 0, [], AT_BISON_CHECK([[-o glr-regr2a.c -rall glr-regr2a.y]], 0, [],
[[glr-regr2a.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr] [[glr-regr2a.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
glr-regr2a.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr2a.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr2a]) AT_COMPILE([glr-regr2a])
@@ -350,7 +350,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr3.c -rall glr-regr3.y]], 0, [], AT_BISON_CHECK([[-o glr-regr3.c -rall glr-regr3.y]], 0, [],
[[glr-regr3.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[glr-regr3.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
glr-regr3.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] glr-regr3.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
glr-regr3.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr3.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr3]) AT_COMPILE([glr-regr3])
@@ -447,7 +447,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr4.c -rall glr-regr4.y]], 0, [], AT_BISON_CHECK([[-o glr-regr4.c -rall glr-regr4.y]], 0, [],
[[glr-regr4.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] [[glr-regr4.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
glr-regr4.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr4.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr4]) AT_COMPILE([glr-regr4])
@@ -505,7 +505,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr5.c -rall glr-regr5.y]], 0, [], AT_BISON_CHECK([[-o glr-regr5.c -rall glr-regr5.y]], 0, [],
[[glr-regr5.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[glr-regr5.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
glr-regr5.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr5.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr5]) AT_COMPILE([glr-regr5])
@@ -555,7 +555,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr6.c -rall glr-regr6.y]], 0, [], AT_BISON_CHECK([[-o glr-regr6.c -rall glr-regr6.y]], 0, [],
[[glr-regr6.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[glr-regr6.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
glr-regr6.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr6.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr6]) AT_COMPILE([glr-regr6])
@@ -646,7 +646,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr7.c -rall glr-regr7.y]], 0, [], AT_BISON_CHECK([[-o glr-regr7.c -rall glr-regr7.y]], 0, [],
[[glr-regr7.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] [[glr-regr7.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
glr-regr7.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr7.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr7]) AT_COMPILE([glr-regr7])
@@ -737,7 +737,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr8.c -rall glr-regr8.y]], 0, [], AT_BISON_CHECK([[-o glr-regr8.c -rall glr-regr8.y]], 0, [],
[[glr-regr8.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[glr-regr8.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
glr-regr8.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr8.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr8]) AT_COMPILE([glr-regr8])
@@ -819,7 +819,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr9.c -rall glr-regr9.y]], 0, [], AT_BISON_CHECK([[-o glr-regr9.c -rall glr-regr9.y]], 0, [],
[[glr-regr9.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] [[glr-regr9.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
glr-regr9.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr9.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr9]) AT_COMPILE([glr-regr9])
@@ -877,7 +877,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr10.c -rall glr-regr10.y]], 0, [], AT_BISON_CHECK([[-o glr-regr10.c -rall glr-regr10.y]], 0, [],
[[glr-regr10.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[glr-regr10.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
glr-regr10.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr10.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr10]) AT_COMPILE([glr-regr10])
@@ -937,7 +937,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr11.c -rall glr-regr11.y]], 0, [], AT_BISON_CHECK([[-o glr-regr11.c -rall glr-regr11.y]], 0, [],
[[glr-regr11.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[glr-regr11.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
glr-regr11.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr11.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr11]) AT_COMPILE([glr-regr11])
@@ -1060,7 +1060,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr12.c -rall glr-regr12.y]], 0, [], AT_BISON_CHECK([[-o glr-regr12.c -rall glr-regr12.y]], 0, [],
[[glr-regr12.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] [[glr-regr12.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
glr-regr12.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] glr-regr12.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
glr-regr12.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr12.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr12]) AT_COMPILE([glr-regr12])
@@ -1392,7 +1392,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr14.c -rall glr-regr14.y]], 0, [], AT_BISON_CHECK([[-o glr-regr14.c -rall glr-regr14.y]], 0, [],
[[glr-regr14.y: warning: 5 reduce/reduce conflicts [-Wconflicts-rr] [[glr-regr14.y: warning: 5 reduce/reduce conflicts [-Wconflicts-rr]
glr-regr14.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr14.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr14]) AT_COMPILE([glr-regr14])
@@ -1487,7 +1487,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr15.c -rall glr-regr15.y]], 0, [], AT_BISON_CHECK([[-o glr-regr15.c -rall glr-regr15.y]], 0, [],
[[glr-regr15.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr] [[glr-regr15.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
glr-regr15.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr15.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr15]) AT_COMPILE([glr-regr15])
@@ -1549,7 +1549,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr16.c -rall glr-regr16.y]], 0, [], AT_BISON_CHECK([[-o glr-regr16.c -rall glr-regr16.y]], 0, [],
[[glr-regr16.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[glr-regr16.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
glr-regr16.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr16.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr16]) AT_COMPILE([glr-regr16])
@@ -1625,7 +1625,7 @@ AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-o glr-regr17.c -rall glr-regr17.y]], 0, [], AT_BISON_CHECK([[-o glr-regr17.c -rall glr-regr17.y]], 0, [],
[[glr-regr17.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr] [[glr-regr17.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
glr-regr17.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] glr-regr17.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([glr-regr17]) AT_COMPILE([glr-regr17])
@@ -1719,7 +1719,7 @@ d: /* nada. */;
AT_BISON_CHECK([[-o input.c input.y]], 0, [], AT_BISON_CHECK([[-o input.c input.y]], 0, [],
[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]]) ]])
AT_COMPILE([input]) AT_COMPILE([input])
-1
View File
@@ -2887,7 +2887,6 @@ input.y:13.1-14: note: previous definition
input.y:14.16-29: warning: %define variable 'parse.error' redefined [-Wother] input.y:14.16-29: warning: %define variable 'parse.error' redefined [-Wother]
input.y:13.16-29: note: previous definition input.y:13.16-29: note: previous definition
input.y: error: reduce/reduce conflicts: 0 found, 42 expected input.y: error: reduce/reduce conflicts: 0 found, 42 expected
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother]
input.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother] input.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother]
]]) ]])
+8 -3
View File
@@ -1169,11 +1169,16 @@ m4_define([AT_BISON_CHECK_XML],
[cp xml-tests/test.output expout] [cp xml-tests/test.output expout]
AT_CHECK([[$XSLTPROC \ AT_CHECK([[$XSLTPROC \
`]]AT_SET_ENV[[ bison --print-datadir`/xslt/xml2text.xsl \ `]]AT_SET_ENV[[ bison --print-datadir`/xslt/xml2text.xsl \
xml-tests/test.xml]], [[0]], [expout]) xml-tests/test.xml]], [[0]], [stdout])
# xml2text and xml2dot always use '•', while --report uses '•' or '.'
# depending on the locale, and the test suite is run with the plain
# C locale.
AT_CHECK([[sed -e 's/•/./g' stdout]], [], [expout])
[sort xml-tests/test.gv > expout] [sort xml-tests/test.gv > expout]
AT_CHECK([[$XSLTPROC \ AT_CHECK([[$XSLTPROC \
`]]AT_SET_ENV[[ bison --print-datadir`/xslt/xml2dot.xsl \ `]]AT_SET_ENV[[ bison --print-datadir`/xslt/xml2dot.xsl \
xml-tests/test.xml | sort]], [[0]], [expout]) xml-tests/test.xml | sort | sed -e 's/•/./g']],
[[0]], [stdout])
[rm -rf xml-tests expout] [rm -rf xml-tests expout]
AT_RESTORE_SPECIAL_FILES AT_RESTORE_SPECIAL_FILES
[fi]]) [fi]])
@@ -1194,7 +1199,7 @@ m4_define([AT_BISON_CHECK_XML],
# The testsuite verbose output, at least, will be incorrect, but nothing may # The testsuite verbose output, at least, will be incorrect, but nothing may
# fail to make sure you notice. # fail to make sure you notice.
m4_define([AT_SET_ENV_IF], m4_define([AT_SET_ENV_IF],
[[[COLUMNS=1000; export COLUMNS;]] m4_null_if($1, [], [[[VALGRIND_OPTS="$VALGRIND_OPTS --leak-check=summary --show-reachable=no"; export VALGRIND_OPTS; ]]])]) [[[COLUMNS=1000; export COLUMNS; NO_TERM_HYPERLINKS=1; export NO_TERM_HYPERLINKS;]] m4_null_if($1, [], [[[VALGRIND_OPTS="$VALGRIND_OPTS --leak-check=summary --show-reachable=no"; export VALGRIND_OPTS; ]]])])
# AT_SET_ENV # AT_SET_ENV
+8
View File
@@ -36,6 +36,14 @@ $(top_srcdir)/%D%/package.m4: $(top_srcdir)/configure
} >$@.tmp } >$@.tmp
$(AM_V_at)mv $@.tmp $@ $(AM_V_at)mv $@.tmp $@
# Update the test cases. Consider the latest test results to be the
# correct expectations, and change the test cases to match them.
.PHONY: update-tests
update-tests:
$(AM_V_GEN)cd $(top_srcdir) \
&& build-aux/update-test $(abs_builddir)/%D%/testsuite.dir/*/testsuite.log
## ------------------------- ## ## ------------------------- ##
## Generate the test suite. ## ## Generate the test suite. ##
## ------------------------- ## ## ------------------------- ##
+1 -1
View File
@@ -1300,7 +1300,7 @@ dnl INPUT
dnl BISON-STDERR dnl BISON-STDERR
[AT_COND_CASE([[LALR]], [AT_COND_CASE([[LALR]],
[[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr] [[input.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
]], [])], ]], [])],
dnl TABLES dnl TABLES
+746 -79
View File
@@ -764,24 +764,24 @@ AT_CHECK([[sed -e 's/bison-xml-report version="[^"]*"/bison-xml-report version="
</rule> </rule>
</rules> </rules>
<terminals> <terminals>
<terminal symbol-number="0" token-number="0" name="&quot;end of file&quot;" usefulness="useful"/> <terminal symbol-number="0" token-number="0" name="&quot;end of file&quot;" type="" usefulness="useful"/>
<terminal symbol-number="1" token-number="256" name="error" usefulness="useful"/> <terminal symbol-number="1" token-number="256" name="error" type="" usefulness="useful"/>
<terminal symbol-number="3" token-number="258" name="&quot;:=&quot;" usefulness="useful"/> <terminal symbol-number="3" token-number="258" name="&quot;:=&quot;" type="" usefulness="useful"/>
<terminal symbol-number="4" token-number="259" name="&quot;incr&quot;" usefulness="useful"/> <terminal symbol-number="4" token-number="259" name="&quot;incr&quot;" type="" usefulness="useful"/>
<terminal symbol-number="5" token-number="260" name="&quot;identifier&quot;" usefulness="useful"/> <terminal symbol-number="5" token-number="260" name="&quot;identifier&quot;" type="std::string" usefulness="useful"/>
<terminal symbol-number="6" token-number="261" name="&quot;number&quot;" usefulness="useful"/> <terminal symbol-number="6" token-number="261" name="&quot;number&quot;" type="int" usefulness="useful"/>
<terminal symbol-number="7" token-number="262" name="&quot;(&quot;" usefulness="useful"/> <terminal symbol-number="7" token-number="262" name="&quot;(&quot;" type="" usefulness="useful"/>
<terminal symbol-number="8" token-number="263" name="&quot;)&quot;" usefulness="useful"/> <terminal symbol-number="8" token-number="263" name="&quot;)&quot;" type="" usefulness="useful"/>
</terminals> </terminals>
<nonterminals> <nonterminals>
<nonterminal symbol-number="9" name="$accept" usefulness="useful"/> <nonterminal symbol-number="9" name="$accept" type="" usefulness="useful"/>
<nonterminal symbol-number="10" name="unit" usefulness="useful"/> <nonterminal symbol-number="10" name="unit" type="" usefulness="useful"/>
<nonterminal symbol-number="11" name="assignments" usefulness="useful"/> <nonterminal symbol-number="11" name="assignments" type="" usefulness="useful"/>
<nonterminal symbol-number="12" name="assignment" usefulness="useful"/> <nonterminal symbol-number="12" name="assignment" type="" usefulness="useful"/>
<nonterminal symbol-number="13" name="id" usefulness="useful"/> <nonterminal symbol-number="13" name="id" type="std::string" usefulness="useful"/>
<nonterminal symbol-number="14" name="exp" usefulness="useful"/> <nonterminal symbol-number="14" name="exp" type="int" usefulness="useful"/>
<nonterminal symbol-number="15" name="@1" usefulness="useful"/> <nonterminal symbol-number="15" name="@1" type="int" usefulness="useful"/>
<nonterminal symbol-number="16" name="@2" usefulness="useful"/> <nonterminal symbol-number="16" name="@2" type="int" usefulness="useful"/>
</nonterminals> </nonterminals>
</grammar> </grammar>
@@ -1137,6 +1137,373 @@ AT_CHECK([[sed -e 's/bison-xml-report version="[^"]*"/bison-xml-report version="
</bison-xml-report> </bison-xml-report>
]]) ]])
# Check HTML output.
if test x"$XSLTPROC" != x""; then
AT_CHECK([[$XSLTPROC \
`]]AT_SET_ENV[[ bison --print-datadir`/xslt/xml2xhtml.xsl \
input.xml | \
sed -e 's/GNU Bison [0-9][-.0-9a-z]*/GNU Bison VERSION/' \
>input.html]])
AT_CHECK([cat input.html], [],
[[<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:bison="http://www.gnu.org/software/bison/">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>input.yy - GNU Bison XML Automaton Report</title>
<style type="text/css">
body {
font-family: "Nimbus Sans L", Arial, sans-serif;
font-size: 9pt;
}
a:link {
color: #1f00ff;
text-decoration: none;
}
a:visited {
color: #1f00ff;
text-decoration: none;
}
a:hover {
color: red;
}
#menu a {
text-decoration: underline;
}
.i {
font-style: italic;
}
.pre {
font-family: monospace;
white-space: pre;
}
ol.decimal {
list-style-type: decimal;
}
ol.lower-alpha {
list-style-type: lower-alpha;
}
.dot {
color: #cc0000;
}
#footer {
margin-top: 3.5em;
font-size: 7pt;
}
</style>
</head>
<body><h1>GNU Bison XML Automaton Report</h1><p>
input grammar: <span class="i">input.yy</span></p>
<h3>Table of Contents</h3><ul id="menu"><li><a href="#reductions">Reductions</a><ul class="lower-alpha"><li><a href="#nonterminals_useless_in_grammar">Nonterminals useless in grammar</a></li><li><a href="#terminals_unused_in_grammar">Terminals unused in grammar</a></li><li><a href="#rules_useless_in_grammar">Rules useless in grammar</a></li></ul></li><li><a href="#conflicts">Conflicts</a></li><li><a href="#grammar">Grammar</a><ul class="lower-alpha"><li><a href="#grammar">Itemset</a></li><li><a href="#terminals">Terminal symbols</a></li><li><a href="#nonterminals">Nonterminal symbols</a></li></ul></li><li><a href="#automaton">Automaton</a></li></ul><h2><a name="reductions" id="reductions"></a> Reductions</h2><h3><a name="nonterminals_useless_in_grammar" id="nonterminals_useless_in_grammar"></a> Nonterminals useless in grammar</h3>
<h3><a name="terminals_unused_in_grammar" id="terminals_unused_in_grammar"></a> Terminals unused in grammar</h3>
<h3><a name="rules_useless_in_grammar" id="rules_useless_in_grammar"></a> Rules useless in grammar</h3>
<h2><a name="conflicts" id="conflicts"></a> Conflicts</h2>
<h2><a name="grammar" id="grammar"></a> Grammar</h2>
<p class="pre">
<a name="rule_0" id="rule_0"> 0</a> <span class="i">$accept</span> → <span class="i">unit</span> <b>"end of file"</b>
<a name="rule_1" id="rule_1"> 1</a> <span class="i">unit</span> → <span class="i">assignments</span> <span class="i">exp</span>
<a name="rule_2" id="rule_2"> 2</a> <span class="i">assignments</span> → %empty
<a name="rule_3" id="rule_3"> 3</a> | <span class="i">assignments</span> <span class="i">assignment</span>
<a name="rule_4" id="rule_4"> 4</a> <span class="i">assignment</span> → <span class="i">id</span> <b>":="</b> <span class="i">exp</span>
<a name="rule_5" id="rule_5"> 5</a> <span class="i">id</span> → <b>"identifier"</b>
<a name="rule_6" id="rule_6"> 6</a> <span class="i">@1</span> → %empty
<a name="rule_7" id="rule_7"> 7</a> <span class="i">@2</span> → %empty
<a name="rule_8" id="rule_8"> 8</a> <span class="i">exp</span> → <b>"incr"</b> <span class="i">exp</span> <span class="i">@1</span> <span class="i">@2</span> <span class="i">exp</span>
<a name="rule_9" id="rule_9"> 9</a> | <b>"("</b> <span class="i">exp</span> <b>")"</b>
<a name="rule_10" id="rule_10"> 10</a> | <b>"identifier"</b>
<a name="rule_11" id="rule_11"> 11</a> | <b>"number"</b>
</p>
<h3><a name="terminals" id="terminals"></a> Terminals, with rules where they appear</h3>
<ul>
<li><b>"end of file"</b> (0) <a href="#rule_0">0</a></li>
<li><b>error</b> (256)</li>
<li><b>":="</b> (258) <a href="#rule_4">4</a></li>
<li><b>"incr"</b> (259) <a href="#rule_8">8</a></li>
<li><b>"identifier"</b> &lt;std::string&gt; (260) <a href="#rule_5">5</a> <a href="#rule_10">10</a></li>
<li><b>"number"</b> &lt;int&gt; (261) <a href="#rule_11">11</a></li>
<li><b>"("</b> (262) <a href="#rule_9">9</a></li>
<li><b>")"</b> (263) <a href="#rule_9">9</a></li>
</ul>
<h3><a name="nonterminals" id="nonterminals"></a> Nonterminals, with rules where they appear</h3>
<ul>
<li><b>$accept</b> (9)
<ul>
<li>on left: <a href="#rule_0">0</a></li>
</ul>
</li>
<li><b>unit</b> (10)
<ul>
<li>on left: <a href="#rule_1">1</a></li>
<li>on right: <a href="#rule_0">0</a></li>
</ul>
</li>
<li><b>assignments</b> (11)
<ul>
<li>on left: <a href="#rule_2">2</a> <a href="#rule_3">3</a></li>
<li>on right: <a href="#rule_1">1</a> <a href="#rule_3">3</a></li>
</ul>
</li>
<li><b>assignment</b> (12)
<ul>
<li>on left: <a href="#rule_4">4</a></li>
<li>on right: <a href="#rule_3">3</a></li>
</ul>
</li>
<li><b>id</b> &lt;std::string&gt; (13)
<ul>
<li>on left: <a href="#rule_5">5</a></li>
<li>on right: <a href="#rule_4">4</a></li>
</ul>
</li>
<li><b>exp</b> &lt;int&gt; (14)
<ul>
<li>on left: <a href="#rule_8">8</a> <a href="#rule_9">9</a> <a href="#rule_10">10</a> <a href="#rule_11">11</a></li>
<li>on right: <a href="#rule_1">1</a> <a href="#rule_4">4</a> <a href="#rule_8">8</a> <a href="#rule_9">9</a></li>
</ul>
</li>
<li><b>@1</b> &lt;int&gt; (15)
<ul>
<li>on left: <a href="#rule_6">6</a></li>
<li>on right: <a href="#rule_8">8</a></li>
</ul>
</li>
<li><b>@2</b> &lt;int&gt; (16)
<ul>
<li>on left: <a href="#rule_7">7</a></li>
<li>on right: <a href="#rule_8">8</a></li>
</ul>
</li>
</ul><h2><a name="automaton" id="automaton"></a> Automaton</h2>
<h3><a name="state_0" id="state_0"></a>State 0</h3>
<p class="pre"> <a href="#rule_0"> 0</a> <span class="i">$accept</span> → <span class="dot">•</span> <span class="i">unit</span> <b>"end of file"</b>
<a href="#rule_1"> 1</a> <span class="i">unit</span> → <span class="dot">•</span> <span class="i">assignments</span> <span class="i">exp</span>
<a href="#rule_2"> 2</a> <span class="i">assignments</span> → <span class="dot">•</span> %empty
<a href="#rule_3"> 3</a> | <span class="dot">•</span> <span class="i">assignments</span> <span class="i">assignment</span>
$default <a href="#rule_2">reduce using rule 2</a> (assignments)
unit <a href="#state_1">go to state 1</a>
assignments <a href="#state_2">go to state 2</a>
</p>
<h3><a name="state_1" id="state_1"></a>State 1</h3>
<p class="pre"> <a href="#rule_0"> 0</a> <span class="i">$accept</span> → <span class="i">unit</span> <span class="dot">•</span> <b>"end of file"</b>
"end of file" <a href="#state_3">shift, and go to state 3</a>
</p>
<h3><a name="state_2" id="state_2"></a>State 2</h3>
<p class="pre"> <a href="#rule_1"> 1</a> <span class="i">unit</span> → <span class="i">assignments</span> <span class="dot">•</span> <span class="i">exp</span>
<a href="#rule_3"> 3</a> <span class="i">assignments</span> → <span class="i">assignments</span> <span class="dot">•</span> <span class="i">assignment</span>
<a href="#rule_4"> 4</a> <span class="i">assignment</span> → <span class="dot">•</span> <span class="i">id</span> <b>":="</b> <span class="i">exp</span>
<a href="#rule_5"> 5</a> <span class="i">id</span> → <span class="dot">•</span> <b>"identifier"</b>
<a href="#rule_8"> 8</a> <span class="i">exp</span> → <span class="dot">•</span> <b>"incr"</b> <span class="i">exp</span> <span class="i">@1</span> <span class="i">@2</span> <span class="i">exp</span>
<a href="#rule_9"> 9</a> | <span class="dot">•</span> <b>"("</b> <span class="i">exp</span> <b>")"</b>
<a href="#rule_10"> 10</a> | <span class="dot">•</span> <b>"identifier"</b>
<a href="#rule_11"> 11</a> | <span class="dot">•</span> <b>"number"</b>
"incr" <a href="#state_4">shift, and go to state 4</a>
"identifier" <a href="#state_5">shift, and go to state 5</a>
"number" <a href="#state_6">shift, and go to state 6</a>
"(" <a href="#state_7">shift, and go to state 7</a>
assignment <a href="#state_8">go to state 8</a>
id <a href="#state_9">go to state 9</a>
exp <a href="#state_10">go to state 10</a>
</p>
<h3><a name="state_3" id="state_3"></a>State 3</h3>
<p class="pre"> <a href="#rule_0"> 0</a> <span class="i">$accept</span> → <span class="i">unit</span> <b>"end of file"</b> <span class="dot">•</span>
$default accept
</p>
<h3><a name="state_4" id="state_4"></a>State 4</h3>
<p class="pre"> <a href="#rule_8"> 8</a> <span class="i">exp</span> → <span class="dot">•</span> <b>"incr"</b> <span class="i">exp</span> <span class="i">@1</span> <span class="i">@2</span> <span class="i">exp</span>
<a href="#rule_8"> 8</a> | <b>"incr"</b> <span class="dot">•</span> <span class="i">exp</span> <span class="i">@1</span> <span class="i">@2</span> <span class="i">exp</span>
<a href="#rule_9"> 9</a> | <span class="dot">•</span> <b>"("</b> <span class="i">exp</span> <b>")"</b>
<a href="#rule_10"> 10</a> | <span class="dot">•</span> <b>"identifier"</b>
<a href="#rule_11"> 11</a> | <span class="dot">•</span> <b>"number"</b>
"incr" <a href="#state_4">shift, and go to state 4</a>
"identifier" <a href="#state_11">shift, and go to state 11</a>
"number" <a href="#state_6">shift, and go to state 6</a>
"(" <a href="#state_7">shift, and go to state 7</a>
exp <a href="#state_12">go to state 12</a>
</p>
<h3><a name="state_5" id="state_5"></a>State 5</h3>
<p class="pre"> <a href="#rule_5"> 5</a> <span class="i">id</span> → <b>"identifier"</b> <span class="dot">•</span> [":="]
<a href="#rule_10"> 10</a> <span class="i">exp</span> → <b>"identifier"</b> <span class="dot">•</span> ["end of file"]
"end of file" <a href="#rule_10">reduce using rule 10</a> (exp)
$default <a href="#rule_5">reduce using rule 5</a> (id)
</p>
<h3><a name="state_6" id="state_6"></a>State 6</h3>
<p class="pre"> <a href="#rule_11"> 11</a> <span class="i">exp</span> → <b>"number"</b> <span class="dot">•</span>
$default <a href="#rule_11">reduce using rule 11</a> (exp)
</p>
<h3><a name="state_7" id="state_7"></a>State 7</h3>
<p class="pre"> <a href="#rule_8"> 8</a> <span class="i">exp</span> → <span class="dot">•</span> <b>"incr"</b> <span class="i">exp</span> <span class="i">@1</span> <span class="i">@2</span> <span class="i">exp</span>
<a href="#rule_9"> 9</a> | <span class="dot">•</span> <b>"("</b> <span class="i">exp</span> <b>")"</b>
<a href="#rule_9"> 9</a> | <b>"("</b> <span class="dot">•</span> <span class="i">exp</span> <b>")"</b>
<a href="#rule_10"> 10</a> | <span class="dot">•</span> <b>"identifier"</b>
<a href="#rule_11"> 11</a> | <span class="dot">•</span> <b>"number"</b>
"incr" <a href="#state_4">shift, and go to state 4</a>
"identifier" <a href="#state_11">shift, and go to state 11</a>
"number" <a href="#state_6">shift, and go to state 6</a>
"(" <a href="#state_7">shift, and go to state 7</a>
exp <a href="#state_13">go to state 13</a>
</p>
<h3><a name="state_8" id="state_8"></a>State 8</h3>
<p class="pre"> <a href="#rule_3"> 3</a> <span class="i">assignments</span> → <span class="i">assignments</span> <span class="i">assignment</span> <span class="dot">•</span>
$default <a href="#rule_3">reduce using rule 3</a> (assignments)
</p>
<h3><a name="state_9" id="state_9"></a>State 9</h3>
<p class="pre"> <a href="#rule_4"> 4</a> <span class="i">assignment</span> → <span class="i">id</span> <span class="dot">•</span> <b>":="</b> <span class="i">exp</span>
":=" <a href="#state_14">shift, and go to state 14</a>
</p>
<h3><a name="state_10" id="state_10"></a>State 10</h3>
<p class="pre"> <a href="#rule_1"> 1</a> <span class="i">unit</span> → <span class="i">assignments</span> <span class="i">exp</span> <span class="dot">•</span>
$default <a href="#rule_1">reduce using rule 1</a> (unit)
</p>
<h3><a name="state_11" id="state_11"></a>State 11</h3>
<p class="pre"> <a href="#rule_10"> 10</a> <span class="i">exp</span> → <b>"identifier"</b> <span class="dot">•</span>
$default <a href="#rule_10">reduce using rule 10</a> (exp)
</p>
<h3><a name="state_12" id="state_12"></a>State 12</h3>
<p class="pre"> <a href="#rule_6"> 6</a> <span class="i">@1</span> → <span class="dot">•</span> %empty
<a href="#rule_8"> 8</a> <span class="i">exp</span> → <b>"incr"</b> <span class="i">exp</span> <span class="dot">•</span> <span class="i">@1</span> <span class="i">@2</span> <span class="i">exp</span>
$default <a href="#rule_6">reduce using rule 6</a> (@1)
@1 <a href="#state_15">go to state 15</a>
</p>
<h3><a name="state_13" id="state_13"></a>State 13</h3>
<p class="pre"> <a href="#rule_9"> 9</a> <span class="i">exp</span> → <b>"("</b> <span class="i">exp</span> <span class="dot">•</span> <b>")"</b>
")" <a href="#state_16">shift, and go to state 16</a>
</p>
<h3><a name="state_14" id="state_14"></a>State 14</h3>
<p class="pre"> <a href="#rule_4"> 4</a> <span class="i">assignment</span> → <span class="i">id</span> <b>":="</b> <span class="dot">•</span> <span class="i">exp</span>
<a href="#rule_8"> 8</a> <span class="i">exp</span> → <span class="dot">•</span> <b>"incr"</b> <span class="i">exp</span> <span class="i">@1</span> <span class="i">@2</span> <span class="i">exp</span>
<a href="#rule_9"> 9</a> | <span class="dot">•</span> <b>"("</b> <span class="i">exp</span> <b>")"</b>
<a href="#rule_10"> 10</a> | <span class="dot">•</span> <b>"identifier"</b>
<a href="#rule_11"> 11</a> | <span class="dot">•</span> <b>"number"</b>
"incr" <a href="#state_4">shift, and go to state 4</a>
"identifier" <a href="#state_11">shift, and go to state 11</a>
"number" <a href="#state_6">shift, and go to state 6</a>
"(" <a href="#state_7">shift, and go to state 7</a>
exp <a href="#state_17">go to state 17</a>
</p>
<h3><a name="state_15" id="state_15"></a>State 15</h3>
<p class="pre"> <a href="#rule_7"> 7</a> <span class="i">@2</span> → <span class="dot">•</span> %empty
<a href="#rule_8"> 8</a> <span class="i">exp</span> → <b>"incr"</b> <span class="i">exp</span> <span class="i">@1</span> <span class="dot">•</span> <span class="i">@2</span> <span class="i">exp</span>
$default <a href="#rule_7">reduce using rule 7</a> (@2)
@2 <a href="#state_18">go to state 18</a>
</p>
<h3><a name="state_16" id="state_16"></a>State 16</h3>
<p class="pre"> <a href="#rule_9"> 9</a> <span class="i">exp</span> → <b>"("</b> <span class="i">exp</span> <b>")"</b> <span class="dot">•</span>
$default <a href="#rule_9">reduce using rule 9</a> (exp)
</p>
<h3><a name="state_17" id="state_17"></a>State 17</h3>
<p class="pre"> <a href="#rule_4"> 4</a> <span class="i">assignment</span> → <span class="i">id</span> <b>":="</b> <span class="i">exp</span> <span class="dot">•</span>
$default <a href="#rule_4">reduce using rule 4</a> (assignment)
</p>
<h3><a name="state_18" id="state_18"></a>State 18</h3>
<p class="pre"> <a href="#rule_8"> 8</a> <span class="i">exp</span> → <span class="dot">•</span> <b>"incr"</b> <span class="i">exp</span> <span class="i">@1</span> <span class="i">@2</span> <span class="i">exp</span>
<a href="#rule_8"> 8</a> | <b>"incr"</b> <span class="i">exp</span> <span class="i">@1</span> <span class="i">@2</span> <span class="dot">•</span> <span class="i">exp</span>
<a href="#rule_9"> 9</a> | <span class="dot">•</span> <b>"("</b> <span class="i">exp</span> <b>")"</b>
<a href="#rule_10"> 10</a> | <span class="dot">•</span> <b>"identifier"</b>
<a href="#rule_11"> 11</a> | <span class="dot">•</span> <b>"number"</b>
"incr" <a href="#state_4">shift, and go to state 4</a>
"identifier" <a href="#state_11">shift, and go to state 11</a>
"number" <a href="#state_6">shift, and go to state 6</a>
"(" <a href="#state_7">shift, and go to state 7</a>
exp <a href="#state_19">go to state 19</a>
</p>
<h3><a name="state_19" id="state_19"></a>State 19</h3>
<p class="pre"> <a href="#rule_8"> 8</a> <span class="i">exp</span> → <b>"incr"</b> <span class="i">exp</span> <span class="i">@1</span> <span class="i">@2</span> <span class="i">exp</span> <span class="dot">•</span>
$default <a href="#rule_8">reduce using rule 8</a> (exp)
</p>
<div id="footer"><hr />This document was generated using
<a href="http://www.gnu.org/software/bison/" title="GNU Bison">
GNU Bison VERSION</a>
XML Automaton Report.<br />
Verbatim copying and distribution of this entire page is
permitted in any medium, provided this notice is preserved.</div></body>
</html>
]])
fi
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
AT_CLEANUP AT_CLEANUP
@@ -1170,41 +1537,70 @@ exp
AT_CHECK([LC_ALL="$locale" bison -fno-caret -o input.cc -rall -Wcex --graph=input.gv --xml input.y], [], [], AT_CHECK([LC_ALL="$locale" bison -fno-caret -o input.cc -rall -Wcex --graph=input.gv --xml input.y], [], [],
[[input.y: warning: 3 shift/reduce conflicts [-Wconflicts-sr] [[input.y: warning: 3 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr] input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
Shift/reduce conflict on token "⊕": input.y: warning: shift/reduce conflict on token "⊕" [-Wcounterexamples]
Example exp "+" exp • "⊕" exp Example: exp "+" exp • "⊕" exp
First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ] Shift derivation
Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ] exp
↳ exp "+" exp
Reduce/reduce conflict on tokens $end, "+", "⊕": ↳ exp • "⊕" exp
Example exp "+" exp • Reduce derivation
First derivation exp ::=[ exp "+" exp • ] exp
Second derivation exp ::=[ exp "+" exp • ] ↳ exp "" exp
↳ exp "+" exp •
Shift/reduce conflict on token "⊕": input.y: warning: reduce/reduce conflict on tokens $end, "+", "⊕" [-Wcounterexamples]
Example exp "+" exp • "⊕" exp Example: exp "+" exp •
First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ] First reduce derivation
Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ] exp
↳ exp "+" exp •
Shift/reduce conflict on token "⊕": Second reduce derivation
Example exp "⊕" exp • "⊕" exp exp
First derivation exp ::=[ exp ::=[ exp "" exp • ] "⊕" exp ] exp "+" exp •
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "⊕" exp ] ] input.y: warning: shift/reduce conflict on token "⊕" [-Wcounterexamples]
Example: exp "+" exp • "⊕" exp
Shift/reduce conflict on token "+": Shift derivation
Example exp "⊕" exp • "+" exp exp
First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "+" exp ] ↳ exp "+" exp
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "+" exp ] ] exp • "" exp
Reduce derivation
Shift/reduce conflict on token "+": exp
Example exp "⊕" exp • "+" exp ↳ exp "⊕" exp
First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "+" exp ] exp "+" exp
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "+" exp ] ] input.y: warning: shift/reduce conflict on token "⊕" [-Wcounterexamples]
Example: exp "⊕" exp • "⊕" exp
Shift derivation
exp
↳ exp "⊕" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "⊕" exp •
input.y: warning: shift/reduce conflict on token "+" [-Wcounterexamples]
Example: exp "⊕" exp • "+" exp
Shift derivation
exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce derivation
exp
↳ exp "+" exp
↳ exp "⊕" exp •
input.y: warning: shift/reduce conflict on token "+" [-Wcounterexamples]
Example: exp "⊕" exp • "+" exp
Shift derivation
exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce derivation
exp
↳ exp "+" exp
↳ exp "⊕" exp •
input.y:6.3-13: warning: rule useless in parser due to conflicts [-Wother] input.y:6.3-13: warning: rule useless in parser due to conflicts [-Wother]
]]) ]])
# Check the contents of the report. # Check the contents of the report.
AT_CHECK([cat input.output], [], # FIXME: Avoid trailing white spaces.
AT_CHECK([sed -e 's/ *$//' input.output], [],
[[Rules useless in parser due to conflicts [[Rules useless in parser due to conflicts
3 exp: exp "+" exp 3 exp: exp "+" exp
@@ -1343,26 +1739,42 @@ State 7
Conflict between rule 2 and token "+" resolved as reduce (%left "+"). Conflict between rule 2 and token "+" resolved as reduce (%left "+").
Shift/reduce conflict on token "⊕": shift/reduce conflict on token "⊕":
2 exp: exp "+" exp • 2 exp: exp "+" exp •
1 exp: exp • "⊕" exp 1 exp: exp • "⊕" exp
Example exp "+" exp • "⊕" exp Example: exp "+" exp • "⊕" exp
First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ] Shift derivation
Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ] exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "+" exp •
Reduce/reduce conflict on tokens $end, "+", "⊕": reduce/reduce conflict on tokens $end, "+", "⊕":
2 exp: exp "+" exp • 2 exp: exp "+" exp •
3 exp: exp "+" exp • 3 exp: exp "+" exp •
Example exp "+" exp • Example: exp "+" exp •
First derivation exp ::=[ exp "+" exp • ] First reduce derivation
Second derivation exp ::=[ exp "+" exp • ] exp
↳ exp "+" exp •
Second reduce derivation
exp
↳ exp "+" exp •
Shift/reduce conflict on token "⊕": shift/reduce conflict on token "⊕":
3 exp: exp "+" exp • 3 exp: exp "+" exp •
1 exp: exp • "⊕" exp 1 exp: exp • "⊕" exp
Example exp "+" exp • "⊕" exp Example: exp "+" exp • "⊕" exp
First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ] Shift derivation
Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ] exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "+" exp •
@@ -1380,26 +1792,44 @@ State 8
"⊕" [reduce using rule 1 (exp)] "⊕" [reduce using rule 1 (exp)]
$default reduce using rule 1 (exp) $default reduce using rule 1 (exp)
Shift/reduce conflict on token "⊕": shift/reduce conflict on token "⊕":
1 exp: exp "⊕" exp • 1 exp: exp "⊕" exp •
1 exp: exp • "⊕" exp 1 exp: exp • "⊕" exp
Example exp "⊕" exp • "⊕" exp Example: exp "⊕" exp • "⊕" exp
First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "⊕" exp ] Shift derivation
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "⊕" exp ] ] exp
↳ exp "⊕" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "⊕" exp •
Shift/reduce conflict on token "+": shift/reduce conflict on token "+":
1 exp: exp "⊕" exp • 1 exp: exp "⊕" exp •
2 exp: exp • "+" exp 2 exp: exp • "+" exp
Example exp "⊕" exp • "+" exp Example: exp "⊕" exp • "+" exp
First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "+" exp ] Shift derivation
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "+" exp ] ] exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce derivation
exp
↳ exp "+" exp
↳ exp "⊕" exp •
Shift/reduce conflict on token "+": shift/reduce conflict on token "+":
1 exp: exp "⊕" exp • 1 exp: exp "⊕" exp •
3 exp: exp • "+" exp 3 exp: exp • "+" exp
Example exp "⊕" exp • "+" exp Example: exp "⊕" exp • "+" exp
First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "+" exp ] Shift derivation
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "+" exp ] ] exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce derivation
exp
↳ exp "+" exp
↳ exp "⊕" exp •
]]) ]])
@@ -1514,16 +1944,16 @@ AT_CHECK([[sed -e 's/bison-xml-report version="[^"]*"/bison-xml-report version="
</rule> </rule>
</rules> </rules>
<terminals> <terminals>
<terminal symbol-number="0" token-number="0" name="$end" usefulness="useful"/> <terminal symbol-number="0" token-number="0" name="$end" type="" usefulness="useful"/>
<terminal symbol-number="1" token-number="256" name="error" usefulness="useful"/> <terminal symbol-number="1" token-number="256" name="error" type="" usefulness="useful"/>
<terminal symbol-number="3" token-number="258" name="&quot;+&quot;" usefulness="useful" prec="1" assoc="left"/> <terminal symbol-number="3" token-number="258" name="&quot;+&quot;" type="" usefulness="useful" prec="1" assoc="left"/>
<terminal symbol-number="4" token-number="259" name="&quot;⊕&quot;" usefulness="useful"/> <terminal symbol-number="4" token-number="259" name="&quot;⊕&quot;" type="" usefulness="useful"/>
<terminal symbol-number="5" token-number="260" name="&quot;number&quot;" usefulness="useful"/> <terminal symbol-number="5" token-number="260" name="&quot;number&quot;" type="" usefulness="useful"/>
<terminal symbol-number="6" token-number="261" name="&quot;Ñùṃéℝô&quot;" usefulness="useful"/> <terminal symbol-number="6" token-number="261" name="&quot;Ñùṃéℝô&quot;" type="" usefulness="useful"/>
</terminals> </terminals>
<nonterminals> <nonterminals>
<nonterminal symbol-number="7" name="$accept" usefulness="useful"/> <nonterminal symbol-number="7" name="$accept" type="" usefulness="useful"/>
<nonterminal symbol-number="8" name="exp" usefulness="useful"/> <nonterminal symbol-number="8" name="exp" type="" usefulness="useful"/>
</nonterminals> </nonterminals>
</grammar> </grammar>
@@ -1725,6 +2155,243 @@ AT_CHECK([[sed -e 's/bison-xml-report version="[^"]*"/bison-xml-report version="
</bison-xml-report> </bison-xml-report>
]]) ]])
# Check HTML output.
if test x"$XSLTPROC" != x""; then
AT_CHECK([[$XSLTPROC \
`]]AT_SET_ENV[[ bison --print-datadir`/xslt/xml2xhtml.xsl \
input.xml | \
sed -e 's/GNU Bison [0-9][-.0-9a-z]*/GNU Bison VERSION/' \
>input.html]])
AT_CHECK([cat input.html], [],
[[<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:bison="http://www.gnu.org/software/bison/">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>input.y - GNU Bison XML Automaton Report</title>
<style type="text/css">
body {
font-family: "Nimbus Sans L", Arial, sans-serif;
font-size: 9pt;
}
a:link {
color: #1f00ff;
text-decoration: none;
}
a:visited {
color: #1f00ff;
text-decoration: none;
}
a:hover {
color: red;
}
#menu a {
text-decoration: underline;
}
.i {
font-style: italic;
}
.pre {
font-family: monospace;
white-space: pre;
}
ol.decimal {
list-style-type: decimal;
}
ol.lower-alpha {
list-style-type: lower-alpha;
}
.dot {
color: #cc0000;
}
#footer {
margin-top: 3.5em;
font-size: 7pt;
}
</style>
</head>
<body><h1>GNU Bison XML Automaton Report</h1><p>
input grammar: <span class="i">input.y</span></p>
<h3>Table of Contents</h3><ul id="menu"><li><a href="#reductions">Reductions</a><ul class="lower-alpha"><li><a href="#nonterminals_useless_in_grammar">Nonterminals useless in grammar</a></li><li><a href="#terminals_unused_in_grammar">Terminals unused in grammar</a></li><li><a href="#rules_useless_in_grammar">Rules useless in grammar</a></li><li><a href="#rules_useless_in_parser">Rules useless in parser due to conflicts</a></li></ul></li><li><a href="#conflicts">Conflicts</a></li><li><a href="#grammar">Grammar</a><ul class="lower-alpha"><li><a href="#grammar">Itemset</a></li><li><a href="#terminals">Terminal symbols</a></li><li><a href="#nonterminals">Nonterminal symbols</a></li></ul></li><li><a href="#automaton">Automaton</a></li></ul><h2><a name="reductions" id="reductions"></a> Reductions</h2><h3><a name="nonterminals_useless_in_grammar" id="nonterminals_useless_in_grammar"></a> Nonterminals useless in grammar</h3>
<h3><a name="terminals_unused_in_grammar" id="terminals_unused_in_grammar"></a> Terminals unused in grammar</h3>
<h3><a name="rules_useless_in_grammar" id="rules_useless_in_grammar"></a> Rules useless in grammar</h3>
<h2><a name="rules_useless_in_parser" id="rules_useless_in_parser"></a> Rules useless in parser due to conflicts</h2>
<p class="pre">
<a href="#rule_3"> 3</a> <span class="i">exp</span> → <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span>
</p>
<h2><a name="conflicts" id="conflicts"></a> Conflicts</h2>
<p class="pre"><a href="#state_7">State 7</a> conflicts: 1 shift/reduce, 3 reduce/reduce
<a href="#state_8">State 8</a> conflicts: 2 shift/reduce
</p><h2><a name="grammar" id="grammar"></a> Grammar</h2>
<p class="pre">
<a name="rule_0" id="rule_0"> 0</a> <span class="i">$accept</span> → <span class="i">exp</span> <b>$end</b>
<a name="rule_1" id="rule_1"> 1</a> <span class="i">exp</span> → <span class="i">exp</span> <b>"⊕"</b> <span class="i">exp</span>
<a name="rule_2" id="rule_2"> 2</a> | <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span>
<a name="rule_3" id="rule_3"> 3</a> | <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span>
<a name="rule_4" id="rule_4"> 4</a> | <b>"number"</b>
<a name="rule_5" id="rule_5"> 5</a> | <b>"Ñùṃéℝô"</b>
</p>
<h3><a name="terminals" id="terminals"></a> Terminals, with rules where they appear</h3>
<ul>
<li><b>$end</b> (0) <a href="#rule_0">0</a></li>
<li><b>error</b> (256)</li>
<li><b>"+"</b> (258) <a href="#rule_2">2</a> <a href="#rule_3">3</a></li>
<li><b>"⊕"</b> (259) <a href="#rule_1">1</a></li>
<li><b>"number"</b> (260) <a href="#rule_4">4</a></li>
<li><b>"Ñùṃéℝô"</b> (261) <a href="#rule_5">5</a></li>
</ul>
<h3><a name="nonterminals" id="nonterminals"></a> Nonterminals, with rules where they appear</h3>
<ul>
<li><b>$accept</b> (7)
<ul>
<li>on left: <a href="#rule_0">0</a></li>
</ul>
</li>
<li><b>exp</b> (8)
<ul>
<li>on left: <a href="#rule_1">1</a> <a href="#rule_2">2</a> <a href="#rule_3">3</a> <a href="#rule_4">4</a> <a href="#rule_5">5</a></li>
<li>on right: <a href="#rule_0">0</a> <a href="#rule_1">1</a> <a href="#rule_2">2</a> <a href="#rule_3">3</a></li>
</ul>
</li>
</ul><h2><a name="automaton" id="automaton"></a> Automaton</h2>
<h3><a name="state_0" id="state_0"></a>State 0</h3>
<p class="pre"> <a href="#rule_0"> 0</a> <span class="i">$accept</span> → <span class="dot">•</span> <span class="i">exp</span> <b>$end</b>
<a href="#rule_1"> 1</a> <span class="i">exp</span> → <span class="dot">•</span> <span class="i">exp</span> <b>"⊕"</b> <span class="i">exp</span>
<a href="#rule_2"> 2</a> | <span class="dot">•</span> <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span>
<a href="#rule_3"> 3</a> | <span class="dot">•</span> <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span>
<a href="#rule_4"> 4</a> | <span class="dot">•</span> <b>"number"</b>
<a href="#rule_5"> 5</a> | <span class="dot">•</span> <b>"Ñùṃéℝô"</b>
"number" <a href="#state_1">shift, and go to state 1</a>
"Ñùṃéℝô" <a href="#state_2">shift, and go to state 2</a>
exp <a href="#state_3">go to state 3</a>
</p>
<h3><a name="state_1" id="state_1"></a>State 1</h3>
<p class="pre"> <a href="#rule_4"> 4</a> <span class="i">exp</span> → <b>"number"</b> <span class="dot">•</span>
$default <a href="#rule_4">reduce using rule 4</a> (exp)
</p>
<h3><a name="state_2" id="state_2"></a>State 2</h3>
<p class="pre"> <a href="#rule_5"> 5</a> <span class="i">exp</span> → <b>"Ñùṃéℝô"</b> <span class="dot">•</span>
$default <a href="#rule_5">reduce using rule 5</a> (exp)
</p>
<h3><a name="state_3" id="state_3"></a>State 3</h3>
<p class="pre"> <a href="#rule_0"> 0</a> <span class="i">$accept</span> → <span class="i">exp</span> <span class="dot">•</span> <b>$end</b>
<a href="#rule_1"> 1</a> <span class="i">exp</span> → <span class="i">exp</span> <span class="dot">•</span> <b>"⊕"</b> <span class="i">exp</span>
<a href="#rule_2"> 2</a> | <span class="i">exp</span> <span class="dot">•</span> <b>"+"</b> <span class="i">exp</span>
<a href="#rule_3"> 3</a> | <span class="i">exp</span> <span class="dot">•</span> <b>"+"</b> <span class="i">exp</span>
$end <a href="#state_4">shift, and go to state 4</a>
"+" <a href="#state_5">shift, and go to state 5</a>
"⊕" <a href="#state_6">shift, and go to state 6</a>
</p>
<h3><a name="state_4" id="state_4"></a>State 4</h3>
<p class="pre"> <a href="#rule_0"> 0</a> <span class="i">$accept</span> → <span class="i">exp</span> <b>$end</b> <span class="dot">•</span>
$default accept
</p>
<h3><a name="state_5" id="state_5"></a>State 5</h3>
<p class="pre"> <a href="#rule_1"> 1</a> <span class="i">exp</span> → <span class="dot">•</span> <span class="i">exp</span> <b>"⊕"</b> <span class="i">exp</span>
<a href="#rule_2"> 2</a> | <span class="dot">•</span> <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span>
<a href="#rule_2"> 2</a> | <span class="i">exp</span> <b>"+"</b> <span class="dot">•</span> <span class="i">exp</span>
<a href="#rule_3"> 3</a> | <span class="dot">•</span> <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span>
<a href="#rule_3"> 3</a> | <span class="i">exp</span> <b>"+"</b> <span class="dot">•</span> <span class="i">exp</span>
<a href="#rule_4"> 4</a> | <span class="dot">•</span> <b>"number"</b>
<a href="#rule_5"> 5</a> | <span class="dot">•</span> <b>"Ñùṃéℝô"</b>
"number" <a href="#state_1">shift, and go to state 1</a>
"Ñùṃéℝô" <a href="#state_2">shift, and go to state 2</a>
exp <a href="#state_7">go to state 7</a>
</p>
<h3><a name="state_6" id="state_6"></a>State 6</h3>
<p class="pre"> <a href="#rule_1"> 1</a> <span class="i">exp</span> → <span class="dot">•</span> <span class="i">exp</span> <b>"⊕"</b> <span class="i">exp</span>
<a href="#rule_1"> 1</a> | <span class="i">exp</span> <b>"⊕"</b> <span class="dot">•</span> <span class="i">exp</span>
<a href="#rule_2"> 2</a> | <span class="dot">•</span> <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span>
<a href="#rule_3"> 3</a> | <span class="dot">•</span> <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span>
<a href="#rule_4"> 4</a> | <span class="dot">•</span> <b>"number"</b>
<a href="#rule_5"> 5</a> | <span class="dot">•</span> <b>"Ñùṃéℝô"</b>
"number" <a href="#state_1">shift, and go to state 1</a>
"Ñùṃéℝô" <a href="#state_2">shift, and go to state 2</a>
exp <a href="#state_8">go to state 8</a>
</p>
<h3><a name="state_7" id="state_7"></a>State 7</h3>
<p class="pre"> <a href="#rule_1"> 1</a> <span class="i">exp</span> → <span class="i">exp</span> <span class="dot">•</span> <b>"⊕"</b> <span class="i">exp</span>
<a href="#rule_2"> 2</a> | <span class="i">exp</span> <span class="dot">•</span> <b>"+"</b> <span class="i">exp</span>
<a href="#rule_2"> 2</a> | <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span> <span class="dot">•</span> [$end, "+", "⊕"]
<a href="#rule_3"> 3</a> | <span class="i">exp</span> <span class="dot">•</span> <b>"+"</b> <span class="i">exp</span>
<a href="#rule_3"> 3</a> | <span class="i">exp</span> <b>"+"</b> <span class="i">exp</span> <span class="dot">•</span> [$end, "+", "⊕"]
"⊕" <a href="#state_6">shift, and go to state 6</a>
$end <a href="#rule_2">reduce using rule 2</a> (exp)
$end [<a href="#rule_3">reduce using rule 3</a> (exp)]
"+" <a href="#rule_2">reduce using rule 2</a> (exp)
"+" [<a href="#rule_3">reduce using rule 3</a> (exp)]
"⊕" [<a href="#rule_2">reduce using rule 2</a> (exp)]
"⊕" [<a href="#rule_3">reduce using rule 3</a> (exp)]
$default <a href="#rule_2">reduce using rule 2</a> (exp)
Conflict between <a href="#rule_2">rule 2</a> and token "+" resolved as reduce (%left "+").
</p>
<h3><a name="state_8" id="state_8"></a>State 8</h3>
<p class="pre"> <a href="#rule_1"> 1</a> <span class="i">exp</span> → <span class="i">exp</span> <span class="dot">•</span> <b>"⊕"</b> <span class="i">exp</span>
<a href="#rule_1"> 1</a> | <span class="i">exp</span> <b>"⊕"</b> <span class="i">exp</span> <span class="dot">•</span> [$end, "+", "⊕"]
<a href="#rule_2"> 2</a> | <span class="i">exp</span> <span class="dot">•</span> <b>"+"</b> <span class="i">exp</span>
<a href="#rule_3"> 3</a> | <span class="i">exp</span> <span class="dot">•</span> <b>"+"</b> <span class="i">exp</span>
"+" <a href="#state_5">shift, and go to state 5</a>
"⊕" <a href="#state_6">shift, and go to state 6</a>
"+" [<a href="#rule_1">reduce using rule 1</a> (exp)]
"⊕" [<a href="#rule_1">reduce using rule 1</a> (exp)]
$default <a href="#rule_1">reduce using rule 1</a> (exp)
</p>
<div id="footer"><hr />This document was generated using
<a href="http://www.gnu.org/software/bison/" title="GNU Bison">
GNU Bison VERSION</a>
XML Automaton Report.<br />
Verbatim copying and distribution of this entire page is
permitted in any medium, provided this notice is preserved.</div></body>
</html>
]])
fi
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS
AT_CLEANUP AT_CLEANUP
+1 -1
View File
@@ -285,7 +285,7 @@ term: 'n'
AT_BISON_CHECK([[-fcaret input.y]], [], [], AT_BISON_CHECK([[-fcaret input.y]], [], [],
[[input.y: warning: 5 reduce/reduce conflicts [-Wconflicts-rr] [[input.y: warning: 5 reduce/reduce conflicts [-Wconflicts-rr]
input.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother] input.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
input.y:2.14-17: warning: rule useless in parser due to conflicts [-Wother] input.y:2.14-17: warning: rule useless in parser due to conflicts [-Wother]
2 | expr: term | term | term | term | term | term 2 | expr: term | term | term | term | term | term
| ^~~~ | ^~~~
+4 -4
View File
@@ -283,11 +283,11 @@ m4_popdef([AT_TEST])
## Many lookahead tokens. ## ## Many lookahead tokens. ##
## ------------------------ ## ## ------------------------ ##
# AT_DATA_LOOKAHEAD_TOKENS_GRAMMAR(FILE-NAME, SIZE) # AT_DATA_LOOKAHEADS_GRAMMAR(FILE-NAME, SIZE)
# -------------------------------------------------- # -------------------------------------------
# Create FILE-NAME, containing a self checking parser for a grammar # Create FILE-NAME, containing a self checking parser for a grammar
# requiring SIZE lookahead tokens. # requiring SIZE lookahead tokens.
m4_define([AT_DATA_LOOKAHEAD_TOKENS_GRAMMAR], m4_define([AT_DATA_LOOKAHEADS_GRAMMAR],
[AT_BISON_OPTION_PUSHDEFS [AT_BISON_OPTION_PUSHDEFS
AT_DATA([[gengram.pl]], AT_DATA([[gengram.pl]],
[[#! /usr/bin/perl -w [[#! /usr/bin/perl -w
@@ -384,7 +384,7 @@ AT_BISON_OPTION_POPDEFS
AT_SETUP([Many lookahead tokens]) AT_SETUP([Many lookahead tokens])
AT_DATA_LOOKAHEAD_TOKENS_GRAMMAR([input.y], [1000]) AT_DATA_LOOKAHEADS_GRAMMAR([input.y], [1000])
# GNU m4 requires about 70 MiB for this test on a 32-bit host. # GNU m4 requires about 70 MiB for this test on a 32-bit host.
# Ask for 200 MiB, which should be plenty even on a 64-bit host. # Ask for 200 MiB, which should be plenty even on a 64-bit host.