# Exercising Bison on conflicts. -*- Autotest -*-
-# Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009 Free Software
-# Foundation, Inc.
+# Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009, 2010 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
AT_COMPILE([input])
AT_PARSER_CHECK([./input '0<0'])
-# FIXME: This is an actual bug, but a new one, in the sense that
-# no one has ever spotted it! The messages are *wrong*: there should
-# be nothing there, it should be expected eof.
AT_PARSER_CHECK([./input '0<0<0'], [1], [],
- [syntax error, unexpected '<', expecting '<' or '>'
+ [syntax error, unexpected '<'
])
AT_PARSER_CHECK([./input '0>0'])
AT_PARSER_CHECK([./input '0>0>0'], [1], [],
- [syntax error, unexpected '>', expecting '<' or '>'
+ [syntax error, unexpected '>'
])
AT_PARSER_CHECK([./input '0<0>0'], [1], [],
- [syntax error, unexpected '>', expecting '<' or '>'
+ [syntax error, unexpected '>'
])
+# We must disable default reductions in inconsistent states in order to
+# have an explicit list of all expected tokens. (However, unless we use
+# canonical LR, lookahead sets are merged for different left contexts,
+# so it is still possible to have extra incorrect tokens in the expected
+# list. That just doesn't happen to be a problem for this test case.)
+
+AT_BISON_CHECK([-Dlr.default-reductions=consistent -o input.c input.y])
+AT_COMPILE([input])
+
+AT_PARSER_CHECK([./input '0<0'])
+AT_PARSER_CHECK([./input '0<0<0'], [1], [],
+ [syntax error, unexpected '<', expecting $end
+])
+
+AT_PARSER_CHECK([./input '0>0'])
+AT_PARSER_CHECK([./input '0>0>0'], [1], [],
+ [syntax error, unexpected '>', expecting $end
+])
+
+AT_PARSER_CHECK([./input '0<0>0'], [1], [],
+ [syntax error, unexpected '>', expecting $end
+])
+
+AT_CLEANUP
+
+
+
+## -------------------------------------- ##
+## %error-verbose and consistent errors. ##
+## -------------------------------------- ##
+
+AT_SETUP([[%error-verbose and consistent errors]])
+
+m4_pushdef([AT_CONSISTENT_ERRORS_CHECK], [
+
+AT_DATA_GRAMMAR([input.y],
+[[%code {
+ #include <assert.h>
+ #include <stdio.h>
+ int yylex (void);
+ void yyerror (char const *);
+ #define USE(Var)
+}
+
+]$1[
+
+%error-verbose
+
+%%
+
+]$2[
+
+%%
+
+int
+yylex (void)
+{
+ static char const *input = "]$3[";
+ yylval = 1;
+ return *input++;
+}
+
+void
+yyerror (char const *msg)
+{
+ fprintf (stderr, "%s\n", msg);
+}
+
+int
+main (void)
+{
+ return yyparse ();
+}
+]])
+AT_BISON_CHECK([[-o input.c input.y]])
+AT_COMPILE([[input]])
+
+m4_pushdef([AT_EXPECTING], [m4_if($5, [ab], [[, expecting 'a' or 'b']],
+ $5, [a], [[, expecting 'a']],
+ $5, [b], [[, expecting 'b']])])
+
+AT_PARSER_CHECK([[./input]], [[1]], [[]],
+[[syntax error, unexpected ]$4[]AT_EXPECTING[
+]])
+
+m4_popdef([AT_EXPECTING])
+
+])
+
+m4_pushdef([AT_USER_ACTION_GRAMMAR],
+[[%nonassoc 'a';
+
+// If yylval=0 here, then we know that the 'a' destructor is being
+// invoked incorrectly for the 'b' set in the semantic action below.
+// All 'a' tokens are returned by yylex, which sets yylval=1.
+%destructor {
+ if (!$$)
+ fprintf (stderr, "Wrong destructor.\n");
+} 'a';
+
+// The lookahead assigned by the semantic action isn't needed before
+// either error action is encountered. In a previous version of Bison,
+// this was a problem as it meant yychar was not translated into yytoken
+// before either error action. The second error action thus invoked a
+// destructor that it selected according to the incorrect yytoken. The
+// first error action would have reported an incorrect unexpected token
+// except that, due to another bug, the unexpected token is not reported
+// at all because the error action is the default action in a consistent
+// state. That bug still needs to be fixed.
+start: error-reduce consistent-error 'a' { USE ($][3); } ;
+
+error-reduce:
+ 'a' 'a' consistent-reduction consistent-error 'a'
+ { USE (($][1, $][2, $][5)); }
+| 'a' error
+ { USE ($][1); }
+;
+
+consistent-reduction: /*empty*/ {
+ assert (yychar == YYEMPTY);
+ yylval = 0;
+ yychar = 'b';
+} ;
+
+consistent-error:
+ 'a' { USE ($][1); }
+| /*empty*/ %prec 'a'
+;
+
+// Provide another context in which all rules are useful so that this
+// test case looks a little more realistic.
+start: 'b' consistent-error 'b' ;
+]])
+m4_pushdef([AT_USER_ACTION_INPUT], [[aa]])
+
+# See comments in grammar for why this test doesn't succeed.
+AT_XFAIL_IF([[:]])
+
+AT_CONSISTENT_ERRORS_CHECK([[]],
+ [AT_USER_ACTION_GRAMMAR],
+ [AT_USER_ACTION_INPUT],
+ [['b']], [[none]])
+AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions consistent]],
+ [AT_USER_ACTION_GRAMMAR],
+ [AT_USER_ACTION_INPUT],
+ [['b']], [[none]])
+
+# Canonical LR doesn't foresee the error for 'a'!
+AT_CONSISTENT_ERRORS_CHECK([[%define lr.default-reductions accepting]],
+ [AT_USER_ACTION_GRAMMAR],
+ [AT_USER_ACTION_INPUT],
+ [[$end]], [[a]])
+AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]],
+ [AT_USER_ACTION_GRAMMAR],
+ [AT_USER_ACTION_INPUT],
+ [[$end]], [[a]])
+
+m4_popdef([AT_USER_ACTION_GRAMMAR])
+m4_popdef([AT_USER_ACTION_INPUT])
+
+m4_popdef([AT_CONSISTENT_ERRORS_CHECK])
+
AT_CLEANUP
AT_CLEANUP
-## ------------------------------ ##
-## %expect with reduce conflicts ##
-## ------------------------------ ##
+## ------------------------------- ##
+## %expect with reduce conflicts. ##
+## ------------------------------- ##
AT_SETUP([%expect with reduce conflicts])
AT_CLEANUP
-## ------------------------------- ##
-## %no-default-prec without %prec ##
-## ------------------------------- ##
+## ------------------------- ##
+## %prec with user strings. ##
+## ------------------------- ##
+
+AT_SETUP([%prec with user string])
+
+AT_DATA([[input.y]],
+[[%%
+exp:
+ "foo" %prec "foo"
+;
+]])
+
+AT_BISON_CHECK([-o input.c input.y])
+AT_CLEANUP
+
+
+## -------------------------------- ##
+## %no-default-prec without %prec. ##
+## -------------------------------- ##
AT_SETUP([%no-default-prec without %prec])
AT_CLEANUP
-## ---------------------------- ##
-## %no-default-prec with %prec ##
-## ---------------------------- ##
+## ----------------------------- ##
+## %no-default-prec with %prec. ##
+## ----------------------------- ##
AT_SETUP([%no-default-prec with %prec])
AT_CLEANUP
-## ---------------- ##
-## %default-prec ##
-## ---------------- ##
+## --------------- ##
+## %default-prec. ##
+## --------------- ##
AT_SETUP([%default-prec])