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