Compare commits

...
33 Commits
Author SHA1 Message Date
Valentin Tolmer c8c9212bbd news: new syntax (%gprec and %precr) 2013-08-01 15:56:00 +02:00
Valentin Tolmer d992a222af regen 2013-08-01 15:56:00 +02:00
Valentin Tolmer 86a2a43854 tests: new tests for %gprec and %precr
3 grammars: one typical, with normal test cases, one to display all the
warnings introduced, and one with the errors introduced.

* tests/conflicts.at: New
2013-08-01 15:24:52 +02:00
Valentin Tolmer d8de391c38 syntax: introducing %precr to add specific precedence relations
It is now possible to add specific precedence relations between two symbols,
or a symbol and a group, with the %precr keyword:

%gprec arith {
  %left '+' '-'
  %left '*' '/'
}
%gprec boolean {
  %left OR
  %left AND
}
%right '^'

%precr '^' > arith
%precr OR AND > '^'

Here, the symbol ^ is of higher priority than the the ones in arith, but of
lower priority than both OR and AND. OR and '+', for example, cannot be
compared.

* src/parse-gram.y, src/scan-gram.l: Lexer and grammar implementation of
%precr.
* src/symtab.c, src/symtab.h: implementation of the addition of single link
precedence relationships.
2013-08-01 15:24:52 +02:00
Valentin Tolmer f8a710c6f4 syntax: introducing %gprec for precedence groups
It is now possible to introduce precedence groups, with precedence
relationships inside the group, but not with the outside tokens.  Ex:

%gprec arith {
  %left '+' '-'
  %left '*' '/'
  %right '^'
}

%gprec {
  %left OR
  %left AND
}

%left OTHER
%precedence OTHER2

Here, the arithmetical operators (in the "arith" group) can be compared, the
boolean operators can be compared, but OTHER can only be compared to OTHER2.

* src/gram.c, src/gram.h, src/scan-gram.l, src/parse-gram.y: {} blocks after
%gprec are understood by the lexer
* src/parse-gram.y: New syntax
* tests/input.at, tests/regression.at: Fix due to lexer change
2013-08-01 15:24:52 +02:00
Valentin Tolmer 2d8fc07778 conflicts: switch to partial order precedence system
Even though it is not yet fully deployed, this commit lays the ground for
the partial order precedence system, by changing to a graph-based order and
introducing precedence groups (only the default one can be used for now).

* src/symtab.h (struct symbol): Removed extra fields
* src/symtab.h: New function declarations
* src/symtab.c: New functions for precedence and groups, new hash table for
groups
* src/AnnotationList.c, src/conflicts.c, src/gram.c, src/print-xml.c,
* src/symtab.c: Adaptation to the new prec_node structure
* tests/existing.at (GAWK LALR): Fix
2013-08-01 15:24:52 +02:00
Valentin Tolmer a910d26cfb introduction of the new structures to prepare for partial order precedence
New structures: symgroup, prec_link, prec_node, and an enum of the
precedence relation operators.  Symbols have two more fields to prepare for
the precedence graph and grouping to come.

* src/symtab.h (struct symbol): Two new fields
* src/symtab.h: New structures
2013-08-01 15:24:52 +02:00
Valentin TolmerandAkim Demaille a728075710 symbols: improve symbol aliasing
Rather than having duplicate info in the symbol and the alias that has
to be resolved later on, both the symbol and the alias have a common
pointer to a separate structure containing this info.

* src/symtab.h (sym_content): New structure.
* src/symtab.c (sym_content_new, sym_content_free, symbol_free): New

* src/AnnotationList.c, src/conflicts.c, src/gram.c, src/gram.h,
* src/graphviz.c, src/ielr.c, src/output.c, src/parse-gram.y, src/print.c
* src/print-xml.c, src/print_graph.c, src/reader.c, src/reduce.c,
* src/state.h, src/symlist.c, src/symtab.c, src/symtab.h, src/tables.c:
Adjust.

* tests/input.at: Fix expectations (order changes).
2013-08-01 12:49:51 +02:00
Akim Demaille c4aa4ff541 build: ship the ASCII art figures
We don't ship the *.txt files that are used to build the info
file.
Reported by Colin Daley.

* doc/figs/example.txt: New.
* doc/local.mk (bison.info): Depend on the txt files.
And ship them.
2013-08-01 11:41:49 +02:00
Akim Demaille b97bbbaed7 doc: prefer the ".gv" extension to ".dot"
See http://marc.info/?l=graphviz-devel&m=129418103126092 for the
motivation (basically, some word processor now uses *.dot).

* doc/figs/example-reduce.dot: Rename as...
* doc/figs/example-reduce.gv: this.
* doc/figs/example-shift.dot: Rename as...
* doc/figs/example-shift.gv: this.
* doc/figs/example.dot: Rename as...
* doc/figs/example.gv: this.
* doc/local.mk: Adjust.
2013-08-01 11:20:13 +02:00
Akim Demaille e386b50f26 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2013-07-25 18:13:53 +02:00
Akim Demaille 534497f54b version 3.0
* NEWS: Record release date.
2013-07-25 17:55:58 +02:00
Akim Demaille a62a7b014c regen 2013-07-25 17:55:32 +02:00
Akim Demaille de1a2f20dd news: prepare 3.0
* NEWS (3.0): Reorder.
2013-07-25 17:53:59 +02:00
Akim Demaille afcc58c63e tests: fix invalid assignment when using variants in C++11
* tests/c++.at (Exception safety): In variant mode $$ is an instance
of Object.  Assigning YY_NULL in C++98 is incorrect, but behaves ok,
as it assigns YY_NULL=0 using Object::operator= (char v).  It is wrong
in C++11 as there is operator for "$$ = nullptr".
2013-07-25 17:53:59 +02:00
Akim Demaille d3ae5af6ec yacc: beware of "uninitialized uses" warnings
Again some issues with the fact that yylval is reported by GCC as
possibly not initialized in some cases.  Here, the case at hand is the
%destructor.

I am still not convinced that it is worth going all the trouble of
using pragmas to disable temporarily some warnings, instead of just
initializing the looking symbol once for all, but that's what Paul
voted for, see
<http://lists.gnu.org/archive/html/bison-patches/2012-10/msg00050.html>.

* data/c.m4 (b4_attribute_define): Define
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN, YY_IGNORE_MAYBE_UNINITIALIZED_END,
YY_INITIAL_VALUE here, as we will need them in the generation of the
destructor function, which is defined in yacc.c before yyparse, which
was in charge of defining these macros.
* data/yacc.c (b4_declare_scanner_communication_variables): Simplify:
trying to factor the definitions of the case pure and impure is
too complex.
Actually, it is not even clear that this macro should really exist,
as even the calls are complex.
Be careful not to issue a lone ";", as this is a statement, and C90
forbids declarations after statements ; so write
"YY_INITIAL_VALUE(Decl;)", not "YY_INITIAL_VALUE(Decl);".
2013-07-25 17:53:59 +02:00
Akim Demaille 41dfa1cbf0 gnulib: update 2013-07-25 13:47:01 +02:00
Akim Demaille b7171c45f4 tests: skip C++ tests if we can't compile a simple program
There are possible conflicts between gnulib replacement functions (in
<stdio.h>) and their C++ wrappers (in <stream>).  Trying to address
these in configure seems too hard, and I don't know how to fix the issue
in gnulib.  Cowardly avoid the problem by skipping C++ tests when this
happens.
Reported by Stefano Lattarini.
http://lists.gnu.org/archive/html/bug-bison/2013-06/msg00001.html

* tests/atlocal.in (BISON_CXX_WORKS): Also set it to "skip" if we can't
compile a simple program using <stream>.
* tests/local.at: Comment changes.
2013-07-03 17:18:54 +02:00
Akim Demaille ac953ff80a tests: fix 'find' portability issues
Reported by Stefano Lattarini.
http://lists.gnu.org/archive/html/bug-bison/2013-06/msg00000.html

* tests/output.at (AT_CHECK_OUTPUT): Use Perl instead.
2013-07-03 08:39:41 +02:00
Akim Demaille facb910cbd maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2013-06-24 10:29:36 +02:00
Akim Demaille 8faace8d1d version 2.7.91
* NEWS: Record release date.
2013-06-24 10:21:33 +02:00
Akim Demaille 9cdcbdf2cf NEWS: prepare for 2.7.91
* NEWS (2.7.91): Java push parsers.
2013-06-24 10:20:46 +02:00
Akim Demaille 45c64fa627 java: rename YYMORE as YYPUSH_MORE for consistency with C
http://lists.gnu.org/archive/html/bison-patches/2013-06/msg00008.html

* data/lalr1.java, doc/bison.texi, tests/javapush.at:
s/YYMORE/YYPUSH_MORE.
2013-06-24 09:37:18 +02:00
Akim Demaille 58b465ae5f tests: fix Java push failure when running with BISON_USE_PUSH_FOR_PULL
* tests/javapush.at (Trivial Push Parser with api.push-pull verification):
When push for pull is enabled, there is one such function generated.
2013-06-21 11:39:02 +02:00
Akim Demaille d116722c54 style: minor changes in the Java tests
* tests/java.at (AT_CHECK_JAVA_GREP): Ignore the exit status.
* tests/javapush.at (AT_CHECK_JAVA_GREP): Be more alike the previous
one.
Formating changes.
Remove stray debugging "jj" file.
2013-06-21 11:38:47 +02:00
Akim Demaille 1d678854a4 java: push: do not reset the error counter
* data/lalr1.java (parse): here, when in push-pull is in "both" mode.
This breaks the test suite, for instance
make check TESTSUITEFLAGS='-d 388 BISON_USE_PUSH_FOR_PULL=1'.
More generally make maintainer-push-check.
2013-06-21 11:17:05 +02:00
Akim Demaille 28c4075b58 build: add Valgrind suppression file for GNU/Linux
* build-aux/linux-gnu.valgrind: New.
* build-aux/local.mk: Ship it.
* configure.ac: Use it.
2013-06-14 09:58:12 +02:00
Dennis HeimbignerandAkim Demaille aa94def12d java: add push-parser support
* data/lalr1.java: Capture the declarations as m4 macros to avoid
duplication.  When push parsing, the declarations occur at the class
instance level rather than within the parse() function.

Change the way that the parser state is initialized.  For
push-parsing, the parse state declarations are moved to
"push_parse_initialize()", which is called on the first invocation of
"push_parse()". The %initial-action code is also inserted after the
invocation of "push_parse_initialize()".

The body of the parse loop is modified to return values at appropriate
points when doing push parsing.  In order to make push parsing work,
it is necessary to divide YYNEWSTATE into two states: YYNEWSTATE and
YYGETTOKEN. On the first call to push_parse(), the state is
YYNEWSTATE. On all later entries, the state is set to YYGETTOKEN. The
YYNEWSTATE switch arm falls through into YYGETTOKEN. YYGETTOKEN
indicates that a new token is potentially needed.  Normally, with a
pull parser, this new token would be obtained by calling "yylex()". In
the push parser, the value YYMORE is returned to the caller. On the
next call to push_parse(), the parser will return to the YYGETTOKEN
state and continue operation.

* tests/javapush.at: New test file for java push parsing.
* tests/testsuite.at: Use it.
* tests/local.mk: Adjust.
* doc/bison.texi (Java Push Parser Interface): New.

