1 2 package com.sun.java_cup.internal.runtime; 3 4 import java.util.Stack ; 5 6 114 115 public abstract class lr_parser { 116 117 118 119 120 121 122 public lr_parser() 123 { 124 125 } 126 127 128 public lr_parser(Scanner s) { 129 this(); 130 setScanner(s); 131 } 132 133 134 135 136 137 140 protected final static int _error_sync_size = 3; 141 142 143 144 147 protected int error_sync_size() {return _error_sync_size; } 148 149 150 151 152 153 160 public abstract short[][] production_table(); 161 162 163 164 178 public abstract short[][] action_table(); 179 180 181 182 195 public abstract short[][] reduce_table(); 196 197 198 199 200 public abstract int start_state(); 201 202 203 204 205 public abstract int start_production(); 206 207 208 209 212 public abstract int EOF_sym(); 213 214 215 216 217 public abstract int error_sym(); 218 219 220 221 222 protected boolean _done_parsing = false; 223 224 225 226 230 public void done_parsing() 231 { 232 _done_parsing = true; 233 } 234 235 236 238 239 240 241 protected int tos; 242 243 244 245 246 protected Symbol cur_token; 247 248 249 250 251 protected Stack stack = new Stack (); 252 253 254 255 256 protected short[][] production_tab; 257 258 259 260 261 protected short[][] action_tab; 262 263 264 265 266 protected short[][] reduce_tab; 267 268 269 270 273 private Scanner _scanner; 274 275 278 public void setScanner(Scanner s) { _scanner = s; } 279 280 283 public Scanner getScanner() { return _scanner; } 284 285 286 287 288 289 298 public abstract Symbol do_action( 299 int act_num, 300 lr_parser parser, 301 Stack stack, 302 int top) 303 throws java.lang.Exception ; 304 305 306 307 314 public void user_init() throws java.lang.Exception { } 315 316 317 318 322 protected abstract void init_actions() throws java.lang.Exception ; 323 324 325 326 334 public Symbol scan() throws java.lang.Exception { 335 return getScanner().next_token(); 336 } 337 338 339 340 348 public void report_fatal_error( 349 String message, 350 Object info) 351 throws java.lang.Exception 352 { 353 354 done_parsing(); 355 356 357 report_error(message, info); 358 359 360 throw new Exception ("Can't recover from previous error(s)"); 361 } 362 363 364 365 374 public void report_error(String message, Object info) 375 { 376 System.err.print(message); 377 if (info instanceof Symbol) 378 if (((Symbol)info).left != -1) 379 System.err.println(" at character " + ((Symbol)info).left + 380 " of input"); 381 else System.err.println(""); 382 else System.err.println(""); 383 } 384 385 386 387 393 public void syntax_error(Symbol cur_token) 394 { 395 report_error("Syntax error", cur_token); 396 } 397 398 399 400 405 public void unrecovered_syntax_error(Symbol cur_token) 406 throws java.lang.Exception 407 { 408 report_fatal_error("Couldn't repair and continue parse", cur_token); 409 } 410 411 412 413 423 protected final short get_action(int state, int sym) 424 { 425 short tag; 426 int first, last, probe; 427 short[] row = action_tab[state]; 428 429 430 if (row.length < 20) 431 for (probe = 0; probe < row.length; probe++) 432 { 433 434 tag = row[probe++]; 435 if (tag == sym || tag == -1) 436 { 437 438 return row[probe]; 439 } 440 } 441 442 else 443 { 444 first = 0; 445 last = (row.length-1)/2 - 1; 446 while (first <= last) 447 { 448 probe = (first+last)/2; 449 if (sym == row[probe*2]) 450 return row[probe*2+1]; 451 else if (sym > row[probe*2]) 452 first = probe+1; 453 else 454 last = probe-1; 455 } 456 457 458 return row[row.length-1]; 459 } 460 461 463 return 0; 464 } 465 466 467 468 478 protected final short get_reduce(int state, int sym) 479 { 480 short tag; 481 short[] row = reduce_tab[state]; 482 483 484 if (row == null) 485 return -1; 486 487 for (int probe = 0; probe < row.length; probe++) 488 { 489 490 tag = row[probe++]; 491 if (tag == sym || tag == -1) 492 { 493 494 return row[probe]; 495 } 496 } 497 498 return -1; 499 } 500 501 502 503 509 public Symbol parse() throws java.lang.Exception 510 { 511 512 int act; 513 514 515 Symbol lhs_sym = null; 516 517 518 short handle_size, lhs_sym_num; 519 520 521 522 production_tab = production_table(); 523 action_tab = action_table(); 524 reduce_tab = reduce_table(); 525 526 527 init_actions(); 528 529 530 user_init(); 531 532 533 cur_token = scan(); 534 535 536 stack.removeAllElements(); 537 stack.push(new Symbol(0, start_state())); 538 tos = 0; 539 540 541 for (_done_parsing = false; !_done_parsing; ) 542 { 543 544 if (cur_token.used_by_parser) 545 throw new Error ("Symbol recycling detected (fix your scanner)."); 546 547 548 549 550 act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); 551 552 553 if (act > 0) 554 { 555 556 cur_token.parse_state = act-1; 557 cur_token.used_by_parser = true; 558 stack.push(cur_token); 559 tos++; 560 561 562 cur_token = scan(); 563 } 564 565 else if (act < 0) 566 { 567 568 lhs_sym = do_action((-act)-1, this, stack, tos); 569 570 571 lhs_sym_num = production_tab[(-act)-1][0]; 572 handle_size = production_tab[(-act)-1][1]; 573 574 575 for (int i = 0; i < handle_size; i++) 576 { 577 stack.pop(); 578 tos--; 579 } 580 581 582 act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); 583 584 585 lhs_sym.parse_state = act; 586 lhs_sym.used_by_parser = true; 587 stack.push(lhs_sym); 588 tos++; 589 } 590 591 else if (act == 0) 592 { 593 594 syntax_error(cur_token); 595 596 597 if (!error_recovery(false)) 598 { 599 600 unrecovered_syntax_error(cur_token); 601 602 603 done_parsing(); 604 } else { 605 lhs_sym = (Symbol)stack.peek(); 606 } 607 } 608 } 609 return lhs_sym; 610 } 611 612 613 614 619 public void debug_message(String mess) 620 { 621 System.err.println(mess); 622 } 623 624 625 626 627 public void dump_stack() 628 { 629 if (stack == null) 630 { 631 debug_message("# Stack dump requested, but stack is null"); 632 return; 633 } 634 635 debug_message("============ Parse Stack Dump ============"); 636 637 638 for (int i=0; i<stack.size(); i++) 639 { 640 debug_message("Symbol: " + ((Symbol)stack.elementAt(i)).sym + 641 " State: " + ((Symbol)stack.elementAt(i)).parse_state); 642 } 643 debug_message("=========================================="); 644 } 645 646 647 648 654 public void debug_reduce(int prod_num, int nt_num, int rhs_size) 655 { 656 debug_message("# Reduce with prod #" + prod_num + " [NT=" + nt_num + 657 ", " + "SZ=" + rhs_size + "]"); 658 } 659 660 661 662 666 public void debug_shift(Symbol shift_tkn) 667 { 668 debug_message("# Shift under term #" + shift_tkn.sym + 669 " to state #" + shift_tkn.parse_state); 670 } 671 672 673 674 676 public void debug_stack() { 677 StringBuffer sb=new StringBuffer ("## STACK:"); 678 for (int i=0; i<stack.size(); i++) { 679 Symbol s = (Symbol) stack.elementAt(i); 680 sb.append(" <state "+s.parse_state+", sym "+s.sym+">"); 681 if ((i%3)==2 || (i==(stack.size()-1))) { 682 debug_message(sb.toString()); 683 sb = new StringBuffer (" "); 684 } 685 } 686 } 687 688 689 690 695 public Symbol debug_parse() 696 throws java.lang.Exception 697 { 698 699 int act; 700 701 702 Symbol lhs_sym = null; 703 704 705 short handle_size, lhs_sym_num; 706 707 708 production_tab = production_table(); 709 action_tab = action_table(); 710 reduce_tab = reduce_table(); 711 712 debug_message("# Initializing parser"); 713 714 715 init_actions(); 716 717 718 user_init(); 719 720 721 cur_token = scan(); 722 723 debug_message("# Current Symbol is #" + cur_token.sym); 724 725 726 stack.removeAllElements(); 727 stack.push(new Symbol(0, start_state())); 728 tos = 0; 729 730 731 for (_done_parsing = false; !_done_parsing; ) 732 { 733 734 if (cur_token.used_by_parser) 735 throw new Error ("Symbol recycling detected (fix your scanner)."); 736 737 738 740 741 act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); 742 743 744 if (act > 0) 745 { 746 747 cur_token.parse_state = act-1; 748 cur_token.used_by_parser = true; 749 debug_shift(cur_token); 750 stack.push(cur_token); 751 tos++; 752 753 754 cur_token = scan(); 755 debug_message("# Current token is " + cur_token); 756 } 757 758 else if (act < 0) 759 { 760 761 lhs_sym = do_action((-act)-1, this, stack, tos); 762 763 764 lhs_sym_num = production_tab[(-act)-1][0]; 765 handle_size = production_tab[(-act)-1][1]; 766 767 debug_reduce((-act)-1, lhs_sym_num, handle_size); 768 769 770 for (int i = 0; i < handle_size; i++) 771 { 772 stack.pop(); 773 tos--; 774 } 775 776 777 act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); 778 debug_message("# Reduce rule: top state " + 779 ((Symbol)stack.peek()).parse_state + 780 ", lhs sym " + lhs_sym_num + " -> state " + act); 781 782 783 lhs_sym.parse_state = act; 784 lhs_sym.used_by_parser = true; 785 stack.push(lhs_sym); 786 tos++; 787 788 debug_message("# Goto state #" + act); 789 } 790 791 else if (act == 0) 792 { 793 794 syntax_error(cur_token); 795 796 797 if (!error_recovery(true)) 798 { 799 800 unrecovered_syntax_error(cur_token); 801 802 803 done_parsing(); 804 } else { 805 lhs_sym = (Symbol)stack.peek(); 806 } 807 } 808 } 809 return lhs_sym; 810 } 811 812 813 814 815 816 838 protected boolean error_recovery(boolean debug) 839 throws java.lang.Exception 840 { 841 if (debug) debug_message("# Attempting error recovery"); 842 843 845 if (!find_recovery_config(debug)) 846 { 847 if (debug) debug_message("# Error recovery fails"); 848 return false; 849 } 850 851 852 read_lookahead(); 853 854 855 for (;;) 856 { 857 858 if (debug) debug_message("# Trying to parse ahead"); 859 if (try_parse_ahead(debug)) 860 { 861 break; 862 } 863 864 865 if (lookahead[0].sym == EOF_sym()) 866 { 867 if (debug) debug_message("# Error recovery fails at EOF"); 868 return false; 869 } 870 871 872 if (debug) 873 debug_message("# Consuming Symbol #" + cur_err_token().sym); 874 restart_lookahead(); 875 } 876 877 878 if (debug) debug_message("# Parse-ahead ok, going back to normal parse"); 879 880 881 parse_lookahead(debug); 882 883 884 return true; 885 } 886 887 888 889 892 protected boolean shift_under_error() 893 { 894 895 return get_action(((Symbol)stack.peek()).parse_state, error_sym()) > 0; 896 } 897 898 899 900 907 protected boolean find_recovery_config(boolean debug) 908 { 909 Symbol error_token; 910 int act; 911 912 if (debug) debug_message("# Finding recovery state on stack"); 913 914 915 int right_pos = ((Symbol)stack.peek()).right; 916 int left_pos = ((Symbol)stack.peek()).left; 917 918 919 while (!shift_under_error()) 920 { 921 922 if (debug) 923 debug_message("# Pop stack by one, state was # " + 924 ((Symbol)stack.peek()).parse_state); 925 left_pos = ((Symbol)stack.pop()).left; 926 tos--; 927 928 929 if (stack.empty()) 930 { 931 if (debug) debug_message("# No recovery state found on stack"); 932 return false; 933 } 934 } 935 936 937 act = get_action(((Symbol)stack.peek()).parse_state, error_sym()); 938 if (debug) 939 { 940 debug_message("# Recover state found (#" + 941 ((Symbol)stack.peek()).parse_state + ")"); 942 debug_message("# Shifting on error to state #" + (act-1)); 943 } 944 945 946 error_token = new Symbol(error_sym(), left_pos, right_pos); 947 error_token.parse_state = act-1; 948 error_token.used_by_parser = true; 949 stack.push(error_token); 950 tos++; 951 952 return true; 953 } 954 955 956 957 958 protected Symbol lookahead[]; 959 960 961 protected int lookahead_pos; 962 963 964 965 968 protected void read_lookahead() throws java.lang.Exception 969 { 970 971 lookahead = new Symbol[error_sync_size()]; 972 973 974 for (int i = 0; i < error_sync_size(); i++) 975 { 976 lookahead[i] = cur_token; 977 cur_token = scan(); 978 } 979 980 981 lookahead_pos = 0; 982 } 983 984 985 986 987 protected Symbol cur_err_token() { return lookahead[lookahead_pos]; } 988 989 990 991 994 protected boolean advance_lookahead() 995 { 996 997 lookahead_pos++; 998 999 1000 return lookahead_pos < error_sync_size(); 1001 } 1002 1003 1004 1005 1008 protected void restart_lookahead() throws java.lang.Exception 1009 { 1010 1011 for (int i = 1; i < error_sync_size(); i++) 1012 lookahead[i-1] = lookahead[i]; 1013 1014 1015 cur_token = scan(); 1016 lookahead[error_sync_size()-1] = cur_token; 1017 1018 1019 lookahead_pos = 0; 1020 } 1021 1022 1023 1024 1033 protected boolean try_parse_ahead(boolean debug) 1034 throws java.lang.Exception 1035 { 1036 int act; 1037 short lhs, rhs_size; 1038 1039 1040 virtual_parse_stack vstack = new virtual_parse_stack(stack); 1041 1042 1043 for (;;) 1044 { 1045 1046 act = get_action(vstack.top(), cur_err_token().sym); 1047 1048 1049 if (act == 0) return false; 1050 1051 1052 if (act > 0) 1053 { 1054 1055 vstack.push(act-1); 1056 1057 if (debug) debug_message("# Parse-ahead shifts Symbol #" + 1058 cur_err_token().sym + " into state #" + (act-1)); 1059 1060 1061 if (!advance_lookahead()) return true; 1062 } 1063 1064 else 1065 { 1066 1067 if ((-act)-1 == start_production()) 1068 { 1069 if (debug) debug_message("# Parse-ahead accepts"); 1070 return true; 1071 } 1072 1073 1074 lhs = production_tab[(-act)-1][0]; 1075 rhs_size = production_tab[(-act)-1][1]; 1076 1077 1078 for (int i = 0; i < rhs_size; i++) 1079 vstack.pop(); 1080 1081 if (debug) 1082 debug_message("# Parse-ahead reduces: handle size = " + 1083 rhs_size + " lhs = #" + lhs + " from state #" + vstack.top()); 1084 1085 1086 vstack.push(get_reduce(vstack.top(), lhs)); 1087 if (debug) 1088 debug_message("# Goto state #" + vstack.top()); 1089 } 1090 } 1091 } 1092 1093 1094 1095 1104 protected void parse_lookahead(boolean debug) 1105 throws java.lang.Exception 1106 { 1107 1108 int act; 1109 1110 1111 Symbol lhs_sym = null; 1112 1113 1114 short handle_size, lhs_sym_num; 1115 1116 1117 lookahead_pos = 0; 1118 1119 if (debug) 1120 { 1121 debug_message("# Reparsing saved input with actions"); 1122 debug_message("# Current Symbol is #" + cur_err_token().sym); 1123 debug_message("# Current state is #" + 1124 ((Symbol)stack.peek()).parse_state); 1125 } 1126 1127 1128 while(!_done_parsing) 1129 { 1130 1131 1132 1133 act = 1134 get_action(((Symbol)stack.peek()).parse_state, cur_err_token().sym); 1135 1136 1137 if (act > 0) 1138 { 1139 1140 cur_err_token().parse_state = act-1; 1141 cur_err_token().used_by_parser = true; 1142 if (debug) debug_shift(cur_err_token()); 1143 stack.push(cur_err_token()); 1144 tos++; 1145 1146 1147 if (!advance_lookahead()) 1148 { 1149 if (debug) debug_message("# Completed reparse"); 1150 1151 1152 1156 1157 1158 return; 1159 } 1160 1161 if (debug) 1162 debug_message("# Current Symbol is #" + cur_err_token().sym); 1163 } 1164 1165 else if (act < 0) 1166 { 1167 1168 lhs_sym = do_action((-act)-1, this, stack, tos); 1169 1170 1171 lhs_sym_num = production_tab[(-act)-1][0]; 1172 handle_size = production_tab[(-act)-1][1]; 1173 1174 if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size); 1175 1176 1177 for (int i = 0; i < handle_size; i++) 1178 { 1179 stack.pop(); 1180 tos--; 1181 } 1182 1183 1184 act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); 1185 1186 1187 lhs_sym.parse_state = act; 1188 lhs_sym.used_by_parser = true; 1189 stack.push(lhs_sym); 1190 tos++; 1191 1192 if (debug) debug_message("# Goto state #" + act); 1193 1194 } 1195 1197 else if (act == 0) 1198 { 1199 report_fatal_error("Syntax error", lhs_sym); 1200 return; 1201 } 1202 } 1203 1204 1205 } 1206 1207 1208 1209 1210 protected static short[][] unpackFromStrings(String [] sa) 1211 { 1212 StringBuffer sb = new StringBuffer (sa[0]); 1214 for (int i=1; i<sa.length; i++) 1215 sb.append(sa[i]); 1216 int n=0; int size1 = (((int)sb.charAt(n))<<16) | ((int)sb.charAt(n+1)); n+=2; 1218 short[][] result = new short[size1][]; 1219 for (int i=0; i<size1; i++) { 1220 int size2 = (((int)sb.charAt(n))<<16) | ((int)sb.charAt(n+1)); n+=2; 1221 result[i] = new short[size2]; 1222 for (int j=0; j<size2; j++) 1223 result[i][j] = (short) (sb.charAt(n++)-2); 1224 } 1225 return result; 1226 } 1227} 1228 1229 | Popular Tags |