Compare commits

..
68 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
Akim Demaille 2d90916067 version 3.6.91
* NEWS: Record release date.
2020-07-09 21:10:23 +02:00
Akim Demaille 91e5a23ff2 news: update 2020-07-09 20:29:24 +02:00
Akim Demaille d4ae66c371 gnulib: update 2020-07-09 20:26:16 +02:00
Akim Demaille 70fb574717 examples: add license headers
Prompted by Rici Lake.
https://stackoverflow.com/questions/62658368/#comment110853985_62661621
Discussed with Paul Eggert.

* doc/bison.texi, examples/c/bistromathic/parse.y,
* examples/c/lexcalc/parse.y, examples/c/lexcalc/scan.l,
* examples/c/pushcalc/calc.y, examples/c/reccalc/parse.y,
* examples/c/reccalc/scan.l, examples/d/calc.y,
* examples/java/calc/Calc.y, examples/java/simple/Calc.y:
Install the GPL3+ header.
2020-07-08 22:19:37 +02:00
Akim Demaille 0820f16ca8 style: update comments
* src/reader.c: action_obstack was removed in 2002...
* src/parse-gram.y: Better names.
* src/scan-code.h: More comments.
2020-07-05 09:59:45 +02:00
Akim Demaille 49f1e5f428 style: update comments in the skeletons
* data/skeletons/c++.m4, data/skeletons/glr.c, data/skeletons/lalr1.d,
* data/skeletons/lalr1.java, data/skeletons/yacc.c:
Be more accurate about yychar and yytoken.
Don't name local variables as if they were members.
2020-07-05 09:59:25 +02:00
Akim Demaille 238692ad77 doc: more details about symbols in m4
* data/README.md: here.
* README-hacking.md (Vocabulary): More.
2020-07-05 09:18:27 +02:00
Akim Demaille 5f95583da7 regen 2020-07-05 08:18:51 +02:00
Akim Demaille 964fb2aa6f examples: include the generated header
* examples/c/bistromathic/parse.y, examples/c/lexcalc/parse.y,
* examples/c/reccalc/parse.y: here.
Add some comments.

