Compare commits

..
39 Commits
Author SHA1 Message Date
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
52 changed files with 2457 additions and 695 deletions
+1 -1
View File
@@ -1 +1 @@
3.6.90
3.6.91
+41 -8
View File
@@ -1,5 +1,21 @@
GNU Bison NEWS
* Noteworthy changes in release 3.6.92 (2020-07-19) [beta]
Changes in the display of counterexamples.
** 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
| ^~~
* Noteworthy changes in release 3.6.91 (2020-07-09) [beta]
** Bug fixes
@@ -30,9 +46,17 @@ GNU Bison NEWS
strings in the grammar which can be parsed in two ways due to the
conflict. For example:
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
Shift derivation
exp
↳ exp "+" exp
↳ exp • "/" exp
Example exp "+" exp • "/" exp
Reduce derivation
exp
↳ exp "/" exp
↳ exp "+" exp •
When Bison is installed with text styling enabled, the example is actually
shown twice, with colors highlighting the ambiguity.
@@ -42,15 +66,24 @@ GNU Bison NEWS
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:
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 ]
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 •
In these cases, the parser usually doesn't have enough lookahead to
differentiate the two given examples.
The counterexamples are "focused": in two different ways. First, they do
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.
+1 -1
View File
@@ -444,7 +444,7 @@ added the `[-Wother]` part to all the warnings). Part of the update can be
done with a crude tool: `build-aux/update-test`.
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
+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; }
+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"/>
+35 -67
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
@@ -9936,10 +9904,10 @@ output is actually in color)}:
@example
Shift/reduce conflict on token "else":
@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{]}
Shift derivation @yellow{if_stmt @arrow{} [ "if" expr "then"} @green{stmt @arrow{} [} @blue{if_stmt @arrow{} [ "if" expr "then" stmt} @red{•} @blue{"else" stmt ]} @green{]} @yellow{]}
Example @yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
Reduce derivation @yellow{if_stmt @arrow{} [ "if" expr "then"} @green{stmt @arrow{} [} @blue{if_stmt @arrow{} [ "if" expr "then" stmt} @red{•} @blue{]} @green{]} @yellow{"else" stmt ]}
@end group
@end example
@end ifhtml
@@ -9947,14 +9915,14 @@ Shift/reduce conflict on token "else":
@smallexample
Shift/reduce conflict on token "else":
@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{]}
Shift derivation
@yellow{if_stmt @arrow{} [ "if" expr "then"} @green{stmt @arrow{} [} @blue{if_stmt @arrow{} [ "if" expr "then" stmt} @red{•} @blue{"else" stmt ]} @green{]} @yellow{]}
Example
@yellow{"if" expr "then"} @blue{"if" expr "then" stmt} @red{•} @yellow{"else" stmt}
Reduce derivation
@yellow{if_stmt @arrow{} [ "if" expr "then"} @green{stmt @arrow{} [} @blue{if_stmt @arrow{} [ "if" expr "then" stmt} @red{•} @blue{]} @green{]} @yellow{"else" stmt ]}
@end group
@end smallexample
@end ifnothtml
@@ -9987,22 +9955,22 @@ $ @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{]}
Shift derivation @yellow{sequence @arrow{} [} @green{maybeword @arrow{} [} @red{•} @green{"word" ]} @yellow{]}
Example @red{•} @yellow{"word"}
Reduce derivation @yellow{sequence @arrow{} [} @green{sequence @arrow{} [} @red{•} @green{]} @yellow{"word" ]}
Reduce/reduce conflict on tokens $end, "word":
Example @red{•}
First derivation @yellow{sequence ::=[} @red{•} @yellow{]}
First derivation @yellow{sequence @arrow{} [} @red{•} @yellow{]}
Example @red{•}
Second derivation @yellow{sequence ::=[} @green{maybeword ::=[} @red{•} @green{]} @yellow{]}
Second derivation @yellow{sequence @arrow{} [} @green{maybeword @arrow{} [} @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{]}
Shift derivation @yellow{sequence @arrow{} [} @green{maybeword @arrow{} [} @red{•} @green{"word" ]} @yellow{]}
Example @red{•} @yellow{"word"}
Reduce derivation @yellow{sequence @arrow{} [} @green{sequence @arrow{} [} @blue{maybeword @arrow{} [} @red{•} @blue{]} @green{]} @yellow{"word" ]}
sequence.y:8.3-45: @dwarning{warning}: rule useless in parser due to conflicts [@dwarning{-Wother}]
8 | @dwarning{%empty @{ printf ("empty maybeword\n"); @}}
@@ -10033,10 +10001,10 @@ expr: %empty | expr ID ','
@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 ]}
First example @purple{expr} @red{•} @purple{ID ','} @green{ID} @yellow{$end}
Shift derivation @yellow{$accept @arrow{} [} @green{s @arrow{} [} @blue{a @arrow{} [} @purple{expr @arrow{} [ expr} @red{•} @purple{ID ',' ]} @blue{]} @green{ID ]} @yellow{$end ]}
Second example @blue{expr} @red{•} @green{ID} @yellow{$end}
Reduce derivation @yellow{$accept @arrow{} [} @green{s @arrow{} [} @blue{a @arrow{} [ expr} @red{•} @blue{]} @green{ID ]} @yellow{$end ]}
@end smallexample
This conflict is caused by the parser not having enough information to know
@@ -10432,10 +10400,10 @@ counterexamples within the report, augmented with the corresponding items
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{]}
Shift derivation @yellow{exp @arrow{} [ exp '+'} @green{exp @arrow{} [ exp} @red{•} @green{'/' exp ]} @yellow{]}
Example @green{exp '+' exp} @red{•} @yellow{'/' exp}
Reduce derivation @yellow{exp @arrow{} [} @green{exp @arrow{} [ exp '+' exp} @red{•} @green{]} @yellow{'/' exp ]}
@end example
This shows two separate derivations in the grammar for the same @code{exp}:
@@ -14824,13 +14792,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?
+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: | ^
'
+51 -15
View File
@@ -65,6 +65,15 @@
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.
@@ -74,9 +83,13 @@
# 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.
@@ -116,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
@@ -171,7 +187,7 @@ exp:
{
if ($r == 0)
{
yyerror (&@$, "error: division by zero");
yyerror (&@$, uctx, "error: division by zero");
YYERROR;
}
else
@@ -257,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;
@@ -328,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;
}
}
@@ -366,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);
@@ -378,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.
@@ -407,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;
@@ -449,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++;
@@ -468,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;
+1 -1
Submodule gnulib updated: 12c89745e3...cf6d5db127
+1
View File
@@ -313,6 +313,7 @@
/stdlib.h
/stdlib.in.h
/stpcpy.c
/stpncpy.c
/strchrnul.c
/strchrnul.valgrind
/strdup.c
+1
View File
@@ -175,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);
+17 -17
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);
+102 -82
View File
@@ -76,17 +76,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;
@@ -101,13 +113,14 @@ free_counterexample (counterexample *cex)
}
static void
print_counterexample (counterexample *cex, FILE *out, const char *prefix)
print_counterexample (const counterexample *cex, FILE *out, const char *prefix)
{
const bool flat = getenv ("YYFLAT");
fprintf (out, " %s%-20s ",
prefix, cex->unifying ? _("Example") : _("First example"));
derivation_print_leaves (cex->d1, out, prefix);
fprintf (out, " %s%-20s ",
prefix, _("First derivation"));
fprintf (out, flat ? " %s%-20s " : " %s%s",
prefix, cex->shift_reduce ? _("Shift derivation") : _("First derivation"));
derivation_print (cex->d1, out, prefix);
// If we output to the terminal (via stderr) and we have color
@@ -119,8 +132,8 @@ print_counterexample (counterexample *cex, FILE *out, const char *prefix)
prefix, cex->unifying ? _("Example") : _("Second example"));
derivation_print_leaves (cex->d2, out, prefix);
}
fprintf (out, " %s%-20s ",
prefix, _("Second derivation"));
fprintf (out, flat ? " %s%-20s " : " %s%s",
prefix, cex->shift_reduce ? _("Reduce derivation") : _("Second derivation"));
derivation_print (cex->d2, out, prefix);
fputc ('\n', out);
@@ -144,7 +157,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 +188,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 +203,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 +254,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 +290,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 +411,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 +441,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 +454,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 +463,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 +481,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 +509,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 +541,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 +553,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 +565,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 +599,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 +632,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 +655,7 @@ complete_diverging_examples (search_state *ss,
*/
typedef struct
{
gl_list_t states;
search_state_list states;
int complexity;
} search_state_bundle;
@@ -664,6 +684,8 @@ 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)
{
@@ -679,7 +701,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 +724,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 +778,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 +919,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 +1010,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 +1033,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 +1043,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 +1077,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 +1116,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 +1126,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 +1164,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 +1212,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,6 +1241,8 @@ 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,
@@ -1226,7 +1250,8 @@ counterexample_report_shift_reduce (state_item_number itm1, state_item_number it
{
fputs (prefix, out);
fprintf (out, _("Shift/reduce conflict on token %s:\n"), symbols[next_sym]->tag);
if (*prefix)
// In the report, print the items.
if (*prefix || trace_flag & trace_cex)
{
print_state_item (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix);
@@ -1254,7 +1279,8 @@ counterexample_report_reduce_reduce (state_item_number itm1, state_item_number i
}
fputs (_(":\n"), out);
}
if (*prefix)
// In the report, print the items.
if (*prefix || trace_flag & trace_cex)
{
print_state_item (&state_items[itm1], out, prefix);
print_state_item (&state_items[itm2], out, prefix);
@@ -1265,7 +1291,7 @@ counterexample_report_reduce_reduce (state_item_number itm1, state_item_number i
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 +1303,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 */
+265 -32
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,243 @@ 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, preceeded 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 +379,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 +390,57 @@ 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;
}
void
derivation_print (const derivation *deriv, FILE *out, const char *prefix)
static void
derivation_print_flat (const derivation *deriv, FILE *out, const char *prefix)
{
int counter = 0;
fputs (prefix, out);
derivation_print_impl (deriv, out, false, &counter, "");
derivation_print_flat_impl ((derivation *)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, "");
derivation_print_flat_impl ((derivation *)deriv, out, true, &counter, "");
fputc ('\n', out);
}
void
derivation_print (const derivation *deriv, FILE *out, const char *prefix)
{
if (getenv ("YYFLAT"))
derivation_print_flat (deriv, out, prefix);
else
derivation_print_tree (deriv, out, prefix);
}
+3
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_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
+103
View File
@@ -0,0 +1,103 @@
/* 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>
// In gnulib/lib/unicodeio.h unicode_to_mb uses a buffer of 25 bytes.
typedef char glyph_buffer_t[26];
static glyph_buffer_t arrow_buf;
const char *arrow;
int arrow_width;
static glyph_buffer_t down_arrow_buf;
const char *down_arrow;
int down_arrow_width;
static glyph_buffer_t dot_buf;
const char *dot;
int dot_width;
static glyph_buffer_t empty_buf;
const char *empty;
int empty_width;
const char *derivation_separator = " ";
int derivation_separator_width = 1;
typedef struct
{
const char **glyph;
char *buf;
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->buf);
*stpncpy (arg->buf, 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->buf);
strcpy (arg->buf, arg->fallback);
return 0;
}
static bool
glyph_set (const char **glyph,
char buf[26], int *width,
unsigned code, const char *fallback)
{
callback_arg_t arg = { glyph, buf, fallback };
int res = unicode_to_mb (code, on_success, on_failure, &arg);
*glyph = buf;
*width = mbswidth (*glyph, 0);
return res;
}
void
glyphs_init (void)
{
glyph_set (&arrow, arrow_buf, &arrow_width, 0x2192, "->");
glyph_set (&dot, dot_buf, &dot_width, 0x2022, ".");
glyph_set (&down_arrow, down_arrow_buf, &down_arrow_width, 0x21b3, "`->");
glyph_set (&empty, empty_buf, &empty_width, 0x03b5, "%empty");
strncat (down_arrow_buf, " ", sizeof down_arrow_buf - strlen (down_arrow_buf) - 1);
down_arrow_width += 1;
}
+46
View File
@@ -0,0 +1,46 @@
/* 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);
/* "→", separates the lhs of a rule from its rhs. */
extern const char *arrow;
extern int arrow_width;
/* "•", a point in an item (aka, a dotted rule). */
extern const char *dot;
extern int dot_width;
/* "↳ ", below an lhs to announce the rhs. */
extern const char *down_arrow;
extern int down_arrow_width;
/* "ε", an empty rhs. */
extern const char *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 ();
+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)
+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 =
+55 -17
View File
@@ -865,8 +865,14 @@ State 5
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 ] ]
Shift derivation
exp
`-> exp OP exp
`-> exp . OP exp
Reduce derivation
exp
`-> exp OP exp
`-> exp OP exp .
]])
@@ -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],
[[%%
@@ -1207,8 +1213,14 @@ State 1
3 num: '0' .
4 id: '0' .
Example '0' .
First derivation exp ::=[ num ::=[ '0' . ] ]
Second derivation exp ::=[ id ::=[ '0' . ] ]
First derivation
exp
`-> num
`-> '0' .
Second derivation
exp
`-> id
`-> '0' .
@@ -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
@@ -1753,18 +1767,30 @@ State 4
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':
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'
`-> .
@@ -1781,8 +1807,12 @@ State 5
8 reported_conflicts: 'a' .
9 reported_conflicts: 'a' .
Example 'a' .
First derivation reported_conflicts ::=[ 'a' . ]
Second derivation reported_conflicts ::=[ 'a' . ]
First derivation
reported_conflicts
`-> 'a' .
Second derivation
reported_conflicts
`-> 'a' .
@@ -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'
%%
@@ -1965,8 +1997,14 @@ AT_CHECK([[cat input.output | sed -n '/^State 0$/,/^State 1$/p']], 0,
12 empty_c2: . %empty
13 empty_c3: . %empty
Example . 'c'
First derivation start ::=[ empty_c2 ::=[ . ] 'c' ]
Second derivation start ::=[ empty_c3 ::=[ . ] 'c' ]
First derivation
start
`-> empty_c2 'c'
`-> .
Second derivation
start
`-> empty_c3 'c'
`-> .
+535 -105
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,12 +52,26 @@ 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 ] ]
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]
Shift/reduce conflict on token B:
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 +83,6 @@ AT_CLEANUP
## ------------------- ##
AT_SETUP([Deep Unifying S/R])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B C
@@ -72,17 +94,49 @@ 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 derivation
s
`-> ac
`-> A ac C
`-> b
`-> . B
Reduce derivation
s
`-> a bc
`-> A . `-> 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 ] ]
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]
Shift/reduce conflict on token B:
Example A . B C
Shift derivation s -> [ ac -> [ A ac -> [ b -> [ . B ] ] C ] ]
Reduce derivation s -> [ a -> [ A . ] bc -> [ B C ] ]
Shift/reduce conflict on token B:
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 +148,6 @@ AT_CLEANUP
## ------------------------------------ ##
AT_SETUP([S/R Conflict with Nullable Symbols])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B X Y
@@ -107,18 +160,50 @@ 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 derivation
s
`-> A xby
`-> . B
Reduce derivation
s
`-> ax by
`-> A x `-> B y
`-> . `-> %empty
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 ]
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]
Shift/reduce conflict on token B:
Example A . B
Shift derivation s -> [ A xby -> [ . B ] ]
Reduce derivation s -> [ ax -> [ A x -> [ . ] ] by -> [ B y -> [ ] ] ]
Shift/reduce conflict on token B:
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 +215,6 @@ AT_CLEANUP
## ---------------------------- ##
AT_SETUP([Non-unifying Ambiguous S/R])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B C D E
@@ -143,13 +227,32 @@ 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 ]
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]
Shift/reduce conflict on token C:
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 +264,6 @@ AT_CLEANUP
## ------------------------------ ##
AT_SETUP([Non-unifying Unambiguous S/R])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B
@@ -172,13 +274,32 @@ 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 ]
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]
Shift/reduce conflict on token A:
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 ]
]])
@@ -189,7 +310,6 @@ AT_CLEANUP
## ----------------------- ##
AT_SETUP([S/R after first token])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A B X Y
@@ -205,18 +325,48 @@ 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 derivation
a
`-> s
`-> b . xx y
`-> A X X `-> Y
Reduce derivation
a
`-> r t
`-> b . `-> A x xy
`-> X `-> X 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 ] ] ]
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]
Shift/reduce conflict on token A:
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 ] ] ]
Shift/reduce conflict on token X:
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 +379,6 @@ AT_CLEANUP
## ----------------------------- ##
AT_SETUP([Unifying R/R counterexample])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A
@@ -238,12 +387,25 @@ 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 . ] ]
First derivation
a
`-> A b .
Second 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]
Reduce/reduce conflict on token $end:
Example A b .
First derivation a -> [ A b . ]
Second derivation a -> [ A b -> [ b . ] ]
input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
]])
@@ -255,7 +417,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,13 +426,30 @@ 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 ]
First derivation
$accept
`-> s $end
`-> a A
`-> D .
Second example B D . A $end
Second derivation $accept ::=[ s ::=[ B b ::=[ D . ] A ] $end ]
Second 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]
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:5.4: warning: rule useless in parser due to conflicts [-Wother]
]])
@@ -283,7 +461,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,14 +470,32 @@ 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:
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]
Shift/reduce conflict on token J:
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 +510,6 @@ AT_CLEANUP
# graph search
AT_SETUP([Cex Search Prepend])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token N A B C D
@@ -326,17 +520,48 @@ 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 derivation
s
`-> n
`-> N b
`-> A . B C
Reduce derivation
s
`-> n C
`-> N a B
`-> A .
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 ] ]
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]
Shift/reduce conflict on token B:
Example N A . B C
Shift derivation s -> [ n -> [ N b -> [ A . B C ] ] ]
Reduce derivation s -> [ n -> [ N a -> [ A . ] B ] C ]
Shift/reduce conflict on token B:
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 +576,6 @@ AT_CLEANUP
# precedence/associativity directives work.
AT_SETUP([R/R cex with prec])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%left b
@@ -363,17 +587,49 @@ 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 ::=[ ] ] ]
First derivation
S
`-> B C
`-> A b A `-> A c A
`-> B . `-> %empty `-> %empty `-> %empty
Second derivation
S
`-> B C
`-> A c A
`-> B `-> %empty
`-> A b A
`-> . `-> %empty
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 ::=[ ] ] ]
First derivation
S
`-> C B
`-> A c A `-> A b A
`-> C . `-> %empty `-> %empty `-> %empty
Second derivation
S
`-> C B
`-> A b A
`-> C `-> %empty
`-> A c A
`-> . `-> %empty
]],
[[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 -> [ ] ] ]
]])
@@ -384,7 +640,6 @@ AT_CLEANUP
## ------------------- ##
AT_SETUP([Null nonterminals])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A
@@ -395,57 +650,187 @@ 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 ]
First derivation
$accept
`-> a $end
`-> b d
`-> . `-> c A A
Second example . c A A $end
Second derivation $accept ::=[ a ::=[ c ::=[ . ] d ::=[ c A A ] ] $end ]
Second derivation
$accept
`-> a $end
`-> c d
`-> . `-> c A A
Reduce/reduce conflict on token A:
time limit exceeded: XXX
First example b . c A A $end
First derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] ] ] $end ]
First derivation
$accept
`-> a $end
`-> b d
`-> a
`-> b d
`-> . `-> c A A
Second example b . A $end
Second derivation $accept ::=[ a ::=[ b d ::=[ c ::=[ . ] A ] ] $end ]
Second derivation
$accept
`-> a $end
`-> b d
`-> c A
`-> .
Reduce/reduce conflict on token A:
time limit exceeded: XXX
First example c . c A A $end
First derivation $accept ::=[ a ::=[ c d ::=[ a ::=[ b ::=[ . ] d ::=[ c A A ] ] ] ] $end ]
First derivation
$accept
`-> a $end
`-> c d
`-> a
`-> b d
`-> . `-> c A A
Second example c . A $end
Second derivation $accept ::=[ a ::=[ c d ::=[ c ::=[ . ] A ] ] $end ]
Second derivation
$accept
`-> a $end
`-> c d
`-> c A
`-> .
Shift/reduce conflict on token A:
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 ] ]
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
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 ]
First derivation
$accept
`-> a $end
`-> b d
`-> a
`-> c d
`-> a
`-> b d
`-> . `-> c A A
Second example b c . A $end
Second derivation $accept ::=[ a ::=[ b d ::=[ a ::=[ c d ::=[ c ::=[ . ] A ] ] ] ] $end ]
Second derivation
$accept
`-> a $end
`-> b d
`-> a
`-> c d
`-> c A
`-> .
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 ] ]
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
`-> .
Reduce/reduce conflict on token $end:
Example b d .
First derivation a ::=[ b d . ]
Second derivation a ::=[ b d ::=[ 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 derivation
a
`-> c d .
Second 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]
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:
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:
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:
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 ]
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
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 ]
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 . ] ]
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 +843,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,12 +855,27 @@ 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 ]
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]
Shift/reduce conflict on token J:
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 +890,6 @@ AT_CLEANUP
# are derived correctly.
AT_SETUP([Deep Null Unifying])
AT_KEYWORDS([cex])
AT_DATA([[input.y]],
[[%token A D
@@ -503,12 +901,27 @@ 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 ] ]
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]
Shift/reduce conflict on token D:
Example A a . D
Shift derivation s -> [ A a d -> [ . D ] ]
Reduce derivation s -> [ A a a -> [ b -> [ c -> [ . ] ] ] d -> [ D ] ]
]])
@@ -521,7 +934,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,13 +945,31 @@ 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 ]
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]
Shift/reduce conflict on token D:
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 ]
]])
+96 -12
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`
@@ -534,33 +536,115 @@ 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 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>
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 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>
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 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>
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>
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
Reduce/reduce conflict on token "X":
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 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 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])
+7 -2
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]])
+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. ##
## ------------------------- ##
+722 -49
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
@@ -1172,39 +1539,74 @@ AT_CHECK([LC_ALL="$locale" bison -fno-caret -o input.cc -rall -Wcex --graph=inpu
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 ] ]
Shift derivation
exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce 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 • ]
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 derivation
exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce 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 derivation
exp
↳ exp "⊕" exp
↳ exp • "⊕" exp
Reduce 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 derivation
exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce 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 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
@@ -1347,22 +1749,38 @@ State 7
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 ] ]
Shift derivation
exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "+" exp •
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 • ]
First derivation
exp
↳ exp "+" exp •
Second derivation
exp
↳ exp "+" exp •
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 ] ]
Shift derivation
exp
↳ exp "+" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "+" exp •
@@ -1384,22 +1802,40 @@ State 8
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 ] ]
Shift derivation
exp
↳ exp "⊕" exp
↳ exp • "⊕" exp
Reduce derivation
exp
↳ exp "⊕" exp
↳ exp "⊕" exp •
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 ] ]
Shift derivation
exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce derivation
exp
↳ exp "+" exp
↳ exp "⊕" exp •
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 ] ]
Shift derivation
exp
↳ exp "⊕" exp
↳ exp • "+" exp
Reduce derivation
exp
↳ exp "+" exp
↳ exp "⊕" exp •
]])
@@ -1514,16 +1950,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 +2161,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
+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.