]> git.saurik.com Git - bison.git/blob - tests/regression.at
6a37f759a8e80a330e4ad5cabe88f79125251c34
[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. ##
54 ## ------------------------- ##
55
56
57 AT_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
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 -o input.c input.y])
84 AT_COMPILE([input.o], [-c input.c])
85
86 AT_CLEANUP
87
88
89
90 ## ---------------- ##
91 ## Braces parsing. ##
92 ## ---------------- ##
93
94
95 AT_SETUP([Braces parsing])
96
97 AT_DATA([input.y],
98 [[/* Bison used to swallow the character after `}'. */
99
100 %%
101 exp: { tests = {{{{{{{{{{}}}}}}}}}}; };
102 %%
103 ]])
104
105 AT_CHECK([bison -v -o input.c input.y])
106
107 AT_CHECK([grep 'tests = {{{{{{{{{{}}}}}}}}}};' input.c], 0, [ignore])
108
109 AT_CLEANUP
110
111
112 ## ------------------ ##
113 ## Duplicate string. ##
114 ## ------------------ ##
115
116
117 AT_SETUP([Duplicate string])
118
119 AT_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 %%
128 exp: '(' exp ')' | NUM ;
129 %%
130 ]])
131
132 AT_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
136 AT_CLEANUP
137
138
139 ## ------------------- ##
140 ## Rule Line Numbers. ##
141 ## ------------------- ##
142
143 AT_SETUP([Rule Line Numbers])
144
145 AT_KEYWORDS([report])
146
147 AT_DATA([input.y],
148 [[%%
149 expr:
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
177 AT_CHECK([bison -o input.c -v input.y])
178
179 # Check the contents of the report.
180 AT_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
194 Terminals, with rules where they appear
195
196 $end (0) 0
197 'a' (97) 2
198 'b' (98) 2
199 'c' (99) 4
200 error (256)
201
202
203 Nonterminals, with rules where they appear
204
205 $accept (6)
206 on left: 0
207 expr (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
215 state 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
227 state 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
236 state 2
237
238 0 $accept: expr . $end
239
240 $end shift, and go to state 5
241
242
243 state 3
244
245 4 expr: @2 . 'c'
246
247 'c' shift, and go to state 6
248
249
250 state 4
251
252 2 expr: 'a' @1 . 'b'
253
254 'b' shift, and go to state 7
255
256
257 state 5
258
259 0 $accept: expr $end .
260
261 $default accept
262
263
264 state 6
265
266 4 expr: @2 'c' .
267
268 $default reduce using rule 4 (expr)
269
270
271 state 7
272
273 2 expr: 'a' @1 'b' .
274
275 $default reduce using rule 2 (expr)
276 ]])
277
278 AT_CLEANUP
279
280
281
282 ## ---------------------- ##
283 ## Mixing %token styles. ##
284 ## ---------------------- ##
285
286
287 AT_SETUP([Mixing %token styles])
288
289 # Taken from the documentation.
290 AT_DATA([input.y],
291 [[%token <operator> OR "||"
292 %token <operator> LE 134 "<="
293 %left OR "<="
294 %%
295 exp: ;
296 %%
297 ]])
298
299 AT_CHECK([bison -v -o input.c input.y])
300
301 AT_CLEANUP
302
303
304
305 ## ---------------- ##
306 ## Invalid inputs. ##
307 ## ---------------- ##
308
309
310 AT_SETUP([Invalid inputs])
311
312 AT_DATA([input.y],
313 [[%%
314 ?
315 default: 'a' }
316 %&
317 %a-does-not-exist
318 %-
319 %{
320 ]])
321
322 AT_CHECK([bison input.y], [1], [],
323 [[input.y:2.1: invalid character: `?'
324 input.y:3.14: invalid character: `}'
325 input.y:4.1: invalid character: `%'
326 input.y:4.2: invalid character: `&'
327 input.y:5.1-17: invalid directive: `%a-does-not-exist'
328 input.y:6.1: invalid character: `%'
329 input.y:6.2: invalid character: `-'
330 input.y:7.1-8.0: missing `%}' at end of file
331 ]])
332
333 AT_CLEANUP
334
335
336 AT_SETUP([Invalid inputs with {}])
337
338 AT_DATA([input.y],
339 [[
340 %destructor
341 %initial-action
342 %lex-param
343 %parse-param
344 %printer
345 %union
346 ]])
347
348 AT_CHECK([bison input.y], [1], [],
349 [[input.y:3.1: missing `{' in "%destructor {...}"
350 input.y:4.1: missing `{' in "%initial-action {...}"
351 input.y:4.1: syntax error, unexpected %initial-action {...}, expecting string or identifier
352 ]])
353
354 AT_CLEANUP
355
356
357
358 ## ------------------- ##
359 ## Token definitions. ##
360 ## ------------------- ##
361
362
363 AT_SETUP([Token definitions])
364
365 # Bison managed, when fed with `%token 'f' "f"' to #define 'f'!
366 AT_DATA_GRAMMAR([input.y],
367 [%{
368 #include <stdio.h>
369 void yyerror (const char *s);
370 int 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 %%
380 exp: "a" "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!";
381 %%
382 void
383 yyerror (char const *s)
384 {
385 fprintf (stderr, "%s\n", s);
386 }
387
388 int
389 yylex (void)
390 {
391 return SPECIAL;
392 }
393
394 int
395 main (void)
396 {
397 return yyparse ();
398 }
399 ]])
400
401 AT_CHECK([bison -o input.c input.y])
402 AT_COMPILE([input])
403 AT_DATA([experr],
404 [[syntax error, unexpected "\\'?\"\a\b\f\n\r\t\v\001\201\001\201?\?!", expecting a
405 ]])
406 AT_PARSER_CHECK([./input], 1, [], [experr])
407 AT_CLEANUP
408
409
410
411 ## -------------------- ##
412 ## Characters Escapes. ##
413 ## -------------------- ##
414
415
416 AT_SETUP([Characters Escapes])
417
418 AT_DATA_GRAMMAR([input.y],
419 [%{
420 void yyerror (const char *s);
421 int yylex (void);
422 %}
423 [%%
424 exp:
425 '\'' "\'"
426 | '\"' "\""
427 | '"' "'"
428 ;
429 ]])
430 # Pacify font-lock-mode: "
431
432 AT_CHECK([bison -o input.c input.y])
433 AT_COMPILE([input.o], [-c input.c])
434 AT_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
447 AT_SETUP([Web2c Report])
448
449 AT_KEYWORDS([report])
450
451 AT_DATA([input.y],
452 [[%token undef_id_tok const_id_tok
453
454 %start CONST_DEC_PART
455 \f
456 %%
457 CONST_DEC_PART:
458 CONST_DEC_LIST
459 ;
460
461 CONST_DEC_LIST:
462 CONST_DEC
463 | CONST_DEC_LIST CONST_DEC
464 ;
465
466 CONST_DEC:
467 { } undef_id_tok '=' const_id_tok ';'
468 ;
469 %%
470 ]])
471
472 AT_CHECK([bison -v input.y])
473 AT_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
488 Terminals, with rules where they appear
489
490 $end (0) 0
491 ';' (59) 5
492 '=' (61) 5
493 error (256)
494 undef_id_tok (258) 5
495 const_id_tok (259) 5
496
497
498 Nonterminals, with rules where they appear
499
500 $accept (7)
501 on left: 0
502 CONST_DEC_PART (8)
503 on left: 1, on right: 0
504 CONST_DEC_LIST (9)
505 on left: 2 3, on right: 1 3
506 CONST_DEC (10)
507 on left: 5, on right: 2 3
508 @1 (11)
509 on left: 4, on right: 5
510
511
512 state 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
524 state 1
525
526 0 $accept: CONST_DEC_PART . $end
527
528 $end shift, and go to state 5
529
530
531 state 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
543 state 3
544
545 2 CONST_DEC_LIST: CONST_DEC .
546
547 $default reduce using rule 2 (CONST_DEC_LIST)
548
549
550 state 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
557 state 5
558
559 0 $accept: CONST_DEC_PART $end .
560
561 $default accept
562
563
564 state 6
565
566 3 CONST_DEC_LIST: CONST_DEC_LIST CONST_DEC .
567
568 $default reduce using rule 3 (CONST_DEC_LIST)
569
570
571 state 7
572
573 5 CONST_DEC: @1 undef_id_tok . '=' const_id_tok ';'
574
575 '=' shift, and go to state 8
576
577
578 state 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
585 state 9
586
587 5 CONST_DEC: @1 undef_id_tok '=' const_id_tok . ';'
588
589 ';' shift, and go to state 10
590
591
592 state 10
593
594 5 CONST_DEC: @1 undef_id_tok '=' const_id_tok ';' .
595
596 $default reduce using rule 5 (CONST_DEC)
597 ]])
598
599 AT_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
624 AT_SETUP([Web2c Actions])
625
626 AT_KEYWORDS([report])
627
628 AT_DATA([input.y],
629 [[%%
630 statement: struct_stat;
631 struct_stat: /* empty. */ | if else;
632 if: "if" "const" "then" statement;
633 else: "else" statement;
634 %%
635 ]])
636
637 AT_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
643 AT_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 };
674 static const yytype_uint8 yyprhs[] =
675 {
676 0, 0, 3, 5, 6, 9, 14
677 };
678 static 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 };
683 static const yytype_uint8 yyrline[] =
684 {
685 0, 2, 2, 3, 3, 4, 5
686 };
687 static const char *const yytname[] =
688 {
689 "$end", "error", "$undefined", "\"if\"", "\"const\"", "\"then\"",
690 "\"else\"", "$accept", "statement", "struct_stat", "if", "else", 0
691 };
692 static const yytype_uint16 yytoknum[] =
693 {
694 0, 256, 257, 258, 259, 260, 261
695 };
696 static const yytype_uint8 yyr1[] =
697 {
698 0, 7, 8, 9, 9, 10, 11
699 };
700 static const yytype_uint8 yyr2[] =
701 {
702 0, 2, 1, 0, 2, 4, 2
703 };
704 static const yytype_uint8 yydefact[] =
705 {
706 3, 0, 0, 2, 0, 0, 1, 3, 4, 3,
707 6, 5
708 };
709 static const yytype_int8 yydefgoto[] =
710 {
711 -1, 2, 3, 4, 8
712 };
713 static const yytype_int8 yypact[] =
714 {
715 -2, -1, 4, -8, 0, 2, -8, -2, -8, -2,
716 -8, -8
717 };
718 static const yytype_int8 yypgoto[] =
719 {
720 -8, -7, -8, -8, -8
721 };
722 static const yytype_uint8 yytable[] =
723 {
724 10, 1, 11, 5, 6, 0, 7, 9
725 };
726 static const yytype_int8 yycheck[] =
727 {
728 7, 3, 9, 4, 0, -1, 6, 5
729 };
730 static const yytype_uint8 yystos[] =
731 {
732 0, 3, 8, 9, 10, 4, 0, 6, 11, 5,
733 8, 8
734 };
735 ]])
736
737 AT_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.
751 m4_define([_AT_DATA_DANCER_Y],
752 [AT_DATA_GRAMMAR([dancer.y],
753 [%{
754 static int yylex (AT_LALR1_CC_IF([int *], [void]));
755 AT_LALR1_CC_IF([],
756 [#include <stdio.h>
757 static 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 %%
766 line: header body
767 ;
768
769 header: '<' from ARROW to '>' type ':'
770 | '<' ARROW to '>' type ':'
771 | ARROW to type ':'
772 | type ':'
773 | '<' '>'
774 ;
775
776 from: DATA
777 | STRING
778 | INVALID
779 ;
780
781 to: DATA
782 | STRING
783 | INVALID
784 ;
785
786 type: DATA
787 | STRING
788 | INVALID
789 ;
790
791 body: /* empty */
792 | body member
793 ;
794
795 member: STRING
796 | DATA
797 | '+' NUMBER
798 | '-' NUMBER
799 | NUMBER
800 | INVALID
801 ;
802 %%
803 AT_LALR1_CC_IF(
804 [/* A C++ error reporting function. */
805 void
806 yy::parser::error (const location&, const std::string& m)
807 {
808 std::cerr << m << std::endl;
809 }
810
811 int
812 yyparse ()
813 {
814 yy::parser parser;
815 parser.set_debug_level (!!YYDEBUG);
816 return parser.parse ();
817 }
818 ],
819 [static void
820 yyerror (const char *s)
821 {
822 fprintf (stderr, "%s\n", s);
823 }])
824
825 static int
826 yylex (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
837 int
838 main (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.
849 m4_define([AT_CHECK_DANCER],
850 [AT_SETUP([Dancer $1])
851 AT_BISON_OPTION_PUSHDEFS([$1])
852 _AT_DATA_DANCER_Y([$1])
853 AT_CHECK([bison -o dancer.c dancer.y])
854 AT_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])])
859 AT_PARSER_CHECK([./dancer], 1, [],
860 [syntax error, unexpected ':'
861 ])
862 AT_BISON_OPTION_POPDEFS
863 AT_CLEANUP
864 ])
865
866 AT_CHECK_DANCER()
867 AT_CHECK_DANCER([%glr-parser])
868 AT_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 # --------------------------------
878 m4_define([_AT_DATA_EXPECT2_Y],
879 [AT_DATA_GRAMMAR([expect2.y],
880 [%{
881 static int yylex (AT_LALR1_CC_IF([int *], [void]));
882 AT_LALR1_CC_IF([],
883 [#include <stdio.h>
884 static void yyerror (const char *);])
885 %}
886 $1
887 %defines
888 %error-verbose
889 %token A 1000
890 %token B
891
892 %%
893 program: /* empty */
894 | program e ';'
895 | program error ';';
896
897 e: e '+' t | t;
898 t: A | B;
899
900 %%
901 AT_LALR1_CC_IF(
902 [/* A C++ error reporting function. */
903 void
904 yy::parser::error (const location&, const std::string& m)
905 {
906 std::cerr << m << std::endl;
907 }
908
909 int
910 yyparse ()
911 {
912 yy::parser parser;
913 return parser.parse ();
914 }
915 ],
916 [static void
917 yyerror (const char *s)
918 {
919 fprintf (stderr, "%s\n", s);
920 }])
921
922 static int
923 yylex (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
934 int
935 main (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.
946 m4_define([AT_CHECK_EXPECT2],
947 [AT_SETUP([Expecting two tokens $1])
948 AT_BISON_OPTION_PUSHDEFS([$1])
949 _AT_DATA_EXPECT2_Y([$1])
950 AT_CHECK([bison -o expect2.c expect2.y])
951 AT_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])])
956 AT_PARSER_CHECK([./expect2], 1, [],
957 [syntax error, unexpected '+', expecting A or B
958 ])
959 AT_BISON_OPTION_POPDEFS
960 AT_CLEANUP
961 ])
962
963 AT_CHECK_EXPECT2()
964 AT_CHECK_EXPECT2([%glr-parser])
965 AT_CHECK_EXPECT2([%skeleton "lalr1.cc"])