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