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