1 2 package org.jacorb.idl.runtime; 3 4 import java.util.Stack ; 5 6 111 112 public abstract class lr_parser { 113 114 115 116 117 118 119 public lr_parser() 120 { 121 122 } 123 124 125 126 127 128 131 protected final static int _error_sync_size = 3; 132 133 134 135 138 protected int error_sync_size() {return _error_sync_size; } 139 140 141 142 143 144 151 public abstract short[][] production_table(); 152 153 154 155 169 public abstract short[][] action_table(); 170 171 172 173 186 public abstract short[][] reduce_table(); 187 188 189 190 191 public abstract int start_state(); 192 193 194 195 196 public abstract int start_production(); 197 198 199 200 203 public abstract int EOF_sym(); 204 205 206 207 208 public abstract int error_sym(); 209 210 211 212 213 protected boolean _done_parsing = false; 214 215 216 217 221 public void done_parsing() 222 { 223 _done_parsing = true; 224 } 225 226 227 229 230 231 232 protected int tos; 233 234 235 236 237 protected token cur_token; 238 239 240 241 242 protected Stack stack = new Stack (); 243 244 245 246 247 protected short[][] production_tab; 248 249 250 251 252 protected short[][] action_tab; 253 254 255 256 257 protected short[][] reduce_tab; 258 259 260 261 262 263 272 public abstract symbol do_action( 273 int act_num, 274 lr_parser parser, 275 Stack stack, 276 int top) 277 throws java.lang.Exception ; 278 279 280 281 288 public void user_init() throws java.lang.Exception { } 289 290 291 292 296 protected abstract void init_actions() throws java.lang.Exception ; 297 298 299 300 306 public abstract token scan() throws java.lang.Exception ; 307 308 309 310 318 public void report_fatal_error( 319 String message, 320 Object info) 321 throws java.lang.Exception 322 { 323 324 done_parsing(); 325 326 327 report_error(message, info); 328 329 330 throw new Exception ("Can't recover from previous error(s)"); 331 } 332 333 334 335 344 public void report_error(String message, Object info) 345 { 346 System.err.println(message); 347 } 348 349 350 351 357 public void syntax_error(token cur_token) 358 { 359 report_error("Syntax error", null); 360 } 361 362 363 364 369 public void unrecovered_syntax_error(token cur_token) 370 throws java.lang.Exception 371 { 372 report_fatal_error("Couldn't repair and continue parse", null); 373 } 374 375 376 377 387 protected final short get_action(int state, int sym) 388 { 389 short tag; 390 int first, last, probe; 391 short[] row = action_tab[state]; 392 393 394 if (row.length < 20) 395 for (probe = 0; probe < row.length; probe++) 396 { 397 398 tag = row[probe++]; 399 if (tag == sym || tag == -1) 400 { 401 402 return row[probe]; 403 } 404 } 405 406 else 407 { 408 first = 0; 409 last = (row.length-1)/2 - 1; 410 while (first <= last) 411 { 412 probe = (first+last)/2; 413 if (sym == row[probe*2]) 414 return row[probe*2+1]; 415 else if (sym > row[probe*2]) 416 first = probe+1; 417 else 418 last = probe-1; 419 } 420 421 422 return row[row.length-1]; 423 } 424 425 427 return 0; 428 } 429 430 431 432 442 protected final short get_reduce(int state, int sym) 443 { 444 short tag; 445 short[] row = reduce_tab[state]; 446 447 448 if (row == null) 449 return -1; 450 451 for (int probe = 0; probe < row.length; probe++) 452 { 453 454 tag = row[probe++]; 455 if (tag == sym || tag == -1) 456 { 457 458 return row[probe]; 459 } 460 } 461 462 return -1; 463 } 464 465 466 467 473 public void parse() throws java.lang.Exception 474 { 475 476 int act; 477 478 479 symbol lhs_sym; 480 481 482 short handle_size, lhs_sym_num; 483 484 485 486 production_tab = production_table(); 487 action_tab = action_table(); 488 reduce_tab = reduce_table(); 489 490 491 init_actions(); 492 493 494 user_init(); 495 496 497 cur_token = scan(); 498 499 500 stack.push(new symbol(0, start_state())); 501 tos = 0; 502 503 504 for (_done_parsing = false; !_done_parsing; ) 505 { 506 507 508 if (cur_token == null) 509 { 510 unrecovered_syntax_error (cur_token); 512 } 513 514 act = get_action(((symbol)stack.peek()).parse_state, cur_token.sym); 515 516 517 if (act > 0) 518 { 519 520 cur_token.parse_state = act-1; 521 stack.push(cur_token); 522 tos++; 523 524 525 cur_token = scan(); 526 } 527 528 else if (act < 0) 529 { 530 531 lhs_sym = do_action((-act)-1, this, stack, tos); 532 533 534 lhs_sym_num = production_tab[(-act)-1][0]; 535 handle_size = production_tab[(-act)-1][1]; 536 537 538 for (int i = 0; i < handle_size; i++) 539 { 540 stack.pop(); 541 tos--; 542 } 543 544 545 act = get_reduce(((symbol)stack.peek()).parse_state, lhs_sym_num); 546 547 548 lhs_sym.parse_state = act; 549 stack.push(lhs_sym); 550 tos++; 551 } 552 553 else if (act == 0) 554 { 555 556 syntax_error(cur_token); 557 558 559 if (!error_recovery(false)) 560 { 561 562 unrecovered_syntax_error(cur_token); 563 564 565 done_parsing(); 566 } 567 } 568 } 569 } 570 571 572 573 578 public void debug_message(String mess) 579 { 580 System.err.println(mess); 581 } 582 583 584 585 586 public void dump_stack() 587 { 588 if (stack == null) 589 { 590 debug_message("# Stack dump requested, but stack is null"); 591 return; 592 } 593 594 debug_message("============ Parse Stack Dump ============"); 595 596 597 for (int i=0; i<stack.size(); i++) 598 { 599 debug_message("Symbol: " + ((symbol)stack.elementAt(i)).sym + 600 " State: " + ((symbol)stack.elementAt(i)).parse_state); 601 } 602 debug_message("=========================================="); 603 } 604 605 606 607 613 public void debug_reduce(int prod_num, int nt_num, int rhs_size) 614 { 615 debug_message("# Reduce with prod #" + prod_num + " [NT=" + nt_num + 616 ", " + "SZ=" + rhs_size + "]"); 617 } 618 619 620 621 625 public void debug_shift(token shift_tkn) 626 { 627 debug_message("# Shift under term #" + shift_tkn.sym + 628 " to state #" + shift_tkn.parse_state); 629 } 630 631 632 633 638 public void debug_parse() 639 throws java.lang.Exception 640 { 641 642 int act; 643 644 645 symbol lhs_sym; 646 647 648 short handle_size, lhs_sym_num; 649 650 651 production_tab = production_table(); 652 action_tab = action_table(); 653 reduce_tab = reduce_table(); 654 655 debug_message("# Initializing parser"); 656 657 658 init_actions(); 659 660 661 user_init(); 662 663 664 cur_token = scan(); 665 666 debug_message("# Current token is #" + cur_token.sym); 667 668 669 stack.push(new symbol(0, start_state())); 670 tos = 0; 671 672 673 for (_done_parsing = false; !_done_parsing; ) 674 { 675 676 677 678 act = get_action(((symbol)stack.peek()).parse_state, cur_token.sym); 679 680 681 if (act > 0) 682 { 683 684 cur_token.parse_state = act-1; 685 debug_shift(cur_token); 686 stack.push(cur_token); 687 tos++; 688 689 690 cur_token = scan(); 691 debug_message("# Current token is #" + cur_token.sym); 692 } 693 694 else if (act < 0) 695 { 696 697 lhs_sym = do_action((-act)-1, this, stack, tos); 698 699 700 lhs_sym_num = production_tab[(-act)-1][0]; 701 handle_size = production_tab[(-act)-1][1]; 702 703 debug_reduce((-act)-1, lhs_sym_num, handle_size); 704 705 706 for (int i = 0; i < handle_size; i++) 707 { 708 stack.pop(); 709 tos--; 710 } 711 712 713 act = get_reduce(((symbol)stack.peek()).parse_state, lhs_sym_num); 714 715 716 lhs_sym.parse_state = act; 717 stack.push(lhs_sym); 718 tos++; 719 720 debug_message("# Goto state #" + act); 721 } 722 723 else if (act == 0) 724 { 725 726 syntax_error(cur_token); 727 728 729 if (!error_recovery(true)) 730 { 731 732 unrecovered_syntax_error(cur_token); 733 734 735 done_parsing(); 736 } 737 } 738 } 739 } 740 741 742 743 744 745 767 protected boolean error_recovery(boolean debug) 768 throws java.lang.Exception 769 { 770 if (debug) debug_message("# Attempting error recovery"); 771 772 774 if (!find_recovery_config(debug)) 775 { 776 if (debug) debug_message("# Error recovery fails"); 777 return false; 778 } 779 780 781 read_lookahead(); 782 783 784 for (;;) 785 { 786 787 if (debug) debug_message("# Trying to parse ahead"); 788 if (try_parse_ahead(debug)) 789 { 790 break; 791 } 792 793 794 if (lookahead[0].sym == EOF_sym()) 795 { 796 if (debug) debug_message("# Error recovery fails at EOF"); 797 return false; 798 } 799 800 801 if (debug) 802 debug_message("# Consuming token #" + cur_err_token().sym); 803 restart_lookahead(); 804 } 805 806 807 if (debug) debug_message("# Parse-ahead ok, going back to normal parse"); 808 809 810 parse_lookahead(debug); 811 812 813 return true; 814 } 815 816 817 818 821 protected boolean shift_under_error() 822 { 823 824 return get_action(((symbol)stack.peek()).parse_state, error_sym()) > 0; 825 } 826 827 828 829 836 protected boolean find_recovery_config(boolean debug) 837 { 838 token error_token; 839 int act; 840 841 if (debug) debug_message("# Finding recovery state on stack"); 842 843 844 while (!shift_under_error()) 845 { 846 847 if (debug) 848 debug_message("# Pop stack by one, state was # " + 849 ((symbol)stack.peek()).parse_state); 850 stack.pop(); 851 tos--; 852 853 854 if (stack.empty()) 855 { 856 if (debug) debug_message("# No recovery state found on stack"); 857 return false; 858 } 859 } 860 861 862 act = get_action(((symbol)stack.peek()).parse_state, error_sym()); 863 if (debug) 864 { 865 debug_message("# Recover state found (#" + 866 ((symbol)stack.peek()).parse_state + ")"); 867 debug_message("# Shifting on error to state #" + (act-1)); 868 } 869 870 871 error_token = new token(error_sym()); 872 error_token.parse_state = act-1; 873 stack.push(error_token); 874 tos++; 875 876 return true; 877 } 878 879 880 881 882 protected token lookahead[]; 883 884 885 protected int lookahead_pos; 886 887 888 889 892 protected void read_lookahead() throws java.lang.Exception 893 { 894 895 lookahead = new token[error_sync_size()]; 896 897 898 for (int i = 0; i < error_sync_size(); i++) 899 { 900 lookahead[i] = cur_token; 901 cur_token = scan(); 902 } 903 904 905 lookahead_pos = 0; 906 } 907 908 909 910 911 protected token cur_err_token() { return lookahead[lookahead_pos]; } 912 913 914 915 918 protected boolean advance_lookahead() 919 { 920 921 lookahead_pos++; 922 923 924 return lookahead_pos < error_sync_size(); 925 } 926 927 928 929 932 protected void restart_lookahead() throws java.lang.Exception 933 { 934 935 for (int i = 1; i < error_sync_size(); i++) 936 lookahead[i-1] = lookahead[i]; 937 938 939 cur_token = scan(); 940 lookahead[error_sync_size()-1] = cur_token; 941 942 943 lookahead_pos = 0; 944 } 945 946 947 948 957 protected boolean try_parse_ahead(boolean debug) 958 throws java.lang.Exception 959 { 960 int act; 961 short lhs, rhs_size; 962 963 964 virtual_parse_stack vstack = new virtual_parse_stack(stack); 965 966 967 for (;;) 968 { 969 970 act = get_action(vstack.top(), cur_err_token().sym); 971 972 973 if (act == 0) return false; 974 975 976 if (act > 0) 977 { 978 979 vstack.push(act-1); 980 981 if (debug) debug_message("# Parse-ahead shifts token #" + 982 cur_err_token().sym + " into state #" + (act-1)); 983 984 985 if (!advance_lookahead()) return true; 986 } 987 988 else 989 { 990 991 if ((-act)-1 == start_production()) 992 { 993 if (debug) debug_message("# Parse-ahead accepts"); 994 return true; 995 } 996 997 998 lhs = production_tab[(-act)-1][0]; 999 rhs_size = production_tab[(-act)-1][1]; 1000 1001 1002 for (int i = 0; i < rhs_size; i++) 1003 vstack.pop(); 1004 1005 if (debug) 1006 debug_message("# Parse-ahead reduces: handle size = " + 1007 rhs_size + " lhs = #" + lhs + " from state #" + vstack.top()); 1008 1009 1010 vstack.push(get_reduce(vstack.top(), lhs)); 1011 if (debug) 1012 debug_message("# Goto state #" + vstack.top()); 1013 } 1014 } 1015 } 1016 1017 1018 1019 1028 protected void parse_lookahead(boolean debug) 1029 throws java.lang.Exception 1030 { 1031 1032 int act; 1033 1034 1035 symbol lhs_sym; 1036 1037 1038 short handle_size, lhs_sym_num; 1039 1040 1041 lookahead_pos = 0; 1042 1043 if (debug) 1044 { 1045 debug_message("# Reparsing saved input with actions"); 1046 debug_message("# Current token is #" + cur_err_token().sym); 1047 debug_message("# Current state is #" + 1048 ((symbol)stack.peek()).parse_state); 1049 } 1050 1051 1052 while(!_done_parsing) 1053 { 1054 1055 1056 1057 act = 1058 get_action(((symbol)stack.peek()).parse_state, cur_err_token().sym); 1059 1060 1061 if (act > 0) 1062 { 1063 1064 cur_err_token().parse_state = act-1; 1065 if (debug) debug_shift(cur_err_token()); 1066 stack.push(cur_err_token()); 1067 tos++; 1068 1069 1070 if (!advance_lookahead()) 1071 { 1072 if (debug) debug_message("# Completed reparse"); 1073 1074 1075 cur_token = scan(); 1076 1077 1078 return; 1079 } 1080 1081 if (debug) 1082 debug_message("# Current token is #" + cur_err_token().sym); 1083 } 1084 1085 else if (act < 0) 1086 { 1087 1088 lhs_sym = do_action((-act)-1, this, stack, tos); 1089 1090 1091 lhs_sym_num = production_tab[(-act)-1][0]; 1092 handle_size = production_tab[(-act)-1][1]; 1093 1094 if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size); 1095 1096 1097 for (int i = 0; i < handle_size; i++) 1098 { 1099 stack.pop(); 1100 tos--; 1101 } 1102 1103 1104 act = get_reduce(((symbol)stack.peek()).parse_state, lhs_sym_num); 1105 1106 1107 lhs_sym.parse_state = act; 1108 stack.push(lhs_sym); 1109 tos++; 1110 1111 if (debug) debug_message("# Goto state #" + act); 1112 1113 } 1114 1116 else if (act == 0) 1117 { 1118 report_fatal_error("Syntax error", null); 1119 return; 1120 } 1121 } 1122 } 1123 1124 1125 1126}; 1127 | Popular Tags |