X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/cff03fb2b92a05f61c142783dd3b2e0103782869..dcd39f1d4ab0d2efa467406682175643c7c0ca1d:/tests/conflicts.at diff --git a/tests/conflicts.at b/tests/conflicts.at index 8032256e..f455d1f5 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -1,6 +1,7 @@ # Exercising Bison on conflicts. -*- Autotest -*- -# Copyright (C) 2002, 2003, 2004, 2005, 2007 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 @@ -36,7 +37,7 @@ exp: e 'e'; e: 'e' | /* Nothing. */; ]]) -AT_CHECK([bison -o input.c input.y], 0, [], +AT_BISON_CHECK([-o input.c input.y], 0, [], [[input.y:4.9: warning: rule useless in parser due to conflicts: e: /* empty */ ]]) @@ -94,26 +95,338 @@ main (int argc, const char *argv[]) ]]) # Specify the output files to avoid problems on different file systems. -AT_CHECK([bison -o input.c input.y]) +AT_BISON_CHECK([-o input.c input.y]) 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_BISON_OPTION_PUSHDEFS([$1]) + +m4_pushdef([AT_YYLEX_PROTOTYPE], +[AT_SKEL_CC_IF([[int yylex (yy::parser::semantic_type *lvalp)]], + [[int yylex (YYSTYPE *lvalp)]])]) + +AT_SKEL_JAVA_IF([AT_DATA], [AT_DATA_GRAMMAR])([input.y], +[AT_SKEL_JAVA_IF([[ + +%code imports { + import java.io.IOException; +}]], [[ + +%code {]AT_SKEL_CC_IF([[ + #include + #include ]], [[ + #include + #include + void yyerror (char const *msg);]])[ + ]AT_YYLEX_PROTOTYPE[; + #define USE(Var) +} + +]AT_SKEL_CC_IF([[%defines]], [[%define api.pure]])])[ + +]$1[ + +%error-verbose + +%% + +]$2[ + +]AT_SKEL_JAVA_IF([[%code lexer {]], [[%%]])[ + +/*--------. +| yylex. | +`--------*/]AT_SKEL_JAVA_IF([[ + +public String input = "]$3["; +public int index = 0; +public int yylex () +{ + if (index < input.length ()) + return input.charAt (index++); + else + return 0; +} +public Object getLVal () +{ + return new Integer(1); +}]], [[ + +]AT_YYLEX_PROTOTYPE[ +{ + static char const *input = "]$3["; + *lvalp = 1; + return *input++; +}]])[ + +/*----------. +| yyerror. | +`----------*/]AT_SKEL_JAVA_IF([[ + +public void yyerror (String msg) +{ + System.err.println (msg); +} + +}; + +%%]], [AT_SKEL_CC_IF([[ + +void +yy::parser::error (const yy::location &, std::string const &msg) +{ + std::cerr << msg << std::endl; +}]], [[ + +void +yyerror (char const *msg) +{ + fprintf (stderr, "%s\n", msg); +}]])])[ + +/*-------. +| main. | +`-------*/]AT_SKEL_JAVA_IF([[ + +class input +{ + public static void main (String args[]) throws IOException + { + YYParser p = new YYParser (); + p.parse (); + } +}]], [AT_SKEL_CC_IF([[ + +int +main (void) +{ + yy::parser parser; + return parser.parse (); +}]], [[ + +int +main (void) +{ + return yyparse (); +}]])])[ +]]) + +AT_FULL_COMPILE([[input]]) + +m4_pushdef([AT_EXPECTING], [m4_if($5, [ab], [[, expecting 'a' or 'b']], + $5, [a], [[, expecting 'a']], + $5, [b], [[, expecting 'b']])]) + +AT_SKEL_JAVA_IF([AT_JAVA_PARSER_CHECK([[input]], [[0]]], + [AT_PARSER_CHECK([[./input]], [[1]]]), +[[]], +[[syntax error, unexpected ]$4[]AT_EXPECTING[ +]]) + +m4_popdef([AT_EXPECTING]) +m4_popdef([AT_YYLEX_PROTOTYPE]) +AT_BISON_OPTION_POPDEFS + +]) + +m4_pushdef([AT_PREVIOUS_STATE_GRAMMAR], +[[%nonassoc 'a'; + +start: consistent-error-on-a-a 'a' ; + +consistent-error-on-a-a: + 'a' default-reduction + | 'a' default-reduction 'a' + | 'a' shift + ; + +default-reduction: /*empty*/ ; +shift: 'b' ; + +// Provide another context in which all rules are useful so that this +// test case looks a little more realistic. +start: 'b' consistent-error-on-a-a 'c' ; +]]) + +m4_pushdef([AT_PREVIOUS_STATE_INPUT], [[a]]) + +# Unfortunately, no expected tokens are reported even though 'b' can be +# accepted. Nevertheless, the main point of this test is to make sure +# that at least the unexpected token is reported. In a previous version +# of Bison, it wasn't reported because the error is detected in a +# consistent state with an error action, and that case always triggered +# the simple "syntax error" message. +# +# The point isn't to test IELR here, but state merging happens to +# complicate this example. +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %glr-parser]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %language "c++"]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %language "java"]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[end of input]], [[none]]) + +# Even canonical LR doesn't foresee the error for 'a'! +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %define lr.default-reductions consistent]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[ab]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type ielr + %define lr.default-reductions accepting]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[ab]]) +AT_CONSISTENT_ERRORS_CHECK([[%define lr.type canonical-lr]], + [AT_PREVIOUS_STATE_GRAMMAR], + [AT_PREVIOUS_STATE_INPUT], + [[$end]], [[ab]]) + +m4_popdef([AT_PREVIOUS_STATE_GRAMMAR]) +m4_popdef([AT_PREVIOUS_STATE_INPUT]) + +m4_pushdef([AT_USER_ACTION_GRAMMAR], +[[%nonassoc 'a'; + +// If $$ = 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 $$ = 1. +%destructor { + if (!$$) + fprintf (stderr, "Wrong destructor.\n"); +} 'a'; + +// Rather than depend on an inconsistent state to induce reading a +// lookahead as in the previous grammar, just assign the lookahead in a +// semantic action. That lookahead 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 the bug described in the previous grammar, the +// unexpected token was not reported at all. +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 == ]AT_SKEL_CC_IF([[yyempty_]], [[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]]) + +AT_CONSISTENT_ERRORS_CHECK([[]], + [AT_USER_ACTION_GRAMMAR], + [AT_USER_ACTION_INPUT], + [['b']], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[%glr-parser]], + [AT_USER_ACTION_GRAMMAR], + [AT_USER_ACTION_INPUT], + [['b']], [[none]]) +AT_CONSISTENT_ERRORS_CHECK([[%language "c++"]], + [AT_USER_ACTION_GRAMMAR], + [AT_USER_ACTION_INPUT], + [['b']], [[none]]) +# No Java test because yychar cannot be manipulated by users. + +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 @@ -132,7 +445,7 @@ AT_DATA([input.y], exp: exp OP exp | NUM; ]]) -AT_CHECK([bison -o input.c --report=all input.y], 0, [], +AT_BISON_CHECK([-o input.c --report=all input.y], 0, [], [input.y: conflicts: 1 shift/reduce ]) @@ -240,7 +553,7 @@ AT_DATA([input.y], exp: exp OP exp | NUM; ]]) -AT_CHECK([bison -o input.c --report=all input.y]) +AT_BISON_CHECK([-o input.c --report=all input.y]) # Check the contents of the report. AT_CHECK([cat input.output], [], @@ -362,7 +675,7 @@ id : '0'; %% ]]) -AT_CHECK([bison -o input.c --report=all input.y], 0, [], +AT_BISON_CHECK([-o input.c --report=all input.y], 0, [], [[input.y: conflicts: 1 reduce/reduce input.y:4.6-8: warning: rule useless in parser due to conflicts: id: '0' ]]) @@ -479,7 +792,7 @@ AT_DATA([input.y], exp: exp OP exp | NUM; ]]) -AT_CHECK([bison -o input.c input.y], 1, [], +AT_BISON_CHECK([-o input.c input.y], 1, [], [input.y: conflicts: 1 shift/reduce input.y: expected 0 shift/reduce conflicts ]) @@ -499,7 +812,7 @@ AT_DATA([input.y], exp: exp OP exp | NUM; ]]) -AT_CHECK([bison -o input.c input.y]) +AT_BISON_CHECK([-o input.c input.y]) AT_CLEANUP @@ -516,16 +829,16 @@ AT_DATA([input.y], exp: exp OP exp | NUM; ]]) -AT_CHECK([bison -o input.c input.y], 1, [], +AT_BISON_CHECK([-o input.c input.y], 1, [], [input.y: conflicts: 1 shift/reduce input.y: expected 2 shift/reduce conflicts ]) AT_CLEANUP -## ------------------------------ ## -## %expect with reduce conflicts ## -## ------------------------------ ## +## ------------------------------- ## +## %expect with reduce conflicts. ## +## ------------------------------- ## AT_SETUP([%expect with reduce conflicts]) @@ -536,16 +849,33 @@ program: a 'a' | a a; a: 'a'; ]]) -AT_CHECK([bison -o input.c input.y], 1, [], +AT_BISON_CHECK([-o input.c input.y], 1, [], [input.y: conflicts: 1 reduce/reduce input.y: expected 0 reduce/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]) @@ -563,15 +893,15 @@ e: e '+' e ; ]]) -AT_CHECK([bison -o input.c input.y], 0, [], +AT_BISON_CHECK([-o input.c input.y], 0, [], [[input.y: conflicts: 4 shift/reduce ]]) AT_CLEANUP -## ---------------------------- ## -## %no-default-prec with %prec ## -## ---------------------------- ## +## ----------------------------- ## +## %no-default-prec with %prec. ## +## ----------------------------- ## AT_SETUP([%no-default-prec with %prec]) @@ -589,13 +919,13 @@ e: e '+' e %prec '+' ; ]]) -AT_CHECK([bison -o input.c input.y]) +AT_BISON_CHECK([-o input.c input.y]) AT_CLEANUP -## ---------------- ## -## %default-prec ## -## ---------------- ## +## --------------- ## +## %default-prec. ## +## --------------- ## AT_SETUP([%default-prec]) @@ -613,7 +943,7 @@ e: e '+' e ; ]]) -AT_CHECK([bison -o input.c input.y]) +AT_BISON_CHECK([-o input.c input.y]) AT_CLEANUP @@ -665,7 +995,7 @@ reported_conflicts: ]]) -AT_CHECK([[bison --report=all input.y]], 0, [], +AT_BISON_CHECK([[--report=all input.y]], 0, [], [[input.y: conflicts: 1 shift/reduce, 1 reduce/reduce input.y:12.5-20: warning: rule useless in parser due to conflicts: resolved_conflict: 'a' unreachable1 input.y:20.5-20: warning: rule useless in parser due to conflicts: unreachable1: 'a' unreachable2 @@ -813,11 +1143,11 @@ state 7 ]]) AT_DATA([[input-keep.y]], -[[%define lr.keep_unreachable_states +[[%define lr.keep-unreachable-states ]]) AT_CHECK([[cat input.y >> input-keep.y]]) -AT_CHECK([[bison input-keep.y]], 0, [], +AT_BISON_CHECK([[input-keep.y]], 0, [], [[input-keep.y: conflicts: 2 shift/reduce, 2 reduce/reduce input-keep.y:22.4: warning: rule useless in parser due to conflicts: unreachable1: /* empty */ input-keep.y:26.16: warning: rule useless in parser due to conflicts: unreachable2: /* empty */ @@ -858,7 +1188,7 @@ empty_c1: %prec 'c' ; empty_c2: %prec 'c' ; empty_c3: %prec 'd' ; ]]) -AT_CHECK([[bison --report=all -o input.c input.y]], 0, [], [ignore]) +AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore]) AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0, [[state 0 @@ -934,7 +1264,7 @@ empty_c2: %prec 'c' ; empty_c3: %prec 'c' ; ]]) -AT_CHECK([[bison --report=all -o input.c input.y]], 0, [], [ignore]) +AT_BISON_CHECK([[--report=all -o input.c input.y]], 0, [], [ignore]) AT_CHECK([[cat input.output | sed -n '/^state 0$/,/^state 1$/p']], 0, [[state 0