]> git.saurik.com Git - bison.git/blame_incremental - tests/glr-regression.at
* bootstrap.conf (gnulib_modules): Add config-h.
[bison.git] / tests / glr-regression.at
... / ...
CommitLineData
1# Checking GLR Parsing: Regression Tests -*- Autotest -*-
2# Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
3
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2, or (at your option)
7# any later version.
8
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17# 02110-1301, USA.
18
19AT_BANNER([[GLR Regression Tests]])
20
21## --------------------------- ##
22## Badly Collapsed GLR States. ##
23## --------------------------- ##
24
25AT_SETUP([Badly Collapsed GLR States])
26
27AT_DATA_GRAMMAR([glr-regr1.y],
28[[/* Regression Test: Improper state compression */
29/* Reported by Scott McPeak */
30
31%{
32#include <stdio.h>
33#include <stdlib.h>
34
35#define YYSTYPE int
36static YYSTYPE exprMerge (YYSTYPE x0, YYSTYPE x1);
37int yylex (void);
38void yyerror (char const *msg);
39%}
40
41
42%glr-parser
43
44
45/* -------- productions ------ */
46%%
47
48StartSymbol: E { $$=0; } %merge <exprMerge>
49 ;
50
51E: E 'P' E { $$=1; printf("E -> E 'P' E\n"); } %merge <exprMerge>
52 | 'B' { $$=2; printf("E -> 'B'\n"); } %merge <exprMerge>
53 ;
54
55
56
57/* ---------- C code ----------- */
58%%
59
60static YYSTYPE exprMerge (YYSTYPE x0, YYSTYPE x1)
61{
62 (void) x0;
63 (void) x1;
64 printf ("<OR>\n");
65 return 0;
66}
67
68int
69main (void)
70{
71 return yyparse ();
72}
73
74void
75yyerror (char const *msg)
76{
77 fprintf (stderr, "%s\n", msg);
78}
79
80
81int
82yylex (void)
83{
84 for (;;)
85 {
86 int ch;
87 if (feof (stdin))
88 abort ();
89 ch = getchar ();
90 if (ch == EOF)
91 return 0;
92 else if (ch == 'B' || ch == 'P')
93 return ch;
94 }
95}
96]])
97
98AT_CHECK([[bison -o glr-regr1.c glr-regr1.y]], 0, [],
99[glr-regr1.y: conflicts: 1 shift/reduce
100])
101AT_COMPILE([glr-regr1])
102AT_CHECK([[echo BPBPB | ./glr-regr1]], 0,
103[[E -> 'B'
104E -> 'B'
105E -> E 'P' E
106E -> 'B'
107E -> E 'P' E
108E -> 'B'
109E -> E 'P' E
110E -> E 'P' E
111<OR>
112]], [])
113
114AT_CLEANUP
115
116## ------------------------------------------------------------ ##
117## Improper handling of embedded actions and $-N in GLR parsers ##
118## ------------------------------------------------------------ ##
119
120AT_SETUP([Improper handling of embedded actions and dollar(-N) in GLR parsers])
121
122AT_DATA_GRAMMAR([glr-regr2a.y],
123[[/* Regression Test: Improper handling of embedded actions and $-N */
124/* Reported by S. Eken */
125
126%{
127 #define YYSTYPE char *
128
129 #include <ctype.h>
130 #include <stdio.h>
131 #include <stdlib.h>
132 #include <string.h>
133 int yylex (void);
134 void yyerror (char const *);
135%}
136
137%glr-parser
138
139%%
140
141command:
142 's' var 't'
143 { printf ("Variable: '%s'\n", $2); }
144 'v' 'x' 'q'
145 { free ($2); }
146 | 's' var_list 't' 'e'
147 { printf ("Varlist: '%s'\n", $2); free ($2); }
148 | 's' var 't' var_printer 'x'
149 { free ($2); }
150 ;
151
152var:
153 'V'
154 { $$ = $1; }
155 ;
156
157var_list:
158 var
159 { $$ = $1; }
160 | var ',' var_list
161 {
162 char *s = (char *) realloc ($1, strlen ($1) + 1 + strlen ($3) + 1);
163 strcat (s, ",");
164 strcat (s, $3);
165 free ($3);
166 $$ = s;
167 }
168 ;
169
170var_printer: 'v'
171 { printf ("Variable: '%s'\n", $-1); }
172
173%%
174
175FILE *input;
176
177int
178yylex (void)
179{
180 char buf[50];
181 char *s;
182 if (feof (stdin))
183 abort ();
184 switch (fscanf (input, " %1[a-z,]", buf)) {
185 case 1:
186 return buf[0];
187 case EOF:
188 return 0;
189 default:
190 break;
191 }
192 if (fscanf (input, "%49s", buf) != 1)
193 return 0;
194 if (sizeof buf - 1 <= strlen (buf))
195 abort ();
196 s = (char *) malloc (strlen (buf) + 1);
197 strcpy (s, buf);
198 yylval = s;
199 return 'V';
200}
201
202void
203yyerror (char const *s)
204{ printf ("%s\n", s);
205}
206
207int
208main (int argc, char **argv)
209{
210 input = stdin;
211 if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3;
212 return yyparse ();
213}
214]])
215
216AT_CHECK([[bison -o glr-regr2a.c glr-regr2a.y]], 0, [],
217[glr-regr2a.y: conflicts: 2 shift/reduce
218])
219AT_COMPILE([glr-regr2a])
220
221AT_CHECK([[echo s VARIABLE_1 t v x q | ./glr-regr2a]], 0,
222[[Variable: 'VARIABLE_1'
223]], [])
224AT_CHECK([[echo s VARIABLE_1 , ANOTHER_VARIABLE_2 t e | ./glr-regr2a]], 0,
225[[Varlist: 'VARIABLE_1,ANOTHER_VARIABLE_2'
226]])
227AT_CHECK([[echo s VARIABLE_3 t v x | ./glr-regr2a]], 0,
228[[Variable: 'VARIABLE_3'
229]], [])
230
231
232AT_CLEANUP
233
234## ------------------------------------------------------------ ##
235## Improper merging of GLR delayed action sets ##
236## ------------------------------------------------------------ ##
237
238AT_SETUP([Improper merging of GLR delayed action sets])
239
240AT_DATA_GRAMMAR([glr-regr3.y],
241[[/* Regression Test: Improper merging of GLR delayed action sets. */
242/* Reported by M. Rosien */
243
244%{
245#include <stdio.h>
246#include <stdlib.h>
247#include <stdarg.h>
248
249static int MergeRule (int x0, int x1);
250static void yyerror (char const * s);
251int yylex (void);
252
253#define RULE(x) (1 << (x))
254
255%}
256
257%glr-parser
258
259%token BAD_CHAR
260%token P1 P2 T1 T2 T3 T4 O1 O2
261
262%%
263
264S : P1 T4 O2 NT6 P2 { printf ("Result: %x\n", $4); }
265;
266
267NT1 : P1 T1 O1 T2 P2 { $$ = RULE(2); } %merge<MergeRule>
268;
269
270NT2 : NT1 { $$ = RULE(3); } %merge<MergeRule>
271 | P1 NT1 O1 T3 P2 { $$ = RULE(4); } %merge<MergeRule>
272;
273
274NT3 : T3 { $$ = RULE(5); } %merge<MergeRule>
275 | P1 NT1 O1 T3 P2 { $$ = RULE(6); } %merge<MergeRule>
276;
277
278NT4 : NT3 { $$ = RULE(7); } %merge<MergeRule>
279 | NT2 { $$ = RULE(8); } %merge<MergeRule>
280 | P1 NT2 O1 NT3 P2 { $$ = RULE(9); } %merge<MergeRule>
281;
282
283NT5 : NT4 { $$ = RULE(10); } %merge<MergeRule>
284;
285
286NT6 : P1 NT1 O1 T3 P2 { $$ = RULE(11) | $2; } %merge<MergeRule>
287 | NT5 { $$ = RULE(12) | $1; } %merge<MergeRule>
288;
289
290%%
291
292static int MergeRule (int x0, int x1) {
293 return x0 | x1;
294}
295
296static void yyerror(char const * s) {
297 fprintf(stderr,"error: %s\n",s);
298}
299
300FILE *input = NULL;
301
302int P[] = { P1, P2 };
303int O[] = { O1, O2 };
304int T[] = { T1, T2, T3, T4 };
305
306int yylex (void)
307{
308 char inp[3];
309 if (feof (stdin))
310 abort ();
311 if (fscanf (input, "%2s", inp) == EOF)
312 return 0;
313 switch (inp[0])
314 {
315 case 'p': return P[inp[1] - '1'];
316 case 't': return T[inp[1] - '1'];
317 case 'o': return O[inp[1] - '1'];
318 }
319 return BAD_CHAR;
320}
321
322int main(int argc, char* argv[]) {
323 input = stdin;
324 if (argc == 2 && !(input = fopen (argv[1], "r"))) return 3;
325 return yyparse ();
326}
327]])
328
329AT_CHECK([[bison -o glr-regr3.c glr-regr3.y]], 0, [],
330[glr-regr3.y: conflicts: 1 shift/reduce, 1 reduce/reduce
331])
332AT_COMPILE([glr-regr3])
333
334AT_CHECK([[echo p1 t4 o2 p1 p1 t1 o1 t2 p2 o1 t3 p2 p2 | ./glr-regr3]], 0,
335[[Result: 1c04
336]], [])
337
338AT_CLEANUP
339
340
341## ------------------------------------------------------------------------- ##
342## Duplicate representation of merged trees. See ##
343## <http://lists.gnu.org/archive/html/help-bison/2005-07/msg00013.html>. ##
344## ------------------------------------------------------------------------- ##
345
346AT_SETUP([Duplicate representation of merged trees])
347
348AT_DATA_GRAMMAR([glr-regr4.y],
349[[
350%union { char *ptr; }
351%type <ptr> S A A1 A2 B
352%glr-parser
353
354%{
355 #include <stdio.h>
356 #include <stdlib.h>
357 #include <string.h>
358 static char *merge (YYSTYPE, YYSTYPE);
359 static char *make_value (char const *, char const *);
360 static void yyerror (char const *);
361 static int yylex (void);
362%}
363
364%%
365
366tree: S { printf ("%s\n", $1); } ;
367
368S:
369 A %merge<merge> { $$ = make_value ("S", $1); }
370 | B %merge<merge> { $$ = make_value ("S", $1); }
371 ;
372
373A:
374 A1 %merge<merge> { $$ = make_value ("A", $1); }
375 | A2 %merge<merge> { $$ = make_value ("A", $1); }
376 ;
377
378A1: 'a' { $$ = make_value ("A1", "'a'"); } ;
379A2: 'a' { $$ = make_value ("A2", "'a'"); } ;
380B: 'a' { $$ = make_value ("B", "'a'"); } ;
381
382%%
383
384static int
385yylex (void)
386{
387 static char const input[] = "a";
388 static size_t toknum;
389 if (! (toknum < sizeof input))
390 abort ();
391 return input[toknum++];
392}
393
394int
395main (void)
396{
397 return yyparse ();
398}
399
400static char *
401make_value (char const *parent, char const *child)
402{
403 char const format[] = "%s <- %s";
404 char *value =
405 (char *) malloc (strlen (parent) + strlen (child) + sizeof format);
406 sprintf (value, format, parent, child);
407 return value;
408}
409
410static char *
411merge (YYSTYPE s1, YYSTYPE s2)
412{
413 char const format[] = "merge{ %s and %s }";
414 char *value =
415 (char *) malloc (strlen (s1.ptr) + strlen (s2.ptr) + sizeof format);
416 sprintf (value, format, s1.ptr, s2.ptr);
417 return value;
418}
419
420static void
421yyerror (char const *msg)
422{
423 fprintf (stderr, "%s\n", msg);
424}
425]])
426
427AT_CHECK([[bison -o glr-regr4.c glr-regr4.y]], 0, [],
428[glr-regr4.y: conflicts: 1 reduce/reduce
429])
430AT_COMPILE([glr-regr4])
431
432AT_CHECK([[./glr-regr4]], 0,
433[[merge{ S <- merge{ A <- A1 <- 'a' and A <- A2 <- 'a' } and S <- B <- 'a' }
434]], [])
435
436AT_CLEANUP
437
438
439## -------------------------------------------------------------------------- ##
440## User destructor for unresolved GLR semantic value. See ##
441## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00016.html>. ##
442## -------------------------------------------------------------------------- ##
443
444AT_SETUP([User destructor for unresolved GLR semantic value])
445
446AT_DATA_GRAMMAR([glr-regr5.y],
447[[
448%{
449 #include <stdio.h>
450 #include <stdlib.h>
451 static void yyerror (char const *);
452 static int yylex (void);
453 enum { MAGIC_VALUE = -1057808125 }; /* originally chosen at random */
454%}
455
456%glr-parser
457%union { int value; }
458%type <value> start
459
460%destructor {
461 if ($$ != MAGIC_VALUE)
462 {
463 fprintf (stderr, "Bad destructor call.\n");
464 exit (EXIT_FAILURE);
465 }
466} start
467
468%%
469
470start:
471 'a' { $$ = MAGIC_VALUE; }
472 | 'a' { $$ = MAGIC_VALUE; }
473 ;
474
475%%
476
477static int
478yylex (void)
479{
480 static char const input[] = "a";
481 static size_t toknum;
482 if (! (toknum < sizeof input))
483 abort ();
484 return input[toknum++];
485}
486
487static void
488yyerror (char const *msg)
489{
490 fprintf (stderr, "%s\n", msg);
491}
492
493int
494main (void)
495{
496 return yyparse () != 1;
497}
498]])
499
500AT_CHECK([[bison -o glr-regr5.c glr-regr5.y]], 0, [],
501[glr-regr5.y: conflicts: 1 reduce/reduce
502])
503AT_COMPILE([glr-regr5])
504
505AT_CHECK([[./glr-regr5]], 0, [],
506[syntax is ambiguous
507])
508
509AT_CLEANUP
510
511
512## -------------------------------------------------------------------------- ##
513## User destructor after an error during a split parse. See ##
514## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00029.html>. ##
515## -------------------------------------------------------------------------- ##
516
517AT_SETUP([User destructor after an error during a split parse])
518
519AT_DATA_GRAMMAR([glr-regr6.y],
520[[
521%{
522 #include <stdio.h>
523 #include <stdlib.h>
524 static void yyerror (char const *);
525 static int yylex (void);
526%}
527
528%glr-parser
529%union { int value; }
530%type <value> 'a'
531
532%destructor {
533 printf ("Destructor called.\n");
534} 'a'
535
536%%
537
538start: 'a' | 'a' ;
539
540%%
541
542static int
543yylex (void)
544{
545 static char const input[] = "a";
546 static size_t toknum;
547 if (! (toknum < sizeof input))
548 abort ();
549 return input[toknum++];
550}
551
552static void
553yyerror (char const *msg)
554{
555 fprintf (stderr, "%s\n", msg);
556}
557
558int
559main (void)
560{
561 return yyparse () != 1;
562}
563]])
564
565AT_CHECK([[bison -o glr-regr6.c glr-regr6.y]], 0, [],
566[glr-regr6.y: conflicts: 1 reduce/reduce
567])
568AT_COMPILE([glr-regr6])
569
570AT_CHECK([[./glr-regr6]], 0,
571[Destructor called.
572],
573[syntax is ambiguous
574])
575
576AT_CLEANUP
577
578
579## ------------------------------------------------------------------------- ##
580## Duplicated user destructor for lookahead. See ##
581## <http://lists.gnu.org/archive/html/bison-patches/2005-08/msg00035.html>. ##
582## ------------------------------------------------------------------------- ##
583
584AT_SETUP([Duplicated user destructor for lookahead])
585
586AT_DATA_GRAMMAR([glr-regr7.y],
587[[
588%{
589 #include <stdio.h>
590 #include <stdlib.h>
591 static void yyerror (char const *);
592 static int yylex (void);
593 #define YYSTACKEXPANDABLE 0
594%}
595
596%glr-parser
597%union { int *count; }
598%type <count> 'a'
599
600%destructor {
601 if ((*$$)++)
602 fprintf (stderr, "Destructor called on same value twice.\n");
603} 'a'
604
605%%
606
607start:
608 stack1 start
609 | stack2 start
610 | /* empty */
611 ;
612stack1: 'a' ;
613stack2: 'a' ;
614
615%%
616
617static int
618yylex (void)
619{
620 yylval.count = (int *) malloc (sizeof (int));
621 if (!yylval.count)
622 {
623 fprintf (stderr, "Test inconclusive.\n");
624 exit (EXIT_FAILURE);
625 }
626 *yylval.count = 0;
627 return 'a';
628}
629
630static void
631yyerror (char const *msg)
632{
633 fprintf (stderr, "%s\n", msg);
634}
635
636int
637main (void)
638{
639 return yyparse ();
640}
641]])
642
643AT_CHECK([[bison -o glr-regr7.c glr-regr7.y]], 0, [],
644[glr-regr7.y: conflicts: 2 reduce/reduce
645])
646AT_COMPILE([glr-regr7])
647
648AT_CHECK([[./glr-regr7]], 2, [],
649[memory exhausted
650])
651
652AT_CLEANUP
653
654
655## ------------------------------------------------------------------------- ##
656## Incorrect default location for empty right-hand sides. Adapted from bug ##
657## report by Claudia Hermann. ##
658## See http://lists.gnu.org/archive/html/bug-bison/2005-10/msg00069.html and ##
659## http://lists.gnu.org/archive/html/bug-bison/2005-10/msg00072.html ##
660## ------------------------------------------------------------------------- ##
661
662AT_SETUP([Incorrectly initialized location for empty right-hand side in GLR])
663
664AT_DATA_GRAMMAR([glr-regr8.y],
665[[
666%{
667 #include <stdio.h>
668 #include <stdlib.h>
669 static void yyerror (char const *);
670 static int yylex (void);
671 static void yyerror (char const *msg);
672%}
673
674%token T_CONSTANT
675%token T_PORT
676%token T_SIGNAL
677
678%glr-parser
679
680%%
681
682
683PortClause : T_PORT InterfaceDeclaration T_PORT
684 { printf("%d/%d - %d/%d - %d/%d\n",
685 @1.first_column, @1.last_column,
686 @2.first_column, @2.last_column,
687 @3.first_column, @3.last_column); }
688 ;
689
690InterfaceDeclaration : OptConstantWord %dprec 1
691 | OptSignalWord %dprec 2
692 ;
693
694OptConstantWord : /* empty */
695 | T_CONSTANT
696 ;
697
698OptSignalWord : /* empty */
699 { printf("empty: %d/%d\n", @$.first_column, @$.last_column); }
700 | T_SIGNAL
701 ;
702
703%%
704
705void
706yyerror (char const *msg)
707{
708 fprintf (stderr, "%s\n", msg);
709}
710
711static int lexIndex;
712
713int yylex (void)
714{
715 lexIndex += 1;
716 switch (lexIndex)
717 {
718 default:
719 abort ();
720 case 1:
721 yylloc.first_column = 1;
722 yylloc.last_column = 9;
723 return T_PORT;
724 case 2:
725 yylloc.first_column = 13;
726 yylloc.last_column = 17;
727 return T_PORT;
728 case 3:
729 return 0;
730 }
731}
732
733int
734main (void)
735{
736 yyparse();
737 return 0;
738}
739]])
740
741AT_CHECK([[bison -o glr-regr8.c glr-regr8.y]], 0, [],
742[glr-regr8.y: conflicts: 1 reduce/reduce
743])
744AT_COMPILE([glr-regr8])
745
746AT_CHECK([[./glr-regr8]], 0,
747[empty: 9/9
7481/9 - 9/9 - 13/17
749],
750[])
751
752AT_CLEANUP
753
754
755## ------------------------------------------------------------------------- ##
756## No users destructors if stack 0 deleted. See ##
757## <http://lists.gnu.org/archive/html/bison-patches/2005-09/msg00109.html>. ##
758## ------------------------------------------------------------------------- ##
759
760AT_SETUP([No users destructors if stack 0 deleted])
761
762AT_DATA_GRAMMAR([glr-regr9.y],
763[[
764%{
765# include <stdio.h>
766# include <stdlib.h>
767 static void yyerror (char const *);
768 static int yylex (void);
769# define YYSTACKEXPANDABLE 0
770 static int tokens = 0;
771 static int destructors = 0;
772# define USE(Var)
773%}
774
775%glr-parser
776%union { int dummy; }
777%type <dummy> 'a'
778
779%destructor {
780 destructors += 1;
781} 'a'
782
783%%
784
785start:
786 ambig0 'a' { destructors += 2; USE ($2); }
787 | ambig1 start { destructors += 1; }
788 | ambig2 start { destructors += 1; }
789 ;
790
791ambig0: 'a' ;
792ambig1: 'a' ;
793ambig2: 'a' ;
794
795%%
796
797static int
798yylex (void)
799{
800 tokens += 1;
801 return 'a';
802}
803
804static void
805yyerror (char const *msg)
806{
807 fprintf (stderr, "%s\n", msg);
808}
809
810int
811main (void)
812{
813 int exit_status;
814 exit_status = yyparse ();
815 if (tokens != destructors)
816 {
817 fprintf (stderr, "Tokens = %d, Destructors = %d\n", tokens, destructors);
818 return 1;
819 }
820 return !exit_status;
821}
822]])
823
824AT_CHECK([[bison -o glr-regr9.c glr-regr9.y]], 0, [],
825[glr-regr9.y: conflicts: 1 reduce/reduce
826])
827AT_COMPILE([glr-regr9])
828
829AT_CHECK([[./glr-regr9]], 0, [],
830[memory exhausted
831])
832
833AT_CLEANUP
834
835
836## ------------------------------------------------------------------------- ##
837## Corrupted semantic options if user action cuts parse. ##
838## ------------------------------------------------------------------------- ##
839
840AT_SETUP([Corrupted semantic options if user action cuts parse])
841
842AT_DATA_GRAMMAR([glr-regr10.y],
843[[
844%{
845# include <stdlib.h>
846# include <stdio.h>
847 static void yyerror (char const *);
848 static int yylex (void);
849 #define GARBAGE_SIZE 50
850 static char garbage[GARBAGE_SIZE];
851%}
852
853%glr-parser
854%union { char *ptr; }
855%type <ptr> start
856
857%%
858
859start:
860 %dprec 2 { $$ = garbage; YYACCEPT; }
861 | %dprec 1 { $$ = garbage; YYACCEPT; }
862 ;
863
864%%
865
866static void
867yyerror (char const *msg)
868{
869 fprintf (stderr, "%s\n", msg);
870}
871
872static int
873yylex (void)
874{
875 static int called;
876 if (called++)
877 abort ();
878 return 0;
879}
880
881int
882main (void)
883{
884 int i;
885 for (i = 0; i < GARBAGE_SIZE; i+=1)
886 garbage[i] = 108;
887 return yyparse ();
888}
889]])
890
891AT_CHECK([[bison -o glr-regr10.c glr-regr10.y]], 0, [],
892[glr-regr10.y: conflicts: 1 reduce/reduce
893])
894AT_COMPILE([glr-regr10])
895
896AT_CHECK([[./glr-regr10]], 0, [], [])
897
898AT_CLEANUP
899
900
901## ------------------------------------------------------------------------- ##
902## Undesirable destructors if user action cuts parse. ##
903## ------------------------------------------------------------------------- ##
904
905AT_SETUP([Undesirable destructors if user action cuts parse])
906
907AT_DATA_GRAMMAR([glr-regr11.y],
908[[
909%{
910# include <stdlib.h>
911 static void yyerror (char const *);
912 static int yylex (void);
913 static int destructors = 0;
914# define USE(val)
915%}
916
917%glr-parser
918%union { int dummy; }
919%type <int> 'a'
920%destructor { destructors += 1; } 'a'
921
922%%
923
924start:
925 'a' %dprec 2 { USE ($1); destructors += 1; YYACCEPT; }
926 | 'a' %dprec 1 { USE ($1); destructors += 1; YYACCEPT; }
927 ;
928
929%%
930
931static void
932yyerror (char const *msg)
933{
934 fprintf (stderr, "%s\n", msg);
935}
936
937static int
938yylex (void)
939{
940 static char const input[] = "a";
941 static size_t toknum;
942 if (! (toknum < sizeof input))
943 abort ();
944 return input[toknum++];
945}
946
947int
948main (void)
949{
950 int exit_status = yyparse ();
951 if (destructors != 1)
952 {
953 fprintf (stderr, "Destructor calls: %d\n", destructors);
954 return 1;
955 }
956 return exit_status;
957}
958]])
959
960AT_CHECK([[bison -o glr-regr11.c glr-regr11.y]], 0, [],
961[glr-regr11.y: conflicts: 1 reduce/reduce
962])
963AT_COMPILE([glr-regr11])
964
965AT_CHECK([[./glr-regr11]], 0, [], [])
966
967AT_CLEANUP
968
969
970## ------------------------------------------------------------------------- ##
971## Leaked semantic values if user action cuts parse. ##
972## ------------------------------------------------------------------------- ##
973
974AT_SETUP([Leaked semantic values if user action cuts parse])
975
976AT_DATA_GRAMMAR([glr-regr12.y],
977[[
978%glr-parser
979%union { int dummy; }
980%token PARENT_RHS_AFTER
981%type <dummy> parent_rhs_before merged PARENT_RHS_AFTER
982%destructor { parent_rhs_before_value = 0; } parent_rhs_before
983%destructor { merged_value = 0; } merged
984%destructor { parent_rhs_after_value = 0; } PARENT_RHS_AFTER
985
986%{
987# include <stdlib.h>
988 static int merge (YYSTYPE, YYSTYPE);
989 static void yyerror (char const *);
990 static int yylex (void);
991 static int parent_rhs_before_value = 0;
992 static int merged_value = 0;
993 static int parent_rhs_after_value = 0;
994# define USE(val)
995%}
996
997%%
998
999start:
1000 alt1 %dprec 1
1001 | alt2 %dprec 2
1002 ;
1003
1004alt1:
1005 PARENT_RHS_AFTER {
1006 USE ($1);
1007 parent_rhs_after_value = 0;
1008 }
1009 ;
1010
1011alt2:
1012 parent_rhs_before merged PARENT_RHS_AFTER {
1013 USE (($1, $2, $3));
1014 parent_rhs_before_value = 0;
1015 merged_value = 0;
1016 parent_rhs_after_value = 0;
1017 }
1018 ;
1019
1020parent_rhs_before:
1021 {
1022 USE ($$);
1023 parent_rhs_before_value = 1;
1024 }
1025 ;
1026
1027merged:
1028 %merge<merge> {
1029 USE ($$);
1030 merged_value = 1;
1031 }
1032 | cut %merge<merge> {
1033 USE ($$);
1034 merged_value = 1;
1035 }
1036 ;
1037
1038cut: { YYACCEPT; } ;
1039
1040%%
1041
1042static int
1043merge (YYSTYPE s1, YYSTYPE s2)
1044{
1045 /* Not invoked. */
1046 char dummy = s1.dummy + s2.dummy;
1047 return dummy;
1048}
1049
1050static void
1051yyerror (char const *msg)
1052{
1053 fprintf (stderr, "%s\n", msg);
1054}
1055
1056static int
1057yylex (void)
1058{
1059 static int const input[] = { PARENT_RHS_AFTER, 0 };
1060 static size_t toknum;
1061 if (! (toknum < sizeof input / sizeof *input))
1062 abort ();
1063 if (input[toknum] == PARENT_RHS_AFTER)
1064 parent_rhs_after_value = 1;
1065 return input[toknum++];
1066}
1067
1068int
1069main (void)
1070{
1071 int exit_status = yyparse ();
1072 if (parent_rhs_before_value)
1073 {
1074 fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
1075 exit_status = 1;
1076 }
1077 if (merged_value)
1078 {
1079 fprintf (stderr, "`merged' destructor not called.\n");
1080 exit_status = 1;
1081 }
1082 if (parent_rhs_after_value)
1083 {
1084 fprintf (stderr, "`PARENT_RHS_AFTER' destructor not called.\n");
1085 exit_status = 1;
1086 }
1087 return exit_status;
1088}
1089]])
1090
1091AT_CHECK([[bison -o glr-regr12.c glr-regr12.y]], 0, [],
1092[glr-regr12.y: conflicts: 1 shift/reduce, 1 reduce/reduce
1093])
1094AT_COMPILE([glr-regr12])
1095
1096AT_CHECK([[./glr-regr12]], 0, [], [])
1097
1098AT_CLEANUP
1099
1100
1101## ------------------------------------------------------------------------- ##
1102## Incorrect lookahead during deterministic GLR. See ##
1103## <http://lists.gnu.org/archive/html/help-bison/2005-07/msg00017.html> and ##
1104## <http://lists.gnu.org/archive/html/bison-patches/2006-01/msg00060.html>. ##
1105## ------------------------------------------------------------------------- ##
1106
1107AT_SETUP([Incorrect lookahead during deterministic GLR])
1108
1109AT_DATA_GRAMMAR([glr-regr13.y],
1110[[
1111/* Tests:
1112 - Defaulted state with initial yychar: yychar == YYEMPTY.
1113 - Nondefaulted state: yychar != YYEMPTY.
1114 - Defaulted state after lookahead: yychar != YYEMPTY.
1115 - Defaulted state after shift: yychar == YYEMPTY.
1116 - User action changing the lookahead. */
1117
1118%{
1119 #include <stdio.h>
1120 static void yyerror (char const *);
1121 static int yylex (void);
1122 static void print_lookahead (char const *);
1123 #define USE(value)
1124%}
1125
1126%union { char value; }
1127%type <value> 'a' 'b'
1128%glr-parser
1129%locations
1130
1131%%
1132
1133start:
1134 defstate_init defstate_shift 'b' change_lookahead 'a' {
1135 USE ($3);
1136 print_lookahead ("start <- defstate_init defstate_shift 'b'");
1137 }
1138 ;
1139defstate_init:
1140 {
1141 print_lookahead ("defstate_init <- empty string");
1142 }
1143 ;
1144defstate_shift:
1145 nondefstate defstate_look 'a' {
1146 USE ($3);
1147 print_lookahead ("defstate_shift <- nondefstate defstate_look 'a'");
1148 }
1149 ;
1150defstate_look:
1151 {
1152 print_lookahead ("defstate_look <- empty string");
1153 }
1154 ;
1155nondefstate:
1156 {
1157 print_lookahead ("nondefstate <- empty string");
1158 }
1159 | 'b' {
1160 USE ($1);
1161 print_lookahead ("nondefstate <- 'b'");
1162 }
1163 ;
1164change_lookahead:
1165 {
1166 yychar = 'a';
1167 }
1168 ;
1169
1170%%
1171
1172static void
1173yyerror (char const *msg)
1174{
1175 fprintf (stderr, "%s\n", msg);
1176}
1177
1178static int
1179yylex (void)
1180{
1181 static char const input[] = "ab";
1182 static size_t toknum;
1183 if (! (toknum < sizeof input))
1184 abort ();
1185 yylloc.first_line = yylloc.last_line = 1;
1186 yylloc.first_column = yylloc.last_column = toknum + 1;
1187 yylval.value = input[toknum] + 'A' - 'a';
1188 return input[toknum++];
1189}
1190
1191static void
1192print_lookahead (char const *reduction)
1193{
1194 printf ("%s:\n yychar=", reduction);
1195 if (yychar == YYEMPTY)
1196 printf ("YYEMPTY");
1197 else if (yychar == YYEOF)
1198 printf ("YYEOF");
1199 else
1200 {
1201 printf ("'%c', yylval='", yychar);
1202 if (yylval.value > ' ')
1203 printf ("%c", yylval.value);
1204 printf ("', yylloc=(%d,%d),(%d,%d)",
1205 yylloc.first_line, yylloc.first_column,
1206 yylloc.last_line, yylloc.last_column);
1207 }
1208 printf ("\n");
1209}
1210
1211int
1212main (void)
1213{
1214 yychar = '#'; /* Not a token in the grammar. */
1215 yylval.value = '!';
1216 return yyparse ();
1217}
1218]])
1219
1220AT_CHECK([[bison -o glr-regr13.c glr-regr13.y]], 0, [], [])
1221AT_COMPILE([glr-regr13])
1222
1223AT_CHECK([[./glr-regr13]], 0,
1224[defstate_init <- empty string:
1225 yychar=YYEMPTY
1226nondefstate <- empty string:
1227 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1228defstate_look <- empty string:
1229 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1230defstate_shift <- nondefstate defstate_look 'a':
1231 yychar=YYEMPTY
1232start <- defstate_init defstate_shift 'b':
1233 yychar=YYEMPTY
1234], [])
1235
1236AT_CLEANUP
1237
1238
1239## ------------------------------------------------------------------------- ##
1240## Incorrect lookahead during nondeterministic GLR. ##
1241## ------------------------------------------------------------------------- ##
1242
1243AT_SETUP([Incorrect lookahead during nondeterministic GLR])
1244
1245AT_DATA_GRAMMAR([glr-regr14.y],
1246[[
1247/* Tests:
1248 - Conflicting actions (split-off parse, which copies lookahead need,
1249 which is necessarily yytrue) and nonconflicting actions (non-split-off
1250 parse) for nondefaulted state: yychar != YYEMPTY.
1251 - Merged deferred actions (lookahead need and RHS from different stack
1252 than the target state) and nonmerged deferred actions (same stack).
1253 - Defaulted state after lookahead: yychar != YYEMPTY.
1254 - Defaulted state after shift: yychar == YYEMPTY.
1255 - yychar != YYEMPTY but lookahead need is yyfalse (a previous stack has
1256 seen the lookahead but current stack has not).
1257 - Exceeding stack capacity (stack explosion), and thus reallocating
1258 lookahead need array.
1259 Note that it does not seem possible to see the initial yychar value during
1260 nondeterministic operation since:
1261 - In order to preserve the initial yychar, only defaulted states may be
1262 entered.
1263 - If only defaulted states are entered, there are no conflicts, so
1264 nondeterministic operation does not start. */
1265
1266%union { char value; }
1267
1268%{
1269 #include <stdlib.h>
1270 #include <stdio.h>
1271 static void yyerror (char const *);
1272 static int yylex (void);
1273 static void print_lookahead (char const *);
1274 static char merge (union YYSTYPE, union YYSTYPE);
1275 #define USE(value)
1276%}
1277
1278%type <value> 'a' 'b' 'c' 'd' stack_explosion
1279%glr-parser
1280%locations
1281
1282%%
1283
1284start:
1285 merge 'c' stack_explosion {
1286 USE ($2); USE ($3);
1287 print_lookahead ("start <- merge 'c' stack_explosion");
1288 }
1289 ;
1290
1291/* When merging the 2 deferred actions, the lookahead needs are different. */
1292merge:
1293 nonconflict1 'a' 'b' nonconflict2 %dprec 1 {
1294 USE ($2); USE ($3);
1295 print_lookahead ("merge <- nonconflict1 'a' 'b' nonconflict2");
1296 }
1297 | conflict defstate_look 'a' nonconflict2 'b' defstate_shift %dprec 2 {
1298 USE ($3); USE ($5);
1299 print_lookahead ("merge <- conflict defstate_look 'a' nonconflict2 'b'"
1300 " defstate_shift");
1301 }
1302 ;
1303
1304nonconflict1:
1305 {
1306 print_lookahead ("nonconflict1 <- empty string");
1307 }
1308 ;
1309nonconflict2:
1310 {
1311 print_lookahead ("nonconflict2 <- empty string");
1312 }
1313 | 'a' {
1314 USE ($1);
1315 print_lookahead ("nonconflict2 <- 'a'");
1316 }
1317 ;
1318conflict:
1319 {
1320 print_lookahead ("conflict <- empty string");
1321 }
1322 ;
1323defstate_look:
1324 {
1325 print_lookahead ("defstate_look <- empty string");
1326 }
1327 ;
1328
1329/* yychar != YYEMPTY but lookahead need is yyfalse. */
1330defstate_shift:
1331 {
1332 print_lookahead ("defstate_shift <- empty string");
1333 }
1334 ;
1335
1336stack_explosion:
1337 { $$ = '\0'; }
1338 | alt1 stack_explosion %merge<merge> { $$ = $2; }
1339 | alt2 stack_explosion %merge<merge> { $$ = $2; }
1340 | alt3 stack_explosion %merge<merge> { $$ = $2; }
1341 ;
1342alt1:
1343 'd' no_look {
1344 USE ($1);
1345 if (yychar != 'd' && yychar != YYEOF)
1346 {
1347 fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
1348 }
1349 }
1350 ;
1351alt2:
1352 'd' no_look {
1353 USE ($1);
1354 if (yychar != 'd' && yychar != YYEOF)
1355 {
1356 fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
1357 }
1358 }
1359 ;
1360alt3:
1361 'd' no_look {
1362 USE ($1);
1363 if (yychar != 'd' && yychar != YYEOF)
1364 {
1365 fprintf (stderr, "Incorrect lookahead during stack explosion.\n");
1366 }
1367 }
1368 ;
1369no_look:
1370 {
1371 if (yychar != YYEMPTY)
1372 {
1373 fprintf (stderr,
1374 "Found lookahead where shouldn't during stack explosion.\n");
1375 }
1376 }
1377 ;
1378
1379%%
1380
1381static void
1382yyerror (char const *msg)
1383{
1384 fprintf (stderr, "%s\n", msg);
1385}
1386
1387static int
1388yylex (void)
1389{
1390 static char const input[] = "abcdddd";
1391 static size_t toknum;
1392 if (! (toknum < sizeof input))
1393 abort ();
1394 yylloc.first_line = yylloc.last_line = 1;
1395 yylloc.first_column = yylloc.last_column = toknum + 1;
1396 yylval.value = input[toknum] + 'A' - 'a';
1397 return input[toknum++];
1398}
1399
1400static void
1401print_lookahead (char const *reduction)
1402{
1403 printf ("%s:\n yychar=", reduction);
1404 if (yychar == YYEMPTY)
1405 printf ("YYEMPTY");
1406 else if (yychar == YYEOF)
1407 printf ("YYEOF");
1408 else
1409 {
1410 printf ("'%c', yylval='", yychar);
1411 if (yylval.value > ' ')
1412 printf ("%c", yylval.value);
1413 printf ("', yylloc=(%d,%d),(%d,%d)",
1414 yylloc.first_line, yylloc.first_column,
1415 yylloc.last_line, yylloc.last_column);
1416 }
1417 printf ("\n");
1418}
1419
1420static char
1421merge (union YYSTYPE s1, union YYSTYPE s2)
1422{
1423 char dummy = s1.value + s2.value;
1424 return dummy;
1425}
1426
1427int
1428main (void)
1429{
1430 yychar = '#'; /* Not a token in the grammar. */
1431 yylval.value = '!';
1432 return yyparse ();
1433}
1434]])
1435
1436AT_CHECK([[bison -o glr-regr14.c glr-regr14.y]], 0, [],
1437[glr-regr14.y: conflicts: 3 reduce/reduce
1438])
1439AT_COMPILE([glr-regr14])
1440
1441AT_CHECK([[./glr-regr14]], 0,
1442[conflict <- empty string:
1443 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1444defstate_look <- empty string:
1445 yychar='a', yylval='A', yylloc=(1,1),(1,1)
1446nonconflict2 <- empty string:
1447 yychar='b', yylval='B', yylloc=(1,2),(1,2)
1448defstate_shift <- empty string:
1449 yychar=YYEMPTY
1450merge <- conflict defstate_look 'a' nonconflict2 'b' defstate_shift:
1451 yychar=YYEMPTY
1452start <- merge 'c' stack_explosion:
1453 yychar=YYEOF
1454], [])
1455
1456AT_CLEANUP
1457
1458
1459## ------------------------------------------------------------------------- ##
1460## Leaked semantic values when reporting ambiguity. ##
1461## ------------------------------------------------------------------------- ##
1462
1463AT_SETUP([Leaked semantic values when reporting ambiguity])
1464
1465AT_DATA_GRAMMAR([glr-regr15.y],
1466[[
1467%glr-parser
1468%destructor { parent_rhs_before_value = 0; } parent_rhs_before
1469
1470%{
1471# include <stdlib.h>
1472 static void yyerror (char const *);
1473 static int yylex (void);
1474 static int parent_rhs_before_value = 0;
1475# define USE(val)
1476%}
1477
1478%%
1479
1480start:
1481 alt1 %dprec 1
1482 | alt2 %dprec 2
1483 ;
1484
1485/* This stack must be merged into the other stacks *last* (added at the
1486 beginning of the semantic options list) so that yyparse will choose to clean
1487 it up rather than the tree for which some semantic actions have been
1488 performed. Thus, if yyreportAmbiguity longjmp's to yyparse, the values from
1489 those other trees are not cleaned up. */
1490alt1: ;
1491
1492alt2:
1493 parent_rhs_before ambiguity {
1494 USE ($1);
1495 parent_rhs_before_value = 0;
1496 }
1497 ;
1498
1499parent_rhs_before:
1500 {
1501 USE ($$);
1502 parent_rhs_before_value = 1;
1503 }
1504 ;
1505
1506ambiguity: ambiguity1 | ambiguity2 ;
1507ambiguity1: ;
1508ambiguity2: ;
1509
1510%%
1511
1512static void
1513yyerror (char const *msg)
1514{
1515 fprintf (stderr, "%s\n", msg);
1516}
1517
1518static int
1519yylex (void)
1520{
1521 static int called;
1522 if (called++)
1523 abort ();
1524 return 0;
1525}
1526
1527int
1528main (void)
1529{
1530 int exit_status = yyparse () != 1;
1531 if (parent_rhs_before_value)
1532 {
1533 fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
1534 exit_status = 1;
1535 }
1536 return exit_status;
1537}
1538]])
1539
1540AT_CHECK([[bison -o glr-regr15.c glr-regr15.y]], 0, [],
1541[glr-regr15.y: conflicts: 2 reduce/reduce
1542])
1543AT_COMPILE([glr-regr15])
1544
1545AT_CHECK([[./glr-regr15]], 0, [],
1546[syntax is ambiguous
1547])
1548
1549AT_CLEANUP
1550
1551
1552## ------------------------------------------------------------------------- ##
1553## Leaked lookahead after nondeterministic parse syntax error. ##
1554## ------------------------------------------------------------------------- ##
1555
1556AT_SETUP([Leaked lookahead after nondeterministic parse syntax error])
1557AT_DATA_GRAMMAR([glr-regr16.y],
1558[[
1559%glr-parser
1560%destructor { lookahead_value = 0; } 'b'
1561
1562%{
1563# include <stdlib.h>
1564 static void yyerror (char const *);
1565 static int yylex (void);
1566 static int lookahead_value = 0;
1567# define USE(val)
1568%}
1569
1570%%
1571
1572start: alt1 'a' | alt2 'a' ;
1573alt1: ;
1574alt2: ;
1575
1576%%
1577
1578static void
1579yyerror (char const *msg)
1580{
1581 fprintf (stderr, "%s\n", msg);
1582}
1583
1584static int
1585yylex (void)
1586{
1587 static char const input[] = "ab";
1588 static size_t toknum;
1589 if (! (toknum < sizeof input))
1590 abort ();
1591 if (input[toknum] == 'b')
1592 lookahead_value = 1;
1593 return input[toknum++];
1594}
1595
1596int
1597main (void)
1598{
1599 int exit_status = yyparse () != 1;
1600 if (lookahead_value)
1601 {
1602 fprintf (stderr, "Lookahead destructor not called.\n");
1603 exit_status = 1;
1604 }
1605 return exit_status;
1606}
1607]])
1608
1609AT_CHECK([[bison -o glr-regr16.c glr-regr16.y]], 0, [],
1610[glr-regr16.y: conflicts: 1 reduce/reduce
1611])
1612AT_COMPILE([glr-regr16])
1613
1614AT_CHECK([[./glr-regr16]], 0, [],
1615[syntax error
1616])
1617
1618AT_CLEANUP
1619
1620
1621## ------------------------------------------------------------------------- ##
1622## Uninitialized location when reporting ambiguity. ##
1623## ------------------------------------------------------------------------- ##
1624
1625AT_SETUP([Uninitialized location when reporting ambiguity])
1626AT_DATA_GRAMMAR([glr-regr17.y],
1627[[
1628%glr-parser
1629%locations
1630%pure-parser
1631%error-verbose
1632
1633%union { int dummy; }
1634
1635%{
1636 static void yyerror (YYLTYPE *, char const *);
1637 static int yylex (YYSTYPE *, YYLTYPE *);
1638%}
1639
1640%initial-action {
1641 @$.first_line = 1;
1642 @$.first_column = 1;
1643 @$.last_line = 1;
1644 @$.last_column = 1;
1645}
1646
1647%%
1648
1649/* Tests the case of an empty RHS that has inherited the location of the
1650 previous nonterminal, which is unresolved. That location is reported as the
1651 last position of the ambiguity. */
1652start: ambig1 empty1 | ambig2 empty2 ;
1653
1654/* Tests multiple levels of yyresolveLocations recursion. */
1655ambig1: sub_ambig1 | sub_ambig2 ;
1656ambig2: sub_ambig1 | sub_ambig2 ;
1657
1658/* Tests the case of a non-empty RHS as well as the case of an empty RHS that
1659 has inherited the initial location. The empty RHS's location is reported as
1660 the first position in the ambiguity. */
1661sub_ambig1: empty1 'a' 'b' ;
1662sub_ambig2: empty2 'a' 'b' ;
1663empty1: ;
1664empty2: ;
1665
1666%%
1667
1668static void
1669yyerror (YYLTYPE *locp, char const *msg)
1670{
1671 fprintf (stderr, "Error at %d.%d-%d.%d: %s.\n", locp->first_line,
1672 locp->first_column, locp->last_line, locp->last_column, msg);
1673}
1674
1675static int
1676yylex (YYSTYPE *lvalp, YYLTYPE *llocp)
1677{
1678 static char const input[] = "ab";
1679 static size_t toknum;
1680 if (! (toknum < sizeof input))
1681 abort ();
1682 lvalp->dummy = 0;
1683 llocp->first_line = llocp->last_line = 2;
1684 llocp->first_column = toknum + 1;
1685 llocp->last_column = llocp->first_column + 1;
1686 return input[toknum++];
1687}
1688
1689int
1690main (void)
1691{
1692 return yyparse () != 1;
1693}
1694]])
1695
1696AT_CHECK([[bison -o glr-regr17.c glr-regr17.y]], 0, [],
1697[glr-regr17.y: conflicts: 3 reduce/reduce
1698])
1699AT_COMPILE([glr-regr17])
1700
1701AT_CHECK([[./glr-regr17]], 0, [],
1702[Error at 1.1-2.3: syntax is ambiguous.
1703])
1704
1705AT_CLEANUP
1706
1707
1708## -------------------------------------------------------------##
1709## Missed %merge type warnings when LHS type is declared later. ##
1710## -------------------------------------------------------------##
1711
1712AT_SETUP([Missed %merge type warnings when LHS type is declared later])
1713AT_DATA_GRAMMAR([glr-regr18.y],
1714[[%glr-parser
1715
1716%{
1717 #include <stdlib.h>
1718 static void yyerror (char const *);
1719 static int yylex ();
1720%}
1721
1722%union {
1723 int type1;
1724 int type2;
1725 int type3;
1726}
1727
1728%%
1729
1730sym1: sym2 %merge<merge> { $$ = $1; } ;
1731sym2: sym3 %merge<merge> { $$ = $1; } ;
1732sym3: %merge<merge> { $$ = 0; } ;
1733
1734%type <type1> sym1;
1735%type <type2> sym2;
1736%type <type3> sym3;
1737
1738%%
1739
1740static void
1741yyerror (char const *msg)
1742{
1743 fprintf (stderr, "%s\n", msg);
1744}
1745
1746static int
1747yylex ()
1748{
1749 static int called;
1750 if (called++)
1751 abort ();
1752 return 0;
1753}
1754
1755int
1756main (void)
1757{
1758 return yyparse ();
1759}
1760]])
1761
1762AT_CHECK([[bison -o glr-regr18.c glr-regr18.y]], 1, [],
1763[glr-regr18.y:26.18-24: result type clash on merge function `merge': <type2> != <type1>
1764glr-regr18.y:25.18-24: previous declaration
1765glr-regr18.y:27.13-19: result type clash on merge function `merge': <type3> != <type2>
1766glr-regr18.y:26.18-24: previous declaration
1767])
1768
1769AT_CLEANUP