1 2 package java_cup; 3 4 import java.util.Hashtable ; 5 import java.util.Enumeration ; 6 import java.util.Stack ; 7 8 51 52 public class lalr_state { 53 54 55 56 57 60 public lalr_state(lalr_item_set itms) throws internal_error 61 { 62 63 if (itms == null) 64 throw new internal_error( 65 "Attempt to construct an LALR state from a null item set"); 66 67 if (find_state(itms) != null) 68 throw new internal_error( 69 "Attempt to construct a duplicate LALR state"); 70 71 72 _index = next_index++; 73 74 75 _items = itms; 76 77 78 _all.put(_items,this); 79 } 80 81 82 83 84 85 86 protected static Hashtable _all = new Hashtable (); 87 88 89 public static Enumeration all() {return _all.elements();} 90 91 public static void clear() { 93 _all.clear(); 94 _all_kernels.clear(); 95 next_index=0; 96 } 97 98 99 100 101 public static int number() {return _all.size();} 102 103 104 105 109 protected static Hashtable _all_kernels = new Hashtable (); 110 111 112 113 120 public static lalr_state find_state(lalr_item_set itms) 121 { 122 if (itms == null) 123 return null; 124 else 125 return (lalr_state)_all.get(itms); 126 } 127 128 129 130 131 protected static int next_index = 0; 132 133 134 135 136 137 138 protected lalr_item_set _items; 139 140 141 public lalr_item_set items() {return _items;} 142 143 144 145 146 protected lalr_transition _transitions = null; 147 148 149 public lalr_transition transitions() {return _transitions;} 150 151 152 153 154 protected int _index; 155 156 157 public int index() {return _index;} 158 159 160 161 162 163 166 protected static void dump_state(lalr_state st) throws internal_error 167 { 168 lalr_item_set itms; 169 lalr_item itm; 170 production_part part; 171 172 if (st == null) 173 { 174 System.out.println("NULL lalr_state"); 175 return; 176 } 177 178 System.out.println("lalr_state [" + st.index() + "] {"); 179 itms = st.items(); 180 for (Enumeration e = itms.all(); e.hasMoreElements(); ) 181 { 182 itm = (lalr_item)e.nextElement(); 183 System.out.print(" ["); 184 System.out.print(itm.the_production().lhs().the_symbol().name()); 185 System.out.print(" ::= "); 186 for (int i = 0; i<itm.the_production().rhs_length(); i++) 187 { 188 if (i == itm.dot_pos()) System.out.print("(*) "); 189 part = itm.the_production().rhs(i); 190 if (part.is_action()) 191 System.out.print("{action} "); 192 else 193 System.out.print(((symbol_part)part).the_symbol().name() + " "); 194 } 195 if (itm.dot_at_end()) System.out.print("(*) "); 196 System.out.println("]"); 197 } 198 System.out.println("}"); 199 } 200 201 202 203 210 protected static void propagate_all_lookaheads() throws internal_error 211 { 212 213 for (Enumeration st = all(); st.hasMoreElements(); ) 214 { 215 216 ((lalr_state)st.nextElement()).propagate_lookaheads(); 217 } 218 } 219 220 221 222 223 224 228 public void add_transition(symbol on_sym, lalr_state to_st) 229 throws internal_error 230 { 231 lalr_transition trans; 232 233 234 trans = new lalr_transition(on_sym, to_st, _transitions); 235 _transitions = trans; 236 } 237 238 239 240 277 278 public static lalr_state build_machine(production start_prod) 279 throws internal_error 280 { 281 lalr_state start_state; 282 lalr_item_set start_items; 283 lalr_item_set new_items; 284 lalr_item_set linked_items; 285 lalr_item_set kernel; 286 Stack work_stack = new Stack (); 287 lalr_state st, new_st; 288 symbol_set outgoing; 289 lalr_item itm, new_itm, existing, fix_itm; 290 symbol sym, sym2; 291 Enumeration i, s, fix; 292 293 294 if (start_prod == null) 295 throw new internal_error( 296 "Attempt to build viable prefix recognizer using a null production"); 297 298 299 start_items = new lalr_item_set(); 300 301 itm = new lalr_item(start_prod); 302 itm.lookahead().add(terminal.EOF); 303 304 start_items.add(itm); 305 306 307 kernel = new lalr_item_set(start_items); 308 309 310 start_items.compute_closure(); 311 312 313 start_state = new lalr_state(start_items); 314 work_stack.push(start_state); 315 316 317 _all_kernels.put(kernel, start_state); 318 319 320 while (!work_stack.empty()) 321 { 322 323 st = (lalr_state)work_stack.pop(); 324 325 326 outgoing = new symbol_set(); 327 for (i = st.items().all(); i.hasMoreElements(); ) 328 { 329 itm = (lalr_item)i.nextElement(); 330 331 332 sym = itm.symbol_after_dot(); 333 if (sym != null) outgoing.add(sym); 334 } 335 336 337 for (s = outgoing.all(); s.hasMoreElements(); ) 338 { 339 sym = (symbol)s.nextElement(); 340 341 342 linked_items = new lalr_item_set(); 343 344 346 new_items = new lalr_item_set(); 347 for (i = st.items().all(); i.hasMoreElements();) 348 { 349 itm = (lalr_item)i.nextElement(); 350 351 352 sym2 = itm.symbol_after_dot(); 353 if (sym.equals(sym2)) 354 { 355 356 new_items.add(itm.shift()); 357 358 359 linked_items.add(itm); 360 } 361 } 362 363 364 kernel = new lalr_item_set(new_items); 365 366 367 new_st = (lalr_state)_all_kernels.get(kernel); 368 369 370 if (new_st == null) 371 { 372 373 new_items.compute_closure(); 374 375 376 new_st = new lalr_state(new_items); 377 378 379 work_stack.push(new_st); 380 381 382 _all_kernels.put(kernel, new_st); 383 } 384 385 else 386 { 387 388 for (fix = linked_items.all(); fix.hasMoreElements(); ) 389 { 390 fix_itm = (lalr_item)fix.nextElement(); 391 392 393 for (int l =0; l < fix_itm.propagate_items().size(); l++) 394 { 395 396 new_itm = 397 (lalr_item)fix_itm.propagate_items().elementAt(l); 398 399 400 existing = new_st.items().find(new_itm); 401 402 403 if (existing != null) 404 fix_itm.propagate_items().setElementAt(existing ,l); 405 } 406 } 407 } 408 409 410 st.add_transition(sym, new_st); 411 } 412 } 413 414 415 416 417 propagate_all_lookaheads(); 418 419 return start_state; 420 } 421 422 423 424 428 protected void propagate_lookaheads() throws internal_error 429 { 430 431 for (Enumeration itm = items().all(); itm.hasMoreElements(); ) 432 ((lalr_item)itm.nextElement()).propagate_lookaheads(null); 433 } 434 435 436 437 458 public void build_table_entries( 459 parse_action_table act_table, 460 parse_reduce_table reduce_table) 461 throws internal_error 462 { 463 parse_action_row our_act_row; 464 parse_reduce_row our_red_row; 465 lalr_item itm; 466 parse_action act, other_act; 467 symbol sym; 468 terminal_set conflict_set = new terminal_set(); 469 470 471 our_act_row = act_table.under_state[index()]; 472 our_red_row = reduce_table.under_state[index()]; 473 474 475 for (Enumeration i = items().all(); i.hasMoreElements(); ) 476 { 477 itm = (lalr_item)i.nextElement(); 478 479 480 481 if (itm.dot_at_end()) 482 { 483 act = new reduce_action(itm.the_production()); 484 485 486 for (int t = 0; t < terminal.number(); t++) 487 { 488 489 if (!itm.lookahead().contains(t)) continue; 490 491 492 if (our_act_row.under_term[t].kind() == 493 parse_action.ERROR) 494 { 495 our_act_row.under_term[t] = act; 496 } 497 else 498 { 499 500 terminal term = terminal.find(t); 501 other_act = our_act_row.under_term[t]; 502 503 504 if ((other_act.kind() != parse_action.SHIFT) && 505 (other_act.kind() != parse_action.NONASSOC)) 506 { 507 508 if (itm.the_production().index() < 509 ((reduce_action)other_act).reduce_with().index()) 510 { 511 512 our_act_row.under_term[t] = act; 513 } 514 } else { 515 516 if(fix_with_precedence(itm.the_production(), 517 t, our_act_row, act)) { 518 term = null; 519 } 520 } 521 if(term!=null) { 522 523 conflict_set.add(term); 524 } 525 } 526 } 527 } 528 } 529 530 531 for (lalr_transition trans=transitions(); trans!=null; trans=trans.next()) 532 { 533 534 sym = trans.on_symbol(); 535 if (!sym.is_non_term()) 536 { 537 act = new shift_action(trans.to_state()); 538 539 540 if ( our_act_row.under_term[sym.index()].kind() == 541 parse_action.ERROR) 542 { 543 our_act_row.under_term[sym.index()] = act; 544 } 545 else 546 { 547 548 production p = ((reduce_action)our_act_row.under_term[sym.index()]).reduce_with(); 549 550 551 if (!fix_with_precedence(p, sym.index(), our_act_row, act)) { 552 our_act_row.under_term[sym.index()] = act; 553 conflict_set.add(terminal.find(sym.index())); 554 } 555 } 556 } 557 else 558 { 559 560 our_red_row.under_non_term[sym.index()] = trans.to_state(); 561 } 562 } 563 564 565 if (!conflict_set.empty()) 566 report_conflicts(conflict_set); 567 } 568 569 570 571 572 590 591 protected boolean fix_with_precedence( 592 production p, 593 int term_index, 594 parse_action_row table_row, 595 parse_action act) 596 597 throws internal_error { 598 599 terminal term = terminal.find(term_index); 600 601 602 if (p.precedence_num() > assoc.no_prec) { 603 604 605 if (p.precedence_num() > term.precedence_num()) { 606 table_row.under_term[term_index] = 607 insert_reduce(table_row.under_term[term_index],act); 608 return true; 609 } 610 611 612 else if (p.precedence_num() < term.precedence_num()) { 613 table_row.under_term[term_index] = 614 insert_shift(table_row.under_term[term_index],act); 615 return true; 616 } 617 else { 618 619 621 if (term.precedence_side() == assoc.right) { 622 table_row.under_term[term_index] = 623 insert_shift(table_row.under_term[term_index],act); 624 return true; 625 } 626 627 628 else if (term.precedence_side() == assoc.left) { 629 table_row.under_term[term_index] = 630 insert_reduce(table_row.under_term[term_index],act); 631 return true; 632 } 633 634 636 else if (term.precedence_side() == assoc.nonassoc) { 637 table_row.under_term[term_index] = new nonassoc_action(); 638 return true; 639 } else { 640 641 throw new internal_error("Unable to resolve conflict correctly"); 642 } 643 } 644 } 645 647 else if (term.precedence_num() > assoc.no_prec) { 648 table_row.under_term[term_index] = 649 insert_shift(table_row.under_term[term_index],act); 650 return true; 651 } 652 653 655 return false; 656 } 657 658 659 660 661 667 protected parse_action insert_action( 668 parse_action a1, 669 parse_action a2, 670 int act_type) 671 throws internal_error 672 { 673 if ((a1.kind() == act_type) && (a2.kind() == act_type)) { 674 throw new internal_error("Conflict resolution of bogus actions"); 675 } else if (a1.kind() == act_type) { 676 return a1; 677 } else if (a2.kind() == act_type) { 678 return a2; 679 } else { 680 throw new internal_error("Conflict resolution of bogus actions"); 681 } 682 } 683 684 685 protected parse_action insert_shift( 686 parse_action a1, 687 parse_action a2) 688 throws internal_error 689 { 690 return insert_action(a1, a2, parse_action.SHIFT); 691 } 692 693 694 protected parse_action insert_reduce( 695 parse_action a1, 696 parse_action a2) 697 throws internal_error 698 { 699 return insert_action(a1, a2, parse_action.REDUCE); 700 } 701 702 703 704 705 protected void report_conflicts(terminal_set conflict_set) 706 throws internal_error 707 { 708 lalr_item itm, compare; 709 symbol shift_sym; 710 711 boolean after_itm; 712 713 714 for (Enumeration itms = items().all(); itms.hasMoreElements(); ) 715 { 716 itm = (lalr_item)itms.nextElement(); 717 718 719 720 721 if (itm.dot_at_end()) 722 { 723 724 after_itm = false; 725 726 727 for (Enumeration comps = items().all(); comps.hasMoreElements(); ) 728 { 729 compare = (lalr_item)comps.nextElement(); 730 731 732 if (itm == compare) after_itm = true; 733 734 735 if (itm != compare) 736 { 737 738 if (compare.dot_at_end()) 739 { 740 741 if (after_itm) 742 743 if (compare.lookahead().intersects(itm.lookahead())) 744 745 report_reduce_reduce(itm, compare); 746 } 747 } 748 } 749 750 for (int t = 0; t < terminal.number(); t++) 751 if (conflict_set.contains(t)) 752 report_shift_reduce(itm,t); 753 } 754 } 755 } 756 757 758 759 764 protected void report_reduce_reduce(lalr_item itm1, lalr_item itm2) 765 throws internal_error 766 { 767 boolean comma_flag = false; 768 769 String message = "*** Reduce/Reduce conflict found in state #"+index()+"\n" + 770 " between " + itm1.to_simple_string() + "\n" + 771 " and " + itm2.to_simple_string() + "\n" + 772 " under symbols: {"; 773 for (int t = 0; t < terminal.number(); t++) 774 { 775 if (itm1.lookahead().contains(t) && itm2.lookahead().contains(t)) 776 { 777 if (comma_flag) message+=(", "); else comma_flag = true; 778 message += (terminal.find(t).name()); 779 } 780 } 781 message += "}\n Resolved in favor of "; 782 if (itm1.the_production().index() < itm2.the_production().index()) 783 message+="the first production.\n"; 784 else 785 message+="the second production.\n"; 786 787 788 emit.num_conflicts++; 789 ErrorManager.getManager().emit_warning(message); 790 } 791 792 793 794 799 protected void report_shift_reduce( 800 lalr_item red_itm, 801 int conflict_sym) 802 throws internal_error 803 { 804 lalr_item itm; 805 symbol shift_sym; 806 807 808 String message = "*** Shift/Reduce conflict found in state #"+index()+"\n" + 809 " between " + red_itm.to_simple_string()+"\n"; 810 811 812 for (Enumeration itms = items().all(); itms.hasMoreElements(); ) 813 { 814 itm = (lalr_item)itms.nextElement(); 815 816 817 if (itm != red_itm && !itm.dot_at_end()) 818 { 819 820 shift_sym = itm.symbol_after_dot(); 821 if (!shift_sym.is_non_term() && shift_sym.index() == conflict_sym) 822 { 823 824 message += " and " + itm.to_simple_string()+"\n"; 825 } 826 } 827 } 828 message += " under symbol "+ terminal.find(conflict_sym).name() + "\n"+ 829 " Resolved in favor of shifting.\n"; 830 831 832 emit.num_conflicts++; 833 ErrorManager.getManager().emit_warning(message); 834 } 835 836 837 838 839 public boolean equals(lalr_state other) 840 { 841 842 return other != null && items().equals(other.items()); 843 } 844 845 846 847 848 public boolean equals(Object other) 849 { 850 if (!(other instanceof lalr_state)) 851 return false; 852 else 853 return equals((lalr_state)other); 854 } 855 856 857 858 859 public int hashCode() 860 { 861 862 return items().hashCode(); 863 } 864 865 866 867 868 public String toString() 869 { 870 String result; 871 lalr_transition tr; 872 873 874 result = "lalr_state [" + index() + "]: " + _items + "\n"; 875 876 877 for (tr = transitions(); tr != null; tr = tr.next()) 878 { 879 result += tr; 880 result += "\n"; 881 } 882 883 return result; 884 } 885 886 887 } 888 | Popular Tags |