Signed-off-by: Akim Demaille <[email protected]>
2013-06-13 10:38:14 +02:00
Akim Demaille 0fcc2e9a74 build: ship all the files, even if the C++ compiler is broken
* examples/calc++/local.mk: Be sure to ship calc++.test even if
the current C++ compiler is not sufficient to run the tests.
2013-06-11 16:36:38 +02:00
Dennis HeimbignerandAkim Demaille 94a6225578 style: comment changes in Java skeleton
* data/lalr1.java: Here.
2013-06-05 10:04:21 +02:00
Akim Demaille 02798ba13d tests: fix a G++ warning
* tests/c++.at: Use YY_NULL instead of 0 for the null pointer.
And formatting changes.
2013-06-03 16:41:17 +02:00
Akim Demaille 8e13c5c03b build: fix a warning from clang
* src/muscle-tab.c: Declare local functions static.
2013-06-03 16:40:30 +02:00
Akim Demaille 266cdc3025 maint: post-release administrivia
* NEWS: Add header line for next release.
* .prev-version: Record previous version.
* cfg.mk (old_NEWS_hash): Auto-update.
2013-05-30 15:28:44 +02:00
52 changed files with 3408 additions and 1201 deletions
+1 -1
View File
@@ -1 +1 @@
2.7.1
3.0
+34 -3
View File
@@ -1,6 +1,35 @@
GNU Bison NEWS
* Noteworthy changes in release 2.7.90 (2013-05-30) [beta]
* Noteworthy changes in release ?.? (????-??-??) [?]
** New syntax: partial-order precedence relationships
Formerly, the precedence order of tokens was linear, depending only on the
order in which they were declared. With the new syntax, all the tokens are
not necessarily comparable. It is possible to declare a group of tokens with
no links outside of the group, and to later on add only those needed.
The uncomparability of tokens would allow for more feedback on new conflicts
silently resolved via precedence.
An example of the new syntax applied to arithmetic and boolean operators,
with '^' serving as both numerical power and boolean XOR:
%gprec arith {
%left '+' '-'
%left '*' '/'
}
%gprec bool {
%left OR
%left AND
}
%gprec { %right '^' }
%precr '^' > arith
%precr OR AND > '^'
Here, AND is not comparable with '+', but '^' > '+' and AND > '^'
* Noteworthy changes in release 3.0 (2013-07-25) [stable]
** WARNING: Future backward-incompatibilities!
@@ -516,11 +545,13 @@ GNU Bison NEWS
** Java skeleton improvements
Contributed by Paolo Bonzini.
The constants for token names were moved to the Lexer interface. Also, it
is possible to add code to the parser's constructors using "%code init"
and "%define init_throws".
Contributed by Paolo Bonzini.
The Java skeleton now supports push parsing.
Contributed by Dennis Heimbigner.
** C++ skeletons improvements
+1
View File
@@ -25,6 +25,7 @@ Bruce Lilly [email protected]
Bruno Haible [email protected]
Charles-Henri de Boysson [email protected]
Christian Burger [email protected]
Colin Daley [email protected]
Cris Bailiff [email protected]
Cris van Pelt [email protected]
Csaba Raduly [email protected]
+20 -13
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Print a version string.
scriptversion=2013-05-08.20; # UTC
scriptversion=2013-07-03.20; # UTC
# Bootstrap this package from checked-out sources.
@@ -256,12 +256,12 @@ esac
# Extra files from gnulib, which override files from other sources.
test -z "${gnulib_extra_files}" && \
gnulib_extra_files="
$build_aux/install-sh
$build_aux/mdate-sh
$build_aux/texinfo.tex
$build_aux/depcomp
$build_aux/config.guess
$build_aux/config.sub
build-aux/install-sh
build-aux/mdate-sh
build-aux/texinfo.tex
build-aux/depcomp
build-aux/config.guess
build-aux/config.sub
doc/INSTALL
"
@@ -551,7 +551,7 @@ fi
echo "$0: Bootstrapping from checked-out $package sources..."
# See if we can use gnulib's git-merge-changelog merge driver.
if test -d .git && (git --version) >/dev/null 2>/dev/null ; then
if $use_git && test -d .git && (git --version) >/dev/null 2>/dev/null ; then
if git config merge.merge-changelog.driver >/dev/null ; then
:
elif (git-merge-changelog --version) >/dev/null 2>/dev/null ; then
@@ -574,13 +574,17 @@ git_modules_config () {
test -f .gitmodules && git config --file .gitmodules "$@"
}
gnulib_path=$(git_modules_config submodule.gnulib.path)
test -z "$gnulib_path" && gnulib_path=gnulib
if $use_git; then
gnulib_path=$(git_modules_config submodule.gnulib.path)
test -z "$gnulib_path" && gnulib_path=gnulib
fi
# Get gnulib files.
# Get gnulib files. Populate $GNULIB_SRCDIR, possibly updating a
# submodule, for use in the rest of the script.
case ${GNULIB_SRCDIR--} in
-)
# Note that $use_git is necessarily true in this case.
if git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..."
git submodule init || exit $?
@@ -601,8 +605,8 @@ case ${GNULIB_SRCDIR--} in
GNULIB_SRCDIR=$gnulib_path
;;
*)
# Use GNULIB_SRCDIR as a reference.
if test -d "$GNULIB_SRCDIR"/.git && \
# Use GNULIB_SRCDIR directly or as a reference.
if $use_git && test -d "$GNULIB_SRCDIR"/.git && \
git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..."
if git submodule -h|grep -- --reference > /dev/null; then
@@ -628,6 +632,9 @@ case ${GNULIB_SRCDIR--} in
;;
esac
# $GNULIB_SRCDIR now points to the version of gnulib to use, and
# we no longer need to use git or $gnulib_path below here.
if $bootstrap_sync; then
cmp -s "$0" "$GNULIB_SRCDIR/build-aux/bootstrap" || {
echo "$0: updating bootstrap and restarting..."
+16
View File
@@ -0,0 +1,16 @@
# Linux seattle 2.6.32-5-amd64 #1 SMP Thu Mar 22 17:26:33 UTC 2012
# x86_64 GNU/Linux
{
index
Memcheck:Cond
fun:index
fun:expand_dynamic_string_token
fun:_dl_map_object
fun:map_doit
fun:_dl_catch_error
fun:do_preload
fun:dl_main
fun:_dl_sysdep_start
fun:_dl_start
obj:/lib/ld-2.11.3.so
}
+1
View File
@@ -16,6 +16,7 @@
EXTRA_DIST += \
build-aux/cross-options.pl \
build-aux/darwin11.4.0.valgrind \
build-aux/linux-gnu.valgrind \
build-aux/move-if-change \
build-aux/prev-version.txt \
build-aux/update-b4-copyright
+8 -2
View File
@@ -230,10 +230,16 @@ case $VALGRIND:$host_os in
'':*) ;;
*:darwin*)
# See README-hacking.
# VALGRIND+=' --suppressions=$(abs_top_srcdir)/build-aux/darwin11.4.0.valgrind'
# VALGRIND+='-q --suppressions=$(abs_top_srcdir)/build-aux/darwin11.4.0.valgrind'
VALGRIND=;;
*:*)
AC_SUBST([VALGRIND_PREBISON], ["$VALGRIND -q"]);;
suppfile=build-aux/$host_os.valgrind
if test -f "$srcdir/$suppfile"; then
VALGRIND="$VALGRIND --gen-suppressions=all"
VALGRIND="$VALGRIND --suppressions=\$(abs_top_srcdir)/$suppfile"
fi
AC_SUBST([VALGRIND_PREBISON], ["$VALGRIND -q"])
;;
esac
AM_MISSING_PROG([AUTOM4TE], [autom4te])
+24 -3
View File
@@ -221,6 +221,25 @@ m4_define([b4_attribute_define],
#else
# define YYUSE(E) /* empty */
#endif
#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
# define YY_INITIAL_VALUE(Value) Value
#endif
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
#ifndef YY_INITIAL_VALUE
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
])
@@ -446,7 +465,9 @@ m4_ifset([b4_parse_param], [, b4_parse_param]))[
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
]b4_symbol_actions([destructor])[
YY_IGNORE_MAYBE_UNINITIALIZED_END
}]dnl
])
@@ -456,9 +477,9 @@ m4_ifset([b4_parse_param], [, b4_parse_param]))[
# Define the "yy_symbol_print" function.
m4_define_default([b4_yy_symbol_print_define],
[[
/*--------------------------------.
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
/*----------------------------------------.
| Print this symbol's value on YYOUTPUT. |
`----------------------------------------*/
]b4_function_define([yy_symbol_value_print],
[static void],
+259 -70
View File
@@ -20,7 +20,8 @@ m4_include(b4_pkgdatadir/[java.m4])
b4_defines_if([b4_fatal([%s: %%defines does not make sense in Java],
[b4_skeleton])])
# We don't depend on %debug in Java, but pacify warnings about non-used flags.
# We do not depend on %debug in Java, but pacify warnings about
# non-used flags.
b4_parse_trace_if([0], [0])
m4_define([b4_symbol_no_destructor_assert],
@@ -30,6 +31,57 @@ m4_define([b4_symbol_no_destructor_assert],
[b4_symbol_action_location([$1], [destructor])])])])
b4_symbol_foreach([b4_symbol_no_destructor_assert])
# Setup some macros for api.push-pull.
b4_percent_define_default([[api.push-pull]], [[pull]])
b4_percent_define_check_values([[[[api.push-pull]],
[[pull]], [[push]], [[both]]]])
# Define m4 conditional macros that encode the value
# of the api.push-pull flag.
b4_define_flag_if([pull]) m4_define([b4_pull_flag], [[1]])
b4_define_flag_if([push]) m4_define([b4_push_flag], [[1]])
m4_case(b4_percent_define_get([[api.push-pull]]),
[pull], [m4_define([b4_push_flag], [[0]])],
[push], [m4_define([b4_pull_flag], [[0]])])
# Define a macro to be true when api.push-pull has the value "both".
m4_define([b4_both_if],[b4_push_if([b4_pull_if([$1],[$2])],[$2])])
# Handle BISON_USE_PUSH_FOR_PULL for the test suite. So that push parsing
# tests function as written, do not let BISON_USE_PUSH_FOR_PULL modify the
# behavior of Bison at all when push parsing is already requested.
b4_define_flag_if([use_push_for_pull])
b4_use_push_for_pull_if([
b4_push_if([m4_define([b4_use_push_for_pull_flag], [[0]])],
[m4_define([b4_push_flag], [[1]])])])
# Define a macro to encapsulate the parse state variables.
# This allows them to be defined either in parse() when doing
# pull parsing, or as class instance variable when doing push parsing.
m4_define([b4_define_state],[[
/* Lookahead and lookahead in internal form. */
int yychar = yyempty_;
int yytoken = 0;
/* State. */
int yyn = 0;
int yylen = 0;
int yystate = 0;
YYStack yystack = new YYStack ();
int label = YYNEWSTATE;
/* Error handling. */
int yynerrs_ = 0;
]b4_locations_if([/* The location where the error started. */
b4_location_type yyerrloc = null;
/* Location. */
b4_location_type yylloc = new b4_location_type (null, null);])[
/* Semantic value of the lookahead. */
]b4_yystype[ yylval = null;
]])
b4_output_begin([b4_parser_file_name])
b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Java],
[2007-2013])
@@ -55,7 +107,9 @@ b4_percent_define_get3([implements], [ implements ])[
{
]b4_identification[
]b4_error_verbose_if([[
/** True if verbose error messages are enabled. */
/**
* True if verbose error messages are enabled.
*/
private boolean yyErrorVerbose = true;
/**
@@ -76,18 +130,24 @@ b4_locations_if([[
* A class defining a pair of positions. Positions, defined by the
* <code>]b4_position_type[</code> class, denote a point in the input.
* Locations represent a part of the input through the beginning
* and ending positions. */
* and ending positions.
*/
public class ]b4_location_type[ {
/** The first, inclusive, position in the range. */
/**
* The first, inclusive, position in the range.
*/
public ]b4_position_type[ begin;
/** The first position beyond the range. */
/**
* The first position beyond the range.
*/
public ]b4_position_type[ end;
/**
* Create a <code>]b4_location_type[</code> denoting an empty range located at
* a given point.
* @@param loc The position at which the range is anchored. */
* @@param loc The position at which the range is anchored.
*/
public ]b4_location_type[ (]b4_position_type[ loc) {
this.begin = this.end = loc;
}
@@ -95,7 +155,8 @@ b4_locations_if([[
/**
* Create a <code>]b4_location_type[</code> from the endpoints of the range.
* @@param begin The first position included in the range.
* @@param end The first position beyond the range. */
* @@param end The first position beyond the range.
*/
public ]b4_location_type[ (]b4_position_type[ begin, ]b4_position_type[ end) {
this.begin = begin;
this.end = end;
@@ -104,7 +165,8 @@ b4_locations_if([[
/**
* Print a representation of the location. For this to be correct,
* <code>]b4_position_type[</code> should override the <code>equals</code>
* method. */
* method.
*/
public String toString () {
if (begin.equals (end))
return begin.toString ();
@@ -136,24 +198,28 @@ b4_locations_if([[
]b4_locations_if([[/**
* Method to retrieve the beginning position of the last scanned token.
* @@return the position at which the last scanned token starts. */
* @@return the position at which the last scanned token starts.
*/
]b4_position_type[ getStartPos ();
/**
* Method to retrieve the ending position of the last scanned token.
* @@return the first position beyond the last scanned token. */
* @@return the first position beyond the last scanned token.
*/
]b4_position_type[ getEndPos ();]])[
/**
* Method to retrieve the semantic value of the last scanned token.
* @@return the semantic value of the last scanned token. */
* @@return the semantic value of the last scanned token.
*/
]b4_yystype[ getLVal ();
/**
* Entry point for the scanner. Returns the token identifier corresponding
* to the next token and prepares to return the semantic value
* ]b4_locations_if([and beginning/ending positions ])[of the token.
* @@return the token identifier corresponding to the next token. */
* @@return the token identifier corresponding to the next token.
*/
int yylex () ]b4_maybe_throws([b4_lex_throws])[;
/**
@@ -162,7 +228,8 @@ b4_locations_if([[
*
* ]b4_locations_if([[@@param loc The location of the element to which the
* error message is related]])[
* @@param msg The string for the error message. */
* @@param msg The string for the error message.
*/
void yyerror (]b4_locations_if([b4_location_type[ loc, ]])[String msg);]
}
@@ -170,7 +237,9 @@ b4_locations_if([[
]b4_percent_code_get([[lexer]])[
}
]])[/** The object doing lexical analysis for us. */
]])[/**
* The object doing lexical analysis for us.
*/
private Lexer yylexer;
]
b4_parse_param_vars
@@ -336,34 +405,49 @@ b4_lexer_if([[
/**
* Returned by a Bison action in order to stop the parsing process and
* return success (<tt>true</tt>). */
* return success (<tt>true</tt>).
*/
public static final int YYACCEPT = 0;
/**
* Returned by a Bison action in order to stop the parsing process and
* return failure (<tt>false</tt>). */
* return failure (<tt>false</tt>).
*/
public static final int YYABORT = 1;
]b4_push_if([
/**
* Returned by a Bison action in order to request a new token.
*/
public static final int YYPUSH_MORE = 4;])[
/**
* Returned by a Bison action in order to start error recovery without
* printing an error message. */
* printing an error message.
*/
public static final int YYERROR = 2;
// Internal return codes that are not supported for user semantic
// actions.
/**
* Internal return codes that are not supported for user semantic
* actions.
*/
private static final int YYERRLAB = 3;
private static final int YYNEWSTATE = 4;
private static final int YYDEFAULT = 5;
private static final int YYREDUCE = 6;
private static final int YYERRLAB1 = 7;
private static final int YYRETURN = 8;
]b4_push_if([[ private static final int YYGETTOKEN = 9; /* Signify that a new token is expected when doing push-parsing. */]])[
private int yyerrstatus_ = 0;
]b4_push_if([dnl
b4_define_state])[
/**
* Return whether error recovery is being done. In this state, the parser
* reads token until it reaches a known state, and then restarts normal
* operation. */
* operation.
*/
public final boolean recovering ()
{
return yyerrstatus_ == 0;
@@ -463,6 +547,7 @@ b4_lexer_if([[
+ (yyvaluep == null ? "(null)" : yyvaluep.toString ()) + ")");
}
]b4_push_if([],[[
/**
* Parse input from the scanner that was specified at object construction
* time. Return whether the end of the input was reached successfully.
@@ -470,46 +555,53 @@ b4_lexer_if([[
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors.
*/
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[]])[
]b4_push_if([
/**
* Push Parse input from external lexer
*
* @@param yylextoken current token
* @@param yylexval current lval
]b4_locations_if([ * @@param yylexloc current position])[
*
* @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
*/
public int push_parse (int yylextoken, b4_yystype yylexval[]b4_locations_if([, b4_location_type yylexloc]))
b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])])[
{
/// Lookahead and lookahead in internal form.
int yychar = yyempty_;
int yytoken = 0;
/* State. */
int yyn = 0;
int yylen = 0;
int yystate = 0;
YYStack yystack = new YYStack ();
/* Error handling. */
int yynerrs_ = 0;
]b4_locations_if([/// The location where the error started.
]b4_location_type[ yyerrloc = null;
/// ]b4_location_type[ of the lookahead.
]b4_location_type[ yylloc = new ]b4_location_type[ (null, null);
/// @@$.
]b4_location_type[ yyloc;])
/// Semantic value of the lookahead.
b4_yystype[ yylval = null;
]b4_locations_if([/* @@$. */
b4_location_type yyloc;])[
]b4_push_if([],[[
]b4_define_state[
yycdebug ("Starting parse\n");
yyerrstatus_ = 0;
/* Initialize the stack. */
yystack.push (yystate, yylval ]b4_locations_if([, yylloc])[);
]m4_ifdef([b4_initial_action], [
b4_dollar_pushdef([yylval], [], [yylloc])dnl
/* User initialization code. */
b4_user_initial_action
b4_dollar_popdef])[]dnl
b4_dollar_popdef[]dnl
])[
]])[
]b4_push_if([[
if (!this.push_parse_initialized)
{
push_parse_initialize ();
]m4_ifdef([b4_initial_action], [
b4_dollar_pushdef([yylval], [], [yylloc])dnl
/* User initialization code. */
b4_user_initial_action
b4_dollar_popdef[]dnl
])[
yycdebug ("Starting parse\n");
yyerrstatus_ = 0;
} else
label = YYGETTOKEN;
[ /* Initialize the stack. */
yystack.push (yystate, yylval]b4_locations_if([, yylloc])[);
int label = YYNEWSTATE;
boolean push_token_consumed = true;
]])[
for (;;)
switch (label)
{
@@ -522,7 +614,8 @@ b4_dollar_popdef])[]dnl
/* Accept? */
if (yystate == yyfinal_)
return true;
]b4_push_if([{label = YYACCEPT; break;}],
[return true;])[
/* Take a decision. First try without lookahead. */
yyn = yypact_[yystate];
@@ -531,16 +624,27 @@ b4_dollar_popdef])[]dnl
label = YYDEFAULT;
break;
}
]b4_push_if([ /* Fall Through */
case YYGETTOKEN:])[
/* Read a lookahead token. */
if (yychar == yyempty_)
{
]b4_push_if([[
if (!push_token_consumed)
return YYPUSH_MORE;
yycdebug ("Reading a token: ");
yychar = yylexer.yylex ();]
b4_locations_if([[
yylloc = new ]b4_location_type[(yylexer.getStartPos (),
yylexer.getEndPos ());]])
yylval = yylexer.getLVal ();[
yychar = yylextoken;
yylval = yylexval;]b4_locations_if([
yylloc = yylexloc;])[
push_token_consumed = false;]])[
]b4_push_if([],[[
yycdebug ("Reading a token: ");
yychar = yylexer.yylex ();
yylval = yylexer.getLVal ();]b4_locations_if([
yylloc = new b4_location_type (yylexer.getStartPos (),
yylexer.getEndPos ());])[
]])[
}
/* Convert token to internal form. */
@@ -637,10 +741,10 @@ b4_dollar_popdef])[]dnl
{
/* Return failure if at end of input. */
if (yychar == Lexer.EOF)
return false;
]b4_push_if([{label = YYABORT; break;}],[return false;])[
}
else
yychar = yyempty_;
yychar = yyempty_;
}
/* Else will try to reuse lookahead token after shifting the error
@@ -648,9 +752,9 @@ b4_dollar_popdef])[]dnl
label = YYERRLAB1;
break;
/*---------------------------------------------------.
/*-------------------------------------------------.
| errorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/
`-------------------------------------------------*/
case YYERROR:
]b4_locations_if([yyerrloc = yystack.locationAt (yylen - 1);])[
@@ -682,9 +786,10 @@ b4_dollar_popdef])[]dnl
}
}
/* Pop the current state because it cannot handle the error token. */
/* Pop the current state because it cannot handle the
* error token. */
if (yystack.height == 0)
return false;
]b4_push_if([{label = YYABORT; break;}],[return false;])[
]b4_locations_if([yyerrloc = yystack.locationAt (0);])[
yystack.pop ();
@@ -693,7 +798,11 @@ b4_dollar_popdef])[]dnl
yystack.print (yyDebugStream);
}
]b4_locations_if([
if (label == YYABORT)
/* Leave the switch. */
break;
]b4_locations_if([
/* Muck with the stack to setup for yylloc. */
yystack.push (0, null, yylloc);
yystack.push (0, null, yyerrloc);
@@ -711,13 +820,91 @@ b4_dollar_popdef])[]dnl
/* Accept. */
case YYACCEPT:
return true;
]b4_push_if([this.push_parse_initialized = false; return YYACCEPT;],
[return true;])[
/* Abort. */
case YYABORT:
return false;
]b4_push_if([this.push_parse_initialized = false; return YYABORT;],
[return false;])[
}
}
]b4_push_if([[
boolean push_parse_initialized = false;
/**
* (Re-)Initialize the state of the push parser.
*/
public void push_parse_initialize()
{
/* Lookahead and lookahead in internal form. */
this.yychar = yyempty_;
this.yytoken = 0;
/* State. */
this.yyn = 0;
this.yylen = 0;
this.yystate = 0;
this.yystack = new YYStack ();
this.label = YYNEWSTATE;
/* Error handling. */
this.yynerrs_ = 0;
]b4_locations_if([/* The location where the error started. */
this.yyerrloc = null;
this.yylloc = new b4_location_type (null, null);])[
/* Semantic value of the lookahead. */
this.yylval = null;
yystack.push (this.yystate, this.yylval]b4_locations_if([, this.yylloc])[);
this.push_parse_initialized = true;
}
]b4_locations_if([
/**
* Push parse given input from an external lexer.
*
* @@param yylextoken current token
* @@param yylexval current lval
* @@param yyylexpos current position
*
* @@return <tt>YYACCEPT, YYABORT, YYPUSH_MORE</tt>
*/
public int push_parse (int yylextoken, b4_yystype yylexval, b4_position_type yylexpos)
b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])
{
return push_parse (yylextoken, yylexval, new b4_location_type (yylexpos));
}
])[]])
b4_both_if([[
/**
* Parse input from the scanner that was specified at object construction
* time. Return whether the end of the input was reached successfully.
* This version of parse () is defined only when api.push-push=both.
*
* @@return <tt>true</tt> if the parsing succeeds. Note that this does not
* imply that there were no syntax errors.
*/
public boolean parse () ]b4_maybe_throws([b4_list2([b4_lex_throws], [b4_throws])])[
{
if (yylexer == null)
throw new NullPointerException("Null Lexer");
int status;
do {
int token = yylexer.yylex();
]b4_yystype[ lval = yylexer.getLVal();
]b4_locations_if([dnl
b4_location_type yyloc = new b4_location_type (yylexer.getStartPos (),
yylexer.getEndPos ());])[
]b4_locations_if([status = push_parse(token,lval,yyloc);],[
status = push_parse(token,lval);])[
} while (status == YYPUSH_MORE);
return (status == YYACCEPT);
}
]])[
// Generate an error message.
private String yysyntax_error (int yystate, int tok)
@@ -752,8 +939,8 @@ b4_dollar_popdef])[]dnl
*/
if (tok != yyempty_)
{
// FIXME: This method of building the message is not compatible
// with internationalization.
/* FIXME: This method of building the message is not compatible
with internationalization. */
StringBuffer res =
new StringBuffer ("syntax error, unexpected ");
res.append (yytnamerr_ (yytname_[tok]));
@@ -802,8 +989,9 @@ b4_dollar_popdef])[]dnl
}
/**
* Whether the given <code>yytable_</code> value indicates a syntax error.
* @@param yyvalue the value to check
* Whether the given <code>yytable_</code>
* value indicates a syntax error.
* @@param yyvalue the value to check
*/
private static boolean yy_table_value_is_error_ (int yyvalue)
{
@@ -825,6 +1013,7 @@ b4_dollar_popdef])[]dnl
]b4_integral_parser_table_define([rline], [b4_rline],
[[YYRLINE[YYN] -- Source line where rule number YYN was defined.]])[
// Report on the debug stream that the rule yyrule is going to be reduced.
private void yy_reduce_print (int yyrule, YYStack yystack)
{
+9 -26
View File
@@ -175,36 +175,19 @@ m4_define([b4_declare_scanner_communication_variables], [[
int yychar;
]b4_pure_if([[
#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
/* The semantic value of the lookahead symbol. */
/* Default value used for initialization, for pacifying older GCCs
or non-GCC compilers. */
static YYSTYPE yyval_default;
# define YY_INITIAL_VALUE(Value) = Value
#endif]b4_locations_if([[
static YYLTYPE yyloc_default][]b4_yyloc_default[;]])])[
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
#ifndef YY_INITIAL_VALUE
# define YY_INITIAL_VALUE(Value) /* Nothing. */
#endif
/* The semantic value of the lookahead symbol. */
YYSTYPE yylval YY_INITIAL_VALUE (yyval_default);]b4_locations_if([[
YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);]b4_locations_if([[
/* Location data for the lookahead symbol. */
YYLTYPE yylloc]b4_pure_if([ = yyloc_default], [b4_yyloc_default])[;
]])b4_pure_if([], [[
static YYLTYPE yyloc_default]b4_yyloc_default[;
YYLTYPE yylloc = yyloc_default;]])],
[[/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;]b4_locations_if([[
/* Location data for the lookahead symbol. */
YYLTYPE yylloc]b4_yyloc_default[;]])[
/* Number of syntax errors so far. */
int yynerrs;]])])
+69 -1
View File
@@ -366,6 +366,7 @@ Java Parsers
* Java Parser Interface:: Instantiating and running the parser
* Java Scanner Interface:: Specifying the scanner for the parser
* Java Action Features:: Special features for use in actions
* Java Push Parser Interface:: Instantiating and running the a push parser
* Java Differences:: Differences between C/C++ and Java Grammars
* Java Declarations Summary:: List of Bison declarations used with Java
@@ -11500,6 +11501,7 @@ main (int argc, char *argv[])
* Java Parser Interface:: Instantiating and running the parser
* Java Scanner Interface:: Specifying the scanner for the parser
* Java Action Features:: Special features for use in actions
* Java Push Parser Interface:: Instantiating and running the a push parser
* Java Differences:: Differences between C/C++ and Java Grammars
* Java Declarations Summary:: List of Bison declarations used with Java
@end menu
@@ -11811,7 +11813,6 @@ The return type can be changed using @samp{%define api.value.type
@{@var{class-name}@}}.
@end deftypemethod
@node Java Action Features
@subsection Special Features for Use in Java Actions
@@ -11890,6 +11891,73 @@ instance in use. The @code{Location} and @code{Position} parameters are
available only if location tracking is active.
@end deftypefn
@node Java Push Parser Interface
@subsection Java Push Parser Interface
@c - define push_parse
@findex %define api.push-pull
(The current push parsing interface is experimental and may evolve. More
user feedback will help to stabilize it.)
Normally, Bison generates a pull parser for Java.
The following Bison declaration says that you want the parser to be a push
parser (@pxref{%define Summary,,api.push-pull}):
@example
%define api.push-pull push
@end example
Most of the discussion about the Java pull Parser Interface, (@pxref{Java
Parser Interface}) applies to the push parser interface as well.
When generating a push parser, the method @code{push_parse} is created with
the following signature (depending on if locations are enabled).
@deftypemethod {YYParser} {void} push_parse ({int} @var{token}, {Object} @var{yylval})
@deftypemethodx {YYParser} {void} push_parse ({int} @var{token}, {Object} @var{yylval}, {Location} @var{yyloc})
@deftypemethodx {YYParser} {void} push_parse ({int} @var{token}, {Object} @var{yylval}, {Position} @var{yypos})
@end deftypemethod
The primary difference with respect to a pull parser is that the parser
method @code{push_parse} is invoked repeatedly to parse each token. This
function is available if either the "%define api.push-pull push" or "%define
api.push-pull both" declaration is used (@pxref{%define
Summary,,api.push-pull}). The @code{Location} and @code{Position}
parameters are available only if location tracking is active.
The value returned by the @code{push_parse} method is one of the following
four constants: @code{YYABORT}, @code{YYACCEPT}, @code{YYERROR}, or
@code{YYPUSH_MORE}. This new value, @code{YYPUSH_MORE}, may be returned if
more input is required to finish parsing the grammar.
If api.push-pull is declared as @code{both}, then the generated parser class
will also implement the @code{parse} method. This method's body is a loop
that repeatedly invokes the scanner and then passes the values obtained from
the scanner to the @code{push_parse} method.
There is one additional complication. Technically, the push parser does not
need to know about the scanner (i.e. an object implementing the
@code{YYParser.Lexer} interface), but it does need access to the
@code{yyerror} method. Currently, the @code{yyerror} method is defined in
the @code{YYParser.Lexer} interface. Hence, an implementation of that
interface is still required in order to provide an implementation of
@code{yyerror}. The current approach (and subject to change) is to require
the @code{YYParser} constructor to be given an object implementing the
@code{YYParser.Lexer} interface. This object need only implement the
@code{yyerror} method; the other methods can be stubbed since they will
never be invoked. The simplest way to do this is to add a trivial scanner
implementation to your grammar file using whatever implementation of
@code{yyerror} is desired. The following code sample shows a simple way to
accomplish this.
@example
%code lexer
@{
public Object getLVal () @{return null;@}
public int yylex () @{return 0;@}
public void yyerror (String s) @{System.err.println(s);@}
@}
@end example
@node Java Differences
@subsection Differences between C/C++ and Java Grammars
+2
View File
@@ -0,0 +1,2 @@
This file is a stub, not used by the documentation. If you feel like
contributing ASCII art for example.gv, please step forward!
+14 -13
View File
@@ -23,9 +23,10 @@ doc_bison_TEXINFOS = \
# Cannot express dependencies directly on file names because of Automake.
# Obfuscate with a variable.
doc_bison = doc/bison
$(doc_bison).dvi: $(FIGS_DOT:.dot=.eps)
$(doc_bison).pdf: $(FIGS_DOT:.dot=.pdf)
$(doc_bison).html: $(FIGS_DOT:.dot=.png)
$(doc_bison).dvi: $(FIGS_GV:.gv=.eps)
$(doc_bison).info: $(FIGS_GV:.gv=.txt)
$(doc_bison).pdf: $(FIGS_GV:.gv=.pdf)
$(doc_bison).html: $(FIGS_GV:.gv=.png)
TEXI2DVI = texi2dvi --build-dir=doc/bison.t2d -I doc
CLEANDIRS = doc/bison.t2d
@@ -124,25 +125,25 @@ nodist_man_MANS = doc/yacc.1
## ----------------------------- ##
CLEANDIRS += doc/figs
FIGS_DOT = \
doc/figs/example.dot \
doc/figs/example-reduce.dot doc/figs/example-shift.dot
EXTRA_DIST += \
$(FIGS_DOT) \
$(FIGS_DOT:.dot=.eps) $(FIGS_DOT:.dot=.pdf) $(FIGS_DOT:.dot=.png)
SUFFIXES += .dot .eps .pdf .png
FIGS_GV = \
doc/figs/example.gv \
doc/figs/example-reduce.gv doc/figs/example-shift.gv
EXTRA_DIST += \
$(FIGS_GV) $(FIGS_GV:.gv=.txt) \
$(FIGS_GV:.gv=.eps) $(FIGS_GV:.gv=.pdf) $(FIGS_GV:.gv=.png)
SUFFIXES += .gv .eps .pdf .png
.dot.eps:
.gv.eps:
$(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
$(AM_V_at) $(DOT) -Gmargin=0 -Teps $< >$@.tmp
$(AM_V_at) mv $@.tmp $@
.dot.pdf:
.gv.pdf:
$(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
$(AM_V_at) $(DOT) -Gmargin=0 -Tpdf $< >$@.tmp
$(AM_V_at) mv $@.tmp $@
.dot.png:
.gv.png:
$(AM_V_GEN) $(MKDIR_P) `echo "./$@" | sed -e 's,/[^/]*$$,,'`
$(AM_V_at) $(DOT) -Gmargin=0 -Tpng $< >$@.tmp
$(AM_V_at) mv $@.tmp $@
+2
View File
@@ -71,4 +71,6 @@ nodist_examples_calc___calc___SOURCES = \
examples_calc___calc___CPPFLAGS = -I$(top_builddir)/examples/calc++
examples_calc___calc___CXXFLAGS = $(AM_CXXFLAGS) $(FLEX_SCANNER_CXXFLAGS)
dist_TESTS += examples/calc++/calc++.test
else
EXTRA_DIST += examples/calc++/calc++.test
endif
+1 -1
Submodule gnulib updated: e28fbd787c...03e96cc338
+9 -8
View File
@@ -242,7 +242,7 @@ AnnotationList__computePredecessorAnnotations (AnnotationList *self, state *s,
{
symbol_number contribution_token =
InadequacyList__getContributionToken (self->inadequacyNode, ci)
->number;
->content->number;
if (AnnotationList__isContributionAlways (self, ci))
{
annotation_node->contributions[ci] = NULL;
@@ -549,7 +549,7 @@ AnnotationList__compute_from_inadequacies (
does discard annotations in the simplest case of a S/R
conflict with no token precedence. */
aver (!bitset_test (shift_tokens, conflicted_token)
|| symbols[conflicted_token]->prec);
|| symbols[conflicted_token]->content->prec);
++annotation_counts[s->number];
if (contribution_count > *max_contributionsp)
*max_contributionsp = contribution_count;
@@ -595,7 +595,7 @@ AnnotationList__debug (AnnotationList const *self, size_t nitems, int spaces)
{
symbol_number token =
InadequacyList__getContributionToken (a->inadequacyNode, ci)
->number;
->content->number;
{
int j;
for (j = 0; j < spaces+2; ++j)
@@ -644,7 +644,7 @@ AnnotationList__computeLookaheadFilter (AnnotationList const *self,
Sbitset biter;
symbol_number token =
InadequacyList__getContributionToken (self->inadequacyNode, ci)
->number;
->content->number;
SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item)
bitset_set (lookahead_filter[item], token);
}
@@ -679,7 +679,8 @@ AnnotationList__stateMakesContribution (AnnotationList const *self,
return false;
{
symbol_number token =
InadequacyList__getContributionToken (self->inadequacyNode, ci)->number;
InadequacyList__getContributionToken (self->inadequacyNode, ci)
->content->number;
Sbitset__Index item;
Sbitset biter;
SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item)
@@ -709,7 +710,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self,
ContributionIndex ci;
int actioni;
ContributionIndex ci_rr_dominator = ContributionIndex__none;
int shift_precedence = token->prec;
int shift_precedence = token->content->prec;
/* If the token has no precedence set, shift is always chosen. */
if (!shift_precedence)
@@ -739,7 +740,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self,
if (reduce_precedence
&& (reduce_precedence < shift_precedence
|| (reduce_precedence == shift_precedence
&& token->assoc == right_assoc)))
&& token->content->prec_node->assoc == right_assoc)))
continue;
if (!AnnotationList__stateMakesContribution (self, nitems, ci,
lookaheads))
@@ -747,7 +748,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self,
/* This uneliminated reduction contributes, so see if it can cause
an error action. */
if (reduce_precedence == shift_precedence
&& token->assoc == non_assoc)
&& token->content->prec_node->assoc == non_assoc)
{
/* It's not possible to find split-stable domination over
shift after a potential %nonassoc. */
+81 -60
View File
@@ -53,7 +53,8 @@ enum conflict_resolution
reduce_resolution,
left_resolution,
right_resolution,
nonassoc_resolution
nonassoc_resolution,
uncomparable_resolution
};
@@ -90,6 +91,7 @@ log_resolution (rule *r, symbol_number token,
break;
case nonassoc_resolution:
case uncomparable_resolution:
obstack_printf (&solved_conflicts_obstack,
_(" Conflict between rule %d and token %s"
" resolved as an error"),
@@ -104,7 +106,7 @@ log_resolution (rule *r, symbol_number token,
case shift_resolution:
obstack_printf (&solved_conflicts_obstack,
" (%s < %s)",
r->prec->tag,
r->prec->symbol->tag,
symbols[token]->tag);
break;
@@ -112,7 +114,7 @@ log_resolution (rule *r, symbol_number token,
obstack_printf (&solved_conflicts_obstack,
" (%s < %s)",
symbols[token]->tag,
r->prec->tag);
r->prec->symbol->tag);
break;
case left_resolution:
@@ -132,6 +134,12 @@ log_resolution (rule *r, symbol_number token,
" (%%nonassoc %s)",
symbols[token]->tag);
break;
case uncomparable_resolution:
obstack_printf (&solved_conflicts_obstack,
" (%s uncomparable with %s)",
r->prec->symbol->tag,
symbols[token]->tag);
break;
}
obstack_sgrow (&solved_conflicts_obstack, ".\n");
@@ -161,6 +169,7 @@ log_resolution (rule *r, symbol_number token,
xml_escape (symbols[token]->tag));
break;
case uncomparable_resolution:
case nonassoc_resolution:
obstack_printf (&solved_conflicts_xml_obstack,
" <resolution rule=\"%d\" symbol=\"%s\""
@@ -176,7 +185,7 @@ log_resolution (rule *r, symbol_number token,
case shift_resolution:
obstack_printf (&solved_conflicts_xml_obstack,
"%s &lt; %s",
xml_escape_n (0, r->prec->tag),
xml_escape_n (0, r->prec->symbol->tag),
xml_escape_n (1, symbols[token]->tag));
break;
@@ -184,7 +193,7 @@ log_resolution (rule *r, symbol_number token,
obstack_printf (&solved_conflicts_xml_obstack,
"%s &lt; %s",
xml_escape_n (0, symbols[token]->tag),
xml_escape_n (1, r->prec->tag));
xml_escape_n (1, r->prec->symbol->tag));
break;
case left_resolution:
@@ -203,7 +212,13 @@ log_resolution (rule *r, symbol_number token,
obstack_printf (&solved_conflicts_xml_obstack,
"%%nonassoc %s",
xml_escape (symbols[token]->tag));
break;
break;
case uncomparable_resolution:
obstack_printf (&solved_conflicts_xml_obstack,
"%s uncomparable with %s",
xml_escape_n (0, symbols[token]->tag),
xml_escape_n (1, r->prec->symbol->tag));
break;
}
obstack_sgrow (&solved_conflicts_xml_obstack, "</resolution>\n");
@@ -243,7 +258,6 @@ flush_reduce (bitset lookahead_tokens, int token)
bitset_reset (lookahead_tokens, token);
}
/*------------------------------------------------------------------.
| Attempt to resolve shift-reduce conflict for one rule by means of |
| precedence declarations. It has already been checked that the |
@@ -263,66 +277,73 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
reductions *reds = s->reductions;
/* Find the rule to reduce by to get precedence of reduction. */
rule *redrule = reds->rules[ruleno];
int redprec = redrule->prec->prec;
prec_node *redprecsym = redrule->prec->prec_node;
bitset lookahead_tokens = reds->lookahead_tokens[ruleno];
for (i = 0; i < ntokens; i++)
if (bitset_test (lookahead_tokens, i)
&& bitset_test (lookahead_set, i)
&& symbols[i]->prec)
&& bitset_test (lookahead_set, i))
{
/* Shift-reduce conflict occurs for token number i
and it has a precedence.
The precedence of shifting is that of token i. */
if (symbols[i]->prec < redprec)
if (redprecsym && symbols[i]->content->prec_node)
{
register_precedence (redrule->prec->number, i);
log_resolution (redrule, i, reduce_resolution);
flush_shift (s, i);
}
else if (symbols[i]->prec > redprec)
{
register_precedence (i, redrule->prec->number);
log_resolution (redrule, i, shift_resolution);
flush_reduce (lookahead_tokens, i);
/* Shift-reduce conflict occurs for token number i
and it has a precedence.
The precedence of shifting is that of token i. */
if (is_prec_superior (redprecsym, symbols[i]->content->prec_node))
{
register_precedence (redrule->prec->number, i);
log_resolution (redrule, i, reduce_resolution);
flush_shift (s, i);
}
else if (is_prec_superior (symbols[i]->content->prec_node,
redprecsym))
{
register_precedence (i, redrule->prec->number);
log_resolution (redrule, i, shift_resolution);
flush_reduce (lookahead_tokens, i);
}
else if (is_prec_equal (redprecsym, symbols[i]->content->prec_node))
/* Matching precedence levels.
For non-defined associativity, keep both: unexpected
associativity conflict.
For left associativity, keep only the reduction.
For right associativity, keep only the shift.
For nonassociativity, keep neither. */
switch (symbols[i]->content->prec_node->assoc)
{
case undef_assoc:
break;
case precedence_assoc:
break;
case right_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, right_resolution);
flush_reduce (lookahead_tokens, i);
break;
case left_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, left_resolution);
flush_shift (s, i);
break;
case non_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, nonassoc_resolution);
flush_shift (s, i);
flush_reduce (lookahead_tokens, i);
/* Record an explicit error for this token. */
errors[(*nerrs)++] = symbols[i];
break;
}
else
log_resolution (redrule, i, uncomparable_resolution);
}
else
/* Matching precedence levels.
For non-defined associativity, keep both: unexpected
associativity conflict.
For left associativity, keep only the reduction.
For right associativity, keep only the shift.
For nonassociativity, keep neither. */
switch (symbols[i]->assoc)
{
case undef_assoc:
abort ();
case precedence_assoc:
break;
case right_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, right_resolution);
flush_reduce (lookahead_tokens, i);
break;
case left_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, left_resolution);
flush_shift (s, i);
break;
case non_assoc:
register_assoc (i, redrule->prec->number);
log_resolution (redrule, i, nonassoc_resolution);
flush_shift (s, i);
flush_reduce (lookahead_tokens, i);
/* Record an explicit error for this token. */
errors[(*nerrs)++] = symbols[i];
break;
}
log_resolution (redrule, i, uncomparable_resolution);
}
}
@@ -354,7 +375,7 @@ set_conflicts (state *s, symbol **errors)
check for shift-reduce conflict, and try to resolve using
precedence. */
for (i = 0; i < reds->num; ++i)
if (reds->rules[i]->prec && reds->rules[i]->prec->prec
if (reds->rules[i]->prec /* && reds->rules[i]->prec->prec */
&& !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set))
resolve_sr_conflict (s, i, errors, &nerrs);
+11 -9
View File
@@ -44,6 +44,8 @@ int nvars = 0;
symbol_number *token_translations = NULL;
enum braces_state prec_braces = 0;
int max_user_token_number = 256;
bool
@@ -65,19 +67,19 @@ rule_useless_in_parser_p (rule const *r)
}
void
rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out)
rule_lhs_print (rule const *r, sym_content const *previous_lhs, FILE *out)
{
fprintf (out, " %3d ", r->number);
if (previous_lhs != r->lhs)
fprintf (out, "%s:", r->lhs->tag);
fprintf (out, "%s:", r->lhs->symbol->tag);
else
fprintf (out, "%*s|", (int) strlen (previous_lhs->tag), "");
fprintf (out, "%*s|", (int) strlen (previous_lhs->symbol->tag), "");
}
void
rule_lhs_print_xml (rule const *r, FILE *out, int level)
{
xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->tag);
xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->symbol->tag);
}
size_t
@@ -158,7 +160,7 @@ grammar_rules_partial_print (FILE *out, const char *title,
{
rule_number r;
bool first = true;
symbol *previous_lhs = NULL;
sym_content *previous_lhs = NULL;
/* rule # : LHS -> RHS */
for (r = 0; r < nrules + nuseless_productions; r++)
@@ -209,7 +211,7 @@ grammar_rules_print_xml (FILE *out, int level)
rules[r].number, usefulness);
if (rules[r].precsym)
fprintf (out, " percent_prec=\"%s\"",
xml_escape (rules[r].precsym->tag));
xml_escape (rules[r].precsym->symbol->tag));
fputs (">\n", out);
}
rule_lhs_print_xml (&rules[r], out, level + 3);
@@ -239,7 +241,7 @@ grammar_dump (FILE *out, const char *title)
for (i = ntokens; i < nsyms; i++)
fprintf (out, "%5d %5d %5d %s\n",
i,
symbols[i]->prec, symbols[i]->assoc,
symbols[i]->content->prec, symbols[i]->content->prec_node->assoc,
symbols[i]->tag);
fprintf (out, "\n\n");
}
@@ -262,7 +264,7 @@ grammar_dump (FILE *out, const char *title)
fprintf (out, "%3d (%2d, %2d, %2d, %2u-%2u) %2d ->",
i,
rule_i->prec ? rule_i->prec->prec : 0,
rule_i->prec ? rule_i->prec->assoc : 0,
rule_i->prec ? rule_i->prec->prec_node->assoc : 0,
rule_i->useful,
rhs_itemno,
rhs_itemno + rhs_count - 1,
@@ -280,7 +282,7 @@ grammar_dump (FILE *out, const char *title)
rule_number r;
for (r = 0; r < nrules + nuseless_productions; r++)
{
fprintf (out, "%-5d %s:", r, rules[r].lhs->tag);
fprintf (out, "%-5d %s:", r, rules[r].lhs->symbol->tag);
rule_rhs_print (&rules[r], out);
fprintf (out, "\n");
}
+16 -4
View File
@@ -117,6 +117,17 @@ typedef int item_number;
extern item_number *ritem;
extern unsigned int nritems;
enum braces_state
{
default_braces_state,
gprec_seen,
group_name_seen,
braces_seen
};
/* Marker for the lexer and parser, to correctly interpret braces. */
extern enum braces_state prec_braces;
/* There is weird relationship between OT1H item_number and OTOH
symbol_number and rule_number: we store the latter in
item_number. symbol_number values are stored as-is, while
@@ -180,17 +191,17 @@ typedef struct
except if some rules are useless. */
rule_number number;
symbol *lhs;
sym_content *lhs;
item_number *rhs;
/* This symbol provides both the associativity, and the precedence. */
symbol *prec;
sym_content *prec;
int dprec;
int merger;
/* This symbol was attached to the rule via %prec. */
symbol *precsym;
sym_content *precsym;
location location;
bool useful;
@@ -220,7 +231,8 @@ bool rule_useless_in_parser_p (rule const *r);
/* Print this rule's number and lhs on OUT. If a PREVIOUS_LHS was
already displayed (by a previous call for another rule), avoid
useless repetitions. */
void rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out);
void rule_lhs_print (rule const *r, sym_content const *previous_lhs,
FILE *out);
void rule_lhs_print_xml (rule const *r, FILE *out, int level);
/* Return the length of the RHS. */
+1 -1
View File
@@ -93,7 +93,7 @@ no_reduce_bitset_init (state const *s, bitset *no_reduce_set)
bitset_set (*no_reduce_set, TRANSITION_SYMBOL (s->transitions, n));
for (n = 0; n < s->errs->num; ++n)
if (s->errs->symbols[n])
bitset_set (*no_reduce_set, s->errs->symbols[n]->number);
bitset_set (*no_reduce_set, s->errs->symbols[n]->content->number);
}
static void
+2 -2
View File
@@ -424,7 +424,7 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
if (item_number_is_rule_number (ritem[s->items[item] - 2]))
{
state **predecessor;
aver (lhs != accept->number);
aver (lhs != accept->content->number);
for (predecessor = predecessors[s->number];
*predecessor;
++predecessor)
@@ -580,7 +580,7 @@ typedef struct state_list {
static void
ielr_compute_goto_follow_set (bitsetv follow_kernel_items,
bitsetv always_follows, state_list *s,
symbol *n, bitset follow_set)
sym_content *n, bitset follow_set)
{
goto_number n_goto = map_goto (s->lr0Isocore->state->number, n->number);
bitset_copy (follow_set, always_follows[n_goto]);
+1
View File
@@ -557,6 +557,7 @@ muscle_percent_define_use (char const *variable)
/* The value of %define variable VARIABLE (corresponding to FIELD, if
defined). Do not register as used, but diagnose unset variables. */
static
char const *
muscle_percent_define_get_raw (char const *variable, char const *field)
{
+12 -10
View File
@@ -149,7 +149,7 @@ prepare_symbols (void)
MUSCLE_INSERT_INT ("tokens_number", ntokens);
MUSCLE_INSERT_INT ("nterms_number", nvars);
MUSCLE_INSERT_INT ("symbols_number", nsyms);
MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number);
MUSCLE_INSERT_INT ("undef_token_number", undeftoken->content->number);
MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number);
muscle_insert_symbol_number_table ("translate",
@@ -197,7 +197,7 @@ prepare_symbols (void)
int i;
int *values = xnmalloc (ntokens, sizeof *values);
for (i = 0; i < ntokens; ++i)
values[i] = symbols[i]->user_token_number;
values[i] = symbols[i]->content->user_token_number;
muscle_insert_int_table ("toknum", values,
values[0], 1, ntokens);
free (values);
@@ -283,9 +283,9 @@ prepare_states (void)
static int
symbol_type_name_cmp (const symbol **lhs, const symbol **rhs)
{
int res = uniqstr_cmp ((*lhs)->type_name, (*rhs)->type_name);
int res = uniqstr_cmp ((*lhs)->content->type_name, (*rhs)->content->type_name);
if (!res)
res = (*lhs)->number - (*rhs)->number;
res = (*lhs)->content->number - (*rhs)->content->number;
return res;
}
@@ -320,8 +320,9 @@ type_names_output (FILE *out)
/* The index of the first symbol of the current type-name. */
int i0 = i;
fputs (i ? ",\n[" : "[", out);
for (; i < nsyms && syms[i]->type_name == syms[i0]->type_name; ++i)
fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->number);
for (; i < nsyms
&& syms[i]->content->type_name == syms[i0]->content->type_name; ++i)
fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->content->number);
fputs ("]", out);
}
fputs ("])\n\n", out);
@@ -428,20 +429,21 @@ prepare_symbol_definitions (void)
MUSCLE_INSERT_STRING (key, sym->tag);
SET_KEY ("user_number");
MUSCLE_INSERT_INT (key, sym->user_token_number);
MUSCLE_INSERT_INT (key, sym->content->user_token_number);
SET_KEY ("is_token");
MUSCLE_INSERT_INT (key,
i < ntokens && sym != errtoken && sym != undeftoken);
SET_KEY ("number");
MUSCLE_INSERT_INT (key, sym->number);
MUSCLE_INSERT_INT (key, sym->content->number);
SET_KEY ("has_type");
MUSCLE_INSERT_INT (key, !!sym->type_name);
MUSCLE_INSERT_INT (key, !!sym->content->type_name);
SET_KEY ("type");
MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : "");
MUSCLE_INSERT_STRING (key, sym->content->type_name
? sym->content->type_name : "");
{
int j;
+795 -659
View File
File diff suppressed because it is too large Load Diff
+67 -60
View File
@@ -1,4 +1,4 @@
/* A Bison parser, made by GNU Bison 2.7.90. */
/* A Bison parser, made by GNU Bison 3.0. */
/* Bison interface for Yacc-like parsers in C
@@ -48,11 +48,11 @@
extern int gram_debug;
#endif
/* "%code requires" blocks. */
#line 21 "src/parse-gram.y" /* yacc.c:1926 */
#line 21 "src/parse-gram.y" /* yacc.c:1909 */
#include "symlist.h"
#include "symtab.h"
#line 221 "src/parse-gram.y" /* yacc.c:1926 */
#line 233 "src/parse-gram.y" /* yacc.c:1909 */
typedef enum
{
@@ -61,10 +61,10 @@ extern int gram_debug;
param_parse = 1 << 1,
param_both = param_lex | param_parse
} param_type;
#line 645 "src/parse-gram.y" /* yacc.c:1926 */
#line 723 "src/parse-gram.y" /* yacc.c:1909 */
#include "muscle-tab.h"
#line 68 "src/parse-gram.h" /* yacc.c:1926 */
#line 68 "src/parse-gram.h" /* yacc.c:1909 */
/* Token type. */
#ifndef GRAM_TOKENTYPE
@@ -84,49 +84,54 @@ extern int gram_debug;
PERCENT_PRECEDENCE = 267,
PERCENT_PREC = 268,
PERCENT_DPREC = 269,
PERCENT_MERGE = 270,
PERCENT_CODE = 271,
PERCENT_DEFAULT_PREC = 272,
PERCENT_DEFINE = 273,
PERCENT_DEFINES = 274,
PERCENT_ERROR_VERBOSE = 275,
PERCENT_EXPECT = 276,
PERCENT_EXPECT_RR = 277,
PERCENT_FLAG = 278,
PERCENT_FILE_PREFIX = 279,
PERCENT_GLR_PARSER = 280,
PERCENT_INITIAL_ACTION = 281,
PERCENT_LANGUAGE = 282,
PERCENT_NAME_PREFIX = 283,
PERCENT_NO_DEFAULT_PREC = 284,
PERCENT_NO_LINES = 285,
PERCENT_NONDETERMINISTIC_PARSER = 286,
PERCENT_OUTPUT = 287,
PERCENT_REQUIRE = 288,
PERCENT_SKELETON = 289,
PERCENT_START = 290,
PERCENT_TOKEN_TABLE = 291,
PERCENT_VERBOSE = 292,
PERCENT_YACC = 293,
BRACED_CODE = 294,
BRACED_PREDICATE = 295,
BRACKETED_ID = 296,
CHAR = 297,
EPILOGUE = 298,
EQUAL = 299,
ID = 300,
ID_COLON = 301,
PERCENT_PERCENT = 302,
PIPE = 303,
PROLOGUE = 304,
SEMICOLON = 305,
TAG = 306,
TAG_ANY = 307,
TAG_NONE = 308,
INT = 309,
PERCENT_PARAM = 310,
PERCENT_UNION = 311,
PERCENT_EMPTY = 312
PERCENT_GPREC = 270,
PERCENT_PRECR = 271,
PERCENT_MERGE = 272,
PERCENT_CODE = 273,
PERCENT_DEFAULT_PREC = 274,
PERCENT_DEFINE = 275,
PERCENT_DEFINES = 276,
PERCENT_ERROR_VERBOSE = 277,
PERCENT_EXPECT = 278,
PERCENT_EXPECT_RR = 279,
PERCENT_FLAG = 280,
PERCENT_FILE_PREFIX = 281,
PERCENT_GLR_PARSER = 282,
PERCENT_INITIAL_ACTION = 283,
PERCENT_LANGUAGE = 284,
PERCENT_NAME_PREFIX = 285,
PERCENT_NO_DEFAULT_PREC = 286,
PERCENT_NO_LINES = 287,
PERCENT_NONDETERMINISTIC_PARSER = 288,
PERCENT_OUTPUT = 289,
PERCENT_REQUIRE = 290,
PERCENT_SKELETON = 291,
PERCENT_START = 292,
PERCENT_TOKEN_TABLE = 293,
PERCENT_VERBOSE = 294,
PERCENT_YACC = 295,
BRACED_CODE = 296,
BRACED_PREDICATE = 297,
BRACKETED_ID = 298,
CHAR = 299,
EPILOGUE = 300,
EQUAL = 301,
ID = 302,
ID_COLON = 303,
PERCENT_PERCENT = 304,
PIPE = 305,
PROLOGUE = 306,
SEMICOLON = 307,
GT = 308,
TAG = 309,
TAG_ANY = 310,
TAG_NONE = 311,
LBRACE = 312,
RBRACE = 313,
INT = 314,
PERCENT_PARAM = 315,
PERCENT_UNION = 316,
PERCENT_EMPTY = 317
};
#endif
@@ -135,27 +140,29 @@ extern int gram_debug;
typedef union GRAM_STYPE GRAM_STYPE;
union GRAM_STYPE
{
#line 182 "src/parse-gram.y" /* yacc.c:1926 */
#line 187 "src/parse-gram.y" /* yacc.c:1909 */
unsigned char character;
#line 186 "src/parse-gram.y" /* yacc.c:1926 */
#line 191 "src/parse-gram.y" /* yacc.c:1909 */
char *code;
#line 191 "src/parse-gram.y" /* yacc.c:1926 */
#line 196 "src/parse-gram.y" /* yacc.c:1909 */
uniqstr uniqstr;
#line 199 "src/parse-gram.y" /* yacc.c:1926 */
#line 204 "src/parse-gram.y" /* yacc.c:1909 */
int integer;
#line 203 "src/parse-gram.y" /* yacc.c:1926 */
#line 208 "src/parse-gram.y" /* yacc.c:1909 */
symbol *symbol;
#line 208 "src/parse-gram.y" /* yacc.c:1926 */
#line 213 "src/parse-gram.y" /* yacc.c:1909 */
assoc assoc;
#line 211 "src/parse-gram.y" /* yacc.c:1926 */
#line 216 "src/parse-gram.y" /* yacc.c:1909 */
symbol_list *list;
#line 214 "src/parse-gram.y" /* yacc.c:1926 */
#line 219 "src/parse-gram.y" /* yacc.c:1909 */
named_ref *named_ref;
#line 241 "src/parse-gram.y" /* yacc.c:1926 */
#line 224 "src/parse-gram.y" /* yacc.c:1909 */
prec_rel_comparator prec_rel_comparator;
#line 253 "src/parse-gram.y" /* yacc.c:1909 */
param_type param;
#line 409 "src/parse-gram.y" /* yacc.c:1926 */
#line 423 "src/parse-gram.y" /* yacc.c:1909 */
code_props_type code_type;
#line 647 "src/parse-gram.y" /* yacc.c:1926 */
#line 725 "src/parse-gram.y" /* yacc.c:1909 */
struct
{
@@ -163,7 +170,7 @@ code_props_type code_type;
muscle_kind kind;
} value;
#line 167 "src/parse-gram.h" /* yacc.c:1926 */
#line 174 "src/parse-gram.h" /* yacc.c:1909 */
};
# define GRAM_STYPE_IS_TRIVIAL 1
# define GRAM_STYPE_IS_DECLARED 1
+78
View File
@@ -130,6 +130,8 @@
%token PERCENT_PREC "%prec"
%token PERCENT_DPREC "%dprec"
%token PERCENT_GPREC "%gprec"
%token PERCENT_PRECR "%precr"
%token PERCENT_MERGE "%merge"
/*----------------------.
@@ -175,9 +177,12 @@
%token PIPE "|"
%token PROLOGUE "%{...%}"
%token SEMICOLON ";"
%token GT ">"
%token TAG "<tag>"
%token TAG_ANY "<*>"
%token TAG_NONE "<>"
%token LBRACE "{"
%token RBRACE "}"
%union {unsigned char character;}
%type <character> CHAR
@@ -214,6 +219,13 @@
%union {named_ref *named_ref;}
%type <named_ref> named_ref.opt
%type <uniqstr> prec_group_name.opt string_or_id
%union {prec_rel_comparator prec_rel_comparator;}
%type <prec_rel_comparator> prec_rel_comparator
%type <list> precedence_relation_symbols precedence_symbol
/*---------.
| %param. |
`---------*/
@@ -365,6 +377,8 @@ params:
grammar_declaration:
precedence_declaration
| precedence_group_declaration
| precedence_relation_declaration
| symbol_declaration
| "%start" symbol
{
@@ -457,6 +471,30 @@ symbol_declaration:
}
;
/* A group of symbols for precedence declaration */
precedence_group_declaration:
"%gprec" prec_group_name.opt
{
set_current_group ($2, &@2);
}
"{" precedence_declarations "}"
{
set_current_group (DEFAULT_GROUP_NAME, NULL);
}
;
/* Name for the precedence group. If none is present a new unique one is
generated. */
prec_group_name.opt:
%empty { $$ = new_anonymous_group_name (); }
| variable /* Just a string, maybe there's a better way? */
;
precedence_declarations:
precedence_declaration
| precedence_declarations precedence_declaration
;
precedence_declaration:
precedence_declarator tag.opt symbols.prec
{
@@ -484,6 +522,46 @@ tag.opt:
| TAG { current_type = $1; tag_seen = true; }
;
/* Declaration of a precedence relation between two (lists of) tokens */
precedence_relation_declaration:
"%precr" precedence_relation_symbols
{ prec_braces = default_braces_state; }
prec_rel_comparator
precedence_relation_symbols
{ declare_precedence_relation ($2, $5, $4, @4); }
;
precedence_relation_symbols:
precedence_symbol { $$ = $1; }
| precedence_relation_symbols precedence_symbol
{ $$ = symbol_list_append ($1, $2); }
;
precedence_symbol:
string_or_id
{
if (is_prec_group ($1))
$$ = expand_symbol_group (symgroup_from_uniqstr($1, &@1), @1);
else
$$ = symbol_list_sym_new (symbol_from_uniqstr ($1, @1), @1);
}
| CHAR
{
$$ = symbol_list_sym_new (symbol_from_uniqstr (uniqstr_new (char_name ($1)), @1), @1);
}
;
string_or_id:
STRING { $$ = uniqstr_new (quotearg_style (c_quoting_style, $1)); }
| ID { $$ = $1; }
;
prec_rel_comparator:
">" { $$ = prec_superior; }
| "=" { $$ = prec_equal; }
| ">" ">" { $$ = prec_superior_strict; }
;
/* Just like symbols.1 but accept INT for the sake of POSIX. */
symbols.prec:
symbol.prec
+5 -4
View File
@@ -260,7 +260,7 @@ print_reductions (FILE *out, int level, state *s)
bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
for (i = 0; i < s->errs->num; ++i)
if (s->errs->symbols[i])
bitset_set (no_reduce_set, s->errs->symbols[i]->number);
bitset_set (no_reduce_set, s->errs->symbols[i]->content->number);
if (default_reduction)
report = true;
@@ -388,11 +388,12 @@ print_grammar (FILE *out, int level)
/* Terminals */
xml_puts (out, level + 1, "<terminals>");
for (i = 0; i < max_user_token_number + 1; i++)
if (token_translations[i] != undeftoken->number)
if (token_translations[i] != undeftoken->content->number)
{
char const *tag = symbols[token_translations[i]]->tag;
int precedence = symbols[token_translations[i]]->prec;
assoc associativity = symbols[token_translations[i]]->assoc;
int precedence = symbols[token_translations[i]]->content->prec;
assoc associativity = symbols[token_translations[i]]->content->prec_node
->assoc;
xml_indent (out, level + 2);
fprintf (out,
"<terminal symbol-number=\"%d\" token-number=\"%d\""
+5 -4
View File
@@ -72,7 +72,7 @@ print_core (FILE *out, state *s)
size_t i;
item_number *sitems = s->items;
size_t snritems = s->nitems;
symbol *previous_lhs = NULL;
sym_content *previous_lhs = NULL;
/* Output all the items of a state, not only its kernel. */
if (report_flag & report_itemsets)
@@ -223,7 +223,8 @@ print_reduction (FILE *out, size_t width,
if (!enabled)
fputc ('[', out);
if (r->number)
fprintf (out, _("reduce using rule %d (%s)"), r->number, r->lhs->tag);
fprintf (out, _("reduce using rule %d (%s)"), r->number,
r->lhs->symbol->tag);
else
fprintf (out, _("accept"));
if (!enabled)
@@ -257,7 +258,7 @@ print_reductions (FILE *out, state *s)
bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
for (i = 0; i < s->errs->num; ++i)
if (s->errs->symbols[i])
bitset_set (no_reduce_set, s->errs->symbols[i]->number);
bitset_set (no_reduce_set, s->errs->symbols[i]->content->number);
/* Compute the width of the lookahead token column. */
if (default_reduction)
@@ -408,7 +409,7 @@ print_grammar (FILE *out)
/* TERMINAL (type #) : rule #s terminal is on RHS */
fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
for (i = 0; i < max_user_token_number + 1; i++)
if (token_translations[i] != undeftoken->number)
if (token_translations[i] != undeftoken->content->number)
{
const char *tag = symbols[token_translations[i]]->tag;
rule_number r;
+5 -4
View File
@@ -46,7 +46,7 @@ static void
print_core (struct obstack *oout, state *s)
{
item_number const *sitems = s->items;
symbol *previous_lhs = NULL;
sym_content *previous_lhs = NULL;
size_t i;
size_t snritems = s->nitems;
@@ -72,11 +72,12 @@ print_core (struct obstack *oout, state *s)
r = &rules[item_number_as_rule_number (*sp)];
obstack_printf (oout, "%3d ", r->number);
if (previous_lhs && UNIQSTR_EQ (previous_lhs->tag, r->lhs->tag))
if (previous_lhs && UNIQSTR_EQ (previous_lhs->symbol->tag,
r->lhs->symbol->tag))
obstack_printf (oout, "%*s| ",
(int) strlen (previous_lhs->tag), "");
(int) strlen (previous_lhs->symbol->tag), "");
else
obstack_printf (oout, "%s: ", escape (r->lhs->tag));
obstack_printf (oout, "%s: ", escape (r->lhs->symbol->tag));
previous_lhs = r->lhs;
for (sp = r->rhs; sp < sp1; sp++)
+27 -26
View File
@@ -240,13 +240,13 @@ grammar_current_rule_begin (symbol *lhs, location loc,
current_rule = grammar_end;
/* Mark the rule's lhs as a nonterminal if not already so. */
if (lhs->class == unknown_sym)
if (lhs->content->class == unknown_sym)
{
lhs->class = nterm_sym;
lhs->number = nvars;
lhs->content->class = nterm_sym;
lhs->content->number = nvars;
++nvars;
}
else if (lhs->class == token_sym)
else if (lhs->content->class == token_sym)
complain (&loc, complaint, _("rule given for %s, which is a token"),
lhs->tag);
}
@@ -292,15 +292,15 @@ grammar_rule_check (const symbol_list *r)
Don't worry about the default action if $$ is untyped, since $$'s
value can't be used. */
if (!r->action_props.code && r->content.sym->type_name)
if (!r->action_props.code && r->content.sym->content->type_name)
{
symbol *first_rhs = r->next->content.sym;
/* If $$ is being set in default way, report if any type mismatch. */
if (first_rhs)
{
char const *lhs_type = r->content.sym->type_name;
char const *lhs_type = r->content.sym->content->type_name;
const char *rhs_type =
first_rhs->type_name ? first_rhs->type_name : "";
first_rhs->content->type_name ? first_rhs->content->type_name : "";
if (!UNIQSTR_EQ (lhs_type, rhs_type))
complain (&r->location, Wother,
_("type clash on default action: <%s> != <%s>"),
@@ -350,7 +350,8 @@ grammar_rule_check (const symbol_list *r)
it for char literals and strings, which are always tokens. */
if (r->ruleprec
&& r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"'
&& r->ruleprec->status != declared && !r->ruleprec->prec)
&& r->ruleprec->content->status != declared
&& !r->ruleprec->content->prec)
complain (&r->location, Wother,
_("token for %%prec is not defined: %s"), r->ruleprec->tag);
}
@@ -517,8 +518,8 @@ grammar_current_rule_symbol_append (symbol *sym, location loc,
p = grammar_symbol_append (sym, loc);
if (name)
assign_named_ref (p, name);
if (sym->status == undeclared || sym->status == used)
sym->status = needed;
if (sym->content->status == undeclared || sym->content->status == used)
sym->content->status = needed;
}
/* Attach an ACTION to the current rule. */
@@ -558,11 +559,11 @@ packgram (void)
for (p = grammar; p; p = p->next)
{
symbol *ruleprec = p->ruleprec;
record_merge_function_type (p->merger, p->content.sym->type_name,
record_merge_function_type (p->merger, p->content.sym->content->type_name,
p->merger_declaration_location);
rules[ruleno].user_number = ruleno;
rules[ruleno].number = ruleno;
rules[ruleno].lhs = p->content.sym;
rules[ruleno].lhs = p->content.sym->content;
rules[ruleno].rhs = ritem + itemno;
rules[ruleno].prec = NULL;
rules[ruleno].dprec = p->dprec;
@@ -604,11 +605,11 @@ packgram (void)
/* item_number = symbol_number.
But the former needs to contain more: negative rule numbers. */
ritem[itemno++] =
symbol_number_as_item_number (p->content.sym->number);
symbol_number_as_item_number (p->content.sym->content->number);
/* A rule gets by default the precedence and associativity
of its last token. */
if (p->content.sym->class == token_sym && default_prec)
rules[ruleno].prec = p->content.sym;
if (p->content.sym->content->class == token_sym && default_prec)
rules[ruleno].prec = p->content.sym->content;
}
}
@@ -616,8 +617,8 @@ packgram (void)
the specified symbol's precedence replaces the default. */
if (ruleprec)
{
rules[ruleno].precsym = ruleprec;
rules[ruleno].prec = ruleprec;
rules[ruleno].precsym = ruleprec->content;
rules[ruleno].prec = ruleprec->content;
}
/* An item ends by the rule number (negated). */
ritem[itemno++] = rule_number_as_item_number (ruleno);
@@ -647,19 +648,19 @@ reader (void)
/* Construct the accept symbol. */
accept = symbol_get ("$accept", empty_location);
accept->class = nterm_sym;
accept->number = nvars++;
accept->content->class = nterm_sym;
accept->content->number = nvars++;
/* Construct the error token */
errtoken = symbol_get ("error", empty_location);
errtoken->class = token_sym;
errtoken->number = ntokens++;
errtoken->content->class = token_sym;
errtoken->content->number = ntokens++;
/* Construct a token that represents all undefined literal tokens.
It is always token number 2. */
undeftoken = symbol_get ("$undefined", empty_location);
undeftoken->class = token_sym;
undeftoken->number = ntokens++;
undeftoken->content->class = token_sym;
undeftoken->content->number = ntokens++;
gram_in = xfopen (grammar_file, "r");
@@ -721,10 +722,10 @@ check_and_convert_grammar (void)
if (!endtoken)
{
endtoken = symbol_get ("$end", empty_location);
endtoken->class = token_sym;
endtoken->number = 0;
endtoken->content->class = token_sym;
endtoken->content->number = 0;
/* Value specified by POSIX. */
endtoken->user_token_number = 0;
endtoken->content->user_token_number = 0;
}
/* Report any undefined symbols and consider them nonterminals. */
+9 -9
View File
@@ -163,9 +163,9 @@ inaccessable_symbols (void)
Pp = bitset_create (nrules, BITSET_FIXED);
/* If the start symbol isn't useful, then nothing will be useful. */
if (bitset_test (N, accept->number - ntokens))
if (bitset_test (N, accept->content->number - ntokens))
{
bitset_set (V, accept->number);
bitset_set (V, accept->content->number);
while (1)
{
@@ -196,9 +196,9 @@ inaccessable_symbols (void)
V = Vp;
/* Tokens 0, 1, and 2 are internal to Bison. Consider them useful. */
bitset_set (V, endtoken->number); /* end-of-input token */
bitset_set (V, errtoken->number); /* error token */
bitset_set (V, undeftoken->number); /* some undefined token */
bitset_set (V, endtoken->content->number); /* end-of-input token */
bitset_set (V, errtoken->content->number); /* error token */
bitset_set (V, undeftoken->content->number); /* some undefined token */
bitset_free (P);
P = Pp;
@@ -298,7 +298,7 @@ nonterminals_reduce (void)
if (!bitset_test (V, i))
{
nontermmap[i - ntokens] = n++;
if (symbols[i]->status != used)
if (symbols[i]->content->status != used)
complain (&symbols[i]->location, Wother,
_("nonterminal useless in grammar: %s"),
symbols[i]->tag);
@@ -310,7 +310,7 @@ nonterminals_reduce (void)
symbol **symbols_sorted = xnmalloc (nvars, sizeof *symbols_sorted);
for (i = ntokens; i < nsyms; i++)
symbols[i]->number = nontermmap[i - ntokens];
symbols[i]->content->number = nontermmap[i - ntokens];
for (i = ntokens; i < nsyms; i++)
symbols_sorted[nontermmap[i - ntokens] - ntokens] = symbols[i];
for (i = ntokens; i < nsyms; i++)
@@ -328,7 +328,7 @@ nonterminals_reduce (void)
*rhsp = symbol_number_as_item_number (nontermmap[*rhsp
- ntokens]);
}
accept->number = nontermmap[accept->number - ntokens];
accept->content->number = nontermmap[accept->content->number - ntokens];
}
nsyms -= nuseless_nonterminals;
@@ -415,7 +415,7 @@ reduce_grammar (void)
reduce_print ();
if (!bitset_test (N, accept->number - ntokens))
if (!bitset_test (N, accept->content->number - ntokens))
complain (&startsymbol_location, fatal,
_("start symbol %s does not derive any sentence"),
startsymbol->tag);
+17
View File
@@ -223,6 +223,10 @@ eqopt ([[:space:]]*=)?
"%fixed-output-files" return PERCENT_YACC;
"%initial-action" return PERCENT_INITIAL_ACTION;
"%glr-parser" return PERCENT_GLR_PARSER;
"%gprec" {
prec_braces = gprec_seen;
return PERCENT_GPREC;
}
"%language" return PERCENT_LANGUAGE;
"%left" return PERCENT_LEFT;
"%lex-param" RETURN_PERCENT_PARAM(lex);
@@ -239,6 +243,7 @@ eqopt ([[:space:]]*=)?
"%parse-param" RETURN_PERCENT_PARAM(parse);
"%prec" return PERCENT_PREC;
"%precedence" return PERCENT_PRECEDENCE;
"%precr" return PERCENT_PRECR;
"%printer" return PERCENT_PRINTER;
"%pure-parser" RETURN_PERCENT_FLAG("api.pure");
"%require" return PERCENT_REQUIRE;
@@ -273,10 +278,17 @@ eqopt ([[:space:]]*=)?
"=" return EQUAL;
"|" return PIPE;
";" return SEMICOLON;
"}" return RBRACE;
">" return GT;
{id} {
val->uniqstr = uniqstr_new (yytext);
id_loc = *loc;
if (prec_braces == gprec_seen)
{
prec_braces = group_name_seen;
return ID;
}
bracketed_id_str = NULL;
BEGIN SC_AFTER_IDENTIFIER;
}
@@ -307,6 +319,11 @@ eqopt ([[:space:]]*=)?
/* Code in between braces. */
"{" {
if (prec_braces == gprec_seen || prec_braces == group_name_seen)
{
prec_braces = braces_seen;
return LBRACE;
}
STRING_GROW;
nesting = 0;
code_start = loc->start;
+1 -1
View File
@@ -135,7 +135,7 @@ typedef struct
/* Is the TRANSITIONS->states[Num] labelled by the error token? */
# define TRANSITION_IS_ERROR(Transitions, Num) \
(TRANSITION_SYMBOL (Transitions, Num) == errtoken->number)
(TRANSITION_SYMBOL (Transitions, Num) == errtoken->content->number)
/* When resolving a SR conflicts, if the reduction wins, the shift is
disabled. */
+3 -3
View File
@@ -205,7 +205,7 @@ symbol_list_n_type_name_get (symbol_list *l, location loc, int n)
return NULL;
}
aver (l->content_type == SYMLIST_SYMBOL);
return l->content.sym->type_name;
return l->content.sym->content->type_name;
}
bool
@@ -223,8 +223,8 @@ symbol_list_code_props_set (symbol_list *node, code_props_type kind,
{
case SYMLIST_SYMBOL:
symbol_code_props_set (node->content.sym, kind, cprops);
if (node->content.sym->status == undeclared)
node->content.sym->status = used;
if (node->content.sym->content->status == undeclared)
node->content.sym->content->status = used;
break;
case SYMLIST_TYPE:
semantic_type_code_props_set
+607 -157
View File
File diff suppressed because it is too large Load Diff
+114 -8
View File
@@ -31,6 +31,8 @@
# include "scan-code.h"
# include "uniqstr.h"
typedef struct symbol_list symbol_list;
/*----------.
| Symbols. |
`----------*/
@@ -50,6 +52,7 @@ typedef int symbol_number;
typedef struct symbol symbol;
typedef struct sym_content sym_content;
/* Declaration status of a symbol.
@@ -61,6 +64,8 @@ typedef struct symbol symbol;
When status are checked at the end, "declared" symbols are fine,
"used" symbols trigger warnings, otherwise it's an error. */
typedef struct prec_node prec_node;
typedef enum
{
/** Used in the input file for an unknown reason (error). */
@@ -82,8 +87,6 @@ enum code_props_type
enum { CODE_PROPS_SIZE = 2 };
/* When extending this structure, be sure to complete
symbol_check_alias_consistency. */
struct symbol
{
/** The key, name of the symbol. */
@@ -91,6 +94,20 @@ struct symbol
/** The location of its first occurrence. */
location location;
/* Points to the other in the symbol-string pair for an alias. */
symbol *alias;
/** Whether this symbol is the alias of another or not. */
bool is_alias;
/** All the info about the pointed symbol is there. */
sym_content *content;
};
struct sym_content
{
symbol *symbol;
/** Its \c \%type.
Beware that this is the type_name as was entered by the user,
@@ -112,17 +129,21 @@ struct symbol
code_props props[CODE_PROPS_SIZE];
symbol_number number;
location prec_location;
/* Not used anymore, to remove. */
int prec;
assoc assoc;
int user_token_number;
/* Points to the other in the symbol-string pair for an alias.
Special value USER_NUMBER_HAS_STRING_ALIAS in the symbol half of the
symbol-string pair for an alias. */
symbol *alias;
symbol_class class;
status status;
/* The next element in the symbol precedence group. */
sym_content *group_next;
/* The graph node containing all the precedence information for this
symbol. */
prec_node *prec_node;
};
/** Undefined user number. */
@@ -277,6 +298,91 @@ void print_precedence_warnings (void);
void register_assoc (graphid i, graphid j);
/*------------------.
| Groups of symbols |
`------------------*/
#define DEFAULT_GROUP_NAME uniqstr_new ("__default__")
typedef struct symgroup symgroup;
struct symgroup
{
/** The name of the group. */
uniqstr tag;
/** The list of symbols in the group. */
sym_content * symbol_list;
location location;
} ;
/** Get a dummy name for an anonymous group. */
uniqstr new_anonymous_group_name (void);
/** Set the current group in the token precedence declaration to a new group
* with this name */
void set_current_group (const uniqstr name, location *loc);
/** Get or create the group by that name. The location information is used for
* creation when available. */
symgroup *
symgroup_from_uniqstr (const uniqstr key, location *loc);
/** Check if there is a symbol precedence group by that name. */
bool
is_prec_group (const uniqstr key);
/*----------------------------------.
| Graph of precedence relationships |
`----------------------------------*/
typedef struct prec_link prec_link;
struct prec_link
{
prec_node *target;
bool transitive;
prec_link *next;
};
struct prec_node
{
symbol *symbol;
/** Associativity for the symbol. */
assoc assoc;
location prec_location;
prec_link *sons;
prec_link *equals;
};
typedef enum prec_rel_comparator prec_rel_comparator;
enum prec_rel_comparator
{
prec_equal,
prec_superior,
prec_superior_strict,
};
/** Declare a precedence relationship between the symbols of the two lists,
* as defined by the operator. */
void
declare_precedence_relation (symbol_list *l1, symbol_list *l2,
prec_rel_comparator c, location loc);
/** Return the list of symbols contained in the group. */
symbol_list *
expand_symbol_group (symgroup * group, location loc);
/** Check if s1 and s2 have the same precedence level. */
bool is_prec_equal (prec_node * s1, prec_node * s2);
/** Check if from > to . */
bool is_prec_superior (prec_node * from, prec_node * to);
/*-----------------.
| Semantic types. |
`-----------------*/
+2 -2
View File
@@ -290,7 +290,7 @@ action_row (state *s)
/* Do not use any default reduction if there is a shift for
error */
if (sym == errtoken->number)
if (sym == errtoken->content->number)
nodefault = true;
}
@@ -300,7 +300,7 @@ action_row (state *s)
for (i = 0; i < errp->num; i++)
{
symbol *sym = errp->symbols[i];
actrow[sym->number] = ACTION_NUMBER_MINIMUM;
actrow[sym->content->number] = ACTION_NUMBER_MINIMUM;
}
/* Turn off default reductions where requested by the user. See
+31
View File
@@ -50,6 +50,37 @@ CXXFLAGS="$NO_WERROR_CXXFLAGS @WERROR_CXXFLAGS@"
# If 'exit 77'; skip all C++ tests; otherwise ':'.
BISON_CXX_WORKS='@BISON_CXX_WORKS@'
# Be sure that the C++ compiler is not broken because of gnulib. This
# cannot be checked in configure (gnulib is not parameterized yet),
# and checking this in every C++ test in AC_COMPILE_CXX is too costly.
#
# http://lists.gnu.org/archive/html/bug-bison/2013-06/msg00001.html
#
# FIXME: Check (say 2014) whether this is still needed.
if $BISON_CXX_WORKS; then
# See AT_DATA_SOURCE_PROLOGUE.
cat >conftest.cc <<EOF
#include <config.h>
/* We don't need perfect functions for these tests. */
#undef malloc
#undef memcmp
#undef realloc
#include <iostream>
int main ()
{
std::cout << "Works" << std::endl;
}
EOF
ls
$CXX $CXXFLAGS $CPPFLAGS $LDFLAGS $LIBS -o conftest conftest.cc
case $? in
0);;
*) BISON_CXX_WORKS="as_fn_error 77 cannot-compile-simple-program";;
esac
rm -f conftest*
fi
# Whether the compiler supports POSIXLY_CORRECT defined.
: ${C_COMPILER_POSIXLY_CORRECT='@C_COMPILER_POSIXLY_CORRECT@'}
: ${CXX_COMPILER_POSIXLY_CORRECT='@CXX_COMPILER_POSIXLY_CORRECT@'}
+7 -7
View File
@@ -790,16 +790,16 @@ list:
;
item:
'a' { $$][ = $][1; }
| 'e' { YYUSE ($][$); YYUSE($][1); error ("syntax error"); }
'a' { $$][ = $][1; }
| 'e' { YYUSE ($][$); YYUSE($][1); error ("syntax error"); }
// Not just 'E', otherwise we reduce when 'E' is the lookahead, and
// then the stack is emptied, defeating the point of the test.
| 'E' 'a' { YYUSE($][1); $][$ = $][2; }
| 'R' { $][$ = 0; ]AT_VARIANT_IF([], [delete $][1]; )[YYERROR; }
| 'p' { $][$ = $][1; }
| 's' { $][$ = $][1; throw std::runtime_error ("reduction"); }
| 'T' { $][$ = 0; ]AT_VARIANT_IF([], [delete $][1]; )[YYABORT; }
| error { $][$ = 0; yyerrok; }
| 'R' { ]AT_VARIANT_IF([], [$][$ = YY_NULL; delete $][1]; )[YYERROR; }
| 'p' { $][$ = $][1; }
| 's' { $][$ = $][1; throw std::runtime_error ("reduction"); }
| 'T' { ]AT_VARIANT_IF([], [$][$ = YY_NULL; delete $][1]; )[YYABORT; }
| error { ]AT_VARIANT_IF([], [$][$ = YY_NULL; ])[yyerrok; }
;
%%
+146
View File
@@ -17,6 +17,152 @@
AT_BANNER([[Conflicts.]])
## ----------------- ##
## Precedence groups ##
## ----------------- ##
# Sample use case of precedence groups and relations, working.
AT_SETUP([Precedence groups])
AT_DATA_GRAMMAR([[input.y]],
[[%token CARET "^"
%token NUM BOOL '^' OR AND
%left '+' '-'
%gprec {
%right CARET
}
%gprec boolean {
%left OR
%left AND
}
%left '*' '/'
%precr boolean >> "^"
%precr CARET > '*' '/' '-' '+'
%%
stmt:
exp
| bool_exp
exp:
NUM
| exp '+' exp
| exp '-' exp
| exp '*' exp
| exp '/' exp
| exp "^" exp
bool_exp:
BOOL
| bool_exp AND bool_exp
| bool_exp OR bool_exp
| bool_exp CARET bool_exp
]])
AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [])
AT_CLEANUP
## -------------------------------- ##
## Conflicting precedence relations ##
## -------------------------------- ##
AT_SETUP([Conflicting precedence relations])
AT_DATA_GRAMMAR([[input.y]],
[[%token TOKEN
%precedence A
%precedence B
%precedence C
%precedence D E
%gprec group {
%precedence F
%precedence G
}
%precr B = C
%precr A > B
%precr C > B
%precr F > G
%precr F > A
%%
exp:
TOKEN
| exp A exp
| exp B exp
| exp C exp
| exp D exp
| exp E exp
| exp F exp
| exp G exp
]])
AT_BISON_CHECK([[-Wall -o input.c input.y]], 0, [],
[[input.y:20.10: warning: contradicting declaration: B = C is in conflict with the previous declaration: B > C [-Wprecedence]
input.y:21.10: warning: contradicting declaration: A > B is in conflict with the previous declaration: A < B [-Wprecedence]
input.y:22.10: warning: contradicting declaration: C > B is in conflict with the previous declaration: C = B [-Wprecedence]
input.y:23.10: warning: contradicting declaration: F > G is in conflict with the previous declaration: F < G [-Wprecedence]
input.y: warning: 27 shift/reduce conflicts [-Wconflicts-sr]
]])
AT_CLEANUP
## ------------------------------ ##
## Duplicate precedence relations ##
## ------------------------------ ##
AT_SETUP([Duplicate precedence relations])
AT_DATA_GRAMMAR([[input.y]],
[[%token TOKEN
%precedence A
%precedence B
%precedence C
%precedence D E
%gprec group {
%precedence F
%precedence G
}
%precr D = E
%precr B > A
%precr C > B
%precr G > F
%precr F > A
%precr C > group
%precr C > F
%%
exp:
TOKEN
| exp A exp
| exp B exp
| exp C exp
| exp D exp
| exp E exp
| exp F exp
| exp G exp
]])
AT_BISON_CHECK([[-Wall -o input.c input.y]], 0, [],
[[input.y:20.10: warning: duplicate declaration of the precedence relationship D = E [-Wprecedence]
input.y:20.10: warning: duplicate declaration of the precedence relationship E = D [-Wprecedence]
input.y:21.10: warning: duplicate declaration of the precedence relationship B > A [-Wprecedence]
input.y:22.10: warning: duplicate declaration of the precedence relationship C > B [-Wprecedence]
input.y:23.10: warning: duplicate declaration of the precedence relationship G > F [-Wprecedence]
input.y:26.10: warning: duplicate declaration of the precedence relationship C > F [-Wprecedence]
input.y: warning: 23 shift/reduce conflicts [-Wconflicts-sr]
]])
AT_CLEANUP
## ------------------------- ##
## Token declaration order. ##
## ------------------------- ##
+4 -4
View File
@@ -484,7 +484,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%'
NAME [reduce using rule 152 (opt_variable)]
'$' [reduce using rule 152 (opt_variable)]
@@ -5379,7 +5379,7 @@
@@ -5385,7 +5385,7 @@
156 | . '$' non_post_simp_exp
NAME shift, and go to state 9
@@ -493,7 +493,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%'
NAME [reduce using rule 152 (opt_variable)]
'$' [reduce using rule 152 (opt_variable)]
@@ -5399,7 +5399,7 @@
@@ -5405,7 +5405,7 @@
156 | . '$' non_post_simp_exp
NAME shift, and go to state 9
@@ -502,7 +502,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%'
NAME [reduce using rule 152 (opt_variable)]
'$' [reduce using rule 152 (opt_variable)]
@@ -6214,7 +6214,7 @@
@@ -6220,7 +6220,7 @@
156 | . '$' non_post_simp_exp
NAME shift, and go to state 9
@@ -511,7 +511,7 @@ dnl - 61 -> 328: reduce -> shift on '*', '/', and '%'
NAME [reduce using rule 152 (opt_variable)]
'$' [reduce using rule 152 (opt_variable)]
@@ -11099,3 +11099,274 @@
@@ -11117,3 +11117,274 @@
45 statement: LEX_FOR '(' opt_exp semi opt_nls exp semi opt_nls opt_exp r_paren opt_nls statement .
$default reduce using rule 45 (statement)
+10 -11
View File
@@ -64,14 +64,13 @@ AT_CHECK([[$PERL -pi -e 's/\\(\d{3})/chr(oct($1))/ge' input.y || exit 77]])
AT_BISON_CHECK([input.y], [1], [],
[[input.y:1.1-2: error: invalid characters: '\0\001\002\377?'
input.y:3.1: error: invalid character: '?'
input.y:4.14: error: invalid character: '}'
input.y:4.14: error: syntax error, unexpected }
input.y:5.1: error: invalid character: '%'
input.y:5.2: error: invalid character: '&'
input.y:6.1-17: error: invalid directive: '%a-does-not-exist'
input.y:7.1: error: invalid character: '%'
input.y:7.2: error: invalid character: '-'
input.y:8.1-9.0: error: missing '%}' at end of file
input.y:8.1-9.0: error: syntax error, unexpected %{...%}
]])
AT_CLEANUP
@@ -672,25 +671,25 @@ exp: foo;
]])
AT_BISON_CHECK([-fcaret input.y], [1], [],
[[input.y:8.7-11: error: %type redeclaration for foo
[[input.y:8.7-11: error: %type redeclaration for "foo"
%type <baz> "foo"
^^^^^
input.y:3.7-11: previous declaration
%type <bar> foo
^^^^^
input.y:10.13-17: error: %destructor redeclaration for foo
%destructor {baz} "foo"
^^^^^
input.y:5.13-17: previous declaration
%destructor {bar} foo
^^^^^
input.y:9.10-14: error: %printer redeclaration for foo
input.y:9.10-14: error: %printer redeclaration for "foo"
%printer {baz} "foo"
^^^^^
input.y:4.10-14: previous declaration
%printer {bar} foo
^^^^^
input.y:11.1-5: error: %left redeclaration for foo
input.y:10.13-17: error: %destructor redeclaration for "foo"
%destructor {baz} "foo"
^^^^^
input.y:5.13-17: previous declaration
%destructor {bar} foo
^^^^^
input.y:11.1-5: error: %left redeclaration for "foo"
%left "foo"
^^^^^
input.y:6.1-5: previous declaration
+2 -3
View File
@@ -444,9 +444,8 @@ m4_define([AT_CHECK_JAVA_MINIMAL_W_LEXER],
# Check that YYParser.java contains exactly COUNT lines matching ^LINE$
# with grep.
m4_define([AT_CHECK_JAVA_GREP],
[AT_CHECK([grep -c '^$1$' YYParser.java], [], [m4_default([$2], [1])
])
])
[AT_CHECK([grep -c '^$1$' YYParser.java], [ignore], [m4_default([$2], [1])
])])
# ------------------------------------- #
+864
View File
@@ -0,0 +1,864 @@
# Checking Java Push Parsing. -*- Autotest -*-
# Copyright (C) 2013 Free Software Foundation, Inc.
# 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/>.
# The Java push parser tests are intended primarily
# to verify that the sequence of states that the parser
# traverses is the same as a pull parser would traverse.
##################################################
# Provide a way to generate data with and without push parsing
# so it is possible to capture the output for comparison
# (except the "trivial" tests).
# Use "both" rather than "push" so we can also set it to "pull" to
# get the "experr" data.
m4_define([PUSHPULLFLAG],[-Dapi.push-pull=both])
# AT_CHECK_JAVA_GREP(FILE, [LINE], [COUNT=1])
# -------------------------------------------
# Check that FILE contains exactly COUNT lines matching ^LINE$
# with grep. Unquoted so that COUNT can be a shell expression.
m4_define([AT_CHECK_JAVA_GREP],
[AT_CHECK_UNQUOTED([grep -c '^$2$' $1], [ignore], [m4_default([$3], [1])
])])
##################################################
AT_BANNER([[Java Push Parsing Tests]])
# Define a single copy of the trivial parser grammar.
# This is missing main(), so two versions
# are instantiated with different main() procedures.
m4_define([AT_TRIVIAL_GRAMMAR],[
%define parser_class_name {YYParser}
%error-verbose
%code imports {
import java.io.*;
import java.util.*;
}
%%
start: 'a' 'b' 'c' ;
%%
])
# Define comon code across to be includede in
# class Main for the trivial parser tests.
m4_define([AT_TRIVIAL_COMMON],[
static class YYerror implements YYParser.Lexer
{
public Object getLVal() {return null;}
public int yylex () throws java.io.IOException { return 0; }
public void yyerror (String msg) { System.err.println(msg); }
}
static YYParser parser = null;
static YYerror yyerror = null;
static int teststate = -1;
static void setup()
throws IOException
{
yyerror = new YYerror();
parser = new YYParser(yyerror);
parser.setDebugLevel(1);
teststate = -1;
}
static String[[]] teststatename
= new String[[]]{"YYACCEPT","YYABORT","YYERROR","UNKNOWN","YYPUSH_MORE"};
static void check(int teststate, int expected, String msg)
{
System.err.println("teststate="+teststatename[[teststate]]
+"; expected="+teststatename[[expected]]);
if (teststate == expected)
return;
System.err.println("unexpected state: "+msg);
System.exit(1);
}
])
m4_define([AT_TRIVIAL_PARSER],[
AT_TRIVIAL_GRAMMAR
public class Main
{
AT_TRIVIAL_COMMON
static public void main (String[[]] argv)
throws IOException
{
setup();
teststate = parser.push_parse('a', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('a', null)");
setup();
teststate = parser.push_parse('a', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('a', null)");
teststate = parser.push_parse('b', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('b', null)");
teststate = parser.push_parse('c', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('c', null)");
teststate = parser.push_parse('\0', null);
check(teststate,YYParser.YYACCEPT,"push_parse('\\0', null)");
/* Reuse the parser instance and cause a failure */
teststate = parser.push_parse('b', null);
check(teststate,YYParser.YYABORT,"push_parse('b', null)");
System.exit(0);
}
}
])
m4_define([AT_TRIVIAL_PARSER_INITIAL_ACTION],[
AT_TRIVIAL_GRAMMAR
public class Main
{
AT_TRIVIAL_COMMON
static public void main (String[[]] argv)
throws IOException
{
setup();
teststate = parser.push_parse('a', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('a', null)");
teststate = parser.push_parse('b', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('b', null)");
teststate = parser.push_parse('c', null);
check(teststate,YYParser.YYPUSH_MORE,"push_parse('c', null)");
teststate = parser.push_parse('\0', null);
check(teststate,YYParser.YYACCEPT,"push_parse('\\0', null)");
System.exit(0);
}
}
])
## ----------------------------------------------------- ##
## Trivial Push Parser with api.push-pull verification. ##
## ----------------------------------------------------- ##
AT_SETUP([Trivial Push Parser with api.push-pull verification])
AT_BISON_OPTION_PUSHDEFS
AT_DATA([[input.y]],
[[%language "Java"
]AT_TRIVIAL_PARSER[
]])
# Verify that the proper procedure(s) are generated for each case.
AT_BISON_CHECK([[-Dapi.push-pull=pull -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]],
[1])
# If BISON_USE_PUSH_FOR_PULL is set, then we have one occurrence of
# this function, otherwise it should not be there.
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]],
[${BISON_USE_PUSH_FOR_PULL-0}])
AT_BISON_CHECK([[-Dapi.push-pull=both -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]],
[1])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]],
[1])
AT_BISON_CHECK([[-Dapi.push-pull=push -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public boolean parse ().*]],
[0])
AT_CHECK_JAVA_GREP([[Main.java]],
[[.*public int push_parse (int yylextoken, Object yylexval).*]],
[1])
AT_JAVA_COMPILE([[Main.java]])
AT_JAVA_PARSER_CHECK([Main], 0, [], [stderr-nolog])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
## ------------------------------------------ ##
## Trivial Push Parser with %initial-action. ##
## ------------------------------------------ ##
AT_SETUP([Trivial Push Parser with %initial-action])
AT_BISON_OPTION_PUSHDEFS
AT_DATA([[input.y]],[[%language "Java"
%initial-action {
System.err.println("Initial action invoked");
}
]AT_TRIVIAL_PARSER_INITIAL_ACTION[
]])
AT_BISON_OPTION_POPDEFS
AT_BISON_CHECK([[-Dapi.push-pull=push -o Main.java input.y]])
AT_CHECK_JAVA_GREP([[Main.java]],
[[System.err.println("Initial action invoked");]])
AT_JAVA_COMPILE([[Main.java]])
AT_JAVA_PARSER_CHECK([Main], 0, [], [stderr-nolog])
# Verify that initial action is called exactly once.
AT_CHECK_JAVA_GREP(
[[stderr]],
[[Initial action invoked]],
[1])
AT_CLEANUP
# Define a single copy of the Calculator grammar.
m4_define([AT_CALC_BODY],[
%code imports {
import java.io.*;
}
%code {
static StringReader
getinput(String filename) throws IOException
{
StringBuilder buf = new StringBuilder();
FileReader file = new FileReader(filename);
int c;
while ((c=file.read()) > 0)
buf.append((char)c);
file.close();
return new StringReader(buf.toString());
}
}
/* Bison Declarations */
%token <Integer> NUM "number"
%type <Integer> exp
%nonassoc '=' /* comparison */
%left '-' '+'
%left '*' '/'
%left NEG /* negation--unary minus */
%right '^' /* exponentiation */
/* Grammar follows */
%%
input:
line
| input line
;
line:
'\n'
| exp '\n'
{System.out.println("total = "+$[]1);}
| error '\n'
;
exp:
NUM { $[]$ = $[]1;}
| exp '=' exp
{
if ($[]1.intValue() != $[]3.intValue())
yyerror (]AT_LOCATION_IF([[@$,]])[ "calc: error: " + $[]1 + " != " + $[]3);
}
| exp '+' exp
{ $[]$ = new Integer ($[]1.intValue () + $[]3.intValue ()); }
| exp '-' exp
{ $[]$ = new Integer ($[]1.intValue () - $[]3.intValue ()); }
| exp '*' exp
{ $[]$ = new Integer ($[]1.intValue () * $[]3.intValue ()); }
| exp '/' exp
{ $[]$ = new Integer ($[]1.intValue () / $[]3.intValue ()); }
| '-' exp %prec NEG
{ $[]$ = new Integer (-$[]2.intValue ()); }
| exp '^' exp
{ $[]$ = new Integer ((int)Math.pow ($[]1.intValue (),
$[]3.intValue ())); }
| '(' exp ')' { $[]$ = $[]2;}
| '(' error ')' { $[]$ = new Integer (1111);}
| '!' { $[]$ = new Integer (0); return YYERROR;}
| '-' error { $[]$ = new Integer (0); return YYERROR;}
;
])
# Test that the states transitioned by the push parser are the
# same as for the pull parser. This test is assumed to work
# if it produces the same partial trace of stack states as is
# produced when using pull parsing. The output is verbose,
# but seems essential for verifying push parsing.
AT_SETUP([Calc parser with api.push-pull both])
AT_BISON_OPTION_PUSHDEFS
# Define the calculator input.
# Warning: if you changes the input file
# then the locations test file position numbers
# may be incorrect and you will have
# to modify that file as well.
AT_DATA([input],[[1 + 2 * 3 = 7
1 + 2 * -3 = -5
-1^2 = -1
(-1)^2 = 1
---1 = -1
1 - 2 - 3 = -4
1 - (2 - 3) = 2
2^2^3 = 256
(2^2)^3 = 64
]])
# Compose pieces to build the actual .y file.
AT_DATA([Calc.y],[[/* Infix notation calculator--calc */
%language "Java"
%name-prefix "Calc"
%define parser_class_name {Calc}
%code {
static class UserLexer implements Calc.Lexer
{
StreamTokenizer st;
StringReader rdr;
public UserLexer(StringReader reader)
{
rdr = reader;
st = new StreamTokenizer(rdr);
st.resetSyntax();
st.eolIsSignificant(true);
st.whitespaceChars(9, 9);
st.whitespaceChars(32, 32);
st.wordChars(48, 57);
}
Integer yylval;
public Object getLVal() { return yylval; }
public void yyerror(String msg) { System.err.println(msg); }
public int yylex () throws IOException
{
switch (st.nextToken()) {
case StreamTokenizer.TT_EOF: return EOF;
case StreamTokenizer.TT_EOL: return (int) '\n';
case StreamTokenizer.TT_WORD:
yylval = new Integer (st.sval);
return NUM;
default: return st.ttype;
}
}
}
}
%code {
public static void main (String[] argv)
throws IOException
{
StringReader reader = getinput(argv[0]);
UserLexer lexer = new UserLexer(reader);
Calc calc = new Calc(lexer);
calc.setDebugLevel(1);
calc.parse();
}//main
}
]AT_CALC_BODY[
]])
# This data was captured from running a pull parser.
AT_DATA([[expout]],[[Stack now 0
Stack now 0 2
Stack now 0 9
Stack now 0 9 19
Stack now 0 9 19 2
Stack now 0 9 19 28
Stack now 0 9 19 28 20
Stack now 0 9 19 28 20 2
Stack now 0 9 19 28 20 29
Stack now 0 9 19 28
Stack now 0 9
Stack now 0 9 17
Stack now 0 9 17 2
Stack now 0 9 17 26
Stack now 0 9
Stack now 0 9 23
Stack now 0 8
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 19
Stack now 0 7 9 19 2
Stack now 0 7 9 19 28
Stack now 0 7 9 19 28 20
Stack now 0 7 9 19 28 20 3
Stack now 0 7 9 19 28 20 3 2
Stack now 0 7 9 19 28 20 3 12
Stack now 0 7 9 19 28 20 29
Stack now 0 7 9 19 28
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 3
Stack now 0 7 3 2
Stack now 0 7 3 12
Stack now 0 7 3 12 22
Stack now 0 7 3 12 22 2
Stack now 0 7 3 12 22 31
Stack now 0 7 3 12
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 5
Stack now 0 7 5 3
Stack now 0 7 5 3 2
Stack now 0 7 5 3 12
Stack now 0 7 5 14
Stack now 0 7 5 14 25
Stack now 0 7 9
Stack now 0 7 9 22
Stack now 0 7 9 22 2
Stack now 0 7 9 22 31
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 3
Stack now 0 7 3 3
Stack now 0 7 3 3 3
Stack now 0 7 3 3 3 2
Stack now 0 7 3 3 3 12
Stack now 0 7 3 3 12
Stack now 0 7 3 12
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 18
Stack now 0 7 9 18 2
Stack now 0 7 9 18 27
Stack now 0 7 9
Stack now 0 7 9 18
Stack now 0 7 9 18 2
Stack now 0 7 9 18 27
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 3
Stack now 0 7 9 17 3 2
Stack now 0 7 9 17 3 12
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 18
Stack now 0 7 9 18 5
Stack now 0 7 9 18 5 2
Stack now 0 7 9 18 5 14
Stack now 0 7 9 18 5 14 18
Stack now 0 7 9 18 5 14 18 2
Stack now 0 7 9 18 5 14 18 27
Stack now 0 7 9 18 5 14
Stack now 0 7 9 18 5 14 25
Stack now 0 7 9 18 27
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 4
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 2
Stack now 0 7 9
Stack now 0 7 9 22
Stack now 0 7 9 22 2
Stack now 0 7 9 22 31
Stack now 0 7 9 22 31 22
Stack now 0 7 9 22 31 22 2
Stack now 0 7 9 22 31 22 31
Stack now 0 7 9 22 31
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 5
Stack now 0 7 5 2
Stack now 0 7 5 14
Stack now 0 7 5 14 22
Stack now 0 7 5 14 22 2
Stack now 0 7 5 14 22 31
Stack now 0 7 5 14
Stack now 0 7 5 14 25
Stack now 0 7 9
Stack now 0 7 9 22
Stack now 0 7 9 22 2
Stack now 0 7 9 22 31
Stack now 0 7 9
Stack now 0 7 9 17
Stack now 0 7 9 17 2
Stack now 0 7 9 17 26
Stack now 0 7 9
Stack now 0 7 9 23
Stack now 0 7 16
Stack now 0 7
Stack now 0 7 15
]])
AT_BISON_CHECK([PUSHPULLFLAG [-o Calc.java Calc.y]])
AT_JAVA_COMPILE([[Calc.java]])
#Verify that this is a push parser.
AT_CHECK_JAVA_GREP([[Calc.java]],
[[.*public void push_parse_initialize().*]])
# Capture stderr output for comparison purposes.
AT_JAVA_PARSER_CHECK([Calc input], 0, [ignore-nolog], [stderr-nolog])
# Extract the "Stack Now" lines from the error output,
# send them to stdout (via the sed command) and compare to expout.
# NOTE: because the target is "expout", this macro automatically
# compares the output of the sed command with the contents of
# the file "expout" (defined above).
AT_CHECK([[sed -e '/^Stack now.*$/p' -e d ./stderr]],
[ignore], [expout], [ignore-nolog])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
# This test looks for location reporting by looking
# at the lexer output with locations enabled.
# It defines a lexer that reports location info.
AT_SETUP([Calc parser with %locations %code lexer and api.push-pull both])
AT_BISON_OPTION_PUSHDEFS
AT_DATA([Calc.y],[[/* Infix notation calculator--calc. */
%language "Java"
%name-prefix "Calc"
%define parser_class_name {Calc}
%lex-param { Reader rdr }
%locations
%code imports {
import java.io.*;
}
%code lexer {
StreamTokenizer st;
Integer yylval;
public YYLexer(Reader rdr)
{
st = new StreamTokenizer(rdr);
st.resetSyntax();
st.eolIsSignificant(true);
st.whitespaceChars(9, 9);
st.whitespaceChars(32, 32);
st.wordChars(48, 57);
}
Position yypos = new Position (1, 0);
public Position getStartPos() { return yypos; }
public Position getEndPos() { return yypos; }
public Object getLVal() { return yylval; }
public void yyerror(Location loc, String msg)
{
System.err.println(loc+":"+msg);
}
public int yylex () throws IOException
{
yypos = new Position (yypos.lineno (),yypos.token () + 1);
switch (st.nextToken()) {
case StreamTokenizer.TT_EOF:
return EOF;
case StreamTokenizer.TT_EOL:
yypos = new Position (yypos.lineno () + 1, 0);
return (int) '\n';
case StreamTokenizer.TT_WORD:
yylval = new Integer (st.sval);
return NUM;
default:
return st.ttype;
}
}
}
%code {
class Position {
public int line;
public int token;
public Position () { line = 0; token = 0; }
public Position (int l, int t) { line = l; token = t; }
public boolean equals (Position l)
{
return l.line == line && l.token == token;
}
public String toString ()
{
return Integer.toString(line) + "." + Integer.toString(token);
}
public int lineno () { return line; }
public int token () { return token; }
}//Class Position
}
%code {
public static void main (String[] argv)
throws IOException
{
StringReader reader = getinput(argv[0]);
Calc calc = new Calc(reader);
calc.setDebugLevel(1);
calc.parse();
}
}
]AT_CALC_BODY[
]])
# Define the expected calculator output.
# This should match the output from a pull parser.
AT_DATA([output],[[total = 7
total = -5
total = -1
total = 1
total = -1
total = -4
total = 2
total = 256
total = 64
]])
AT_DATA([locations],[[Next token is token "number" (1.1: 1)
Next token is token '+' (1.2: 1)
Next token is token "number" (1.3: 2)
Next token is token '*' (1.4: 2)
Next token is token "number" (1.5: 3)
Next token is token '=' (1.6: 3)
Next token is token '=' (1.6: 3)
Next token is token '=' (1.6: 3)
Next token is token "number" (1.7: 7)
Next token is token '\n' (2.0: 7)
Next token is token '\n' (2.0: 7)
Next token is token "number" (2.1: 1)
Next token is token '+' (2.2: 1)
Next token is token "number" (2.3: 2)
Next token is token '*' (2.4: 2)
Next token is token '-' (2.5: 2)
Next token is token "number" (2.6: 3)
Next token is token '=' (2.7: 3)
Next token is token '=' (2.7: 3)
Next token is token '=' (2.7: 3)
Next token is token '=' (2.7: 3)
Next token is token '-' (2.8: 3)
Next token is token "number" (2.9: 5)
Next token is token '\n' (3.0: 5)
Next token is token '\n' (3.0: 5)
Next token is token '\n' (3.0: 5)
Next token is token '\n' (4.0: 5)
Next token is token '-' (4.1: 5)
Next token is token "number" (4.2: 1)
Next token is token '^' (4.3: 1)
Next token is token "number" (4.4: 2)
Next token is token '=' (4.5: 2)
Next token is token '=' (4.5: 2)
Next token is token '=' (4.5: 2)
Next token is token '-' (4.6: 2)
Next token is token "number" (4.7: 1)
Next token is token '\n' (5.0: 1)
Next token is token '\n' (5.0: 1)
Next token is token '\n' (5.0: 1)
Next token is token '(' (5.1: 1)
Next token is token '-' (5.2: 1)
Next token is token "number" (5.3: 1)
Next token is token ')' (5.4: 1)
Next token is token ')' (5.4: 1)
Next token is token '^' (5.5: 1)
Next token is token "number" (5.6: 2)
Next token is token '=' (5.7: 2)
Next token is token '=' (5.7: 2)
Next token is token "number" (5.8: 1)
Next token is token '\n' (6.0: 1)
Next token is token '\n' (6.0: 1)
Next token is token '\n' (7.0: 1)
Next token is token '-' (7.1: 1)
Next token is token '-' (7.2: 1)
Next token is token '-' (7.3: 1)
Next token is token "number" (7.4: 1)
Next token is token '=' (7.5: 1)
Next token is token '=' (7.5: 1)
Next token is token '=' (7.5: 1)
Next token is token '=' (7.5: 1)
Next token is token '-' (7.6: 1)
Next token is token "number" (7.7: 1)
Next token is token '\n' (8.0: 1)
Next token is token '\n' (8.0: 1)
Next token is token '\n' (8.0: 1)
Next token is token '\n' (9.0: 1)
Next token is token "number" (9.1: 1)
Next token is token '-' (9.2: 1)
Next token is token "number" (9.3: 2)
Next token is token '-' (9.4: 2)
Next token is token '-' (9.4: 2)
Next token is token "number" (9.5: 3)
Next token is token '=' (9.6: 3)
Next token is token '=' (9.6: 3)
Next token is token '-' (9.7: 3)
Next token is token "number" (9.8: 4)
Next token is token '\n' (10.0: 4)
Next token is token '\n' (10.0: 4)
Next token is token '\n' (10.0: 4)
Next token is token "number" (10.1: 1)
Next token is token '-' (10.2: 1)
Next token is token '(' (10.3: 1)
Next token is token "number" (10.4: 2)
Next token is token '-' (10.5: 2)
Next token is token "number" (10.6: 3)
Next token is token ')' (10.7: 3)
Next token is token ')' (10.7: 3)
Next token is token '=' (10.8: 3)
Next token is token '=' (10.8: 3)
Next token is token "number" (10.9: 2)
Next token is token '\n' (11.0: 2)
Next token is token '\n' (11.0: 2)
Next token is token '\n' (12.0: 2)
Next token is token "number" (12.1: 2)
Next token is token '^' (12.2: 2)
Next token is token "number" (12.3: 2)
Next token is token '^' (12.4: 2)
Next token is token "number" (12.5: 3)
Next token is token '=' (12.6: 3)
Next token is token '=' (12.6: 3)
Next token is token '=' (12.6: 3)
Next token is token "number" (12.7: 256)
Next token is token '\n' (13.0: 256)
Next token is token '\n' (13.0: 256)
Next token is token '(' (13.1: 256)
Next token is token "number" (13.2: 2)
Next token is token '^' (13.3: 2)
Next token is token "number" (13.4: 2)
Next token is token ')' (13.5: 2)
Next token is token ')' (13.5: 2)
Next token is token '^' (13.6: 2)
Next token is token "number" (13.7: 3)
Next token is token '=' (13.8: 3)
Next token is token '=' (13.8: 3)
Next token is token "number" (13.9: 64)
Next token is token '\n' (14.0: 64)
Next token is token '\n' (14.0: 64)
]])
# Define the calculator input.
# Warning: if you changes the input file
# then the locations test file position numbers
# may be incorrect and you will have
# to modify that file as well.
AT_DATA([input],[[1 + 2 * 3 = 7
1 + 2 * -3 = -5
-1^2 = -1
(-1)^2 = 1
---1 = -1
1 - 2 - 3 = -4
1 - (2 - 3) = 2
2^2^3 = 256
(2^2)^3 = 64
]])
AT_BISON_CHECK([PUSHPULLFLAG [-o Calc.java Calc.y]])
AT_JAVA_COMPILE([[Calc.java]])
# Verify that this is a push parser
AT_CHECK_JAVA_GREP([[Calc.java]],
[[.*public void push_parse_initialize().*]])
# Capture the stdout and stderr output for comparison purposes.
AT_JAVA_PARSER_CHECK([Calc input], 0, [stdout-nolog], [stderr-nolog])
# 1. Check that the token locations are correct
AT_CHECK([[cp -f ./locations ./expout]],[ignore],[ignore-nolog],[ignore-nolog])
AT_CHECK([[sed -e '/^Next token.*$/p' -e d ./stderr]],[ignore],[expout],[ignore-nolog])
# 2. Check that the calculator output matches that of a pull parser
AT_CHECK([[rm -f ./expout; cp -f ./output ./expout]],[ignore],[ignore-nolog],[ignore-nolog])
AT_CHECK([[cat ./stdout]],[ignore],[expout],[ignore-nolog])
AT_CLEANUP
+4 -3
View File
@@ -339,9 +339,9 @@ m4_define([AT_LANG_DISPATCH],
# AT_DATA_SOURCE_PROLOGUE
# ------------------------
# -----------------------
# The prologue that should be included in any source code that is
# meant to be compiled.
# meant to be compiled. Keep atlocal.in sync (BISON_CXX_WORKS).
m4_define([AT_DATA_SOURCE_PROLOGUE],
[[#include <config.h>
/* We don't need perfect functions for these tests. */
@@ -754,6 +754,7 @@ AT_CHECK(m4_join([ ],
[m4_bmatch([$1], [[.]], [], [$LIBS])]),
0, [ignore], [ignore])])
# AT_COMPILE_CXX(OUTPUT, [SOURCES = OUTPUT.cc])
# ---------------------------------------------
# Compile SOURCES into OUTPUT. If the C++ compiler does not work,
@@ -761,7 +762,7 @@ AT_CHECK(m4_join([ ],
#
# If OUTPUT does not contain '.', assume that we are linking too,
# otherwise pass "-c"; this is a hack. The default SOURCES is OUTPUT
# with trailing .o removed, and ".cc" appended.
# with trailing ".o" removed, and ".cc" appended.
m4_define([AT_COMPILE_CXX],
[AT_KEYWORDS(c++)
AT_CHECK([$BISON_CXX_WORKS], 0, ignore, ignore)
+1
View File
@@ -53,6 +53,7 @@ TESTSUITE_AT = \
tests/headers.at \
tests/input.at \
tests/java.at \
tests/javapush.at \
tests/local.at \
tests/named-refs.at \
tests/output.at \
+5 -4
View File
@@ -37,10 +37,11 @@ foo: {};
]AT_BISON_CHECK([$3 $1 $5], 0)[
# Ignore the files non-generated files
]AT_CHECK([find . -type f -and -not -path './$1' -and -not -path './testsuite.log' |
sed 's,\./,,' |
sort |
xargs echo],
]AT_CHECK([[find . -type f |
$PERL -ne '
s,\./,,; chomp;
push @file, $_ unless m{^($1|testsuite.log)$};
END { print join (" ", sort @file), "\n" }']],
[], [$4
])[
]$6[
+1 -2
View File
@@ -405,14 +405,13 @@ default: 'a' }
AT_BISON_CHECK([input.y], [1], [],
[[input.y:2.1: error: invalid character: '?'
input.y:3.14: error: invalid character: '}'
input.y:3.14: error: syntax error, unexpected }
input.y:4.1: error: invalid character: '%'
input.y:4.2: error: invalid character: '&'
input.y:5.1-17: error: invalid directive: '%a-does-not-exist'
input.y:6.1: error: invalid character: '%'
input.y:6.2: error: invalid character: '-'
input.y:7.1-8.0: error: missing '%}' at end of file
input.y:7.1-8.0: error: syntax error, unexpected %{...%}
]])
AT_CLEANUP
+4 -3
View File
@@ -63,17 +63,18 @@ m4_include([existing.at])
# Some old bugs.
m4_include([regression.at])
# Push parsing specific tests.
m4_include([push.at])
# Some C++ specific tests.
m4_include([c++.at])
# And some Java specific tests.
m4_include([java.at])
m4_include([javapush.at])
# GLR tests:
# C++ types, simplified
m4_include([cxx-type.at])
# Regression tests
m4_include([glr-regression.at])
# Push parsing specific tests.
m4_include([push.at])