• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Bison Regressions.                               -*- Autotest -*-
2
3# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software
4# Foundation, Inc.
5
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2, or (at your option)
9# any later version.
10
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19# 02110-1301, USA.
20
21AT_BANNER([[Regression tests.]])
22
23
24## ------------------ ##
25## Trivial grammars.  ##
26## ------------------ ##
27
28AT_SETUP([Trivial grammars])
29
30AT_DATA_GRAMMAR([input.y],
31[[%{
32void yyerror (char const *);
33int yylex (void);
34#define YYSTYPE int *
35%}
36
37%error-verbose
38
39%%
40
41program: 'x';
42]])
43
44AT_CHECK([bison -o input.c input.y])
45AT_COMPILE([input.o], [-c input.c])
46AT_COMPILE([input.o], [-DYYDEBUG -c input.c])
47
48AT_CLEANUP
49
50
51
52## ------------------------- ##
53## Early token definitions.  ##
54## ------------------------- ##
55
56
57AT_SETUP([Early token definitions])
58
59# Found in GCJ: they expect the tokens to be defined before the user
60# prologue, so that they can use the token definitions in it.
61
62AT_DATA_GRAMMAR([input.y],
63[[%{
64void yyerror (const char *s);
65int yylex (void);
66%}
67
68%union
69{
70  int val;
71};
72%{
73#ifndef MY_TOKEN
74# error "MY_TOKEN not defined."
75#endif
76%}
77%token MY_TOKEN
78%%
79exp: MY_TOKEN;
80%%
81]])
82
83AT_CHECK([bison -o input.c input.y])
84AT_COMPILE([input.o], [-c input.c])
85
86AT_CLEANUP
87
88
89
90## ---------------- ##
91## Braces parsing.  ##
92## ---------------- ##
93
94
95AT_SETUP([Braces parsing])
96
97AT_DATA([input.y],
98[[/* Bison used to swallow the character after `}'. */
99
100%%
101exp: { tests = {{{{{{{{{{}}}}}}}}}}; };
102%%
103]])
104
105AT_CHECK([bison -v -o input.c input.y])
106
107AT_CHECK([grep 'tests = {{{{{{{{{{}}}}}}}}}};' input.c], 0, [ignore])
108
109AT_CLEANUP
110
111
112## ------------------ ##
113## Duplicate string.  ##
114## ------------------ ##
115
116
117AT_SETUP([Duplicate string])
118
119AT_DATA([input.y],
120[[/* `Bison -v' used to dump core when two tokens are defined with the same
121   string, as LE and GE below. */
122
123%token NUM
124%token LE "<="
125%token GE "<="
126
127%%
128exp: '(' exp ')' | NUM ;
129%%
130]])
131
132AT_CHECK([bison -v -o input.c input.y], 0, [],
133[[input.y:6.8-14: warning: symbol `"<="' used more than once as a literal string
134]])
135
136AT_CLEANUP
137
138
139## ------------------- ##
140## Rule Line Numbers.  ##
141## ------------------- ##
142
143AT_SETUP([Rule Line Numbers])
144
145AT_KEYWORDS([report])
146
147AT_DATA([input.y],
148[[%%
149expr:
150'a'
151
152{
153
154}
155
156'b'
157
158{
159
160}
161
162|
163
164
165{
166
167
168}
169
170'c'
171
172{
173
174};
175]])
176
177AT_CHECK([bison -o input.c -v input.y])
178
179# Check the contents of the report.
180AT_CHECK([cat input.output], [],
181[[Grammar
182
183    0 $accept: expr $end
184
185    1 @1: /* empty */
186
187    2 expr: 'a' @1 'b'
188
189    3 @2: /* empty */
190
191    4 expr: @2 'c'
192
193
194Terminals, with rules where they appear
195
196$end (0) 0
197'a' (97) 2
198'b' (98) 2
199'c' (99) 4
200error (256)
201
202
203Nonterminals, with rules where they appear
204
205$accept (6)
206    on left: 0
207expr (7)
208    on left: 2 4, on right: 0
209@1 (8)
210    on left: 1, on right: 2
211@2 (9)
212    on left: 3, on right: 4
213
214
215state 0
216
217    0 $accept: . expr $end
218
219    'a'  shift, and go to state 1
220
221    $default  reduce using rule 3 (@2)
222
223    expr  go to state 2
224    @2    go to state 3
225
226
227state 1
228
229    2 expr: 'a' . @1 'b'
230
231    $default  reduce using rule 1 (@1)
232
233    @1  go to state 4
234
235
236state 2
237
238    0 $accept: expr . $end
239
240    $end  shift, and go to state 5
241
242
243state 3
244
245    4 expr: @2 . 'c'
246
247    'c'  shift, and go to state 6
248
249
250state 4
251
252    2 expr: 'a' @1 . 'b'
253
254    'b'  shift, and go to state 7
255
256
257state 5
258
259    0 $accept: expr $end .
260
261    $default  accept
262
263
264state 6
265
266    4 expr: @2 'c' .
267
268    $default  reduce using rule 4 (expr)
269
270
271state 7
272
273    2 expr: 'a' @1 'b' .
274
275    $default  reduce using rule 2 (expr)
276]])
277
278AT_CLEANUP
279
280
281
282## ---------------------- ##
283## Mixing %token styles.  ##
284## ---------------------- ##
285
286
287AT_SETUP([Mixing %token styles])
288
289# Taken from the documentation.
290AT_DATA([input.y],
291[[%token  <operator>  OR      "||"
292%token  <operator>  LE 134  "<="
293%left  OR  "<="
294%%
295exp: ;
296%%
297]])
298
299AT_CHECK([bison -v -o input.c input.y])
300
301AT_CLEANUP
302
303
304
305## ---------------- ##
306## Invalid inputs.  ##
307## ---------------- ##
308
309
310AT_SETUP([Invalid inputs])
311
312AT_DATA([input.y],
313[[%%
314?
315default: 'a' }
316%&
317%a-does-not-exist
318%-
319%{
320]])
321
322AT_CHECK([bison input.y], [1], [],
323[[input.y:2.1: invalid character: `?'
324input.y:3.14: invalid character: `}'
325input.y:4.1: invalid character: `%'
326input.y:4.2: invalid character: `&'
327input.y:5.1-17: invalid directive: `%a-does-not-exist'
328input.y:6.1: invalid character: `%'
329input.y:6.2: invalid character: `-'
330input.y:7.1-8.0: missing `%}' at end of file
331]])
332
333AT_CLEANUP
334
335
336AT_SETUP([Invalid inputs with {}])
337
338AT_DATA([input.y],
339[[
340%destructor
341%initial-action
342%lex-param
343%parse-param
344%printer
345%union
346]])
347
348AT_CHECK([bison input.y], [1], [],
349[[input.y:3.1: missing `{' in "%destructor {...}"
350input.y:4.1: missing `{' in "%initial-action {...}"
351input.y:4.1: syntax error, unexpected %initial-action {...}, expecting string or identifier
352]])
353
354AT_CLEANUP
355
356
357
358## ------------------- ##
359## Token definitions.  ##
360## ------------------- ##
361
362
363AT_SETUP([Token definitions])
364
365# Bison managed, when fed with `%token 'f' "f"' to #define 'f'!
366AT_DATA_GRAMMAR([input.y],
367[%{
368#include <stdio.h>
369void yyerror (const char *s);
370int yylex (void);
371%}
372[%error-verbose
373%token MYEOF 0 "end of file"
374%token 'a' "a"
375%token B_TOKEN "b"
376%token C_TOKEN 'c'
377%token 'd' D_TOKEN
378%token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!"
379%%
380exp: "a" "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!";
381%%
382void
383yyerror (char const *s)
384{
385  fprintf (stderr, "%s\n", s);
386}
387
388int
389yylex (void)
390{
391  return SPECIAL;
392}
393
394int
395main (void)
396{
397  return yyparse ();
398}
399]])
400
401AT_CHECK([bison -o input.c input.y])
402AT_COMPILE([input])
403AT_DATA([experr],
404[[syntax error, unexpected "\\'?\"\a\b\f\n\r\t\v\001\201\001\201?\?!", expecting a
405]])
406AT_PARSER_CHECK([./input], 1, [], [experr])
407AT_CLEANUP
408
409
410
411## -------------------- ##
412## Characters Escapes.  ##
413## -------------------- ##
414
415
416AT_SETUP([Characters Escapes])
417
418AT_DATA_GRAMMAR([input.y],
419[%{
420void yyerror (const char *s);
421int yylex (void);
422%}
423[%%
424exp:
425  '\'' "\'"
426| '\"' "\""
427| '"'  "'"
428;
429]])
430# Pacify font-lock-mode: "
431
432AT_CHECK([bison -o input.c input.y])
433AT_COMPILE([input.o], [-c input.c])
434AT_CLEANUP
435
436
437
438## -------------- ##
439## Web2c Report.  ##
440## -------------- ##
441
442# The generation of the reduction was once wrong in Bison, and made it
443# miss some reductions.  In the following test case, the reduction on
444# `undef_id_tok' in state 1 was missing.  This is stripped down from
445# the actual web2c.y.
446
447AT_SETUP([Web2c Report])
448
449AT_KEYWORDS([report])
450
451AT_DATA([input.y],
452[[%token	undef_id_tok const_id_tok
453
454%start CONST_DEC_PART
455
456%%
457CONST_DEC_PART:
458         CONST_DEC_LIST
459        ;
460
461CONST_DEC_LIST:
462	  CONST_DEC
463        | CONST_DEC_LIST CONST_DEC
464        ;
465
466CONST_DEC:
467	  { } undef_id_tok '=' const_id_tok ';'
468        ;
469%%
470]])
471
472AT_CHECK([bison -v input.y])
473AT_CHECK([cat input.output], 0,
474[[Grammar
475
476    0 $accept: CONST_DEC_PART $end
477
478    1 CONST_DEC_PART: CONST_DEC_LIST
479
480    2 CONST_DEC_LIST: CONST_DEC
481    3               | CONST_DEC_LIST CONST_DEC
482
483    4 @1: /* empty */
484
485    5 CONST_DEC: @1 undef_id_tok '=' const_id_tok ';'
486
487
488Terminals, with rules where they appear
489
490$end (0) 0
491';' (59) 5
492'=' (61) 5
493error (256)
494undef_id_tok (258) 5
495const_id_tok (259) 5
496
497
498Nonterminals, with rules where they appear
499
500$accept (7)
501    on left: 0
502CONST_DEC_PART (8)
503    on left: 1, on right: 0
504CONST_DEC_LIST (9)
505    on left: 2 3, on right: 1 3
506CONST_DEC (10)
507    on left: 5, on right: 2 3
508@1 (11)
509    on left: 4, on right: 5
510
511
512state 0
513
514    0 $accept: . CONST_DEC_PART $end
515
516    $default  reduce using rule 4 (@1)
517
518    CONST_DEC_PART  go to state 1
519    CONST_DEC_LIST  go to state 2
520    CONST_DEC       go to state 3
521    @1              go to state 4
522
523
524state 1
525
526    0 $accept: CONST_DEC_PART . $end
527
528    $end  shift, and go to state 5
529
530
531state 2
532
533    1 CONST_DEC_PART: CONST_DEC_LIST .
534    3 CONST_DEC_LIST: CONST_DEC_LIST . CONST_DEC
535
536    undef_id_tok  reduce using rule 4 (@1)
537    $default      reduce using rule 1 (CONST_DEC_PART)
538
539    CONST_DEC  go to state 6
540    @1         go to state 4
541
542
543state 3
544
545    2 CONST_DEC_LIST: CONST_DEC .
546
547    $default  reduce using rule 2 (CONST_DEC_LIST)
548
549
550state 4
551
552    5 CONST_DEC: @1 . undef_id_tok '=' const_id_tok ';'
553
554    undef_id_tok  shift, and go to state 7
555
556
557state 5
558
559    0 $accept: CONST_DEC_PART $end .
560
561    $default  accept
562
563
564state 6
565
566    3 CONST_DEC_LIST: CONST_DEC_LIST CONST_DEC .
567
568    $default  reduce using rule 3 (CONST_DEC_LIST)
569
570
571state 7
572
573    5 CONST_DEC: @1 undef_id_tok . '=' const_id_tok ';'
574
575    '='  shift, and go to state 8
576
577
578state 8
579
580    5 CONST_DEC: @1 undef_id_tok '=' . const_id_tok ';'
581
582    const_id_tok  shift, and go to state 9
583
584
585state 9
586
587    5 CONST_DEC: @1 undef_id_tok '=' const_id_tok . ';'
588
589    ';'  shift, and go to state 10
590
591
592state 10
593
594    5 CONST_DEC: @1 undef_id_tok '=' const_id_tok ';' .
595
596    $default  reduce using rule 5 (CONST_DEC)
597]])
598
599AT_CLEANUP
600
601
602## --------------- ##
603## Web2c Actions.  ##
604## --------------- ##
605
606# The generation of the mapping `state -> action' was once wrong in
607# extremely specific situations.  web2c.y exhibits this situation.
608# Below is a stripped version of the grammar.  It looks like one can
609# simplify it further, but just don't: it is tuned to exhibit a bug,
610# which disapears when applying sane grammar transformations.
611#
612# It used to be wrong on yydefact only:
613#
614# static const yytype_uint8 yydefact[] =
615#  {
616# -       2,     0,     1,     0,     0,     2,     3,     2,     5,     4,
617# +       2,     0,     1,     0,     0,     0,     3,     2,     5,     4,
618#         0,     0
619#  };
620#
621# but let's check all the tables.
622
623
624AT_SETUP([Web2c Actions])
625
626AT_KEYWORDS([report])
627
628AT_DATA([input.y],
629[[%%
630statement:  struct_stat;
631struct_stat:  /* empty. */ | if else;
632if: "if" "const" "then" statement;
633else: "else" statement;
634%%
635]])
636
637AT_CHECK([bison -v -o input.c input.y])
638
639# Check only the tables.  We don't use --no-parser, because it is
640# still to be implemented in the experimental branch of Bison.
641[sed -n 's/  *$//;/^static const.*\[\] =/,/^}/p' input.c >tables.c]
642
643AT_CHECK([[cat tables.c]], 0,
644[[static const yytype_uint8 yytranslate[] =
645{
646       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
647       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
648       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
649       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
650       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
651       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
652       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
653       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
654       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
655       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
656       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
657       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
658       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
659       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
660       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
661       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
662       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
663       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
664       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
665       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
666       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
667       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
668       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
669       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
670       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
671       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
672       5,     6
673};
674static const yytype_uint8 yyprhs[] =
675{
676       0,     0,     3,     5,     6,     9,    14
677};
678static const yytype_int8 yyrhs[] =
679{
680       8,     0,    -1,     9,    -1,    -1,    10,    11,    -1,     3,
681       4,     5,     8,    -1,     6,     8,    -1
682};
683static const yytype_uint8 yyrline[] =
684{
685       0,     2,     2,     3,     3,     4,     5
686};
687static const char *const yytname[] =
688{
689  "$end", "error", "$undefined", "\"if\"", "\"const\"", "\"then\"",
690  "\"else\"", "$accept", "statement", "struct_stat", "if", "else", 0
691};
692static const yytype_uint16 yytoknum[] =
693{
694       0,   256,   257,   258,   259,   260,   261
695};
696static const yytype_uint8 yyr1[] =
697{
698       0,     7,     8,     9,     9,    10,    11
699};
700static const yytype_uint8 yyr2[] =
701{
702       0,     2,     1,     0,     2,     4,     2
703};
704static const yytype_uint8 yydefact[] =
705{
706       3,     0,     0,     2,     0,     0,     1,     3,     4,     3,
707       6,     5
708};
709static const yytype_int8 yydefgoto[] =
710{
711      -1,     2,     3,     4,     8
712};
713static const yytype_int8 yypact[] =
714{
715      -2,    -1,     4,    -8,     0,     2,    -8,    -2,    -8,    -2,
716      -8,    -8
717};
718static const yytype_int8 yypgoto[] =
719{
720      -8,    -7,    -8,    -8,    -8
721};
722static const yytype_uint8 yytable[] =
723{
724      10,     1,    11,     5,     6,     0,     7,     9
725};
726static const yytype_int8 yycheck[] =
727{
728       7,     3,     9,     4,     0,    -1,     6,     5
729};
730static const yytype_uint8 yystos[] =
731{
732       0,     3,     8,     9,    10,     4,     0,     6,    11,     5,
733       8,     8
734};
735]])
736
737AT_CLEANUP
738
739
740## ------------------------- ##
741## yycheck Bound Violation.  ##
742## ------------------------- ##
743
744
745# _AT_DATA_DANCER_Y(BISON-OPTIONS)
746# --------------------------------
747# The following grammar, taken from Andrew Suffield's GPL'd implementation
748# of DGMTP, the Dancer Generic Message Transport Protocol, used to violate
749# yycheck's bounds where issuing a verbose error message.  Keep this test
750# so that possible bound checking compilers could check all the skeletons.
751m4_define([_AT_DATA_DANCER_Y],
752[AT_DATA_GRAMMAR([dancer.y],
753[%{
754static int yylex (AT_LALR1_CC_IF([int *], [void]));
755AT_LALR1_CC_IF([],
756[#include <stdio.h>
757static void yyerror (const char *);])
758%}
759$1
760%token ARROW INVALID NUMBER STRING DATA
761%defines
762%verbose
763%error-verbose
764/* Grammar follows */
765%%
766line: header body
767   ;
768
769header: '<' from ARROW to '>' type ':'
770   | '<' ARROW to '>' type ':'
771   | ARROW to type ':'
772   | type ':'
773   | '<' '>'
774   ;
775
776from: DATA
777   | STRING
778   | INVALID
779   ;
780
781to: DATA
782   | STRING
783   | INVALID
784   ;
785
786type: DATA
787   | STRING
788   | INVALID
789   ;
790
791body: /* empty */
792   | body member
793   ;
794
795member: STRING
796   | DATA
797   | '+' NUMBER
798   | '-' NUMBER
799   | NUMBER
800   | INVALID
801   ;
802%%
803AT_LALR1_CC_IF(
804[/* A C++ error reporting function. */
805void
806yy::parser::error (const location&, const std::string& m)
807{
808  std::cerr << m << std::endl;
809}
810
811int
812yyparse ()
813{
814  yy::parser parser;
815  parser.set_debug_level (!!YYDEBUG);
816  return parser.parse ();
817}
818],
819[static void
820yyerror (const char *s)
821{
822  fprintf (stderr, "%s\n", s);
823}])
824
825static int
826yylex (AT_LALR1_CC_IF([int *lval], [void]))
827[{
828  static int toknum = 0;
829  static int tokens[] =
830    {
831      ':', -1
832    };
833  ]AT_LALR1_CC_IF([*lval = 0; /* Pacify GCC.  */])[
834  return tokens[toknum++];
835}]
836
837int
838main (void)
839{
840  return yyparse ();
841}
842])
843])# _AT_DATA_DANCER_Y
844
845
846# AT_CHECK_DANCER(BISON-OPTIONS)
847# ------------------------------
848# Generate the grammar, compile it, run it.
849m4_define([AT_CHECK_DANCER],
850[AT_SETUP([Dancer $1])
851AT_BISON_OPTION_PUSHDEFS([$1])
852_AT_DATA_DANCER_Y([$1])
853AT_CHECK([bison -o dancer.c dancer.y])
854AT_LALR1_CC_IF(
855  [AT_CHECK([bison -o dancer.cc dancer.y])
856   AT_COMPILE_CXX([dancer])],
857  [AT_CHECK([bison -o dancer.c dancer.y])
858   AT_COMPILE([dancer])])
859AT_PARSER_CHECK([./dancer], 1, [],
860[syntax error, unexpected ':'
861])
862AT_BISON_OPTION_POPDEFS
863AT_CLEANUP
864])
865
866AT_CHECK_DANCER()
867AT_CHECK_DANCER([%glr-parser])
868AT_CHECK_DANCER([%skeleton "lalr1.cc"])
869
870
871## ------------------------------------------ ##
872## Diagnostic that expects two alternatives.  ##
873## ------------------------------------------ ##
874
875
876# _AT_DATA_EXPECT2_Y(BISON-OPTIONS)
877# --------------------------------
878m4_define([_AT_DATA_EXPECT2_Y],
879[AT_DATA_GRAMMAR([expect2.y],
880[%{
881static int yylex (AT_LALR1_CC_IF([int *], [void]));
882AT_LALR1_CC_IF([],
883[#include <stdio.h>
884static void yyerror (const char *);])
885%}
886$1
887%defines
888%error-verbose
889%token A 1000
890%token B
891
892%%
893program: /* empty */
894 | program e ';'
895 | program error ';';
896
897e: e '+' t | t;
898t: A | B;
899
900%%
901AT_LALR1_CC_IF(
902[/* A C++ error reporting function. */
903void
904yy::parser::error (const location&, const std::string& m)
905{
906  std::cerr << m << std::endl;
907}
908
909int
910yyparse ()
911{
912  yy::parser parser;
913  return parser.parse ();
914}
915],
916[static void
917yyerror (const char *s)
918{
919  fprintf (stderr, "%s\n", s);
920}])
921
922static int
923yylex (AT_LALR1_CC_IF([int *lval], [void]))
924[{
925  static int toknum = 0;
926  static int tokens[] =
927    {
928      1000, '+', '+', -1
929    };
930  ]AT_LALR1_CC_IF([*lval = 0; /* Pacify GCC.  */])[
931  return tokens[toknum++];
932}]
933
934int
935main (void)
936{
937  return yyparse ();
938}
939])
940])# _AT_DATA_EXPECT2_Y
941
942
943# AT_CHECK_EXPECT2(BISON-OPTIONS)
944# ------------------------------
945# Generate the grammar, compile it, run it.
946m4_define([AT_CHECK_EXPECT2],
947[AT_SETUP([Expecting two tokens $1])
948AT_BISON_OPTION_PUSHDEFS([$1])
949_AT_DATA_EXPECT2_Y([$1])
950AT_CHECK([bison -o expect2.c expect2.y])
951AT_LALR1_CC_IF(
952  [AT_CHECK([bison -o expect2.cc expect2.y])
953   AT_COMPILE_CXX([expect2])],
954  [AT_CHECK([bison -o expect2.c expect2.y])
955   AT_COMPILE([expect2])])
956AT_PARSER_CHECK([./expect2], 1, [],
957[syntax error, unexpected '+', expecting A or B
958])
959AT_BISON_OPTION_POPDEFS
960AT_CLEANUP
961])
962
963AT_CHECK_EXPECT2()
964AT_CHECK_EXPECT2([%glr-parser])
965AT_CHECK_EXPECT2([%skeleton "lalr1.cc"])
966