1 2 package java_cup.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 Symbol sym = getScanner().next_token(); 336 return (sym!=null) ? sym : new Symbol(EOF_sym()); 337 } 338 339 340 341 349 public void report_fatal_error( 350 String message, 351 Object info) 352 throws java.lang.Exception 353 { 354 355 done_parsing(); 356 357 358 report_error(message, info); 359 360 361 throw new Exception ("Can't recover from previous error(s)"); 362 } 363 364 365 366 375 public void report_error(String message, Object info) 376 { 377 System.err.print(message); 378 if (info instanceof Symbol) 379 if (((Symbol)info).left != -1) 380 System.err.println(" at character " + ((Symbol)info).left + 381 " of input"); 382 else System.err.println(""); 383 else System.err.println(""); 384 } 385 386 387 388 394 public void syntax_error(Symbol cur_token) 395 { 396 report_error("Syntax error", cur_token); 397 } 398 399 400 401 406 public void unrecovered_syntax_error(Symbol cur_token) 407 throws java.lang.Exception 408 { 409 report_fatal_error("Couldn't repair and continue parse", cur_token); 410 } 411 412 413 414 424 protected final short get_action(int state, int sym) 425 { 426 short tag; 427 int first, last, probe; 428 short[] row = action_tab[state]; 429 430 431 if (row.length < 20) 432 for (probe = 0; probe < row.length; probe++) 433 { 434 435 tag = row[probe++]; 436 if (tag == sym || tag == -1) 437 { 438 439 return row[probe]; 440 } 441 } 442 443 else 444 { 445 first = 0; 446 last = (row.length-1)/2 - 1; 447 while (first <= last) 448 { 449 probe = (first+last)/2; 450 if (sym == row[probe*2]) 451 return row[probe*2+1]; 452 else if (sym > row[probe*2]) 453 first = probe+1; 454 else 455 last = probe-1; 456 } 457 458 459 return row[row.length-1]; 460 } 461 462 464 return 0; 465 } 466 467 468 469 479 protected final short get_reduce(int state, int sym) 480 { 481 short tag; 482 short[] row = reduce_tab[state]; 483 484 485 if (row == null) 486 return -1; 487 488 for (int probe = 0; probe < row.length; probe++) 489 { 490 491 tag = row[probe++]; 492 if (tag == sym || tag == -1) 493 { 494 495 return row[probe]; 496 } 497 } 498 499 return -1; 500 } 501 502 503 504 510 public Symbol parse() throws java.lang.Exception 511 { 512 513 int act; 514 515 516 Symbol lhs_sym = null; 517 518 519 short handle_size, lhs_sym_num; 520 521 522 523 production_tab = production_table(); 524 action_tab = action_table(); 525 reduce_tab = reduce_table(); 526 527 528 init_actions(); 529 530 531 user_init(); 532 533 534 cur_token = scan(); 535 536 537 stack.removeAllElements(); 538 stack.push(new Symbol(0, start_state())); 539 tos = 0; 540 541 542 for (_done_parsing = false; !_done_parsing; ) 543 { 544 545 if (cur_token.used_by_parser) 546 throw new Error ("Symbol recycling detected (fix your scanner)."); 547 548 549 550 551 act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); 552 553 554 if (act > 0) 555 { 556 557 cur_token.parse_state = act-1; 558 cur_token.used_by_parser = true; 559 stack.push(cur_token); 560 tos++; 561 562 563 cur_token = scan(); 564 } 565 566 else if (act < 0) 567 { 568 569 lhs_sym = do_action((-act)-1, this, stack, tos); 570 571 572 lhs_sym_num = production_tab[(-act)-1][0]; 573 handle_size = production_tab[(-act)-1][1]; 574 575 576 for (int i = 0; i < handle_size; i++) 577 { 578 stack.pop(); 579 tos--; 580 } 581 582 583 act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); 584 585 586 lhs_sym.parse_state = act; 587 lhs_sym.used_by_parser = true; 588 stack.push(lhs_sym); 589 tos++; 590 } 591 592 else if (act == 0) 593 { 594 595 syntax_error(cur_token); 596 597 598 if (!error_recovery(false)) 599 { 600 601 unrecovered_syntax_error(cur_token); 602 603 604 done_parsing(); 605 } else { 606 lhs_sym = (Symbol)stack.peek(); 607 } 608 } 609 } 610 return lhs_sym; 611 } 612 613 614 615 620 public void debug_message(String mess) 621 { 622 System.err.println(mess); 623 } 624 625 626 627 628 public void dump_stack() 629 { 630 if (stack == null) 631 { 632 debug_message("# Stack dump requested, but stack is null"); 633 return; 634 } 635 636 debug_message("============ Parse Stack Dump ============"); 637 638 639 for (int i=0; i<stack.size(); i++) 640 { 641 debug_message("Symbol: " + ((Symbol)stack.elementAt(i)).sym + 642 " State: " + ((Symbol)stack.elementAt(i)).parse_state); 643 } 644 debug_message("=========================================="); 645 } 646 647 648 649 655 public void debug_reduce(int prod_num, int nt_num, int rhs_size) 656 { 657 debug_message("# Reduce with prod #" + prod_num + " [NT=" + nt_num + 658 ", " + "SZ=" + rhs_size + "]"); 659 } 660 661 662 663 667 public void debug_shift(Symbol shift_tkn) 668 { 669 debug_message("# Shift under term #" + shift_tkn.sym + 670 " to state #" + shift_tkn.parse_state); 671 } 672 673 674 675 677 public void debug_stack() { 678 StringBuffer sb=new StringBuffer ("## STACK:"); 679 for (int i=0; i<stack.size(); i++) { 680 Symbol s = (Symbol) stack.elementAt(i); 681 sb.append(" <state "+s.parse_state+", sym "+s.sym+">"); 682 if ((i%3)==2 || (i==(stack.size()-1))) { 683 debug_message(sb.toString()); 684 sb = new StringBuffer (" "); 685 } 686 } 687 } 688 689 690 691 696 public Symbol debug_parse() 697 throws java.lang.Exception 698 { 699 700 int act; 701 702 703 Symbol lhs_sym = null; 704 705 706 short handle_size, lhs_sym_num; 707 708 709 production_tab = production_table(); 710 action_tab = action_table(); 711 reduce_tab = reduce_table(); 712 713 debug_message("# Initializing parser"); 714 715 716 init_actions(); 717 718 719 user_init(); 720 721 722 cur_token = scan(); 723 724 debug_message("# Current Symbol is #" + cur_token.sym); 725 726 727 stack.removeAllElements(); 728 stack.push(new Symbol(0, start_state())); 729 tos = 0; 730 731 732 for (_done_parsing = false; !_done_parsing; ) 733 { 734 735 if (cur_token.used_by_parser) 736 throw new Error ("Symbol recycling detected (fix your scanner)."); 737 738 739 741 742 act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); 743 744 745 if (act > 0) 746 { 747 748 cur_token.parse_state = act-1; 749 cur_token.used_by_parser = true; 750 debug_shift(cur_token); 751 stack.push(cur_token); 752 tos++; 753 754 755 cur_token = scan(); 756 debug_message("# Current token is " + cur_token); 757 } 758 759 else if (act < 0) 760 { 761 762 lhs_sym = do_action((-act)-1, this, stack, tos); 763 764 765 lhs_sym_num = production_tab[(-act)-1][0]; 766 handle_size = production_tab[(-act)-1][1]; 767 768 debug_reduce((-act)-1, lhs_sym_num, handle_size); 769 770 771 for (int i = 0; i < handle_size; i++) 772 { 773 stack.pop(); 774 tos--; 775 } 776 777 778 act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); 779 debug_message("# Reduce rule: top state " + 780 ((Symbol)stack.peek()).parse_state + 781 ", lhs sym " + lhs_sym_num + " -> state " + act); 782 783 784 lhs_sym.parse_state = act; 785 lhs_sym.used_by_parser = true; 786 stack.push(lhs_sym); 787 tos++; 788 789 debug_message("# Goto state #" + act); 790 } 791 792 else if (act == 0) 793 { 794 795 syntax_error(cur_token); 796 797 798 if (!error_recovery(true)) 799 { 800 801 unrecovered_syntax_error(cur_token); 802 803 804 done_parsing(); 805 } else { 806 lhs_sym = (Symbol)stack.peek(); 807 } 808 } 809 } 810 return lhs_sym; 811 } 812 813 814 815 816 817 839 protected boolean error_recovery(boolean debug) 840 throws java.lang.Exception 841 { 842 if (debug) debug_message("# Attempting error recovery"); 843 844 846 if (!find_recovery_config(debug)) 847 { 848 if (debug) debug_message("# Error recovery fails"); 849 return false; 850 } 851 852 853 read_lookahead(); 854 855 856 for (;;) 857 { 858 859 if (debug) debug_message("# Trying to parse ahead"); 860 if (try_parse_ahead(debug)) 861 { 862 break; 863 } 864 865 866 if (lookahead[0].sym == EOF_sym()) 867 { 868 if (debug) debug_message("# Error recovery fails at EOF"); 869 return false; 870 } 871 872 873 if (debug) 879 debug_message("# Consuming Symbol #" + lookahead[ 0 ].sym); 880 restart_lookahead(); 881 } 882 883 884 if (debug) debug_message("# Parse-ahead ok, going back to normal parse"); 885 886 887 parse_lookahead(debug); 888 889 890 return true; 891 } 892 893 894 895 898 protected boolean shift_under_error() 899 { 900 901 return get_action(((Symbol)stack.peek()).parse_state, error_sym()) > 0; 902 } 903 904 905 906 913 protected boolean find_recovery_config(boolean debug) 914 { 915 Symbol error_token; 916 int act; 917 918 if (debug) debug_message("# Finding recovery state on stack"); 919 920 921 int right_pos = ((Symbol)stack.peek()).right; 922 int left_pos = ((Symbol)stack.peek()).left; 923 924 925 while (!shift_under_error()) 926 { 927 928 if (debug) 929 debug_message("# Pop stack by one, state was # " + 930 ((Symbol)stack.peek()).parse_state); 931 left_pos = ((Symbol)stack.pop()).left; 932 tos--; 933 934 935 if (stack.empty()) 936 { 937 if (debug) debug_message("# No recovery state found on stack"); 938 return false; 939 } 940 } 941 942 943 act = get_action(((Symbol)stack.peek()).parse_state, error_sym()); 944 if (debug) 945 { 946 debug_message("# Recover state found (#" + 947 ((Symbol)stack.peek()).parse_state + ")"); 948 debug_message("# Shifting on error to state #" + (act-1)); 949 } 950 951 952 error_token = new Symbol(error_sym(), left_pos, right_pos); 953 error_token.parse_state = act-1; 954 error_token.used_by_parser = true; 955 stack.push(error_token); 956 tos++; 957 958 return true; 959 } 960 961 962 963 964 protected Symbol lookahead[]; 965 966 967 protected int lookahead_pos; 968 969 970 971 974 protected void read_lookahead() throws java.lang.Exception 975 { 976 977 lookahead = new Symbol[error_sync_size()]; 978 979 980 for (int i = 0; i < error_sync_size(); i++) 981 { 982 lookahead[i] = cur_token; 983 cur_token = scan(); 984 } 985 986 987 lookahead_pos = 0; 988 } 989 990 991 992 993 protected Symbol cur_err_token() { return lookahead[lookahead_pos]; } 994 995 996 997 1000 protected boolean advance_lookahead() 1001 { 1002 1003 lookahead_pos++; 1004 1005 1006 return lookahead_pos < error_sync_size(); 1007 } 1008 1009 1010 1011 1014 protected void restart_lookahead() throws java.lang.Exception 1015 { 1016 1017 for (int i = 1; i < error_sync_size(); i++) 1018 lookahead[i-1] = lookahead[i]; 1019 1020 1021 lookahead[error_sync_size()-1] = cur_token; 1026 cur_token = scan(); 1027 1028 1029 lookahead_pos = 0; 1030 } 1031 1032 1033 1034 1043 protected boolean try_parse_ahead(boolean debug) 1044 throws java.lang.Exception 1045 { 1046 int act; 1047 short lhs, rhs_size; 1048 1049 1050 virtual_parse_stack vstack = new virtual_parse_stack(stack); 1051 1052 1053 for (;;) 1054 { 1055 1056 act = get_action(vstack.top(), cur_err_token().sym); 1057 1058 1059 if (act == 0) return false; 1060 1061 1062 if (act > 0) 1063 { 1064 1065 vstack.push(act-1); 1066 1067 if (debug) debug_message("# Parse-ahead shifts Symbol #" + 1068 cur_err_token().sym + " into state #" + (act-1)); 1069 1070 1071 if (!advance_lookahead()) return true; 1072 } 1073 1074 else 1075 { 1076 1077 if ((-act)-1 == start_production()) 1078 { 1079 if (debug) debug_message("# Parse-ahead accepts"); 1080 return true; 1081 } 1082 1083 1084 lhs = production_tab[(-act)-1][0]; 1085 rhs_size = production_tab[(-act)-1][1]; 1086 1087 1088 for (int i = 0; i < rhs_size; i++) 1089 vstack.pop(); 1090 1091 if (debug) 1092 debug_message("# Parse-ahead reduces: handle size = " + 1093 rhs_size + " lhs = #" + lhs + " from state #" + vstack.top()); 1094 1095 1096 vstack.push(get_reduce(vstack.top(), lhs)); 1097 if (debug) 1098 debug_message("# Goto state #" + vstack.top()); 1099 } 1100 } 1101 } 1102 1103 1104 1105 1114 protected void parse_lookahead(boolean debug) 1115 throws java.lang.Exception 1116 { 1117 1118 int act; 1119 1120 1121 Symbol lhs_sym = null; 1122 1123 1124 short handle_size, lhs_sym_num; 1125 1126 1127 lookahead_pos = 0; 1128 1129 if (debug) 1130 { 1131 debug_message("# Reparsing saved input with actions"); 1132 debug_message("# Current Symbol is #" + cur_err_token().sym); 1133 debug_message("# Current state is #" + 1134 ((Symbol)stack.peek()).parse_state); 1135 } 1136 1137 1138 while(!_done_parsing) 1139 { 1140 1141 1142 1143 act = 1144 get_action(((Symbol)stack.peek()).parse_state, cur_err_token().sym); 1145 1146 1147 if (act > 0) 1148 { 1149 1150 cur_err_token().parse_state = act-1; 1151 cur_err_token().used_by_parser = true; 1152 if (debug) debug_shift(cur_err_token()); 1153 stack.push(cur_err_token()); 1154 tos++; 1155 1156 1157 if (!advance_lookahead()) 1158 { 1159 if (debug) debug_message("# Completed reparse"); 1160 1161 1162 1166 1167 1168 return; 1169 } 1170 1171 if (debug) 1172 debug_message("# Current Symbol is #" + cur_err_token().sym); 1173 } 1174 1175 else if (act < 0) 1176 { 1177 1178 lhs_sym = do_action((-act)-1, this, stack, tos); 1179 1180 1181 lhs_sym_num = production_tab[(-act)-1][0]; 1182 handle_size = production_tab[(-act)-1][1]; 1183 1184 if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size); 1185 1186 1187 for (int i = 0; i < handle_size; i++) 1188 { 1189 stack.pop(); 1190 tos--; 1191 } 1192 1193 1194 act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); 1195 1196 1197 lhs_sym.parse_state = act; 1198 lhs_sym.used_by_parser = true; 1199 stack.push(lhs_sym); 1200 tos++; 1201 1202 if (debug) debug_message("# Goto state #" + act); 1203 1204 } 1205 1207 else if (act == 0) 1208 { 1209 report_fatal_error("Syntax error", lhs_sym); 1210 return; 1211 } 1212 } 1213 1214 1215 } 1216 1217 1218 1219 1220 protected static short[][] unpackFromStrings(String [] sa) 1221 { 1222 StringBuffer sb = new StringBuffer (sa[0]); 1224 for (int i=1; i<sa.length; i++) 1225 sb.append(sa[i]); 1226 int n=0; int size1 = (((int)sb.charAt(n))<<16) | ((int)sb.charAt(n+1)); n+=2; 1228 short[][] result = new short[size1][]; 1229 for (int i=0; i<size1; i++) { 1230 int size2 = (((int)sb.charAt(n))<<16) | ((int)sb.charAt(n+1)); n+=2; 1231 result[i] = new short[size2]; 1232 for (int j=0; j<size2; j++) 1233 result[i][j] = (short) (sb.charAt(n++)-2); 1234 } 1235 return result; 1236 } 1237} 1238 1239 | Popular Tags |