* src/parse-gram.y (api_version): Pull out of handle_require.
Bump to 3.7.
2020-07-05 08:18:51 +02:00
Akim Demaille 7c0d36b760 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-04 12:37:45 +02:00
82 changed files with 3529 additions and 1019 deletions
+1 -1
View File
@@ -1 +1 @@
3.6.4
3.6.93
+121 -17
View File
@@ -1,6 +1,6 @@
GNU Bison NEWS
* Noteworthy changes in release 3.6.90 (2020-07-04) [beta]
* Noteworthy changes in release 3.7 (2020-07-23) [stable]
** Deprecated features
@@ -18,28 +18,115 @@ GNU Bison NEWS
Contributed by Vincent Imbimbo.
When given `--report=counterexamples` or `-Wcounterexamples`, bison will
now output counterexamples for conflicts in the grammar. These are
strings in the grammar which can be parsed in two ways due to the
conflict. For example:
When given `-Wcounterexamples`/`-Wcex`, bison will now output
counterexamples for conflicts.
Example exp '+' exp • '/' exp
First derivation exp ::=[ exp ::=[ exp '+' exp • ] '/' exp ]
Second derivation exp ::=[ exp '+' exp ::=[ exp • '/' exp ] ]
**** Unifying Counterexamples
This is a shift/reduce conflict caused by none of the operators having
precedence, so the example can be parsed in the two ways shown. When
bison cannot find an example that can be derived in two ways, it instead
generates two examples that are the same up until the dot:
Unifying counterexamples are strings which can be parsed in two ways due
to the conflict. For example on a grammar that contains the usual
"dangling else" ambiguity:
First example expr • ID $end
First derivation $accept ::=[ s ::=[ a ::=[ expr • ] ID ] $end ]
Second example expr • ID ',' ID $end
Second derivation $accept ::=[ s ::=[ a ::=[ expr ::=[ expr • ID ',' ] ] ID ] $end ]
$ bison else.y
else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
else.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
$ bison else.y -Wcex
else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
else.y: warning: shift/reduce conflict on token "else" [-Wcounterexamples]
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
differentiate the two given examples.
**** Reports
Counterexamples are also included in the report when given
`--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
Contributed by Joshua Watt.
@@ -52,6 +139,11 @@ GNU Bison NEWS
** Changes
*** Diagnostics
When text styling is enabled and the terminal supports it, the warnings
now include hyperlinks to the documentation.
*** Relocatable installation
When installed to be relocatable (via `configure --enable-relocatable`),
@@ -92,6 +184,18 @@ GNU Bison NEWS
Now the parser state can be examined when parsing is finished. The parser
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
*** Include the generated header (yacc.c)
@@ -4357,7 +4461,7 @@ LocalWords: yysymbol yytnamerr yyreport ctx ARGMAX yysyntax stderr LPAREN
LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF
LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc
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:
ispell-dictionary: "american"
+3 -1
View File
@@ -211,6 +211,8 @@ assert/abort), and all the --trace output which is meant for the maintainers
only.
## Vocabulary
- "lookahead", not "look-ahead".
- "midrule", not "mid-rule".
- "nonterminal", not "variable" or "non-terminal" or "non terminal".
Abbreviated as "nterm".
- "shift/reduce" and "reduce/reduce", not "shift-reduce" or "shift reduce",
@@ -442,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`.
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
+1
View File
@@ -45,6 +45,7 @@ Csaba Raduly [email protected]
Dagobert Michelsen [email protected]
Daniel Frużyński [email protected]
Daniel Galloway [email protected]
Daniela Becker [email protected]
Daniel Hagerty [email protected]
David Barto [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
(as shells do).
- Caret diagnostics
** Questions
*** Java
- 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
relocatable-prog relocatable-script
rename
spawn-pipe stdbool stpcpy strdup-posix strerror strverscmp
spawn-pipe stdbool stpcpy stpncpy strdup-posix strerror strverscmp
timevar
unicodeio unistd unistd-safer unlink unlocked-io
update-copyright unsetenv verify
+3 -3
View File
@@ -86,7 +86,7 @@ The macro `b4_symbol(NUM, FIELD)` gives access to the following FIELDS:
- `has_id`: 0 or 1
Whether the symbol has an `id`.
- `id`: string
- `id`: string (e.g., `exp`, `NUM`, or `TOK_NUM` with api.token.prefix)
If `has_id`, the name of the token kind (prefixed by api.token.prefix if
defined), otherwise empty. Guaranteed to be usable as a C identifier.
This is used to define the token kind (i.e., the enum used by the return
@@ -105,9 +105,9 @@ The macro `b4_symbol(NUM, FIELD)` gives access to the following FIELDS:
- `is_token`: 0 or 1
Whether this is a terminal symbol.
- `kind_base`: string
- `kind_base`: string (e.g., `YYSYMBOL_exp`, `YYSYMBOL_NUM`)
The base of the symbol kind, i.e., the enumerator of this symbol (token or
nonterminal) which is mapping to its `number`.
nonterminal) which is mapped to its `number`.
- `kind`: string
Same as `kind_base`, but possibly with a prefix in some languages. E.g.,
+4
View File
@@ -49,6 +49,10 @@
.cex-5 { color: orange; }
.cex-6 { color: brown; }
.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-step { font-style: italic; }
+3 -2
View File
@@ -594,11 +594,12 @@ m4_define([b4_yytranslate_define],
{
]b4_translate[
};
const int code_max_ = ]b4_code_max[;
// Last valid token kind.
const int code_max = ]b4_code_max[;
if (t <= 0)
return symbol_kind::]b4_symbol_prefix[YYEOF;
else if (t <= code_max_)
else if (t <= code_max)
return YY_CAST (symbol_kind_type, translate_table[t]);
else
return symbol_kind::]b4_symbol_prefix[YYUNDEF;]])[
+1 -1
View File
@@ -333,7 +333,7 @@ static YYLTYPE yyloc_default][]b4_yyloc_default;])[
accessed by $0, $-1, etc., in any rule. */
#define YYMAXLEFT ]b4_max_left_semantic_context[
/* YYMAXUTOK -- Last valid token number (for yychar). */
/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK ]b4_code_max[
/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+5 -3
View File
@@ -428,8 +428,9 @@ b4_locations_if([, ref ]b4_location_type[ yylocationp])[)
*/
public bool parse ()
{
/// Lookahead and lookahead in internal form.
// Lookahead token kind.
int yychar = TokenKind.YYEMPTY;
// Lookahead symbol kind.
SymbolKind yytoken = ]b4_symbol(-2, kind)[;
/* State. */
@@ -841,11 +842,12 @@ m4_popdef([b4_at_dollar])])dnl
]b4_translate[
@};
immutable int code_max_ = ]b4_code_max[;
// Last valid token kind.
immutable int code_max = ]b4_code_max[;
if (t <= 0)
return ]b4_symbol(0, kind)[;
else if (t <= code_max_)
else if (t <= code_max)
{
import std.conv : to;
return to!SymbolKind (translate_table[t]);
+6 -4
View File
@@ -53,8 +53,9 @@ b4_use_push_for_pull_if([
# allows them to be defined either in parse() when doing pull parsing,
# or as class instance variable when doing push parsing.
m4_define([b4_define_state],[[
/* Lookahead and lookahead in internal form. */
/* Lookahead token kind. */
int yychar = YYEMPTY_;
/* Lookahead symbol kind. */
SymbolKind yytoken = null;
/* State. */
@@ -1078,17 +1079,18 @@ b4_dollar_popdef[]dnl
/* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */
private static final SymbolKind yytranslate_ (int t)
private static final SymbolKind yytranslate_(int t)
]b4_api_token_raw_if(dnl
[[ {
return SymbolKind.get(t);
}
]],
[[ {
int code_max_ = ]b4_code_max[;
// Last valid token kind.
int code_max = ]b4_code_max[;
if (t <= 0)
return ]b4_symbol(0, kind)[;
else if (t <= code_max_)
else if (t <= code_max)
return SymbolKind.get(yytranslate_table_[t]);
else
return ]b4_symbol(2, kind)[;
+7 -2
View File
@@ -48,6 +48,10 @@ m4_define([b4_pure_if],
## api.push-pull. ##
## --------------- ##
# b4_pull_if, b4_push_if
# ----------------------
# Whether the pull/push APIs are needed. Both can be enabled.
b4_percent_define_default([[api.push-pull]], [[pull]])
b4_percent_define_check_values([[[[api.push-pull]],
[[pull]], [[push]], [[both]]]])
@@ -155,7 +159,7 @@ m4_define([b4_rhs_location],
# Declare the variables that are global, or local to YYPARSE if
# pure-parser.
m4_define([b4_declare_scanner_communication_variables], [[
/* The lookahead symbol. */
/* Lookahead token kind. */
int yychar;
]b4_pure_if([[
@@ -571,6 +575,7 @@ union yyalloc
/* YYNSTATES -- Number of states. */
#define YYNSTATES ]b4_states_number[
/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK ]b4_code_max[
@@ -1544,7 +1549,7 @@ yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])[
int yyn;
/* The return value of yyparse. */
int yyresult;
/* Lookahead token as an internal (translated) token number. */
/* Lookahead symbol kind. */
yysymbol_kind_t yytoken = ]b4_symbol(-2, kind)[;
/* The variables used to return semantic value and location from the
action routines. */
+14 -6
View File
@@ -52,7 +52,7 @@
<xsl:if test="nonterminal[@usefulness='useless-in-grammar']">
<xsl:text>Nonterminals useless in grammar&#10;&#10;</xsl:text>
<xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']">
<xsl:text> </xsl:text>
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
@@ -65,7 +65,7 @@
<xsl:text>Terminals unused in grammar&#10;&#10;</xsl:text>
<xsl:for-each select="terminal[@usefulness='unused-in-grammar']">
<xsl:sort select="@symbol-number" data-type="number"/>
<xsl:text> </xsl:text>
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
@@ -136,6 +136,7 @@
</xsl:template>
<xsl:template match="terminal">
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/>
<xsl:call-template name="line-wrap">
<xsl:with-param name="first-line-length">
@@ -148,6 +149,9 @@
</xsl:with-param>
<xsl:with-param name="line-length" select="66" />
<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:for-each select="key('bison:ruleByRhs', @name)">
<xsl:value-of select="concat(' ', @number)"/>
@@ -157,14 +161,18 @@
</xsl:template>
<xsl:template match="nonterminal">
<xsl:text> </xsl:text>
<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:text>&#10;</xsl:text>
<xsl:variable name="output">
<xsl:call-template name="line-wrap">
<xsl:with-param name="line-length" select="66" />
<xsl:with-param name="text">
<xsl:text> </xsl:text>
<xsl:text> </xsl:text>
<xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>on@left:</xsl:text>
<xsl:for-each select="key('bison:ruleByLhs', @name)">
@@ -173,7 +181,7 @@
</xsl:if>
<xsl:if test="key('bison:ruleByRhs', @name)">
<xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>, </xsl:text>
<xsl:text>&#10; </xsl:text>
</xsl:if>
<xsl:text>on@right:</xsl:text>
<xsl:for-each select="key('bison:ruleByRhs', @name)">
@@ -348,11 +356,11 @@
<!-- RHS -->
<xsl:for-each select="rhs/*">
<xsl:if test="position() = $dot + 1">
<xsl:text> .</xsl:text>
<xsl:text> </xsl:text>
</xsl:if>
<xsl:apply-templates select="."/>
<xsl:if test="position() = last() and position() = $dot">
<xsl:text> .</xsl:text>
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:if test="$lookaheads">
+72 -48
View File
@@ -227,6 +227,7 @@
<xsl:text>&#10;</xsl:text>
<p class="pre">
<xsl:call-template name="style-rule-set">
<xsl:with-param name="anchor" select="'true'" />
<xsl:with-param
name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']"
/>
@@ -238,9 +239,11 @@
</xsl:template>
<xsl:template name="style-rule-set">
<xsl:param name="anchor"/>
<xsl:param name="rule-set"/>
<xsl:for-each select="$rule-set">
<xsl:apply-templates select=".">
<xsl:with-param name="anchor" select="$anchor"/>
<xsl:with-param name="pad" select="'3'"/>
<xsl:with-param name="prev-lhs">
<xsl:if test="position()>1">
@@ -306,9 +309,10 @@
<xsl:text> Terminals, with rules where they appear</xsl:text>
</h3>
<xsl:text>&#10;&#10;</xsl:text>
<p class="pre">
<ul>
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="terminal"/>
</p>
</ul>
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
@@ -318,41 +322,64 @@
<xsl:text> Nonterminals, with rules where they appear</xsl:text>
</h3>
<xsl:text>&#10;&#10;</xsl:text>
<p class="pre">
<ul>
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates
select="nonterminal[@usefulness!='useless-in-grammar']"
/>
</p>
</ul>
</xsl:template>
<xsl:template match="terminal">
<b><xsl:value-of select="@name"/></b>
<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>
<xsl:text> </xsl:text>
<li>
<b><xsl:value-of select="@name"/></b>
<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:for-each select="key('bison:ruleByRhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</li>
<xsl:text>&#10;</xsl:text>
</xsl:template>
<xsl:template match="nonterminal">
<b><xsl:value-of select="@name"/></b>
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
<xsl:text>&#10; </xsl:text>
<xsl:if test="key('bison:ruleByLhs', @name)">
<xsl:text>on left:</xsl:text>
<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:text> </xsl:text>
<li>
<b><xsl:value-of select="@name"/></b>
<xsl:if test="string-length(@type) != 0">
<xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
</xsl:if>
<xsl:text>on right:</xsl:text>
<xsl:for-each select="key('bison:ruleByRhs', @name)">
<xsl:apply-templates select="." mode="number-link"/>
</xsl:for-each>
</xsl:if>
<xsl:value-of select="concat(' (', @symbol-number, ')')"/>
<xsl:text>&#10; </xsl:text>
<ul>
<xsl:text>&#10;</xsl:text>
<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:template>
@@ -385,7 +412,7 @@
<xsl:value-of select="concat('state_', @number)"/>
</xsl:attribute>
</a>
<xsl:text>state </xsl:text>
<xsl:text>State </xsl:text>
<xsl:value-of select="@number"/>
</h3>
<xsl:text>&#10;&#10;</xsl:text>
@@ -464,7 +491,12 @@
</xsl:apply-templates>
</xsl:template>
<!--
anchor = 'true': define as an <a> anchor.
itemset = 'true': show the items.
-->
<xsl:template match="rule">
<xsl:param name="anchor"/>
<xsl:param name="itemset"/>
<xsl:param name="pad"/>
<xsl:param name="prev-lhs"/>
@@ -475,17 +507,21 @@
<xsl:text>&#10;</xsl:text>
</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: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>
<xsl:attribute name="href">
<xsl:value-of select="concat('#rule_', @number)"/>
@@ -495,25 +531,13 @@
<xsl:with-param name="pad" select="number($pad)"/>
</xsl:call-template>
</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:choose>
<xsl:text> </xsl:text>
<!-- LHS -->
<xsl:choose>
<xsl:when test="$itemset != 'true' and $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: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"/>
+474 -115
View File
@@ -263,7 +263,6 @@ Writing GLR Parsers
* Merging GLR Parses:: Using GLR parsers to resolve ambiguities.
* GLR Semantic Actions:: Considerations for semantic values and deferred actions.
* Semantic Predicates:: Controlling a parse with arbitrary computations.
* Compiler Requirements for GLR:: GLR parsers require a modern C compiler.
Examples
@@ -943,7 +942,6 @@ on the resulting values to produce an arbitrary merged result.
* Merging GLR Parses:: Using GLR parsers to resolve ambiguities.
* GLR Semantic Actions:: Considerations for semantic values and deferred actions.
* Semantic Predicates:: Controlling a parse with arbitrary computations.
* Compiler Requirements for GLR:: GLR parsers require a modern C compiler.
@end menu
@node Simple GLR Parsers
@@ -1372,14 +1370,14 @@ widget:
@noindent
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
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
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
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
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.
Predicate actions, however, have no defined value, and may not be given
labels.
@@ -1393,7 +1391,7 @@ widget:
@{ if (!new_syntax) YYERROR; @}
"widget" id new_args @{ $$ = f($3, $4); @}
| @{ if (new_syntax) YYERROR; @}
"widget" id old_args @{ $$ = f($3, $4); @}
"widget" id old_args @{ $$ = f($3, $4); @}
;
@end example
@@ -1411,36 +1409,6 @@ reports an error.
Finally, be careful in writing predicates: deferred actions have not been
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
@section Locations
@cindex location
@@ -1677,6 +1645,31 @@ Here are the C and Bison declarations for the Reverse Polish Notation
calculator. As in C, comments are placed between @samp{/*@dots{}*/} or
after @samp{//}.
@ignore
@comment file: rpcalc.y
@example
/* Parser for rpcalc. -*- C -*-
Copyright (C) 1988-1993, 1995, 1998-2015, 2018-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/>. */
@end example
@end ignore
@comment file: rpcalc.y
@example
/* Reverse Polish Notation calculator. */
@@ -2538,6 +2531,31 @@ Note that multiple assignment and nested function calls are permitted.
Here are the C and Bison declarations for the multi-function calculator.
@ignore
@comment file: mfcalc.y
@example
/* Parser for mfcalc. -*- C -*-
Copyright (C) 1988-1993, 1995, 1998-2015, 2018-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/>. */
@end example
@end ignore
@comment file: mfcalc.y: 1
@example
@group
@@ -2642,6 +2660,31 @@ The symbol table itself consists of a linked list of records. Its
definition, which is kept in the header @file{calc.h}, is as follows. It
provides for either functions or variables to be placed in the table.
@ignore
@comment file: calc.h
@example
/* Functions for mfcalc. -*- C -*-
Copyright (C) 1988-1993, 1995, 1998-2015, 2018-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/>. */
@end example
@end ignore
@comment file: calc.h
@example
@group
@@ -9846,10 +9889,11 @@ initially developed by Chinawat Isradisaikul and Andrew Myers
As a first example, see the example grammar of @ref{Shift/Reduce}, which
features on shift/reduce conflict:
@c see doc/if-then-else.y
@example
$ @kbd{bison if-then-else.y}
if-then-else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
if-then-else.y: warning: rerun with option '-Wcounterexamples' to generate conflict counterexamples [-Wother]
if-then-else.y: @dwarning{warning}: 1 shift/reduce conflict [@dwarning{-Wconflicts-sr}]
if-then-else.y: @dnotice{note}: rerun with option '-Wcounterexamples' to generate conflict counterexamples
@end example
@noindent
@@ -9857,32 +9901,46 @@ Let's rerun @command{bison} with the option
@option{-Wcex}/@option{-Wcounterexamples}@inlinefmt{info, (the following
output is actually in color)}:
@ifhtml
@ifnottex
@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
Example @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"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 ]}
Example @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @blue{"else" stmt}
Second derivation @yellow{if_stmt ::=[ "if" expr "then"} @green{stmt ::=[} @blue{if_stmt ::=[ "if" expr "then" stmt} @red{•} @blue{"else" stmt ]} @green{]} @yellow{]}
Example: @yellow{"if" expr "then"} "if" expr "then" stmt"else" stmt
Shift derivation
@yellow{if_stmt}
@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 example
@end ifhtml
@ifnothtml
@smallexample
Shift/reduce conflict on token "else":
@end ifnottex
@iftex
@example
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
Example
@yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"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 ]}
Example
@yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @blue{"else" stmt}
Second derivation
@yellow{if_stmt ::=[ "if" expr "then"} @green{stmt ::=[} @blue{if_stmt ::=[ "if" expr "then" stmt} @red{•} @blue{"else" stmt ]} @green{]} @yellow{]}
Example: @yellow{"if" expr "then"} "if" expr "then" stmt • "else" stmt
Shift derivation
@yellow{if_stmt}
@yellow{@arrow{} "if" expr "then"} @green{stmt}
@green{@arrow{}} @blue{if_stmt}
@blue{@arrow{} "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{@arrow{} "if" expr "then"} @green{stmt} @yellow{"else" stmt}
@green{@arrow{}} @blue{if_stmt}
@blue{@arrow{} "if" expr "then" stmt} @red{•}
@end group
@end smallexample
@end ifnothtml
@end example
@end iftex
This shows two different derivations for one single expression. That
demonstrates that the grammar is ambiguous.
@@ -9892,6 +9950,7 @@ demonstrates that the grammar is ambiguous.
As a more delicate example, consider the example grammar of
@ref{Reduce/Reduce}, which features a reduce/reduce conflict:
@c doc/sequence.y
@example
%%
sequence:
@@ -9907,32 +9966,112 @@ maybeword:
Bison generates the following counterexamples:
@ifnottex
@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}]
Shift/reduce conflict on token "word":
Example @red{•} @yellow{"word"}
First derivation @yellow{sequence ::=[} @green{sequence ::=[} @red{•} @green{]} @yellow{"word" ]}
Example @red{•} @green{"word"}
Second derivation @yellow{sequence ::=[} @green{maybeword ::=[} @red{•} @green{"word" ]} @yellow{]}
Reduce/reduce conflict on tokens $end, "word":
Example @red{•}
First derivation @yellow{sequence ::=[} @red{•} @yellow{]}
Example @red{•}
Second derivation @yellow{sequence ::=[} @green{maybeword ::=[} @red{•} @green{]} @yellow{]}
Shift/reduce conflict on token "word":
Example @red{•} @yellow{"word"}
First derivation @yellow{sequence ::=[} @green{sequence ::=[} @blue{maybeword ::=[} @red{•} @blue{]} @green{]} @yellow{"word" ]}
Example @red{•} @green{"word"}
Second derivation @yellow{sequence ::=[} @green{maybeword ::=[} @red{•} @green{"word" ]} @yellow{]}
@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{↳} @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{↳} @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}]
8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}}
| @dwarning{^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
@end group
@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.
For instance, the second conflict (the reduce/reduce one) shows that the
@@ -9946,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
LALR). The following example isn't LR(1):
@c doc/ids.y
@example
%token ID
%%
@@ -9956,13 +10096,58 @@ expr: %empty | expr ID ','
@command{bison} reports:
@smallexample
Shift/reduce conflict on token ID:
First example @blue{expr} @red{•} @green{ID} @yellow{$end}
First derivation @yellow{$accept ::=[} @green{s ::=[} @blue{a ::=[ expr} @red{•} @blue{]} @green{ID ]} @yellow{$end ]}
Second example @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
Second derivation @yellow{$accept ::=[} @green{s ::=[} @blue{a ::=[} @purple{expr ::=[ expr} @red{•} @purple{ID ',' ]} @blue{]} @green{ID ]} @yellow{$end ]}
@end smallexample
@ifnottex
@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{↳} @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
the difference between these two examples. The parser would need an
@@ -9998,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:
@c doc/calc.y
@example
@group
%union
@@ -10041,7 +10227,7 @@ calc.y:19.1-7: @dwarning{warning}: nonterminal useless in grammar: useless [@dwa
19 | @dwarning{useless: STR;}
| @dwarning{^~~~~~~}
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
Going back to the calc example, when given @option{--report=state},
@@ -10353,15 +10539,44 @@ When given @option{--report=counterexamples}, @command{bison} will generate
counterexamples within the report, augmented with the corresponding items
(@pxref{Counterexamples}).
@ifnottex
@example
Shift/reduce conflict on token '/':
shift/reduce conflict on token '/':
1 exp: exp '+' exp •
4 exp: exp • '/' exp
Example @green{exp '+' exp} @red{•} @yellow{'/' exp}
First derivation @yellow{exp ::=[} @green{exp ::=[ exp '+' exp} @red{•} @green{]} @yellow{'/' exp ]}
Example @yellow{exp '+'} @green{exp} @red{•} @green{'/' exp}
Second derivation @yellow{exp ::=[ exp '+'} @green{exp ::=[ exp} @red{•} @green{'/' exp ]} @yellow{]}
@group
Example: exp '+' exp • '/' exp
Shift derivation
exp
↳ exp '+' exp
↳ exp • '/' exp
Example: exp '+' exp • '/' exp
Reduce derivation
exp
↳ exp '/' exp
↳ exp '+' exp •
@end group
@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}:
@samp{e1 + e2 / e3}. The derivations show how your rules would parse the
@@ -10972,7 +11187,7 @@ The exit status of @command{bison} is:
@item 0 (success)
when there were no errors. Warnings, which are diagnostics about dubious
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)
when there were errors. No file was generated (except the reports generated
@@ -11209,22 +11424,22 @@ Options controlling the diagnostics.
Output warnings falling in @var{category}. @var{category} can be one
of:
@table @code
@item conflicts-sr
@itemx conflicts-rr
@item @anchor{Wconflicts-sr}conflicts-sr
@itemx @anchor{Wconflicts-rr}conflicts-rr
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
unexpected number of conflicts is an error, and an expected number of
conflicts is not reported, so @option{-W} and @option{--warning} then have
no effect on the conflict report.
@item counterexamples
@item @anchor{Wcounterexamples}counterexamples
@itemx cex
Provide counterexamples for conflicts. @xref{Counterexamples}.
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
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.
String literals, which allow for better error messages, are (too) liberally
@@ -11270,16 +11485,16 @@ foo: "baz" @{@}
| @dwarning{^~~~~}
@end example
@item deprecated
@item @anchor{Wdeprecated}deprecated
Deprecated constructs whose support will be removed in future versions of
Bison.
@item empty-rule
@item @anchor{Wempty-rule}empty-rule
Empty rules without @code{%empty}. @xref{Empty Rules}. Disabled by
default, but enabled by uses of @code{%empty}, unless
@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
of the parent rule.
For example, warn about unused @code{$2} in:
@@ -11299,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
@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.
Consider for instance the following grammar:
@@ -11360,20 +11575,21 @@ One would get the exact same parser with the following directives instead:
@end group
@end example
@item yacc
@item @anchor{Wyacc}yacc
Incompatibilities with POSIX Yacc.
@item other
@item @anchor{Wother}other
All warnings not categorized above. These warnings are enabled by default.
This category is provided merely for the sake of completeness. Future
releases of Bison may move warnings from this category to new, more specific
categories.
@item all
All the warnings except @code{dangling-alias} and @code{yacc}.
@item @anchor{Wall}all
All the warnings except @code{counterexamples}, @code{dangling-alias} and
@code{yacc}.
@item none
@item @anchor{Wnone}none
Turn off all the warnings.
@item error
@@ -11384,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
POSIX Yacc incompatibilities.
@item -Werror
@anchor{-Werror}
@item @anchor{Werror}-Werror
Turn enabled warnings for every @var{category} into errors, unless they are
explicitly disabled by @option{-Wno-error=@var{category}}.
@@ -11745,6 +11960,30 @@ A Bison file has three parts. In the first part, the prologue, we start by
making sure we run a version of Bison which is recent enough, and that we
generate C++.
@ignore
@comment file: c++/simple.yy: 1
@example
/* Simple variant-based parser. -*- C++ -*-
Copyright (C) 2018-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/>. */
@end example
@end ignore
@comment file: c++/simple.yy: 1
@example
%require "3.2"
@@ -12817,6 +13056,30 @@ The declaration of this driver class, in @file{driver.hh}, is as follows.
The first part includes the CPP guard and imports the required standard
library components, and the declaration of the parser class.
@ignore
@comment file: calc++/driver.hh
@example
/* Driver for calc++. -*- C++ -*-
Copyright (C) 2005--2015, 2018--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/>. */
@end example
@end ignore
@comment file: calc++/driver.hh
@example
#ifndef DRIVER_HH
@@ -12889,6 +13152,30 @@ member functions to open and close the scanning phase.
The implementation of the driver (@file{driver.cc}) is straightforward.
@ignore
@comment file: calc++/driver.cc
@example
/* Driver for calc++. -*- C++ -*-
Copyright (C) 2005--2015, 2018--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/>. */
@end example
@end ignore
@comment file: calc++/driver.cc
@example
#include "driver.hh"
@@ -12932,6 +13219,30 @@ parser skeleton, the creation of the parser header file. Because the C++
skeleton changed several times, it is safer to require the version you
designed the grammar for.
@ignore
@comment file: calc++/parser.yy
@example
/* Parser for calc++. -*- C++ -*-
Copyright (C) 2005--2015, 2018--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/>. */
@end example
@end ignore
@comment file: calc++/parser.yy
@example
%skeleton "lalr1.cc" // -*- C++ -*-
@@ -13120,6 +13431,30 @@ yy::parser::error (const location_type& l, const std::string& m)
In addition to standard headers, the Flex scanner includes the driver's,
then the parser's to get the set of defined tokens.
@ignore
@comment file: calc++/scanner.ll
@example
/* Scanner for calc++. -*- C++ -*-
Copyright (C) 2005--2015, 2018--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/>. */
@end example
@end ignore
@comment file: calc++/scanner.ll
@example
%@{ /* -*- C++ -*- */
@@ -13293,7 +13628,7 @@ The rules are simple. The driver is used to report errors.
You should keep your rules simple, both in the parser and in the scanner.
Throwing from the auxiliary functions is then very handy to report errors.
@comment file: scanner.ll
@comment file: calc++/scanner.ll
@example
@group
yy::parser::symbol_type
@@ -13343,7 +13678,31 @@ driver::scan_end ()
The top level file, @file{calc++.cc}, poses no problem.
@comment file: calc++.cc
@ignore
@comment file: calc++/calc++.cc
@example
/* Main for calc++. -*- C++ -*-
Copyright (C) 2005--2015, 2018--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/>. */
@end example
@end ignore
@comment file: calc++/calc++.cc
@example
#include <iostream>
#include "driver.hh"
@@ -14605,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.
@end quotation
Except for GLR parsers (@pxref{Compiler Requirements for GLR}), the C
code that Bison generates requires only C89 or later. However, Bison
itself requires common C99 features such as declarations after
statements. Bison's @code{configure} script attempts to enable C99 (or
later) support on compilers that default to pre-C99. If your compiler
lacks these C99 features entirely, GCC may well be a better choice; or
you can try upgrading to your compiler's latest version.
Except for GLR parsers (which require C99), the C code that Bison generates
requires only C89 or later. However, Bison itself requires common C99
features such as declarations after statements. Bison's @code{configure}
script attempts to enable C99 (or later) support on compilers that default
to pre-C99. If your compiler lacks these C99 features entirely, GCC may
well be a better choice; or you can try upgrading to your compiler's latest
version.
@node Where can I find help?
@section Where can I find help?
@@ -15668,7 +16027,7 @@ London, Department of Computer Science, TR-00-12 (December 2000).
@c LocalWords: TokenKind Automake's rtti Wcounterexamples Chinawat PLDI
@c LocalWords: Isradisaikul tcite pcite rgbGreen colorGreen rgbYellow Wcex
@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 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.
- Its hand-written scanner tracks locations.
- 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
push-parser API to feed the parser with the incoming tokens.
- It features an interactive command line with completion based on the
@@ -62,6 +64,13 @@ This example demonstrates best practices when using Bison.
messages.
- It uses a custom syntax error with location, lookahead correction and
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 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.
- Its hand-written scanner tracks locations.
- 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
push-parser API to feed the parser with the incoming tokens.
- It features an interactive command line with completion based on the
@@ -11,6 +13,13 @@ This example demonstrates best practices when using Bison.
messages.
- It uses a custom syntax error with location, lookahead correction and
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 uses named references instead of the traditional $1, $2, etc.
+40 -9
View File
@@ -101,14 +101,28 @@ cat >input <<EOF
EOF
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
1 + 2 * * 3
EOF
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
1 / 0
@@ -132,8 +146,14 @@ run 0 '> ((1 ++ 2) ** 3)
1332
> ''
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.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 ")".
cat >input <<EOF
@@ -142,7 +162,9 @@ EOF
run 0 '> ()
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
@@ -189,6 +211,8 @@ err: LAC: checking lookahead function: S5
err: LAC: checking lookahead variable: S6
err: LAC: checking lookahead NEG: Err
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: Shifting token error (1.2: )
err: Entering state 10
@@ -286,7 +310,9 @@ run 0 '> (1+
( - atan cos exp ln number sin sqrt
> (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.
sed -e 's/\\t/ /g' >input <<EOF
@@ -294,7 +320,9 @@ sed -e 's/\\t/ /g' >input <<EOF
EOF
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.
sed -e 's/\\t/ /g' >input <<EOF
@@ -313,8 +341,9 @@ sed -e 's/\\t/ /g' >input <<EOF
EOF
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 | 1++ ''
err: | ^
'
# And even when the error was recovered from.
@@ -323,8 +352,10 @@ sed -e 's/\\t/ /g' >input <<EOF
EOF
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 | (1++2) + 3 + ''
err: | ^
err: 1.15: syntax error: expected - or ( or number or function or variable before end of file
err: 1 | (1++2) + 3 + ''
err: | ^
'
+78 -16
View File
@@ -1,5 +1,25 @@
%require "3.6"
/* Parser and scanner for bistromathic. -*- C -*-
Copyright (C) 2019-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/>. */
%require "3.7"
// Emitted on top of the implementation file.
%code top {
#include <ctype.h> // isdigit
#include <locale.h> // LC_ALL
@@ -24,6 +44,7 @@
#endif
}
// Emitted in the header file, before the definition of YYSTYPE.
%code requires {
// Function type.
typedef double (func_t) (double);
@@ -44,19 +65,34 @@
symrec *putsym (char const *name, int sym_type);
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.
%code provides {
# ifndef __attribute__
# ifndef __GNUC__
# define __attribute__(Spec) /* empty */
# endif
# endif
int yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc);
void yyerror (YYLTYPE *loc, char const *format, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
yytoken_kind_t
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.
%code {
#if defined ENABLE_NLS && ENABLE_NLS
# define _(Msgid) gettext (Msgid)
@@ -68,6 +104,9 @@
int done = 0;
}
// Include the header in the implementation rather than duplicating it.
%define api.header.include {"parse.h"}
// Don't share global variables between the scanner and the parser.
%define api.pure full
@@ -90,6 +129,9 @@
// Generate the parser description file (calc.output).
%verbose
// User information exchanged with the parser and scanner.
%param {const user_context *uctx}
// Generate YYSTYPE from the types assigned to symbols.
%define api.value.type union
%token
@@ -145,7 +187,7 @@ exp:
{
if ($r == 0)
{
yyerror (&@$, "error: division by zero");
yyerror (&@$, uctx, "error: division by zero");
YYERROR;
}
else
@@ -231,8 +273,9 @@ symbol_count (void)
| Scanner. |
`----------*/
int
yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
yytoken_kind_t
yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc,
const user_context *uctx)
{
int c;
@@ -302,7 +345,7 @@ yylex (const char **line, YYSTYPE *yylval, YYLTYPE *yylloc)
// Stray characters.
default:
yyerror (yylloc, "syntax error: invalid character: %c", c);
yyerror (yylloc, uctx, "syntax error: invalid character: %c", c);
return TOK_YYerror;
}
}
@@ -340,8 +383,11 @@ error_format_string (int argc)
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 };
yysymbol_kind_t arg[ARGS_MAX];
int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX);
@@ -352,11 +398,12 @@ yyreport_syntax_error (const yypcontext_t *ctx)
argsize = ARGS_MAX;
const char *format = error_format_string (1 + argsize + too_many_expected_tokens);
const YYLTYPE *loc = yypcontext_location (ctx);
while (*format)
// %@: location.
if (format[0] == '%' && format[1] == '@')
{
YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx));
YY_LOCATION_PRINT (stderr, *loc);
format += 2;
}
// %u: unexpected token.
@@ -381,13 +428,25 @@ yyreport_syntax_error (const yypcontext_t *ctx)
++format;
}
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;
}
// 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);
fputs (": ", stderr);
va_list args;
@@ -423,11 +482,13 @@ xstrndup (const char *string, size_t n)
static int
process_line (YYLTYPE *lloc, const char *line)
{
user_context uctx = {0, line};
yypstate *ps = yypstate_new ();
int status = 0;
do {
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);
yypstate_delete (ps);
lloc->last_line++;
@@ -442,18 +503,19 @@ expected_tokens (const char *input,
int *tokens, int ntokens)
{
YYDPRINTF ((stderr, "expected_tokens (\"%s\")", input));
user_context uctx = {1, input};
// Parse the current state of the line.
yypstate *ps = yypstate_new ();
int status = 0;
YYLTYPE lloc = { 1, 1, 1, 1 };
do {
YYLTYPE lloc = { 1, 1, 1, 1 };
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.
if (!token)
if (token == TOK_YYEOF)
break;
status = yypush_parse (ps, token, &lval, &lloc);
status = yypush_parse (ps, token, &lval, &lloc, &uctx);
} while (status == YYPUSH_MORE);
int res = 0;
+22
View File
@@ -1,3 +1,22 @@
/* Parser for lexcalc. -*- C -*-
Copyright (C) 2018-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/>. */
// Prologue (directives).
%expect 0
@@ -19,6 +38,9 @@
#include <stdlib.h> // getenv.
}
// Include the header in the implementation rather than duplicating it.
%define api.header.include {"parse.h"}
// Don't share global variables between the scanner and the parser.
%define api.pure full
+20 -1
View File
@@ -1,4 +1,23 @@
/* Prologue (directives). -*- C -*- */
/* Scanner for lexcalc. -*- C -*-
Copyright (C) 2018-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/>. */
/* Prologue (directives). */
/* Disable Flex features we don't need, to avoid warnings. */
%option nodefault noinput nounput noyywrap
+19
View File
@@ -1,3 +1,22 @@
/* Parser and scanner for pushcalc. -*- C -*-
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/>. */
%code top {
#include <ctype.h> /* isdigit. */
#include <stdio.h> /* printf. */
+36 -2
View File
@@ -1,3 +1,22 @@
/* Parser for reccalc. -*- C -*-
Copyright (C) 2019-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/>. */
// Prologue (directives).
%expect 0
@@ -46,14 +65,29 @@
result parse (void);
}
// Include the header in the implementation rather than duplicating it.
%define api.header.include {"parse.h"}
// Don't share global variables between the scanner and the parser.
%define api.pure full
// To avoid name clashes (e.g., with C's EOF) prefix token definitions
// with TOK_ (e.g., TOK_EOF).
%define api.token.prefix {TOK_}
// Generate YYSTYPE from the types assigned to symbols.
%define api.value.type union
%define parse.error verbose
// Error messages with "unexpected XXX, expected XXX...".
%define parse.error detailed
// Enable run-time traces (yydebug).
%define parse.trace
// Generate the parser description file (parse.output).
%verbose
// Scanner and error count are exchanged between main, yyparse and yylex.
// Scanner and error count are exchanged between main, yyparse and yylex.
%param {yyscan_t scanner}{result *res}
%token
+19
View File
@@ -1,3 +1,22 @@
/* Scanner for reccalc. -*- C -*-
Copyright (C) 2019-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/>. */
/* Prologue (directives). -*- C -*- */
/* Disable Flex features we don't need, to avoid warnings. */
+19
View File
@@ -1,3 +1,22 @@
/* Parser and scanner for calc in D. -*- D -*-
Copyright (C) 2018-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/>. */
%language "D"
%define api.parser.class {Calc}
+19
View File
@@ -1,3 +1,22 @@
/* Parser and scanner for calc in Java. -*- Java -*-
Copyright (C) 2018-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/>. */
%language "Java"
%define api.parser.class {Calc}
+19
View File
@@ -1,3 +1,22 @@
/* Simple parser and scanner in Java. -*- Java -*-
Copyright (C) 2018-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/>. */
%language "Java"
%define api.parser.class {Calc}
+1 -1
Submodule gnulib updated: 845d69187a...ac34618e85
+2
View File
@@ -20,6 +20,7 @@
/assure.h
/attribute.h
/basename-lgpl.c
/basename-lgpl.h
/basename.c
/binary-io.c
/binary-io.h
@@ -312,6 +313,7 @@
/stdlib.h
/stdlib.in.h
/stpcpy.c
/stpncpy.c
/strchrnul.c
/strchrnul.valgrind
/strdup.c
+1 -1
View File
@@ -13,7 +13,6 @@
/codeset.m4
/config-h.m4
/configmake.m4
/dirname.m4
/double-slash-root.m4
/dup2.m4
/eealloc.m4
@@ -176,6 +175,7 @@
/stdio_h.m4
/stdlib_h.m4
/stpcpy.m4
/stpncpy.m4
/strchrnul.m4
/strdup.m4
/strerror.m4
+5 -5
View File
@@ -169,10 +169,10 @@ AnnotationList__compute_conflicted_tokens (bitset shift_tokens,
bitset_copy (tokens, shift_tokens);
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,
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
AnnotationList__compute_from_inadequacies will misbehave. */
aver (i == 0 || reds->rules[i-1] < reds->rules[i]);
@@ -401,7 +401,7 @@ AnnotationList__compute_from_inadequacies (
struct obstack *annotations_obstackp,
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)
return;
@@ -422,7 +422,7 @@ AnnotationList__compute_from_inadequacies (
/* Allocate the annotation node. */
{
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))
++contribution_count;
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)
{
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))
{
bitset_set (actions, rule_i);
+35 -3
View File
@@ -35,6 +35,13 @@
#include "getargs.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;
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
flush (FILE *out)
{
@@ -427,9 +448,20 @@ warnings_print_categories (warnings warn_flags, FILE *out)
const char* style = severity_style (s);
fputs (" [", out);
begin_use_class (style, out);
fprintf (out, "-W%s%s",
s == severity_error ? "error=" : "",
argmatch_warning_argument (&w));
// E.g., "counterexamples".
const char *warning = 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);
fputc (']', out);
/* 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
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. */
rule *redrule = reds->rules[ruleno];
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)
if (bitset_test (lookahead_tokens, i)
if (bitset_test (lookaheads, i)
&& bitset_test (lookahead_set, i)
&& 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);
log_resolution (redrule, i, shift_resolution);
flush_reduce (lookahead_tokens, i);
flush_reduce (lookaheads, i);
}
else
/* Matching precedence levels.
@@ -316,7 +316,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
case right_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, right_resolution);
flush_reduce (lookahead_tokens, i);
flush_reduce (lookaheads, i);
break;
case left_assoc:
@@ -329,7 +329,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, nonassoc_resolution);
flush_shift (s, i);
flush_reduce (lookahead_tokens, i);
flush_reduce (lookaheads, i);
/* Record an explicit error for this token. */
errors[(*nerrs)++] = symbols[i];
break;
@@ -369,7 +369,7 @@ set_conflicts (state *s, symbol **errors)
for (int i = 0; i < reds->num; ++i)
if (reds->rules[i]->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);
if (nerrs)
@@ -385,13 +385,13 @@ set_conflicts (state *s, symbol **errors)
/* Loop over all rules which require lookahead in this state. Check
for conflicts not resolved above.
reds->lookahead_tokens can be NULL if the LR type is LR(0). */
if (reds->lookahead_tokens)
reds->lookaheads can be NULL if the LR type is LR(0). */
if (reds->lookaheads)
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;
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)
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);
@@ -499,7 +499,7 @@ count_state_rr_conflicts (const state *s)
{
int count = 0;
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)
res += count-1;
}
@@ -534,7 +534,7 @@ count_rule_state_sr_conflicts (rule *r, state *s)
for (int i = 0; i < reds->num; ++i)
if (reds->rules[i] == r)
{
bitset lookaheads = reds->lookahead_tokens[i];
bitset lookaheads = reds->lookaheads[i];
int j;
FOR_EACH_SHIFT (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)
{
bitset_and (lookaheads,
reds->lookahead_tokens[i],
reds->lookahead_tokens[j]);
reds->lookaheads[i],
reds->lookaheads[j]);
res += bitset_count (lookaheads);
}
bitset_free (lookaheads);
@@ -686,7 +686,8 @@ conflicts_print (void)
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
would make it ugly. */
{
@@ -703,7 +704,8 @@ conflicts_print (void)
complain (NULL, complaint,
_("shift/reduce conflicts: %d found, %d expected"),
total, expected);
has_unexpected_conflicts = true;
if (total)
unexpected_conflicts_warning = complaint;
}
}
else if (total)
@@ -713,7 +715,7 @@ conflicts_print (void)
"%d shift/reduce conflicts",
total),
total);
has_unexpected_conflicts = true;
unexpected_conflicts_warning = Wconflicts_sr;
}
}
@@ -731,7 +733,8 @@ conflicts_print (void)
complain (NULL, complaint,
_("reduce/reduce conflicts: %d found, %d expected"),
total, expected);
has_unexpected_conflicts = true;
if (total)
unexpected_conflicts_warning = complaint;
}
}
else if (total)
@@ -741,15 +744,16 @@ conflicts_print (void)
"%d reduce/reduce conflicts",
total),
total);
has_unexpected_conflicts = true;
unexpected_conflicts_warning = Wconflicts_rr;
}
}
if (warning_is_enabled (Wcounterexamples))
report_counterexamples ();
else if (has_unexpected_conflicts)
complain (NULL, Wother,
_("rerun with option '-Wcounterexamples' to generate conflict counterexamples"));
else if (unexpected_conflicts_warning != Wnone)
subcomplain (NULL, unexpected_conflicts_warning,
_("rerun with option '-Wcounterexamples'"
" to generate conflict counterexamples"));
}
void
+176 -103
View File
@@ -26,6 +26,7 @@
#include <gl_linked_list.h>
#include <gl_rbtreehash_list.h>
#include <hash.h>
#include <mbswidth.h>
#include <stdlib.h>
#include <textstyle.h>
#include <time.h>
@@ -76,17 +77,29 @@ typedef struct
{
derivation *d1;
derivation *d2;
bool shift_reduce;
bool unifying;
bool timeout;
} counterexample;
static counterexample *
new_counterexample (derivation *d1, derivation *d2,
bool shift_reduce,
bool u, bool t)
{
counterexample *res = xmalloc (sizeof (counterexample));
res->d1 = d1;
res->d2 = d2;
counterexample *res = xmalloc (sizeof *res);
res->shift_reduce = shift_reduce;
if (shift_reduce)
{
// Display the shift first.
res->d1 = d2;
res->d2 = d1;
}
else
{
res->d1 = d1;
res->d2 = d2;
}
res->unifying = u;
res->timeout = t;
return res;
@@ -100,14 +113,37 @@ free_counterexample (counterexample *cex)
free (cex);
}
static void
print_counterexample (counterexample *cex, FILE *out, const char *prefix)
static int max (int a, int b)
{
fprintf (out, " %s%-20s ",
prefix, cex->unifying ? _("Example") : _("First example"));
derivation_print_leaves (cex->d1, out, prefix);
fprintf (out, " %s%-20s ",
prefix, _("First derivation"));
return a < b ? b : a;
}
static void
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);
// 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.
if (!cex->unifying || is_styled (stderr))
{
fprintf (out, " %s%-20s ",
prefix, cex->unifying ? _("Example") : _("Second example"));
derivation_print_leaves (cex->d2, out, prefix);
if (flat)
fprintf (out, " %s%s%*s ", 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 ",
prefix, _("Second derivation"));
if (flat)
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);
fputc ('\n', out);
if (out != stderr)
putc ('\n', out);
}
/*
@@ -144,7 +187,7 @@ typedef struct si_bfs_node
static si_bfs_node *
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->parent = parent;
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
* 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);
gl_list_t queue = gl_list_create (GL_LINKED_LIST, NULL, NULL,
(gl_listelement_dispose_fn) si_bfs_free,
true, 1, (const void **) &init);
si_bfs_node_list queue
= gl_list_create (GL_LINKED_LIST, NULL, NULL,
(gl_listelement_dispose_fn) si_bfs_free,
true, 1, (const void **) &init);
si_bfs_node *node = NULL;
// breadth-first search for a path of productions to the conflict symbol
while (gl_list_size (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);
if (sym == conflict_sym)
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)
{
state_item *si = state_items + n->si;
state_item *si = &state_items[n->si];
item_number *pos = si->item;
if (SI_PRODUCTION (si))
{
@@ -274,7 +320,7 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
*/
static derivation *
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
// 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
conflict, and find a path of shifts from the shift conflict that
goes through the same states. */
static gl_list_t
nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
static state_item_list
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 next_node = gl_list_previous_node (reduce_path, tmp);
gl_list_node_t node = gl_list_previous_node (reduce_path, next_node);
gl_list_remove_node (reduce_path, tmp);
state_item *si = shift_conflict;
gl_list_t result =
state_item_list result =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
// FIXME: bool paths_merged;
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
si_bfs_node *init = si_bfs_new (si - state_items, NULL);
gl_list_t queue =
gl_list_create (GL_LINKED_LIST, NULL, NULL,
(gl_listelement_dispose_fn) si_bfs_free,
true, 1, (const void **) &init);
si_bfs_node_list queue
= gl_list_create (GL_LINKED_LIST, NULL, NULL,
(gl_listelement_dispose_fn) si_bfs_free,
true, 1, (const void **) &init);
si_bfs_node *sis = NULL;
state_item *prevsi = NULL;
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)
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,
// its reverse production items get added to the queue.
// 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;
BITSET_FOR_EACH (biter, rsi, sin, 0)
{
prevsi = state_items + sin;
prevsi = &state_items[sin];
if (SI_TRANSITION (search_si))
{
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
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)
ln = gl_list_add_after (result, ln, state_items + n->si);
ln = gl_list_add_after (result, ln, &state_items[n->si]);
}
si = prevsi;
@@ -493,17 +539,17 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict)
static counterexample *
example_from_path (bool shift_reduce,
state_item_number itm2,
gl_list_t shortest_path, symbol_number next_sym)
state_item_list shortest_path, symbol_number next_sym)
{
derivation *deriv1 =
complete_diverging_example (next_sym, shortest_path, NULL);
gl_list_t path_2
state_item_list path_2
= shift_reduce
? nonunifying_shift_path (shortest_path, &state_items [itm2])
: shortest_path_from_start (itm2, next_sym);
derivation *deriv2 = complete_diverging_example (next_sym, path_2, NULL);
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 *
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[1] = new_parse_state (conflict2);
parse_state_retain (res->states[0]);
@@ -537,7 +583,7 @@ initial_search_state (state_item *conflict1, state_item *conflict2)
static search_state *
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[1] = ps2;
parse_state_retain (res->states[0]);
@@ -549,8 +595,8 @@ new_search_state (parse_state *ps1, parse_state *ps2, int complexity)
static search_state *
copy_search_state (search_state *parent)
{
search_state *res = xmalloc (sizeof (search_state));
memcpy (res, parent, sizeof (search_state));
search_state *res = xmalloc (sizeof *res);
*res = *parent;
parse_state_retain (res->states[0]);
parse_state_retain (res->states[1]);
return res;
@@ -583,6 +629,8 @@ search_state_print (search_state *ss)
putc ('\n', stderr);
}
typedef gl_list_t search_state_list;
static inline bool
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 *
complete_diverging_examples (search_state *ss,
symbol_number next_sym)
symbol_number next_sym,
bool shift_reduce)
{
derivation *new_derivs[2];
for (int i = 0; i < 2; ++i)
{
gl_list_t sitems;
state_item_list sitems;
derivation_list derivs;
parse_state_lists (ss->states[i], &sitems, &derivs);
new_derivs[i] = complete_diverging_example (next_sym, sitems, derivs);
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
{
gl_list_t states;
search_state_list states;
int complexity;
} search_state_bundle;
@@ -664,11 +714,13 @@ ssb_equals (const search_state_bundle *s1, const search_state_bundle *s2)
return s1->complexity == s2->complexity;
}
typedef gl_list_t ssb_list;
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)
+ parse_state_hasher (ss->states[1], max)) % max;
return (parse_state_hasher (ss->states[0], maximum)
+ parse_state_hasher (ss->states[1], maximum)) % maximum;
}
static bool
@@ -679,7 +731,7 @@ visited_comparator (const search_state *ss1, const search_state *ss2)
}
/* Priority queue for search states with minimal complexity. */
static gl_list_t ssb_queue;
static ssb_list ssb_queue;
static Hash_table *visited;
/* The set of parser states on the shortest lookahead-sensitive path. */
static bitset scp_set = NULL;
@@ -702,7 +754,7 @@ ssb_append (search_state *ss)
parse_state_free_contents_early (ss->states[1]);
parse_state_retain (ss->states[0]);
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;
gl_list_node_t n = gl_list_search (ssb_queue, ssb);
if (!n)
@@ -756,12 +808,12 @@ reduction_cost (const parse_state *ps)
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,
int parser_state, int rule_len)
{
(void) conflict_item; // FIXME: Unused
gl_list_t result =
search_state_list result =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, 1);
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.
*/
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;
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.
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);
search_state *red1 = NULL;
for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
search_state_list_next (&iter, &red1);
)
{
gl_list_t reduced2 =
search_state_list reduced2 =
reduction_step (red1, conflict2->item, 1, len2);
search_state *red2 = NULL;
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)
{
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;
for (gl_list_iterator_t iter = gl_list_iterator (reduced1);
search_state_list_next (&iter, &red1);
@@ -1021,7 +1073,7 @@ generate_next_states (search_state *ss, state_item *conflict1,
}
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;
for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2);
search_state_list_next (&iter2, &red2);
@@ -1055,10 +1107,10 @@ static counterexample *
unifying_example (state_item_number itm1,
state_item_number itm2,
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 *conflict2 = state_items + itm2;
state_item *conflict1 = &state_items[itm1];
state_item *conflict2 = &state_items[itm2];
search_state *initial = initial_search_state (conflict1, conflict2);
ssb_queue = gl_list_create_empty (GL_RBTREEHASH_LIST,
(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 *si2src = parse_state_head (ps2);
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
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,
// 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 (d2);
goto cex_search_end;
@@ -1142,7 +1194,7 @@ cex_search_end:;
// If a search state from Stage 3 is available, use it
// to construct a more compact nonunifying counterexample.
if (stage3result)
cex = complete_diverging_examples (stage3result, next_sym);
cex = complete_diverging_examples (stage3result, next_sym, shift_reduce);
// Otherwise, construct a nonunifying counterexample that
// begins from the start state using the shortest
// 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
// 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;
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);
}
// ITM1 denotes a shift, ITM2 a reduce.
static void
counterexample_report_shift_reduce (state_item_number itm1, state_item_number itm2,
symbol_number next_sym,
FILE *out, const char *prefix)
{
fputs (prefix, out);
fprintf (out, _("Shift/reduce conflict on token %s:\n"), symbols[next_sym]->tag);
if (*prefix)
if (out == stderr)
complain (NULL, Wcounterexamples,
_("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[itm2], out, prefix);
@@ -1240,32 +1302,49 @@ counterexample_report_reduce_reduce (state_item_number itm1, state_item_number i
FILE *out, const char *prefix)
{
{
fputs (prefix, out);
fputs (ngettext ("Reduce/reduce conflict on token",
"Reduce/reduce conflict on tokens",
bitset_count (conflict_syms)), out);
struct obstack obstack;
obstack_init (&obstack);
bitset_iterator biter;
state_item_number sym;
const char *sep = " ";
const char *sep = "";
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 = ", ";
}
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[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
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)
&& item_number_as_rule_number (*state_items[i].item) == r->number)
return i;
@@ -1277,41 +1356,35 @@ counterexample_report_state (const state *s, FILE *out, const char *prefix)
{
const state_number sn = s->number;
const reductions *reds = s->reductions;
bitset lookaheads = bitset_create (ntokens, BITSET_FIXED);
for (int i = 0; i < reds->num; ++i)
{
const rule *r1 = reds->rules[i];
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)
if (!SI_DISABLED (j))
for (state_item_number c2 = state_item_map[sn]; c2 < state_item_map[sn + 1]; ++c2)
if (!SI_DISABLED (c2))
{
state_item *si = state_items + j;
item_number conf = *si->item;
item_number conf = *state_items[c2].item;
if (item_number_is_symbol_number (conf)
&& bitset_test (reds->lookahead_tokens[i], conf))
counterexample_report_shift_reduce (c1, j, conf, out, prefix);
&& bitset_test (reds->lookaheads[i], conf))
counterexample_report_shift_reduce (c1, c2, conf, out, prefix);
}
for (int j = i+1; j < reds->num; ++j)
{
bitset conf = bitset_create (ntokens, BITSET_FIXED);
bitset_intersection (conf,
reds->lookahead_tokens[i],
reds->lookahead_tokens[j]);
if (!bitset_empty_p (conf))
{
const rule *r2 = reds->rules[j];
for (int k = state_item_map[sn]; k < state_item_map[sn + 1]; ++k)
if (!SI_DISABLED (k))
{
state_item *si = state_items + k;
const rule *r = item_rule (si->item);
if (r == r2)
{
counterexample_report_reduce_reduce (c1, k, conf, out, prefix);
break;
}
}
}
bitset_free (conf);
const rule *r2 = reds->rules[j];
// Conflicts: common lookaheads.
bitset_intersection (lookaheads,
reds->lookaheads[i],
reds->lookaheads[j]);
if (!bitset_empty_p (lookaheads))
for (state_item_number c2 = state_item_map[sn]; c2 < state_item_map[sn + 1]; ++c2)
if (!SI_DISABLED (c2)
&& item_rule (state_items[c2].item) == r2)
{
counterexample_report_reduce_reduce (c1, c2, lookaheads, out, prefix);
break;
}
}
}
bitset_free (lookaheads);
}
+8 -2
View File
@@ -20,11 +20,17 @@
#ifndef COUNTEREXAMPLE_H
# define COUNTEREXAMPLE_H
# include "state-item.h"
# include "state.h"
// Init/deinit this module.
void counterexample_init (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 */
+272 -41
View File
@@ -20,8 +20,11 @@
#include <config.h>
#include "derivation.h"
#include "glyphs.h"
#include <c-ctype.h>
#include <gl_linked_list.h>
#include <mbswidth.h>
#include "system.h"
#include "complain.h"
@@ -29,11 +32,15 @@
struct derivation
{
symbol_number sym;
gl_list_t children;
derivation_list children;
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_dot (void)
@@ -73,6 +80,7 @@ derivation_new (symbol_number sym, derivation_list children)
deriv->sym = sym;
deriv->children = children;
deriv->reference_count = 0;
deriv->color = -1;
return deriv;
}
@@ -126,27 +134,242 @@ derivation_size (const derivation *deriv)
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
derivation_print_impl (const derivation *deriv, FILE *f,
bool leaves_only,
int *counter, const char *prefix)
all_spaces (const char *s)
{
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)
{
const symbol *sym = symbols[deriv->sym];
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;
begin_use_class (style, f);
char style[20];
snprintf (style, 20, "cex-%d", deriv->color);
begin_use_class (style, out);
if (!leaves_only)
{
fputs (prefix, f);
begin_use_class ("cex-step", f);
fprintf (f, "%s ::=[ ", sym->tag);
end_use_class ("cex-step", f);
fputs (prefix, out);
begin_use_class ("cex-step", out);
fprintf (out, "%s %s [ ", sym->tag, arrow);
end_use_class ("cex-step", out);
prefix = "";
}
bool res = false;
@@ -155,7 +378,8 @@ derivation_print_impl (const derivation *deriv, FILE *f,
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 = " ";
res = true;
@@ -165,49 +389,56 @@ derivation_print_impl (const derivation *deriv, FILE *f,
}
if (!leaves_only)
{
begin_use_class ("cex-step", f);
begin_use_class ("cex-step", out);
if (res)
fputs (" ]", f);
fputs (" ]", out);
else
fputs ("]", f);
end_use_class ("cex-step", f);
fputs ("]", out);
end_use_class ("cex-step", out);
}
end_use_class (style, f);
end_use_class (style, out);
return res;
}
else if (deriv == &d_dot)
{
fputs (prefix, f);
begin_use_class ("cex-dot", f);
print_dot (f);
end_use_class ("cex-dot", f);
fputs (prefix, out);
begin_use_class ("cex-dot", out);
fputs (dot, out);
end_use_class ("cex-dot", out);
}
else // leaf.
{
fputs (prefix, f);
fputs (prefix, out);
const symbol *sym = symbols[deriv->sym];
begin_use_class ("cex-leaf", f);
fprintf (f, "%s", sym->tag);
end_use_class ("cex-leaf", f);
begin_use_class ("cex-leaf", out);
fprintf (out, "%s", sym->tag);
end_use_class ("cex-leaf", out);
}
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
derivation_print (const derivation *deriv, FILE *out, const char *prefix)
{
int counter = 0;
fputs (prefix, out);
derivation_print_impl (deriv, out, false, &counter, "");
fputc ('\n', out);
}
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);
if (getenv ("YYFLAT"))
derivation_print_flat (deriv, out, prefix);
else
derivation_print_tree (deriv, out, prefix);
}
+4 -1
View File
@@ -60,12 +60,15 @@ static inline derivation *derivation_new_leaf (symbol_number sym)
{
return derivation_new (sym, NULL);
}
// Number of symbols.
size_t derivation_size (const derivation *deriv);
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_retain (derivation *deriv);
// A derivation denoting the position of the dot.
derivation *derivation_dot (void);
#endif /* DERIVATION_H */
+1 -1
View File
@@ -221,7 +221,7 @@ static const argmatch_report_arg argmatch_report_args[] =
{ "none", report_none },
{ "states", report_states },
{ "itemsets", report_states | report_itemsets },
{ "lookaheads", report_states | report_lookahead_tokens },
{ "lookaheads", report_states | report_lookaheads },
{ "solved", report_states | report_solved_conflicts },
{ "counterexamples", report_cex },
{ "cex", report_cex },
+1 -1
View File
@@ -77,7 +77,7 @@ enum report
report_none = 0,
report_states = 1 << 0,
report_itemsets = 1 << 1,
report_lookahead_tokens = 1 << 2,
report_lookaheads = 1 << 2,
report_solved_conflicts = 1 << 3,
report_cex = 1 << 4,
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 "getargs.h"
#include "glyphs.h"
#include "gram.h"
#include "print-xml.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++)
fprintf (out, " %s", symbols[*sp]->tag);
putc (' ', out);
print_dot (out);
fprintf (out, " %s", dot);
if (0 <= *r->rhs)
for (item_number *sp = item; 0 <= *sp; ++sp)
fprintf (out, " %s", symbols[*sp]->tag);
-21
View File
@@ -103,8 +103,6 @@
# include "system.h"
# include <unicodeio.h>
# include "location.h"
# include "symtab.h"
@@ -217,25 +215,6 @@ typedef struct
extern rule *rules;
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. */
static inline rule const *
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;
rule_number ruleno = reds->rules[j]->number;
if (reds->lookahead_tokens)
if (reds->lookaheads)
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))
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];
bitset lookahead_set =
node->state->reductions->lookahead_tokens[r];
node->state->reductions->lookaheads[r];
if (item_number_is_rule_number (*this_rule->rhs))
ielr_compute_goto_follow_set (follow_kernel_items,
always_follows, node,
+24 -27
View File
@@ -256,9 +256,9 @@ lookback_find_state (int lookback_index)
state *res = NULL;
for (int j = 0; j < nstates; ++j)
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. */
break;
else
@@ -280,7 +280,7 @@ lookback_print (FILE *out)
{
fprintf (out, " %3d = ", 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];
fprintf (out, "(%3d, ", s->number);
rule_print (r, NULL, out);
@@ -305,7 +305,7 @@ static void
add_lookback_edge (state *s, rule const *r, goto_number gotono)
{
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]);
}
@@ -421,7 +421,7 @@ compute_follows (void)
static void
compute_lookahead_tokens (void)
compute_lookaheads (void)
{
if (trace_flag & trace_automaton)
lookback_print (stderr);
@@ -437,13 +437,12 @@ compute_lookahead_tokens (void)
}
/*----------------------------------------------------.
| Count the number of lookahead tokens required for S |
| (N_LOOKAHEAD_TOKENS member). |
`----------------------------------------------------*/
/*------------------------------------------------------.
| Count the number of lookahead tokens required for S. |
`------------------------------------------------------*/
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 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
initialize_LA (void)
@@ -491,25 +490,23 @@ initialize_LA (void)
/* Compute the total number of reductions requiring a lookahead. */
nLA = 0;
for (state_number i = 0; i < nstates; ++i)
nLA +=
state_lookahead_tokens_count (states[i],
default_reduction_only_for_accept);
nLA += state_lookaheads_count (states[i],
default_reduction_only_for_accept);
/* Avoid having to special case 0. */
if (!nLA)
nLA = 1;
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. */
for (state_number i = 0; i < nstates; ++i)
{
int count =
state_lookahead_tokens_count (states[i],
default_reduction_only_for_accept);
int count = state_lookaheads_count (states[i],
default_reduction_only_for_accept);
if (count)
{
states[i]->reductions->lookahead_tokens = pLA;
states[i]->reductions->lookaheads = pLA;
pLA += count;
}
}
@@ -521,7 +518,7 @@ initialize_LA (void)
`---------------------------------------------*/
static void
lookahead_tokens_print (FILE *out)
lookaheads_print (FILE *out)
{
fputs ("Lookaheads:\n", out);
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)
{
fprintf (out, " rule %d:", reds->rules[j]->number);
if (reds->lookahead_tokens)
if (reds->lookaheads)
{
bitset_iterator iter;
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);
}
fputc ('\n', out);
@@ -564,10 +561,10 @@ lalr (void)
lookback = xcalloc (nLA, sizeof *lookback);
build_relations ();
compute_follows ();
compute_lookahead_tokens ();
compute_lookaheads ();
if (trace_flag & trace_sets)
lookahead_tokens_print (stderr);
lookaheads_print (stderr);
if (trace_flag & trace_automaton)
{
begin_use_class ("trace0", stderr);
@@ -614,6 +611,6 @@ void
lalr_free (void)
{
for (state_number s = 0; s < nstates; ++s)
states[s]->reductions->lookahead_tokens = NULL;
states[s]->reductions->lookaheads = NULL;
bitsetv_free (LA);
}
+2
View File
@@ -53,6 +53,8 @@ src_bison_SOURCES = \
src/flex-scanner.h \
src/getargs.c \
src/getargs.h \
src/glyphs.c \
src/glyphs.h \
src/gram.c \
src/gram.h \
src/graphviz.c \
+13 -11
View File
@@ -82,8 +82,10 @@ lssi_comparator (lssi *s1, lssi *s2)
return false;
}
typedef gl_list_t lssi_list;
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))
{
@@ -100,7 +102,7 @@ append_lssi (lssi *sn, Hash_table *visited, gl_list_t queue)
static void
lssi_print (lssi *l)
{
print_state_item (state_items + l->si, stdout);
print_state_item (&state_items[l->si], stdout);
if (l->lookahead)
{
printf ("FOLLOWL = { ");
@@ -121,7 +123,7 @@ static bitset
eligible_state_items (state_item *target)
{
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,
(const void **) &target);
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
* that can reach the conflict state.
*/
gl_list_t
state_item_list
shortest_path_from_start (state_item_number target, symbol_number next_sym)
{
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_set (il, 0);
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);
append_lssi (init, visited, queue);
// breadth-first search
@@ -175,7 +177,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym)
finished = true;
break;
}
state_item *si = state_items + last;
state_item *si = &state_items[last];
// Transitions don't change follow_L
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);
abort ();
}
gl_list_t res =
state_item_list res =
gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
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);
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
* to its lookahead
*/
gl_list_t
state_item_list
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);
if (SI_TRANSITION (si))
return result;
@@ -320,7 +322,7 @@ lssi_reverse_production (const state_item *si, bitset lookahead)
state_item_number sin;
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))
continue;
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
* next_sym is in the follow_L set of target in that position.
*/
gl_list_t shortest_path_from_start (state_item_number target,
symbol_number next_sym);
state_item_list shortest_path_from_start (state_item_number target,
symbol_number next_sym);
/**
* 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
* 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 */
+2
View File
@@ -38,6 +38,7 @@
#include "files.h"
#include "fixits.h"
#include "getargs.h"
#include "glyphs.h"
#include "gram.h"
#include "ielr.h"
#include "lalr.h"
@@ -85,6 +86,7 @@ main (int argc, char *argv[])
atexit (close_stdout);
glyphs_init ();
uniqstrs_new ();
muscle_init ();
complain_init ();
+22 -20
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.6.4.130-76c4d. */
/* A Bison parser, made by GNU Bison 3.6.90. */
/* Bison implementation for Yacc-like parsers in C
@@ -49,7 +49,7 @@
#define YYBISON 1
/* Bison version. */
#define YYBISON_VERSION "3.6.4.130-76c4d"
#define YYBISON_VERSION "3.6.90"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -234,6 +234,10 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
#include "scan-code.h"
#include "scan-gram.h"
/* Pretend to be at least that version, to check features published
in that version while developping it. */
static const char* api_version = "3.7";
static int current_prec = 0;
static location current_lhs_loc;
static named_ref *current_lhs_named_ref;
@@ -623,6 +627,7 @@ union yyalloc
/* YYNSTATES -- Number of states. */
#define YYNSTATES 167
/* YYMAXUTOK -- Last valid token kind. */
#define YYMAXUTOK 315
@@ -634,19 +639,19 @@ union yyalloc
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_int16 yyrline[] =
{
0, 308, 308, 317, 318, 322, 323, 329, 333, 338,
339, 340, 341, 342, 343, 344, 349, 354, 355, 356,
357, 358, 359, 359, 360, 361, 362, 363, 364, 365,
366, 367, 371, 372, 381, 382, 386, 397, 401, 405,
413, 423, 424, 434, 435, 441, 454, 454, 459, 459,
464, 468, 478, 479, 480, 481, 485, 486, 491, 492,
496, 497, 501, 502, 503, 516, 525, 529, 533, 541,
542, 546, 559, 560, 565, 566, 567, 585, 589, 593,
601, 603, 608, 615, 625, 629, 633, 641, 646, 658,
659, 665, 666, 667, 674, 674, 682, 683, 684, 689,
692, 694, 696, 698, 700, 702, 704, 706, 708, 713,
714, 723, 747, 748, 749, 750, 762, 764, 788, 793,
794, 799, 807, 808
0, 312, 312, 321, 322, 326, 327, 333, 337, 342,
343, 344, 345, 346, 347, 348, 353, 358, 359, 360,
361, 362, 363, 363, 364, 365, 366, 367, 368, 369,
370, 371, 375, 376, 385, 386, 390, 401, 405, 409,
417, 427, 428, 438, 439, 445, 458, 458, 463, 463,
468, 472, 482, 483, 484, 485, 489, 490, 495, 496,
500, 501, 505, 506, 507, 520, 529, 533, 537, 545,
546, 550, 563, 564, 569, 570, 571, 589, 593, 597,
605, 607, 612, 619, 629, 633, 637, 645, 650, 662,
663, 669, 670, 671, 678, 678, 686, 687, 688, 693,
696, 698, 700, 702, 704, 706, 708, 710, 712, 717,
718, 727, 751, 752, 753, 754, 766, 768, 792, 797,
798, 803, 811, 812
};
#endif
@@ -1748,7 +1753,7 @@ yydestruct (const char *yymsg,
int
yyparse (void)
{
/* The lookahead symbol. */
/* Lookahead token kind. */
int yychar;
@@ -1803,7 +1808,7 @@ YYLTYPE yylloc = yyloc_default;
int yyn;
/* The return value of yyparse. */
int yyresult;
/* Lookahead token as an internal (translated) token number. */
/* Lookahead symbol kind. */
yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
/* The variables used to return semantic value and location from the
action routines. */
@@ -3070,9 +3075,6 @@ handle_require (location const *loc, char const *version_quoted)
}
else
{
/* Pretend to be at least that version, to check features published
in that version while developping it. */
const char* api_version = "3.6";
const char* package_version =
0 < strverscmp (api_version, PACKAGE_VERSION)
? api_version : PACKAGE_VERSION;
+1 -1
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 3.6.4.130-76c4d. */
/* A Bison parser, made by GNU Bison 3.6.90. */
/* Bison interface for Yacc-like parsers in C
+6 -5
View File
@@ -58,6 +58,10 @@
#include "scan-code.h"
#include "scan-gram.h"
/* Pretend to be at least that version, to check features published
in that version while developping it. */
static const char* api_version = "3.7";
static int current_prec = 0;
static location current_lhs_loc;
static named_ref *current_lhs_named_ref;
@@ -691,8 +695,8 @@ rhs:
current_lhs_named_ref); }
| rhs symbol named_ref.opt
{ grammar_current_rule_symbol_append ($2, @2, $3); }
| rhs tag.opt "{...}"[act] named_ref.opt[name]
{ grammar_current_rule_action_append ($act, @act, $name, $[tag.opt]); }
| rhs tag.opt "{...}"[action] named_ref.opt[name]
{ grammar_current_rule_action_append ($action, @action, $name, $[tag.opt]); }
| rhs "%?{...}"
{ grammar_current_rule_predicate_append ($2, @2); }
| rhs "%empty"
@@ -1082,9 +1086,6 @@ handle_require (location const *loc, char const *version_quoted)
}
else
{
/* Pretend to be at least that version, to check features published
in that version while developping it. */
const char* api_version = "3.6";
const char* package_version =
0 < strverscmp (api_version, PACKAGE_VERSION)
? api_version : PACKAGE_VERSION;
+32 -34
View File
@@ -34,7 +34,7 @@ typedef struct parse_state
struct si_chunk
{
// elements newly added in this chunk
gl_list_t contents;
state_item_list contents;
// properties of the linked list this chunk represents
const state_item *head_elt;
const state_item *tail_elt;
@@ -135,7 +135,7 @@ static parse_state *
copy_parse_state (bool prepend, parse_state *parent)
{
parse_state *res = xmalloc (sizeof *res);
memcpy (res, parent, sizeof *res);
*res = *parent;
res->state_items.contents
= gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
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)
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;
state_item *last = NULL;
@@ -337,19 +337,17 @@ parser_pop (parse_state *ps, int deriv_index,
for (int i = 0; i < 4; ++i)
chunks[i] = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true);
for (parse_state *pn = ps; pn != NULL; pn = pn->parent)
{
if (pn->prepend)
{
gl_list_add_last (chunks[0], pn->state_items.contents);
gl_list_add_last (chunks[2], pn->derivs.contents);
}
else
{
gl_list_add_first (chunks[1], pn->state_items.contents);
gl_list_add_first (chunks[3], pn->derivs.contents);
}
}
gl_list_t popped_derivs = derivation_list_new ();
if (pn->prepend)
{
gl_list_add_last (chunks[0], pn->state_items.contents);
gl_list_add_last (chunks[2], pn->derivs.contents);
}
else
{
gl_list_add_first (chunks[1], pn->state_items.contents);
gl_list_add_first (chunks[3], pn->derivs.contents);
}
derivation_list popped_derivs = derivation_list_new ();
gl_list_t ret_chunks[4] = { ret->state_items.contents, NULL,
ret->derivs.contents, popped_derivs
};
@@ -390,7 +388,7 @@ parser_pop (parse_state *ps, int deriv_index,
}
void
parse_state_lists (parse_state *ps, gl_list_t *sitems,
parse_state_lists (parse_state *ps, state_item_list *sitems,
derivation_list *derivs)
{
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;
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);
if (ISTOKEN (sp) || !nullable[sp - ntokens])
break;
state_item *nsi = state_items + sin;
state_item *nsi = &state_items[sin];
current_ps = copy_parse_state (false, current_ps);
ps_si_append (current_ps, nsi);
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)
{
const state_item *si = ps->state_items.tail_elt;
symbol_number sym = item_number_as_symbol_number (*si->item);
// Transition on the same next symbol, taking nullable
// 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;
// check for disabled transition, shouldn't happen
// as any state_items that lead to these should be
@@ -446,11 +444,11 @@ simulate_transition (parse_state *ps)
if (si_next < 0)
return result;
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));
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;
}
@@ -473,10 +471,10 @@ compatible (symbol_number sym1, symbol_number sym2)
return false;
}
gl_list_t
parse_state_list
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);
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
// 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;
if (!compatible (*itm1, compat_sym) || !production_allowed (si, next))
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
// item associated with ps's conflict. symbol_set is a lookahead set this
// reduction must be compatible with
gl_list_t
parse_state_list
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 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)
{
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);
}
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
// with possible source state-items.
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.
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);
struct si_chunk *sis = &copy->state_items;
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);
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;
}
gl_list_t
parse_state_list
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;
symbol_number prepend_sym =
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)
{
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))
ps_derivs_prepend (copy, derivation_new_leaf (prepend_sym));
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);
/* 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);
/* 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");
/* Experimental feature: display the lookahead tokens. */
if (report_flag & report_lookahead_tokens
if (report_flag & report_lookaheads
&& item_number_is_rule_number (*sp1))
{
/* Find the reduction we are handling. */
@@ -104,13 +104,13 @@ print_core (struct obstack *oout, state *s)
int redno = state_reduction_find (s, r);
/* Print them if there are. */
if (reds->lookahead_tokens && redno != -1)
if (reds->lookaheads && redno != -1)
{
bitset_iterator biter;
int k;
char const *sep = "";
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_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;
int red = state_reduction_find (s, r);
/* Print item with lookaheads if there are. */
if (reds->lookahead_tokens && red != -1)
if (reds->lookaheads && red != -1)
{
xml_printf (out, level + 1,
"<item rule-number=\"%d\" dot=\"%d\">",
r->number, sp1 - sp);
state_rule_lookahead_tokens_print_xml (s, r,
state_rule_lookaheads_print_xml (s, r,
out, level + 2);
xml_puts (out, level + 1, "</item>");
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'). |
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
| R/R conflicts). |
`-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------.
| 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 |
| R/R conflicts). |
`-------------------------------------------------------------------*/
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)
{
if (r->number)
xml_printf (out, level,
"<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>",
xml_escape (lookahead_token),
xml_escape (lookahead),
r->number,
enabled ? "true" : "false");
else
xml_printf (out, level,
"<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>",
xml_escape (lookahead_token),
xml_escape (lookahead),
enabled ? "true" : "false");
}
@@ -258,13 +258,13 @@ print_reductions (FILE *out, int level, state *s)
if (default_reduction)
report = true;
if (reds->lookahead_tokens)
if (reds->lookaheads)
for (i = 0; i < ntokens; i++)
{
bool count = bitset_test (no_reduce_set, i);
for (j = 0; j < reds->num; ++j)
if (bitset_test (reds->lookahead_tokens[j], i))
if (bitset_test (reds->lookaheads[j], i))
{
if (! count)
{
@@ -289,14 +289,14 @@ print_reductions (FILE *out, int level, state *s)
xml_puts (out, level, "<reductions>");
/* Report lookahead tokens (or $default) and reductions. */
if (reds->lookahead_tokens)
if (reds->lookaheads)
for (i = 0; i < ntokens; i++)
{
bool defaulted = false;
bool count = bitset_test (no_reduce_set, i);
for (j = 0; j < reds->num; ++j)
if (bitset_test (reds->lookahead_tokens[j], i))
if (bitset_test (reds->lookaheads[j], i))
{
if (! count)
{
@@ -382,14 +382,17 @@ print_grammar (FILE *out, int level)
for (int i = 0; i < max_code + 1; i++)
if (token_translations[i] != undeftoken->content->number)
{
char const *tag = symbols[token_translations[i]]->tag;
int precedence = symbols[token_translations[i]]->content->prec;
assoc associativity = symbols[token_translations[i]]->content->assoc;
symbol const *sym = symbols[token_translations[i]];
char const *tag = sym->tag;
char const *type = sym->content->type_name;
int precedence = sym->content->prec;
assoc associativity = sym->content->assoc;
xml_indent (out, level + 2);
fprintf (out,
"<terminal symbol-number=\"%d\" token-number=\"%d\""
" name=\"%s\" usefulness=\"%s\"",
token_translations[i], i, xml_escape (tag),
" name=\"%s\" type=\"%s\" usefulness=\"%s\"",
token_translations[i], i, xml_escape_n (0, tag),
type ? xml_escape_n (1, type) : "",
reduce_token_unused_in_grammar (token_translations[i])
? "unused-in-grammar" : "useful");
if (precedence)
@@ -404,12 +407,16 @@ print_grammar (FILE *out, int level)
xml_puts (out, level + 1, "<nonterminals>");
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,
"<nonterminal symbol-number=\"%d\" name=\"%s\""
" type=\"%s\""
" usefulness=\"%s\"/>",
i, xml_escape (tag),
reduce_nonterminal_useless_in_grammar (symbols[i]->content)
i, xml_escape_n (0, tag),
type ? xml_escape_n (1, type) : "",
reduce_nonterminal_useless_in_grammar (sym->content)
? "useless-in-grammar" : "useful");
}
xml_puts (out, level + 1, "</nonterminals>");
+22 -21
View File
@@ -90,9 +90,9 @@ print_core (FILE *out, const state *s)
previous_rule = r;
/* Display the lookahead tokens? */
if (report_flag & report_lookahead_tokens
if (report_flag & report_lookaheads
&& item_number_is_rule_number (*sp1))
state_rule_lookahead_tokens_print (s, r, out);
state_rule_lookaheads_print (s, r, 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'). |
| If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
| R/R conflicts). |
`-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------.
| 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 |
| R/R conflicts). |
`-------------------------------------------------------------------*/
static void
print_reduction (FILE *out, size_t width,
const char *lookahead_token,
const char *lookahead,
rule *r, bool enabled)
{
fprintf (out, " %s", lookahead_token);
for (int j = width - mbswidth (lookahead_token, 0); j > 0; --j)
fprintf (out, " %s", lookahead);
for (int j = width - mbswidth (lookahead, 0); j > 0; --j)
fputc (' ', out);
if (!enabled)
fputc ('[', out);
@@ -239,13 +239,13 @@ print_reductions (FILE *out, const state *s)
if (default_reduction)
width = mbswidth (_("$default"), 0);
if (reds->lookahead_tokens)
if (reds->lookaheads)
for (int i = 0; i < ntokens; i++)
{
bool count = bitset_test (no_reduce_set, i);
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)
{
@@ -268,7 +268,7 @@ print_reductions (FILE *out, const state *s)
bool default_reduction_only = true;
/* Report lookahead tokens (or $default) and reductions. */
if (reds->lookahead_tokens)
if (reds->lookaheads)
for (int i = 0; i < ntokens; i++)
{
bool defaulted = false;
@@ -277,7 +277,7 @@ print_reductions (FILE *out, const state *s)
default_reduction_only = false;
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)
{
@@ -377,11 +377,11 @@ print_terminal_symbols (FILE *out)
for (int i = 0; i < max_code + 1; ++i)
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);
if (symbols[token_translations[i]]->content->type_name)
fprintf (out, " <%s>",
symbols[token_translations[i]]->content->type_name);
if (sym->content->type_name)
fprintf (out, " <%s>", sym->content->type_name);
fprintf (out, " (%d)", i);
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"));
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_right = false;
@@ -418,9 +419,9 @@ print_nonterminal_symbols (FILE *out)
int column = 4 + mbswidth (tag, 0);
fprintf (out, "%4s%s", "", tag);
if (symbols[i]->content->type_name)
if (sym->content->type_name)
column += fprintf (out, " <%s>",
symbols[i]->content->type_name);
sym->content->type_name);
fprintf (out, " (%d)\n", i);
if (on_left)
+4 -6
View File
@@ -695,12 +695,10 @@ packgram (void)
}
/*------------------------------------------------------------------.
| Read in the grammar specification and record it in the format |
| described in gram.h. All actions are copied into ACTION_OBSTACK, |
| in each case forming the body of a C function (YYACTION) which |
| contains a switch statement to decide which action to execute. |
`------------------------------------------------------------------*/
/*--------------------------------------------------------------.
| Read in the grammar specification and record it in the format |
| described in gram.h. |
`--------------------------------------------------------------*/
void
reader (const char *gram)
+1
View File
@@ -145,6 +145,7 @@ void code_props_symbol_action_init (code_props *self, char const *code,
location code_loc);
/**
* \param type type for midrule actions
* \pre
* - <tt>self != NULL</tt>.
* - <tt>code != NULL</tt>.
+32 -34
View File
@@ -144,13 +144,13 @@ init_state_items (void)
for (int j = 0; j < s->nitems; ++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);
if (rule_search_idx < red->num && red->rules[rule_search_idx] < r)
++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)
si->lookahead = lookahead[rule_search_idx];
}
@@ -163,7 +163,7 @@ init_state_items (void)
state_item_set (sidx, s, off);
if (item_number_is_rule_number (ritem[off]))
{
bitsetv lookahead = red->lookahead_tokens;
bitsetv lookahead = red->lookaheads;
if (lookahead)
state_items[sidx].lookahead = lookahead[rule_search_idx];
++rule_search_idx;
@@ -211,7 +211,7 @@ init_trans (void)
for (int j = 0; j < t->num; ++j)
if (!TRANSITION_IS_DISABLED (t, 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;
if (item_number_is_rule_number (*item))
@@ -222,16 +222,14 @@ init_trans (void)
// find the item in the destination state that corresponds
// to the transition of item
for (int k = 0; k < dst->nitems; ++k)
{
if (item + 1 == ritem + dst->items[k])
{
state_item_number dstSI =
state_item_index_lookup (dst->number, k);
if (item + 1 == ritem + dst->items[k])
{
state_item_number dstSI =
state_item_index_lookup (dst->number, k);
state_items[j].trans = dstSI;
bitset_set (state_items[dstSI].revs, j);
break;
}
state_items[j].trans = dstSI;
bitset_set (state_items[dstSI].revs, j);
break;
}
}
hash_free (transition_set);
@@ -250,10 +248,10 @@ init_prods (void)
// Add the nitems of state to skip to the production portion
// 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)
{
state_item *src = state_items + j;
state_item *src = &state_items[j];
item_number *item = src->item;
symbol_number lhs = item_rule (item)->lhs->number;
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,
// 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);
// Skip reduce items and items with terminals after the dot
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)
{
state_item *si = state_items + i;
state_item *si = &state_items[i];
if (item_number_is_symbol_number (*(si->item)) || !si->lookahead)
continue;
bitset lookahead = si->lookahead;
gl_list_t queue =
state_item_list queue =
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
(const void **) &si);
@@ -339,7 +337,7 @@ init_firsts (void)
firsts = bitsetv_create (nnterms, nsyms, BITSET_FIXED);
for (rule_number i = 0; i < nrules; ++i)
{
rule *r = rules + i;
rule *r = &rules[i];
item_number *n = r->rhs;
// Iterate through nullable nonterminals to try to find a terminal.
while (item_number_is_symbol_number (*n) && ISVAR (*n)
@@ -357,7 +355,7 @@ init_firsts (void)
change = false;
for (rule_number i = 0; i < nrules; ++i)
{
rule *r = rules + i;
rule *r = &rules[i];
symbol_number lhs = r->lhs->number;
bitset f_lhs = FIRSTS (lhs);
for (item_number *n = r->rhs;
@@ -392,7 +390,7 @@ disable_state_item (state_item *si)
static void
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,
(const void **) &si);
@@ -401,7 +399,7 @@ prune_forward (const state_item *si)
state_item *dsi = (state_item *) gl_list_get_at (queue, 0);
gl_list_remove_at (queue, 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)
{
@@ -409,7 +407,7 @@ prune_forward (const state_item *si)
state_item_number sin;
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);
if (bitset_empty_p (prod->revs))
gl_list_add_last (queue, prod);
@@ -427,7 +425,7 @@ prune_forward (const state_item *si)
static void
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,
(const void **) &si);
@@ -441,7 +439,7 @@ prune_backward (const state_item *si)
{
if (SI_DISABLED (sin))
continue;
state_item *rev = state_items + sin;
state_item *rev = &state_items[sin];
if (rev->prods)
{
bitset_reset (rev->prods, dsi - state_items);
@@ -466,7 +464,7 @@ prune_disabled_paths (void)
{
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))
{
prune_forward (si);
@@ -494,9 +492,9 @@ state_items_report (void)
for (state_number i = 0; i < nstates; ++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);
if (SI_DISABLED (j))
{
@@ -508,7 +506,7 @@ state_items_report (void)
if (si->trans >= 0)
{
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 };
@@ -523,7 +521,7 @@ state_items_report (void)
BITSET_FOR_EACH (biter, b, sin, 0)
{
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
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))
{
state_item *si = state_items + i;
state_item *si = &state_items[i];
if (si->prods)
bitset_free (si->prods);
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)
return false;
}
return true;
return true;
}
+12 -8
View File
@@ -28,16 +28,16 @@
# include "state.h"
/* 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
conflict.
state_items is an array of state state-item pairs ordered by state.
state_item_map maps state numbers to the first item which
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
state. This is then followed by productions from the closure of the
state in order by rule.
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 state.
This is then followed by productions from the closure of the state
in order by rule.
There are two type of edges in this graph transitions and
productions. Transitions are the same as transitions from the
@@ -53,9 +53,9 @@
production edges, and all others will have reverse transition
edges. */
# define SI_DISABLED(sin) (state_items[sin].trans == -2)
# define SI_PRODUCTION(si) ((si) == state_items || *((si)->item - 1) < 0)
# define SI_TRANSITION(si) ((si) != state_items && *((si)->item - 1) >= 0)
# define SI_DISABLED(Sin) (state_items[Sin].trans == -2)
# define SI_PRODUCTION(Si) ((Si) == state_items || *((Si)->item - 1) < 0)
# define SI_TRANSITION(Si) ((Si) != state_items && *((Si)->item - 1) >= 0)
typedef int state_item_number;
@@ -69,6 +69,9 @@ typedef struct
bitset lookahead;
} state_item;
// A path of state-items.
typedef gl_list_t state_item_list;
extern bitsetv firsts;
# 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);
// Iterating on a state_item_list.
static inline bool
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;
reductions *res = xmalloc (offsetof (reductions, rules) + rules_size);
res->num = num;
res->lookahead_tokens = NULL;
res->lookaheads = NULL;
memcpy (res->rules, reds, rules_size);
return res;
}
@@ -260,20 +260,20 @@ state_errs_set (state *s, int num, symbol **tokens)
`--------------------------------------------------*/
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. */
reductions *reds = s->reductions;
int red = state_reduction_find (s, r);
/* Print them if there are. */
if (reds->lookahead_tokens && red != -1)
if (reds->lookaheads && red != -1)
{
bitset_iterator biter;
int k;
char const *sep = "";
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);
sep = ", ";
@@ -283,7 +283,7 @@ state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out)
}
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)
{
/* 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);
/* Print them if there are. */
if (reds->lookahead_tokens && red != -1)
if (reds->lookaheads && red != -1)
{
bitset_iterator biter;
int k;
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_escape (symbols[k]->tag));
+5 -5
View File
@@ -62,7 +62,7 @@
Each reductions structure describes the possible reductions at the
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
states should explicitly be errors (for implementing %nonassoc).
@@ -187,7 +187,7 @@ errs *errs_new (int num, symbol **tokens);
typedef struct
{
int num;
bitset *lookahead_tokens;
bitset *lookaheads;
/* Sorted ascendingly on rule number. */
rule *rules[1];
} 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
reduce R. */
void state_rule_lookahead_tokens_print (state const *s, rule const *r, FILE *out);
void state_rule_lookahead_tokens_print_xml (state const *s, rule const *r,
FILE *out, int level);
void state_rule_lookaheads_print (state const *s, rule const *r, FILE *out);
void state_rule_lookaheads_print_xml (state const *s, rule const *r,
FILE *out, int level);
/* Create/destroy the states hash table. */
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
match ACTROW[J]. */
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]
!= rule_number_as_item_number (reds->rules[i]->number)))
{
@@ -247,7 +247,7 @@ action_row (state *s)
reductions *reds = s->reductions;
bool conflicted = false;
if (reds->lookahead_tokens)
if (reds->lookaheads)
/* loop over all the rules available here which require
lookahead (in reverse order to give precedence to the first
rule) */
@@ -257,7 +257,7 @@ action_row (state *s)
{
bitset_iterator biter;
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
token follows. */
@@ -308,7 +308,7 @@ action_row (state *s)
}
/* 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. */
{
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]],
[[0]], [[]],
[[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_PARSER_CHECK([[input]], [[1]], [[]],
@@ -737,7 +737,7 @@ AT_PARSER_CHECK([[input]], [[1]], [[]],
AT_BISON_CHECK([[-Dlr.type=canonical-lr -Dparse.lac=full \
-o input.c input.y]], [[0]], [[]],
[[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_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]],
[[0]], [[]],
[[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_PARSER_CHECK([[input]], [[1]], [[]],
@@ -773,7 +773,7 @@ exp: exp OP exp | NUM;
AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
[[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.
@@ -861,12 +861,18 @@ State 5
OP [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
Example exp OP exp . OP exp
First derivation exp ::=[ exp ::=[ exp OP exp . ] OP exp ]
Second derivation exp ::=[ exp OP exp ::=[ exp . OP exp ] ]
Example: exp OP exp . OP exp
Shift derivation
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, [],
[[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]
]])
@@ -1119,7 +1125,7 @@ m4_popdef([AT_TEST])
# else.
AT_SETUP([Defaulted Conflicted Reduction])
AT_KEYWORDS([report])
AT_KEYWORDS([cex report])
AT_DATA([input.y],
[[%%
@@ -1131,7 +1137,7 @@ id : '0';
AT_BISON_CHECK([-o input.c --report=all input.y], 0, [],
[[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]
]])
@@ -1203,12 +1209,18 @@ State 1
$end [reduce using rule 4 (id)]
$default reduce using rule 3 (num)
Reduce/reduce conflict on token $end:
reduce/reduce conflict on token $end:
3 num: '0' .
4 id: '0' .
Example '0' .
First derivation exp ::=[ num ::=[ '0' . ] ]
Second derivation exp ::=[ id ::=[ '0' . ] ]
Example: '0' .
First reduce derivation
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, [],
[[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
@@ -1297,7 +1309,7 @@ exp: exp OP exp | NUM;
AT_BISON_CHECK([-o input.c input.y], 1, [],
[[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
@@ -1317,7 +1329,7 @@ a: 'a';
AT_BISON_CHECK([-o input.c input.y], 1, [],
[[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
@@ -1518,7 +1530,7 @@ e: e '+' e
AT_BISON_CHECK([-Wall -o input.c input.y], 0, [],
[[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:2.1-5: warning: useless precedence and associativity for '*' [-Wprecedence]
]])
@@ -1579,6 +1591,8 @@ AT_CLEANUP
AT_SETUP([[Unreachable States After Conflict Resolution]])
AT_KEYWORDS([cex 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
# 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, [],
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
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: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]
@@ -1750,21 +1764,33 @@ State 4
reported_conflicts go to state 6
Shift/reduce conflict on token 'a':
shift/reduce conflict on token 'a':
10 reported_conflicts: . %empty
8 reported_conflicts: . 'a'
First example resolved_conflict . 'a'
First derivation start ::=[ resolved_conflict reported_conflicts ::=[ . ] 'a' ]
Second example resolved_conflict . 'a' 'a'
Second derivation start ::=[ resolved_conflict reported_conflicts ::=[ . 'a' ] 'a' ]
First example: resolved_conflict . 'a' 'a'
Shift derivation
start
`-> 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
9 reported_conflicts: . 'a'
First example resolved_conflict . 'a'
First derivation start ::=[ resolved_conflict reported_conflicts ::=[ . ] 'a' ]
Second example resolved_conflict . 'a' 'a'
Second derivation start ::=[ resolved_conflict reported_conflicts ::=[ . 'a' ] 'a' ]
First example: resolved_conflict . 'a' 'a'
Shift derivation
start
`-> 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)]
$default reduce using rule 8 (reported_conflicts)
Reduce/reduce conflict on token 'a':
reduce/reduce conflict on token 'a':
8 reported_conflicts: 'a' .
9 reported_conflicts: 'a' .
Example 'a' .
First derivation reported_conflicts ::=[ 'a' . ]
Second derivation reported_conflicts ::=[ 'a' . ]
Example: 'a' .
First reduce derivation
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, [],
[[input-keep.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
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: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]
@@ -1904,6 +1934,8 @@ AT_CLEANUP
AT_SETUP([[%nonassoc error actions for multiple reductions in a state]])
AT_KEYWORDS([cex report])
AT_DATA([[input.y]],
[[%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 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
13 empty_c3: . %empty
Example . 'c'
First derivation start ::=[ empty_c2 ::=[ . ] 'c' ]
Second derivation start ::=[ empty_c3 ::=[ . ] 'c' ]
Example: . 'c'
First reduce derivation
start
`-> empty_c2 'c'
`-> .
Second reduce derivation
start
`-> empty_c3 'c'
`-> .
@@ -2000,7 +2038,7 @@ exp: 'a' | 'a';
AT_BISON_CHECK([[2.y]], [[0]], [],
[[2.y: warning: %expect-rr applies only to GLR parsers [-Wother]
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]
]])
@@ -2037,15 +2075,14 @@ B: ;
AT_BISON_CHECK([[sr-rr.y]], [[0]], [[]],
[[sr-rr.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
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]], [[]],
[[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]], [[]],
[[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]])[
else
{
issue_note=false
if test -z "$sr_exp_i" && test "$sr_count" -ne 0; then
echo "warning: $sr_count shift/reduce conflicts"
issue_note=true
elif test "$sr_exp_i" -ne "$sr_count"; then
echo "error: shift/reduce conflicts: $sr_count found, $sr_exp_i expected"
if test "$sr_count" -ne 0; then
issue_note=true
fi
fi
if test -z "$rr_exp_i" && test "$rr_count" -ne 0; then
echo "warning: $rr_count reduce/reduce conflicts"
issue_note=true
elif test "$rr_exp_i" -ne "$rr_count"; then
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
} | sed -e "s/^/$file: /" > 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]])[
fi
done
+559 -183
View File
@@ -17,13 +17,23 @@
AT_BANNER([[Counterexamples.]])
# AT_BISON_CHECK_CEX(TREE, FLAT)
# ------------------------------
m4_define([AT_BISON_CHECK_CEX],
[AT_DATA([experr], [$4])
sed -e ['s/time limit exceeded: [0-9][.0-9]*/time limit exceeded: XXX/g'] \
experr >expout
AT_BISON_CHECK([-Wcounterexamples $1], [$2], [$3], [stderr])
[AT_KEYWORDS([cex])
AT_BISON_CHECK([-Wcounterexamples input.y], [0], [], [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]],
[], [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_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B C
@@ -43,13 +52,25 @@ x: B | B C;
y: A | A B;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token B:
Example A . B C
First derivation s ::=[ a ::=[ A . ] x ::=[ B C ] ]
Second derivation s ::=[ y ::=[ A . B ] c ::=[ C ] ]
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example: A . B C
Shift derivation
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]
]])
@@ -60,7 +81,6 @@ AT_CLEANUP
## ------------------- ##
AT_SETUP([Deep Unifying S/R])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B C
@@ -72,18 +92,46 @@ a: A | A a;
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]
Shift/reduce conflict on token B:
Example A . B C
First derivation s ::=[ a ::=[ A . ] bc ::=[ B C ] ]
Second derivation s ::=[ ac ::=[ A ac ::=[ b ::=[ . B ] ] C ] ]
Shift/reduce conflict on token B:
Example A A . B B C C
First derivation s ::=[ a ::=[ A a ::=[ A . ] ] bc ::=[ B bc ::=[ B C ] C ] ]
Second derivation s ::=[ ac ::=[ A ac ::=[ A ac ::=[ b ::=[ . b ::=[ B B ] ] ] C ] C ] ]
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example: A . B C
Shift derivation
s
`-> ac
`-> A ac C
`-> b
`-> . B
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]
]])
@@ -94,7 +142,6 @@ AT_CLEANUP
## ------------------------------------ ##
AT_SETUP([S/R Conflict with Nullable Symbols])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B X Y
@@ -107,19 +154,47 @@ y: %empty | Y 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]
Shift/reduce conflict on token B:
Example A . B
First derivation s ::=[ ax ::=[ A x ::=[ . ] ] by ::=[ B y ::=[ ] ] ]
Second derivation s ::=[ A xby ::=[ . B ] ]
Shift/reduce conflict on token B:
First example A X . B y $end
First derivation $accept ::=[ s ::=[ ax ::=[ A x ::=[ X x ::=[ . ] ] ] by ::=[ B y ] ] $end ]
Second example A X . B Y $end
Second derivation $accept ::=[ s ::=[ A xby ::=[ X xby ::=[ . B ] Y ] ] $end ]
input.y: warning: shift/reduce conflict on token B [-Wcounterexamples]
Example: A . B
Shift derivation
s
`-> A xby
`-> . B
Reduce derivation
s
`-> ax by
`-> 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]
]])
@@ -130,7 +205,6 @@ AT_CLEANUP
## ---------------------------- ##
AT_SETUP([Non-unifying Ambiguous S/R])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B C D E
@@ -143,14 +217,31 @@ cd: C D;
bc: B C;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token C:
First example B . C D $end
First derivation $accept ::=[ g ::=[ x ::=[ b ::=[ B . ] cd ::=[ C D ] ] ] $end ]
Second example B . C $end
Second derivation $accept ::=[ g ::=[ x ::=[ bc ::=[ B . C ] ] ] $end ]
input.y: warning: shift/reduce conflict on token C [-Wcounterexamples]
First example: B . C $end
Shift derivation
$accept
`-> 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]
]])
@@ -161,7 +252,6 @@ AT_CLEANUP
## ------------------------------ ##
AT_SETUP([Non-unifying Unambiguous S/R])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B
@@ -172,14 +262,31 @@ x: A;
y: A A B;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token A:
First example A . A $end
First derivation $accept ::=[ s ::=[ s ::=[ t ::=[ x ::=[ A . ] ] ] t ::=[ x ::=[ A ] ] ] $end ]
Second example A . A B $end
Second derivation $accept ::=[ s ::=[ t ::=[ y ::=[ A . A B ] ] ] $end ]
input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
First example: A . A B $end
Shift derivation
$accept
`-> 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
@@ -189,7 +296,6 @@ AT_CLEANUP
## ----------------------- ##
AT_SETUP([S/R after first token])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B X Y
@@ -205,19 +311,45 @@ xy: X Y;
y: Y;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[input.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
Shift/reduce conflict on token A:
Example b . A X X Y
First derivation a ::=[ r ::=[ b . ] t ::=[ A x ::=[ X ] xy ::=[ X Y ] ] ]
Second derivation a ::=[ s ::=[ b . xx ::=[ A X X ] y ::=[ Y ] ] ]
Shift/reduce conflict on token X:
First example X . X xy
First derivation a ::=[ x ::=[ X . ] t ::=[ X xy ] ]
Second example A X . X
Second derivation a ::=[ t ::=[ A xx ::=[ X . X ] ] ]
input.y: warning: shift/reduce conflict on token A [-Wcounterexamples]
Example: b . A X X Y
Shift derivation
a
`-> s
`-> b . xx y
`-> A X X `-> Y
Reduce derivation
a
`-> 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:8.4: warning: rule useless in parser due to conflicts [-Wother]
]])
@@ -229,7 +361,6 @@ AT_CLEANUP
## ----------------------------- ##
AT_SETUP([Unifying R/R counterexample])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A
@@ -238,13 +369,24 @@ a : A b ;
b : A | b;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[input.y: 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 . ] ]
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: 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]
]])
@@ -255,7 +397,6 @@ AT_CLEANUP
## --------------------------------- ##
AT_SETUP([Non-unifying R/R LR(1) conflict])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B C D
@@ -265,14 +406,29 @@ a: D;
b: D;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[input.y: warning: 2 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on tokens A, C:
First example D . A $end
First derivation $accept ::=[ s ::=[ a ::=[ D . ] A ] $end ]
Second example B D . A $end
Second derivation $accept ::=[ s ::=[ B b ::=[ D . ] A ] $end ]
input.y: warning: reduce/reduce conflict on tokens A, C [-Wcounterexamples]
First example: D . A $end
First reduce derivation
$accept
`-> 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]
]])
@@ -283,7 +439,6 @@ AT_CLEANUP
## --------------------------------- ##
AT_SETUP([Non-unifying R/R LR(2) conflict])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token H J K X
@@ -293,15 +448,31 @@ a: H i;
i: X | i J K;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[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
First example H i . J $end
First derivation $accept ::=[ s ::=[ a ::=[ H i . ] J ] $end ]
Second example H i . J K $end
Second derivation $accept ::=[ a ::=[ H i ::=[ i . J K ] ] $end ]
First example: H i . J K $end
Shift derivation
$accept
`-> 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]
]])
@@ -315,7 +486,6 @@ AT_CLEANUP
# graph search
AT_SETUP([Cex Search Prepend])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token N A B C D
@@ -326,18 +496,45 @@ a: A;
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]
Shift/reduce conflict on token B:
Example N A . B C
First derivation s ::=[ n ::=[ N a ::=[ A . ] B ] C ]
Second derivation s ::=[ n ::=[ N b ::=[ A . B C ] ] ]
Shift/reduce conflict on token B:
Example N N A . B D C
First derivation s ::=[ n ::=[ N n ::=[ N a ::=[ A . ] B ] D ] C ]
Second derivation s ::=[ n ::=[ N n ::=[ N b ::=[ A . B D ] ] C ] ]
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 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]
]])
@@ -351,7 +548,6 @@ AT_CLEANUP
# precedence/associativity directives work.
AT_SETUP([R/R cex with prec])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%left b
@@ -363,18 +559,46 @@ B : A b A;
C : A c A;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[input.y: warning: 4 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on tokens b, c:
Example B . b c
First derivation S ::=[ B ::=[ A ::=[ B . ] b A ::=[ ] ] C ::=[ A ::=[ ] c A ::=[ ] ] ]
Second derivation S ::=[ B C ::=[ A ::=[ B ::=[ A ::=[ . ] b A ::=[ ] ] ] c A ::=[ ] ] ]
Reduce/reduce conflict on tokens b, c:
Example C . c b
First derivation S ::=[ C ::=[ A ::=[ C . ] c A ::=[ ] ] B ::=[ A ::=[ ] b A ::=[ ] ] ]
Second derivation S ::=[ C B ::=[ A ::=[ C ::=[ A ::=[ . ] c A ::=[ ] ] ] b A ::=[ ] ] ]
input.y: warning: reduce/reduce conflict on tokens b, c [-Wcounterexamples]
Example: B . b c
First reduce derivation
S
`-> B C
`-> A b A `-> A c A
`-> B . `-> %empty `-> %empty `-> %empty
Second reduce derivation
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
@@ -384,7 +608,6 @@ AT_CLEANUP
## ------------------- ##
AT_SETUP([Null nonterminals])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A
@@ -395,58 +618,172 @@ c : ;
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: 6 reduce/reduce conflicts [-Wconflicts-rr]
Reduce/reduce conflict on token A:
First example . c A A $end
First derivation $accept ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] $end ]
Second example . c A A $end
Second derivation $accept ::=[ a ::=[ c ::=[ . ] d ::=[ c A A ] ] $end ]
Reduce/reduce conflict on token A:
input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
First example: . c A A $end
First reduce derivation
$accept
`-> a $end
`-> b d
`-> . `-> 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
First example b . c A A $end
First derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] ] ] $end ]
Second example b . A $end
Second derivation $accept ::=[ a ::=[ b d ::=[ c ::=[ . ] A ] ] $end ]
Reduce/reduce conflict on token A:
First example: b . c A A $end
First reduce derivation
$accept
`-> a $end
`-> b d
`-> 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
First example c . c A A $end
First derivation $accept ::=[ a ::=[ c d ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] ] ] $end ]
Second example c . A $end
Second derivation $accept ::=[ a ::=[ c d ::=[ c ::=[ . ] A ] ] $end ]
Shift/reduce conflict on token A:
First example: c . c A A $end
First reduce derivation
$accept
`-> a $end
`-> c d
`-> 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
First example b c . c A A $end
First derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ c d ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] ] ] ] ] $end ]
Second example b c . A
Second derivation a ::=[ b d ::=[ c . A ] ]
Reduce/reduce conflict on token A:
First example b c . c A A $end
First derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ c d ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] ] ] ] ] $end ]
Second example b c . A $end
Second derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ c d ::=[ c ::=[ . ] A ] ] ] ] $end ]
Shift/reduce conflict on token A:
First example b c . A $end
First derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ c d ::=[ c ::=[ . ] A ] ] ] ] $end ]
Second example b c . A
Second derivation a ::=[ b d ::=[ c . A ] ]
Reduce/reduce conflict on token $end:
Example b d .
First derivation a ::=[ b d . ]
Second derivation a ::=[ b d ::=[ d . ] ]
Reduce/reduce conflict on token $end:
Example c d .
First derivation a ::=[ c d . ]
Second derivation a ::=[ c d ::=[ d . ] ]
First example: b c . A
Shift derivation
a
`-> b d
`-> c . A
Second example: b c . c A A $end
Reduce derivation
$accept
`-> a $end
`-> b d
`-> a
`-> c d
`-> a
`-> b d
`-> . `-> c A A
input.y: warning: reduce/reduce conflict on token A [-Wcounterexamples]
First example: b c . c A A $end
First reduce derivation
$accept
`-> a $end
`-> b d
`-> a
`-> c d
`-> a
`-> b 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:6.15: warning: rule useless in parser due to conflicts [-Wother]
]])
@@ -458,7 +795,6 @@ AT_CLEANUP
## --------------------------- ##
AT_SETUP([Non-unifying Prefix Share])
AT_KEYWORDS([cex])
# Tests for a counterexample which should start its derivation
# at a shared symbol rather than the start symbol.
@@ -471,13 +807,26 @@ a: H i J J
i: %empty | i J;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token J:
Example H i J . J J
First derivation s ::=[ a ::=[ H i ::=[ i J . ] J J ] ]
Second derivation s ::=[ a ::=[ H i J . J ] J ]
input.y: warning: shift/reduce conflict on token J [-Wcounterexamples]
Example: H i J . J J
Shift derivation
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]
]])
@@ -491,7 +840,6 @@ AT_CLEANUP
# are derived correctly.
AT_SETUP([Deep Null Unifying])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A D
@@ -503,13 +851,26 @@ c: %empty
d: D;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token D:
Example A a . D
First derivation s ::=[ A a a ::=[ b ::=[ c ::=[ . ] ] ] d ::=[ D ] ]
Second derivation s ::=[ A a d ::=[ . D ] ]
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 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
@@ -521,7 +882,6 @@ AT_CLEANUP
# Tests that expand_to_conflict works with nullable sybols
AT_SETUP([Deep Null Non-unifying])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A D E
@@ -533,14 +893,30 @@ c: %empty
d: D;
]])
AT_BISON_CHECK_CEX([input.y], [], [],
AT_BISON_CHECK_CEX(
[[input.y: warning: 1 shift/reduce conflict [-Wconflicts-sr]
Shift/reduce conflict on token D:
First example A a . D E $end
First derivation $accept ::=[ s ::=[ A a a ::=[ b ::=[ c ::=[ . ] ] ] d ::=[ D ] E ] $end ]
Second example A a . D $end
Second derivation $accept ::=[ s ::=[ A a d ::=[ . D ] ] $end ]
input.y: warning: shift/reduce conflict on token D [-Wcounterexamples]
First example: A a . D $end
Shift derivation
$accept
`-> 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
+105 -26
View File
@@ -28,6 +28,8 @@ m4_pushdef([AT_TEST],
AT_SETUP([$1])
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
# characters. Skip the test if not available.
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])
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.
# 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
# environment.
# 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
@@ -533,34 +535,111 @@ exp
]],
[1],
[[input.y: <error>error:</error> shift/reduce conflicts: 4 found, 0 expected
Shift/reduce conflict on token "+":
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>
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>
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>
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>
Shift/reduce conflict on token "else":
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>
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>
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>
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>
Shift/reduce conflict on token "+":
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>
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>
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>
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>
Shift/reduce conflict on token "+":
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>
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>
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>
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>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>
Shift derivation
<cex-0><cex-step>exp</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>
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>
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>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>]
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>
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>"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>
Reduce 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-leaf> "else"</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-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])
+2 -2
View File
@@ -434,7 +434,7 @@ input.y:323.10: warning: empty rule without %empty [-Wempty-rule]
]AT_COND_CASE([[canonical LR]],
[[input.y: warning: 265 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:44.1-5: warning: useless associativity for YNUMBER, 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: 78 shift/reduce conflicts [-Wconflicts-sr]
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:53.1-6: warning: useless associativity for HASSIGN, 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, [],
[[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_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, [],
[[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])
@@ -350,7 +350,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -447,7 +447,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -505,7 +505,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -555,7 +555,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -646,7 +646,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -737,7 +737,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -819,7 +819,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -877,7 +877,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -937,7 +937,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -1060,7 +1060,7 @@ AT_BISON_OPTION_POPDEFS
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 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])
@@ -1392,7 +1392,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -1487,7 +1487,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -1549,7 +1549,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -1625,7 +1625,7 @@ AT_BISON_OPTION_POPDEFS
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: 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])
@@ -1719,7 +1719,7 @@ d: /* nada. */;
AT_BISON_CHECK([[-o input.c input.y]], 0, [],
[[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])
-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:13.16-29: note: previous definition
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]
]])
+8 -3
View File
@@ -1169,11 +1169,16 @@ m4_define([AT_BISON_CHECK_XML],
[cp xml-tests/test.output expout]
AT_CHECK([[$XSLTPROC \
`]]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]
AT_CHECK([[$XSLTPROC \
`]]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]
AT_RESTORE_SPECIAL_FILES
[fi]])
@@ -1194,7 +1199,7 @@ m4_define([AT_BISON_CHECK_XML],
# The testsuite verbose output, at least, will be incorrect, but nothing may
# fail to make sure you notice.
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
+8
View File
@@ -36,6 +36,14 @@ $(top_srcdir)/%D%/package.m4: $(top_srcdir)/configure
} >$@.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. ##
## ------------------------- ##
+1 -1
View File
@@ -1300,7 +1300,7 @@ dnl INPUT
dnl BISON-STDERR
[AT_COND_CASE([[LALR]],
[[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
+746 -79
View File
@@ -764,24 +764,24 @@ AT_CHECK([[sed -e 's/bison-xml-report version="[^"]*"/bison-xml-report version="
</rule>
</rules>
<terminals>
<terminal symbol-number="0" token-number="0" name="&quot;end of file&quot;" usefulness="useful"/>
<terminal symbol-number="1" token-number="256" name="error" usefulness="useful"/>
<terminal symbol-number="3" token-number="258" name="&quot;:=&quot;" usefulness="useful"/>
<terminal symbol-number="4" token-number="259" name="&quot;incr&quot;" usefulness="useful"/>
<terminal symbol-number="5" token-number="260" name="&quot;identifier&quot;" usefulness="useful"/>
<terminal symbol-number="6" token-number="261" name="&quot;number&quot;" usefulness="useful"/>
<terminal symbol-number="7" token-number="262" name="&quot;(&quot;" usefulness="useful"/>
<terminal symbol-number="8" token-number="263" name="&quot;)&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" type="" 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;" type="" 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;" type="int" 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;" type="" usefulness="useful"/>
</terminals>
<nonterminals>
<nonterminal symbol-number="9" name="$accept" usefulness="useful"/>
<nonterminal symbol-number="10" name="unit" usefulness="useful"/>
<nonterminal symbol-number="11" name="assignments" usefulness="useful"/>
<nonterminal symbol-number="12" name="assignment" usefulness="useful"/>
<nonterminal symbol-number="13" name="id" usefulness="useful"/>
<nonterminal symbol-number="14" name="exp" usefulness="useful"/>
<nonterminal symbol-number="15" name="@1" usefulness="useful"/>
<nonterminal symbol-number="16" name="@2" usefulness="useful"/>
<nonterminal symbol-number="9" name="$accept" type="" usefulness="useful"/>
<nonterminal symbol-number="10" name="unit" type="" usefulness="useful"/>
<nonterminal symbol-number="11" name="assignments" type="" usefulness="useful"/>
<nonterminal symbol-number="12" name="assignment" type="" usefulness="useful"/>
<nonterminal symbol-number="13" name="id" type="std::string" usefulness="useful"/>
<nonterminal symbol-number="14" name="exp" type="int" usefulness="useful"/>
<nonterminal symbol-number="15" name="@1" type="int" usefulness="useful"/>
<nonterminal symbol-number="16" name="@2" type="int" usefulness="useful"/>
</nonterminals>
</grammar>
@@ -1137,6 +1137,373 @@ AT_CHECK([[sed -e 's/bison-xml-report version="[^"]*"/bison-xml-report version="
</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_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], [], [],
[[input.y: warning: 3 shift/reduce conflicts [-Wconflicts-sr]
input.y: warning: 3 reduce/reduce conflicts [-Wconflicts-rr]
Shift/reduce conflict on token "⊕":
Example exp "+" exp • "⊕" exp
First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ]
Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ]
Reduce/reduce conflict on tokens $end, "+", "⊕":
Example exp "+" exp •
First derivation exp ::=[ exp "+" exp • ]
Second derivation exp ::=[ exp "+" exp • ]
Shift/reduce conflict on token "⊕":
Example exp "+" exp • "⊕" exp
First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ]
Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ]
Shift/reduce conflict on token "⊕":
Example exp "⊕" exp • "⊕" exp
First derivation exp ::=[ exp ::=[ exp "" exp • ] "⊕" exp ]
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "⊕" exp ] ]
Shift/reduce conflict on token "+":
Example exp "⊕" exp • "+" exp
First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "+" exp ]
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "+" exp ] ]
Shift/reduce conflict on token "+":
Example exp "⊕" exp • "+" exp
First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "+" exp ]
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: reduce/reduce conflict on tokens $end, "+", "⊕" [-Wcounterexamples]
Example: exp "+" exp •
First reduce derivation
exp
↳ exp "+" exp •
Second reduce derivation
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: 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]
]])
# 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
3 exp: exp "+" exp
@@ -1343,26 +1739,42 @@ State 7
Conflict between rule 2 and token "+" resolved as reduce (%left "+").
Shift/reduce conflict on token "⊕":
shift/reduce conflict on token "⊕":
2 exp: exp "+" exp •
1 exp: exp • "⊕" exp
Example exp "+" exp • "⊕" exp
First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ]
Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ]
Example: exp "+" exp • "⊕" exp
Shift derivation
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 •
3 exp: exp "+" exp •
Example exp "+" exp •
First derivation exp ::=[ exp "+" exp • ]
Second derivation exp ::=[ exp "+" exp • ]
Example: exp "+" exp •
First reduce derivation
exp
↳ exp "+" exp •
Second reduce derivation
exp
↳ exp "+" exp •
Shift/reduce conflict on token "⊕":
shift/reduce conflict on token "⊕":
3 exp: exp "+" exp •
1 exp: exp • "⊕" exp
Example exp "+" exp • "⊕" exp
First derivation exp ::=[ exp ::=[ exp "+" exp • ] "⊕" exp ]
Second derivation exp ::=[ exp "+" exp ::=[ exp • "⊕" exp ] ]
Example: exp "+" exp • "⊕" exp
Shift derivation
exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "+" exp •
@@ -1380,26 +1792,44 @@ State 8
"⊕" [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
Example exp "⊕" exp • "⊕" exp
First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "⊕" exp ]
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "⊕" exp ] ]
Example: exp "⊕" exp • "⊕" exp
Shift derivation
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 •
2 exp: exp • "+" exp
Example exp "⊕" exp • "+" exp
First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "+" exp ]
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "+" exp ] ]
Example: exp "⊕" exp • "+" exp
Shift derivation
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 •
3 exp: exp • "+" exp
Example exp "⊕" exp • "+" exp
First derivation exp ::=[ exp ::=[ exp "⊕" exp • ] "+" exp ]
Second derivation exp ::=[ exp "⊕" exp ::=[ exp • "+" exp ] ]
Example: exp "⊕" exp • "+" exp
Shift derivation
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>
</rules>
<terminals>
<terminal symbol-number="0" token-number="0" name="$end" usefulness="useful"/>
<terminal symbol-number="1" token-number="256" name="error" usefulness="useful"/>
<terminal symbol-number="3" token-number="258" name="&quot;+&quot;" usefulness="useful" prec="1" assoc="left"/>
<terminal symbol-number="4" token-number="259" name="&quot;⊕&quot;" usefulness="useful"/>
<terminal symbol-number="5" token-number="260" name="&quot;number&quot;" usefulness="useful"/>
<terminal symbol-number="6" token-number="261" name="&quot;Ñùṃéℝô&quot;" usefulness="useful"/>
<terminal symbol-number="0" token-number="0" name="$end" type="" usefulness="useful"/>
<terminal symbol-number="1" token-number="256" name="error" type="" usefulness="useful"/>
<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;" type="" 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;" type="" usefulness="useful"/>
</terminals>
<nonterminals>
<nonterminal symbol-number="7" name="$accept" usefulness="useful"/>
<nonterminal symbol-number="8" name="exp" usefulness="useful"/>
<nonterminal symbol-number="7" name="$accept" type="" usefulness="useful"/>
<nonterminal symbol-number="8" name="exp" type="" usefulness="useful"/>
</nonterminals>
</grammar>
@@ -1725,6 +2155,243 @@ AT_CHECK([[sed -e 's/bison-xml-report version="[^"]*"/bison-xml-report version="
</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_CLEANUP
+1 -1
View File
@@ -285,7 +285,7 @@ term: 'n'
AT_BISON_CHECK([[-fcaret input.y]], [], [],
[[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]
2 | expr: term | term | term | term | term | term
| ^~~~
+4 -4
View File
@@ -283,11 +283,11 @@ m4_popdef([AT_TEST])
## 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
# requiring SIZE lookahead tokens.
m4_define([AT_DATA_LOOKAHEAD_TOKENS_GRAMMAR],
m4_define([AT_DATA_LOOKAHEADS_GRAMMAR],
[AT_BISON_OPTION_PUSHDEFS
AT_DATA([[gengram.pl]],
[[#! /usr/bin/perl -w
@@ -384,7 +384,7 @@ AT_BISON_OPTION_POPDEFS
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.
# Ask for 200 MiB, which should be plenty even on a 64-bit host.