1 11 package org.eclipse.jdt.internal.compiler.parser.diagnose; 12 13 import org.eclipse.jdt.core.compiler.CharOperation; 14 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 15 import org.eclipse.jdt.internal.compiler.parser.Parser; 16 import org.eclipse.jdt.internal.compiler.parser.ParserBasicInformation; 17 import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner; 18 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; 19 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; 20 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; 21 import org.eclipse.jdt.internal.compiler.util.Util; 22 23 public class DiagnoseParser implements ParserBasicInformation, TerminalTokens { 24 private static final boolean DEBUG = false; 25 private boolean DEBUG_PARSECHECK = false; 26 27 private static final int STACK_INCREMENT = 256; 28 29 private static final int BEFORE_CODE = 2; 31 private static final int INSERTION_CODE = 3; 32 private static final int INVALID_CODE = 4; 33 private static final int SUBSTITUTION_CODE = 5; 34 private static final int DELETION_CODE = 6; 35 private static final int MERGE_CODE = 7; 36 private static final int MISPLACED_CODE = 8; 37 private static final int SCOPE_CODE = 9; 38 private static final int SECONDARY_CODE = 10; 39 private static final int EOF_CODE = 11; 40 41 private static final int BUFF_UBOUND = 31; 42 private static final int BUFF_SIZE = 32; 43 private static final int MAX_DISTANCE = 30; 44 private static final int MIN_DISTANCE = 3; 45 46 private CompilerOptions options; 47 48 private LexStream lexStream; 49 private int errorToken; 50 private int errorTokenStart; 51 52 private int currentToken = 0; 53 54 private int stackLength; 55 private int stateStackTop; 56 private int[] stack; 57 58 private int[] locationStack; 59 private int[] locationStartStack; 60 61 private int tempStackTop; 62 private int[] tempStack; 63 64 private int prevStackTop; 65 private int[] prevStack; 66 private int nextStackTop; 67 private int[] nextStack; 68 69 private int scopeStackTop; 70 private int[] scopeIndex; 71 private int[] scopePosition; 72 73 int[] list = new int[NUM_SYMBOLS + 1]; 74 int[] buffer = new int[BUFF_SIZE]; 75 76 private static final int NIL = -1; 77 int[] stateSeen; 78 79 int statePoolTop; 80 StateInfo[] statePool; 81 82 private Parser parser; 83 84 private RecoveryScanner recoveryScanner; 85 86 private boolean reportProblem; 87 88 private static class RepairCandidate { 89 public int symbol; 90 public int location; 91 92 public RepairCandidate(){ 93 this.symbol = 0; 94 this.location = 0; 95 } 96 } 97 98 private static class PrimaryRepairInfo { 99 public int distance; 100 public int misspellIndex; 101 public int code; 102 public int bufferPosition; 103 public int symbol; 104 105 public PrimaryRepairInfo(){ 106 this.distance = 0; 107 this.misspellIndex = 0; 108 this.code = 0; 109 this.bufferPosition = 0; 110 this.symbol = 0; 111 } 112 113 public PrimaryRepairInfo copy(){ 114 PrimaryRepairInfo c = new PrimaryRepairInfo(); 115 c.distance = this.distance; 116 c.misspellIndex = this.misspellIndex; 117 c.code = this.code; 118 c.bufferPosition = this .bufferPosition; 119 c.symbol = this.symbol; 120 return c; 121 122 } 123 } 124 125 static class SecondaryRepairInfo { 126 public int code; 127 public int distance; 128 public int bufferPosition; 129 public int stackPosition; 130 public int numDeletions; 131 public int symbol; 132 133 boolean recoveryOnNextStack; 134 } 135 136 private static class StateInfo { 137 int state; 138 int next; 139 140 public StateInfo(int state, int next){ 141 this.state = state; 142 this.next = next; 143 } 144 } 145 146 public DiagnoseParser(Parser parser, int firstToken, int start, int end, CompilerOptions options) { 147 this(parser, firstToken, start, end, Util.EMPTY_INT_ARRAY, Util.EMPTY_INT_ARRAY, Util.EMPTY_INT_ARRAY, options); 148 } 149 150 public DiagnoseParser(Parser parser, int firstToken, int start, int end, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip, CompilerOptions options) { 151 this.parser = parser; 152 this.options = options; 153 this.lexStream = new LexStream(BUFF_SIZE, parser.scanner, intervalStartToSkip, intervalEndToSkip, intervalFlagsToSkip, firstToken, start, end); 154 this.recoveryScanner = parser.recoveryScanner; 155 } 156 157 private ProblemReporter problemReporter(){ 158 return parser.problemReporter(); 159 } 160 161 private void reallocateStacks() { 162 int old_stack_length = stackLength; 163 164 stackLength += STACK_INCREMENT; 165 166 if(old_stack_length == 0){ 167 stack = new int[stackLength]; 168 locationStack = new int[stackLength]; 169 locationStartStack = new int[stackLength]; 170 tempStack = new int[stackLength]; 171 prevStack = new int[stackLength]; 172 nextStack = new int[stackLength]; 173 scopeIndex = new int[stackLength]; 174 scopePosition = new int[stackLength]; 175 } else { 176 System.arraycopy(stack, 0, stack = new int[stackLength], 0, old_stack_length); 177 System.arraycopy(locationStack, 0, locationStack = new int[stackLength], 0, old_stack_length); 178 System.arraycopy(locationStartStack, 0, locationStartStack = new int[stackLength], 0, old_stack_length); 179 System.arraycopy(tempStack, 0, tempStack = new int[stackLength], 0, old_stack_length); 180 System.arraycopy(prevStack, 0, prevStack = new int[stackLength], 0, old_stack_length); 181 System.arraycopy(nextStack, 0, nextStack = new int[stackLength], 0, old_stack_length); 182 System.arraycopy(scopeIndex, 0, scopeIndex = new int[stackLength], 0, old_stack_length); 183 System.arraycopy(scopePosition, 0, scopePosition = new int[stackLength], 0, old_stack_length); 184 } 185 return; 186 } 187 188 189 public void diagnoseParse(boolean record) { 190 this.reportProblem = true; 191 boolean oldRecord = false; 192 if(this.recoveryScanner != null) { 193 oldRecord = this.recoveryScanner.record; 194 this.recoveryScanner.record = record; 195 } 196 try { 197 lexStream.reset(); 198 199 currentToken = lexStream.getToken(); 200 201 int prev_pos; 202 int pos; 203 int next_pos; 204 int act = START_STATE; 205 206 reallocateStacks(); 207 208 stateStackTop = 0; 212 stack[stateStackTop] = act; 213 214 int tok = lexStream.kind(currentToken); 215 locationStack[stateStackTop] = currentToken; 216 locationStartStack[stateStackTop] = lexStream.start(currentToken); 217 218 boolean forceRecoveryAfterLBracketMissing = false; 219 221 do { 225 prev_pos = -1; 229 prevStackTop = -1; 230 231 next_pos = -1; 232 nextStackTop = -1; 233 234 pos = stateStackTop; 235 tempStackTop = stateStackTop - 1; 236 for (int i = 0; i <= stateStackTop; i++) 237 tempStack[i] = stack[i]; 238 239 act = Parser.tAction(act, tok); 240 while (act <= NUM_RULES) { 247 do { 248 tempStackTop -= (Parser.rhs[act]-1); 249 act = Parser.ntAction(tempStack[tempStackTop], Parser.lhs[act]); 250 } while(act <= NUM_RULES); 251 if (tempStackTop + 1 >= stackLength) 257 reallocateStacks(); 258 pos = pos < tempStackTop ? pos : tempStackTop; 259 tempStack[tempStackTop + 1] = act; 260 act = Parser.tAction(act, tok); 261 } 262 263 while(act > ERROR_ACTION || act < ACCEPT_ACTION) { nextStackTop = tempStackTop + 1; 274 for (int i = next_pos + 1; i <= nextStackTop; i++) 275 nextStack[i] = tempStack[i]; 276 277 for (int i = pos + 1; i <= nextStackTop; i++) { 278 locationStack[i] = locationStack[stateStackTop]; 279 locationStartStack[i] = locationStartStack[stateStackTop]; 280 } 281 282 if (act > ERROR_ACTION) { 287 act -= ERROR_ACTION; 288 do { 289 nextStackTop -= (Parser.rhs[act]-1); 290 act = Parser.ntAction(nextStack[nextStackTop], Parser.lhs[act]); 291 } while(act <= NUM_RULES); 292 pos = pos < nextStackTop ? pos : nextStackTop; 293 } 294 295 if (nextStackTop + 1 >= stackLength) 296 reallocateStacks(); 297 298 tempStackTop = nextStackTop; 299 nextStack[++nextStackTop] = act; 300 next_pos = nextStackTop; 301 302 currentToken = lexStream.getToken(); 307 tok = lexStream.kind(currentToken); 308 act = Parser.tAction(act, tok); 309 while(act <= NUM_RULES) { 310 do { 315 int lhs_symbol = Parser.lhs[act]; 316 if(DEBUG) { 317 System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]); 318 } 319 tempStackTop -= (Parser.rhs[act]-1); 320 act = (tempStackTop > next_pos 321 ? tempStack[tempStackTop] 322 : nextStack[tempStackTop]); 323 act = Parser.ntAction(act, lhs_symbol); 324 } while(act <= NUM_RULES); 325 326 if (tempStackTop + 1 >= stackLength) 332 reallocateStacks(); 333 334 next_pos = next_pos < tempStackTop ? next_pos : tempStackTop; 335 tempStack[tempStackTop + 1] = act; 336 act = Parser.tAction(act, tok); 337 } 338 339 349 if (act != ERROR_ACTION) { 355 prevStackTop = stateStackTop; 356 for (int i = prev_pos + 1; i <= prevStackTop; i++) 357 prevStack[i] = stack[i]; 358 prev_pos = pos; 359 360 stateStackTop = nextStackTop; 361 for (int i = pos + 1; i <= stateStackTop; i++) 362 stack[i] = nextStack[i]; 363 locationStack[stateStackTop] = currentToken; 364 locationStartStack[stateStackTop] = lexStream.start(currentToken); 365 pos = next_pos; 366 } 367 } 368 369 if (act == ERROR_ACTION) { 374 RepairCandidate candidate = errorRecovery(currentToken, forceRecoveryAfterLBracketMissing); 378 379 forceRecoveryAfterLBracketMissing = false; 380 381 if(parser.reportOnlyOneSyntaxError) { 382 return; 383 } 384 385 if(this.parser.problemReporter().options.maxProblemsPerUnit < this.parser.compilationUnit.compilationResult.problemCount) { 386 if(this.recoveryScanner == null || !this.recoveryScanner.record) return; 387 this.reportProblem = false; 388 } 389 390 act = stack[stateStackTop]; 391 392 if (candidate.symbol == 0) { 397 break; 398 } else if (candidate.symbol > NT_OFFSET) { 399 int lhs_symbol = candidate.symbol - NT_OFFSET; 400 if(DEBUG) { 401 System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]); 402 } 403 act = Parser.ntAction(act, lhs_symbol); 404 while(act <= NUM_RULES) { 405 stateStackTop -= (Parser.rhs[act]-1); 406 act = Parser.ntAction(stack[stateStackTop], Parser.lhs[act]); 407 } 408 stack[++stateStackTop] = act; 409 currentToken = lexStream.getToken(); 410 tok = lexStream.kind(currentToken); 411 locationStack[stateStackTop] = currentToken; 412 locationStartStack[stateStackTop] = lexStream.start(currentToken); 413 } else { 414 tok = candidate.symbol; 415 locationStack[stateStackTop] = candidate.location; 416 locationStartStack[stateStackTop] = lexStream.start(candidate.location); 417 } 418 } 419 } while (act != ACCEPT_ACTION); 420 } finally { 421 if(this.recoveryScanner != null) { 422 this.recoveryScanner.record = oldRecord; 423 } 424 } 425 return; 426 } 427 428 private RepairCandidate errorRecovery(int error_token, boolean forcedError) { 445 this.errorToken = error_token; 446 this.errorTokenStart = lexStream.start(error_token); 447 448 int prevtok = lexStream.previous(error_token); 449 int prevtokKind = lexStream.kind(prevtok); 450 451 if(forcedError) { 452 int name_index = Parser.terminal_index[TokenNameLBRACE]; 453 454 reportError(INSERTION_CODE, name_index, prevtok, prevtok); 455 456 RepairCandidate candidate = new RepairCandidate(); 457 candidate.symbol = TokenNameLBRACE; 458 candidate.location = error_token; 459 lexStream.reset(error_token); 460 461 stateStackTop = nextStackTop; 462 for (int j = 0; j <= stateStackTop; j++) { 463 stack[j] = nextStack[j]; 464 } 465 locationStack[stateStackTop] = error_token; 466 locationStartStack[stateStackTop] = lexStream.start(error_token); 467 468 return candidate; 469 } 470 471 RepairCandidate candidate = primaryPhase(error_token); 477 if (candidate.symbol != 0) { 478 return candidate; 479 } 480 481 candidate = secondaryPhase(error_token); 482 if (candidate.symbol != 0) { 483 return candidate; 484 } 485 486 if (lexStream.kind(error_token) == EOFT_SYMBOL) { 487 reportError(EOF_CODE, 488 Parser.terminal_index[EOFT_SYMBOL], 489 prevtok, 490 prevtok); 491 candidate.symbol = 0; 492 candidate.location = error_token; 493 return candidate; 494 } 495 496 while(lexStream.kind(buffer[BUFF_UBOUND]) != EOFT_SYMBOL) { 504 candidate = secondaryPhase(buffer[MAX_DISTANCE - MIN_DISTANCE + 2]); 505 if (candidate.symbol != 0) { 506 return candidate; 507 } 508 } 509 510 int i; 515 for (i = BUFF_UBOUND; lexStream.kind(buffer[i]) == EOFT_SYMBOL; i--){} 516 517 reportError(DELETION_CODE, 518 Parser.terminal_index[prevtokKind], error_token, 520 buffer[i]); 521 522 candidate.symbol = 0; 523 candidate.location = buffer[i]; 524 525 return candidate; 526 } 527 528 private RepairCandidate primaryPhase(int error_token) { 536 PrimaryRepairInfo repair = new PrimaryRepairInfo(); 537 RepairCandidate candidate = new RepairCandidate(); 538 539 int i = (nextStackTop >= 0 ? 3 : 2); 543 buffer[i] = error_token; 544 545 for (int j = i; j > 0; j--) 546 buffer[j - 1] = lexStream.previous(buffer[j]); 547 548 for (int k = i + 1; k < BUFF_SIZE; k++) 549 buffer[k] = lexStream.next(buffer[k - 1]); 550 551 if (nextStackTop >= 0) { 558 repair.bufferPosition = 3; 559 repair = checkPrimaryDistance(nextStack, nextStackTop, repair); 560 } 561 562 PrimaryRepairInfo new_repair = repair.copy(); 566 567 new_repair.bufferPosition = 2; 568 new_repair = checkPrimaryDistance(stack, stateStackTop, new_repair); 569 if (new_repair.distance > repair.distance || new_repair.misspellIndex > repair.misspellIndex) { 570 repair = new_repair; 571 } 572 573 578 if (prevStackTop >= 0) { 579 new_repair = repair.copy(); 580 new_repair.bufferPosition = 1; 581 new_repair = checkPrimaryDistance(prevStack,prevStackTop, new_repair); 582 if (new_repair.distance > repair.distance || new_repair.misspellIndex > repair.misspellIndex) { 583 repair = new_repair; 584 } 585 } 586 587 if (nextStackTop >= 0) { if (secondaryCheck(nextStack,nextStackTop,3,repair.distance)) { 594 return candidate; 595 } 596 } 597 else if (secondaryCheck(stack, stateStackTop, 2, repair.distance)) { 598 return candidate; 599 } 600 601 repair.distance = repair.distance - repair.bufferPosition + 1; 609 610 if (repair.code == INVALID_CODE || 615 repair.code == DELETION_CODE || 616 repair.code == SUBSTITUTION_CODE || 617 repair.code == MERGE_CODE) { 618 repair.distance--; 619 } 620 621 if (repair.distance < MIN_DISTANCE) { 627 return candidate; 628 } 629 630 if (repair.code == INSERTION_CODE) { 638 if (buffer[repair.bufferPosition - 1] == 0) { 639 repair.code = BEFORE_CODE; 640 } 641 } 642 643 if (repair.bufferPosition == 1) { 648 stateStackTop = prevStackTop; 649 for (int j = 0; j <= stateStackTop; j++) { 650 stack[j] = prevStack[j]; 651 } 652 } else if (nextStackTop >= 0 && repair.bufferPosition >= 3) { 653 stateStackTop = nextStackTop; 654 for (int j = 0; j <= stateStackTop; j++) { 655 stack[j] = nextStack[j]; 656 } 657 locationStack[stateStackTop] = buffer[3]; 658 locationStartStack[stateStackTop] = lexStream.start(buffer[3]); 659 } 660 661 return primaryDiagnosis(repair); 662 } 663 664 665 private int mergeCandidate(int state, int buffer_position) { 673 char[] name1 = lexStream.name(buffer[buffer_position]); 674 char[] name2 = lexStream.name(buffer[buffer_position + 1]); 675 676 int len = name1.length + name2.length; 677 678 char[] str = CharOperation.concat(name1, name2); 679 680 for (int k = Parser.asi(state); Parser.asr[k] != 0; k++) { 681 int l = Parser.terminal_index[Parser.asr[k]]; 682 683 if (len == Parser.name[l].length()) { 684 char[] name = Parser.name[l].toCharArray(); 685 686 if (CharOperation.equals(str, name, false)) { 687 return Parser.asr[k]; 688 } 689 } 690 } 691 692 return 0; 693 } 694 695 696 private PrimaryRepairInfo checkPrimaryDistance(int stck[], int stack_top, PrimaryRepairInfo repair) { 714 int i, j, k, next_state, max_pos, act, root, symbol, tok; 715 716 PrimaryRepairInfo scope_repair = scopeTrial(stck, stack_top, repair.copy()); 720 if (scope_repair.distance > repair.distance) 721 repair = scope_repair; 722 723 if(buffer[repair.bufferPosition] != 0 && buffer[repair.bufferPosition + 1] != 0) { symbol = mergeCandidate(stck[stack_top], repair.bufferPosition); 728 if (symbol != 0) { 729 j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+2); 730 if ((j > repair.distance) || (j == repair.distance && repair.misspellIndex < 10)) { 731 repair.misspellIndex = 10; 732 repair.symbol = symbol; 733 repair.distance = j; 734 repair.code = MERGE_CODE; 735 } 736 } 737 } 738 739 j = parseCheck( 743 stck, 744 stack_top, 745 lexStream.kind(buffer[repair.bufferPosition + 1]), 746 repair.bufferPosition + 2); 747 if (lexStream.kind(buffer[repair.bufferPosition]) == EOLT_SYMBOL && 748 lexStream.afterEol(buffer[repair.bufferPosition+1])) { 749 k = 10; 750 } else { 751 k = 0; 752 } 753 if (j > repair.distance || (j == repair.distance && k > repair.misspellIndex)) { 754 repair.misspellIndex = k; 755 repair.code = DELETION_CODE; 756 repair.distance = j; 757 } 758 759 next_state = stck[stack_top]; 765 max_pos = stack_top; 766 tempStackTop = stack_top - 1; 767 768 tok = lexStream.kind(buffer[repair.bufferPosition]); 769 lexStream.reset(buffer[repair.bufferPosition + 1]); 770 act = Parser.tAction(next_state, tok); 771 while(act <= NUM_RULES) { 772 do { 773 tempStackTop -= (Parser.rhs[act]-1); 774 symbol = Parser.lhs[act]; 775 act = (tempStackTop > max_pos 776 ? tempStack[tempStackTop] 777 : stck[tempStackTop]); 778 act = Parser.ntAction(act, symbol); 779 } while(act <= NUM_RULES); 780 max_pos = max_pos < tempStackTop ? max_pos : tempStackTop; 781 tempStack[tempStackTop + 1] = act; 782 next_state = act; 783 act = Parser.tAction(next_state, tok); 784 } 785 786 root = 0; 790 for (i = Parser.asi(next_state); Parser.asr[i] != 0; i++) { 791 symbol = Parser.asr[i]; 792 if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL) { 793 if (root == 0) { 794 list[symbol] = symbol; 795 } else { 796 list[symbol] = list[root]; 797 list[root] = symbol; 798 } 799 root = symbol; 800 } 801 } 802 803 if (stck[stack_top] != next_state) { 804 for (i = Parser.asi(stck[stack_top]); Parser.asr[i] != 0; i++) { 805 symbol = Parser.asr[i]; 806 if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL && list[symbol] == 0) { 807 if (root == 0) { 808 list[symbol] = symbol; 809 } else { 810 list[symbol] = list[root]; 811 list[root] = symbol; 812 } 813 root = symbol; 814 } 815 } 816 } 817 818 i = list[root]; 819 list[root] = 0; 820 root = i; 821 822 symbol = root; 827 while(symbol != 0) { 828 if (symbol == EOLT_SYMBOL && lexStream.afterEol(buffer[repair.bufferPosition])) { 829 k = 10; 830 } else { 831 k = 0; 832 } 833 j = parseCheck(stck, stack_top, symbol, repair.bufferPosition); 834 if (j > repair.distance) { 835 repair.misspellIndex = k; 836 repair.distance = j; 837 repair.symbol = symbol; 838 repair.code = INSERTION_CODE; 839 } else if (j == repair.distance && k > repair.misspellIndex) { 840 repair.misspellIndex = k; 841 repair.distance = j; 842 repair.symbol = symbol; 843 repair.code = INSERTION_CODE; 844 } else if (j == repair.distance && k == repair.misspellIndex && isBetterSymbol(symbol, repair.symbol)) { 845 repair.misspellIndex = k; 846 repair.distance = j; 847 repair.symbol = symbol; 848 repair.code = INSERTION_CODE; 849 } 850 851 symbol = list[symbol]; 852 } 853 854 symbol = root; 859 860 if(buffer[repair.bufferPosition] != 0) { while(symbol != 0) { 862 if (symbol == EOLT_SYMBOL && lexStream.afterEol(buffer[repair.bufferPosition+1])) { 863 k = 10; 864 } else { 865 k = misspell(symbol, buffer[repair.bufferPosition]); 866 } 867 j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+1); 868 if (j > repair.distance) { 869 repair.misspellIndex = k; 870 repair.distance = j; 871 repair.symbol = symbol; 872 repair.code = SUBSTITUTION_CODE; 873 } else if (j == repair.distance && k > repair.misspellIndex) { 874 repair.misspellIndex = k; 875 repair.symbol = symbol; 876 repair.code = SUBSTITUTION_CODE; 877 } else if (j == repair.distance && k > repair.misspellIndex && isBetterSymbol(symbol, repair.symbol)) { 878 repair.misspellIndex = k; 879 repair.symbol = symbol; 880 repair.code = SUBSTITUTION_CODE; 881 } 882 i = symbol; 883 symbol = list[symbol]; 884 list[i] = 0; } 886 } 887 888 889 for (i = Parser.nasi(stck[stack_top]); Parser.nasr[i] != 0; i++) { 895 symbol = Parser.nasr[i] + NT_OFFSET; 896 j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+1); 897 if (j > repair.distance) { 898 repair.misspellIndex = 0; 899 repair.distance = j; 900 repair.symbol = symbol; 901 repair.code = INVALID_CODE; 902 } 903 904 j = parseCheck(stck, stack_top, symbol, repair.bufferPosition); 905 if ((j > repair.distance) || (j == repair.distance && repair.code == INVALID_CODE)) { 906 repair.misspellIndex = 0; 907 repair.distance = j; 908 repair.symbol = symbol; 909 repair.code = INSERTION_CODE; 910 } 911 } 912 913 return repair; 914 } 915 916 917 private RepairCandidate primaryDiagnosis(PrimaryRepairInfo repair) { 926 int name_index; 927 928 int prevtok = buffer[repair.bufferPosition - 1]; 932 int curtok = buffer[repair.bufferPosition]; 933 934 switch(repair.code) { 935 case INSERTION_CODE: 936 case BEFORE_CODE: { 937 if (repair.symbol > NT_OFFSET) 938 name_index = getNtermIndex(stack[stateStackTop], 939 repair.symbol, 940 repair.bufferPosition); 941 else name_index = getTermIndex(stack, 942 stateStackTop, 943 repair.symbol, 944 repair.bufferPosition); 945 946 int t = (repair.code == INSERTION_CODE ? prevtok : curtok); 947 reportError(repair.code, name_index, t, t); 948 break; 949 } 950 case INVALID_CODE: { 951 name_index = getNtermIndex(stack[stateStackTop], 952 repair.symbol, 953 repair.bufferPosition + 1); 954 reportError(repair.code, name_index, curtok, curtok); 955 break; 956 } 957 case SUBSTITUTION_CODE: { 958 if (repair.misspellIndex >= 6) 959 name_index = Parser.terminal_index[repair.symbol]; 960 else 961 { 962 name_index = getTermIndex(stack, stateStackTop, 963 repair.symbol, 964 repair.bufferPosition + 1); 965 if (name_index != Parser.terminal_index[repair.symbol]) 966 repair.code = INVALID_CODE; 967 } 968 reportError(repair.code, name_index, curtok, curtok); 969 break; 970 } 971 case MERGE_CODE: { 972 reportError(repair.code, 973 Parser.terminal_index[repair.symbol], 974 curtok, 975 lexStream.next(curtok)); 976 break; 977 } 978 case SCOPE_CODE: { 979 for (int i = 0; i < scopeStackTop; i++) { 980 reportError(repair.code, 981 -scopeIndex[i], 982 locationStack[scopePosition[i]], 983 prevtok, 984 Parser.non_terminal_index[Parser.scope_lhs[scopeIndex[i]]]); 985 } 986 987 repair.symbol = Parser.scope_lhs[scopeIndex[scopeStackTop]] + NT_OFFSET; 988 stateStackTop = scopePosition[scopeStackTop]; 989 reportError(repair.code, 990 -scopeIndex[scopeStackTop], 991 locationStack[scopePosition[scopeStackTop]], 992 prevtok, 993 getNtermIndex(stack[stateStackTop], 994 repair.symbol, 995 repair.bufferPosition) 996 ); 997 break; 998 } 999 default: { reportError(repair.code, Parser.terminal_index[ERROR_SYMBOL], curtok, curtok); 1001 } 1002 } 1003 1004 RepairCandidate candidate = new RepairCandidate(); 1008 switch (repair.code) { 1009 case INSERTION_CODE: 1010 case BEFORE_CODE: 1011 case SCOPE_CODE: { 1012 candidate.symbol = repair.symbol; 1013 candidate.location = buffer[repair.bufferPosition]; 1014 lexStream.reset(buffer[repair.bufferPosition]); 1015 break; 1016 } 1017 case INVALID_CODE: 1018 case SUBSTITUTION_CODE: { 1019 candidate.symbol = repair.symbol; 1020 candidate.location = buffer[repair.bufferPosition]; 1021 lexStream.reset(buffer[repair.bufferPosition + 1]); 1022 break; 1023 } 1024 case MERGE_CODE: { 1025 candidate.symbol = repair.symbol; 1026 candidate.location = buffer[repair.bufferPosition]; 1027 lexStream.reset(buffer[repair.bufferPosition + 2]); 1028 break; 1029 } 1030 default: { candidate.location = buffer[repair.bufferPosition + 1]; 1032 candidate.symbol = 1033 lexStream.kind(buffer[repair.bufferPosition + 1]); 1034 lexStream.reset(buffer[repair.bufferPosition + 2]); 1035 break; 1036 } 1037 } 1038 1039 return candidate; 1040 } 1041 1042 1043 private int getTermIndex(int stck[], int stack_top, int tok, int buffer_position) { 1055 int act = stck[stack_top], 1060 max_pos = stack_top, 1061 highest_symbol = tok; 1062 1063 tempStackTop = stack_top - 1; 1064 1065 lexStream.reset(buffer[buffer_position]); 1072 act = Parser.tAction(act, tok); 1073 while(act <= NUM_RULES) { 1074 do { 1079 tempStackTop -= (Parser.rhs[act]-1); 1080 int lhs_symbol = Parser.lhs[act]; 1081 act = (tempStackTop > max_pos 1082 ? tempStack[tempStackTop] 1083 : stck[tempStackTop]); 1084 act = Parser.ntAction(act, lhs_symbol); 1085 } while(act <= NUM_RULES); 1086 1087 max_pos = max_pos < tempStackTop ? max_pos : tempStackTop; 1093 tempStack[tempStackTop + 1] = act; 1094 act = Parser.tAction(act, tok); 1095 } 1096 1097 tempStackTop++; int threshold = tempStackTop; 1112 1113 tok = lexStream.kind(buffer[buffer_position]); 1114 lexStream.reset(buffer[buffer_position + 1]); 1115 1116 if (act > ERROR_ACTION) { act -= ERROR_ACTION; 1118 } else { 1119 tempStack[tempStackTop + 1] = act; 1120 act = Parser.tAction(act, tok); 1121 } 1122 1123 while(act <= NUM_RULES) { 1124 do { 1129 tempStackTop -= (Parser.rhs[act]-1); 1130 1131 if (tempStackTop < threshold) { 1132 return (highest_symbol > NT_OFFSET 1133 ? Parser.non_terminal_index[highest_symbol - NT_OFFSET] 1134 : Parser.terminal_index[highest_symbol]); 1135 } 1136 1137 int lhs_symbol = Parser.lhs[act]; 1138 if (tempStackTop == threshold) 1139 highest_symbol = lhs_symbol + NT_OFFSET; 1140 act = (tempStackTop > max_pos 1141 ? tempStack[tempStackTop] 1142 : stck[tempStackTop]); 1143 act = Parser.ntAction(act, lhs_symbol); 1144 } while(act <= NUM_RULES); 1145 1146 tempStack[tempStackTop + 1] = act; 1147 act = Parser.tAction(act, tok); 1148 } 1149 1150 return (highest_symbol > NT_OFFSET 1151 ? Parser.non_terminal_index[highest_symbol - NT_OFFSET] 1152 : Parser.terminal_index[highest_symbol]); 1153 } 1154 1155 private int getNtermIndex(int start, int sym, int buffer_position) { 1166 int highest_symbol = sym - NT_OFFSET, 1167 tok = lexStream.kind(buffer[buffer_position]); 1168 lexStream.reset(buffer[buffer_position + 1]); 1169 1170 tempStackTop = 0; 1175 tempStack[tempStackTop] = start; 1176 1177 int act = Parser.ntAction(start, highest_symbol); 1178 if (act > NUM_RULES) { tempStack[tempStackTop + 1] = act; 1180 act = Parser.tAction(act, tok); 1181 } 1182 1183 while(act <= NUM_RULES) { 1184 do { 1189 tempStackTop -= (Parser.rhs[act]-1); 1190 if (tempStackTop < 0) 1191 return Parser.non_terminal_index[highest_symbol]; 1192 if (tempStackTop == 0) 1193 highest_symbol = Parser.lhs[act]; 1194 act = Parser.ntAction(tempStack[tempStackTop], Parser.lhs[act]); 1195 } while(act <= NUM_RULES); 1196 tempStack[tempStackTop + 1] = act; 1197 act = Parser.tAction(act, tok); 1198 } 1199 1200 return Parser.non_terminal_index[highest_symbol]; 1201 } 1202 1203 private boolean isBetterSymbol(int symbol, int actualSymbol) { 1204 return false; 1212 } 1213 1214 private int misspell(int sym, int tok) { 1221 1222 1223 char[] name = Parser.name[Parser.terminal_index[sym]].toCharArray(); 1227 int n = name.length; 1228 char[] s1 = new char[n + 1]; 1229 for (int k = 0; k < n; k++) { 1230 char c = name[k]; 1231 s1[k] = ScannerHelper.toLowerCase(c); 1232 } 1233 s1[n] = '\0'; 1234 1235 char[] tokenName = lexStream.name(tok); 1239 int len = tokenName.length; 1240 int m = len < MAX_NAME_LENGTH ? len : MAX_NAME_LENGTH; 1241 char[] s2 = new char[m + 1]; 1242 for (int k = 0; k < m; k++) { 1243 char c = tokenName[k]; 1244 s2[k] = ScannerHelper.toLowerCase(c); 1245 } 1246 s2[m] = '\0'; 1247 1248 if (n == 1 && m == 1) { 1261 if ((s1[0] == ';' && s2[0] == ',') || 1262 (s1[0] == ',' && s2[0] == ';') || 1263 (s1[0] == ';' && s2[0] == ':') || 1264 (s1[0] == ':' && s2[0] == ';') || 1265 (s1[0] == '.' && s2[0] == ',') || 1266 (s1[0] == ',' && s2[0] == '.') || 1267 (s1[0] == '\'' && s2[0] == '\"') || 1268 (s1[0] == '\"' && s2[0] == '\'')) { 1269 return 3; 1270 } 1271 } 1272 1273 int count = 0; 1285 int prefix_length = 0; 1286 int num_errors = 0; 1287 1288 int i = 0; 1289 int j = 0; 1290 while ((i < n) && (j < m)) { 1291 if (s1[i] == s2[j]) { 1292 count++; 1293 i++; 1294 j++; 1295 if (num_errors == 0) { 1296 prefix_length++; 1297 } 1298 } else if (s1[i+1] == s2[j] && s1[i] == s2[j+1]) { 1299 count += 2; 1300 i += 2; 1301 j += 2; 1302 num_errors++; 1303 } else if (s1[i+1] == s2[j+1]) { 1304 i++; 1305 j++; 1306 num_errors++; 1307 } else { 1308 if ((n - i) > (m - j)) { 1309 i++; 1310 } else if ((m - j) > (n - i)) { 1311 j++; 1312 } else { 1313 i++; 1314 j++; 1315 } 1316 num_errors++; 1317 } 1318 } 1319 1320 if (i < n || j < m) 1321 num_errors++; 1322 1323 if (num_errors > ((n < m ? n : m) / 6 + 1)) 1324 count = prefix_length; 1325 1326 return(count * 10 / ((n < len ? len : n) + num_errors)); 1327 } 1328 1329 private PrimaryRepairInfo scopeTrial(int stck[], int stack_top, PrimaryRepairInfo repair) { 1330 stateSeen = new int[stackLength]; 1331 for (int i = 0; i < stackLength; i++) 1332 stateSeen[i] = NIL; 1333 1334 statePoolTop = 0; 1335 statePool = new StateInfo[stackLength]; 1336 1337 scopeTrialCheck(stck, stack_top, repair, 0); 1338 1339 stateSeen = null; 1340 statePoolTop = 0; 1341 1342 repair.code = SCOPE_CODE; 1343 repair.misspellIndex = 10; 1344 1345 return repair; 1346 } 1347 1348 private void scopeTrialCheck(int stck[], int stack_top, PrimaryRepairInfo repair, int indx) { 1349 if(indx > 20) return; 1351 int act = stck[stack_top]; 1352 1353 for (int i = stateSeen[stack_top]; i != NIL; i = statePool[i].next) { 1354 if (statePool[i].state == act) return; 1355 } 1356 1357 int old_state_pool_top = statePoolTop++; 1358 if(statePoolTop >= statePool.length) { 1359 System.arraycopy(statePool, 0, statePool = new StateInfo[statePoolTop * 2], 0, statePoolTop); 1360 } 1361 1362 statePool[old_state_pool_top] = new StateInfo(act, stateSeen[stack_top]); 1363 stateSeen[stack_top] = old_state_pool_top; 1364 1365 next : for (int i = 0; i < SCOPE_SIZE; i++) { 1366 act = stck[stack_top]; 1371 tempStackTop = stack_top - 1; 1372 int max_pos = stack_top; 1373 int tok = Parser.scope_la[i]; 1374 lexStream.reset(buffer[repair.bufferPosition]); 1375 act = Parser.tAction(act, tok); 1376 while(act <= NUM_RULES) { 1377 do { 1382 tempStackTop -= (Parser.rhs[act]-1); 1383 int lhs_symbol = Parser.lhs[act]; 1384 act = (tempStackTop > max_pos 1385 ? tempStack[tempStackTop] 1386 : stck[tempStackTop]); 1387 act = Parser.ntAction(act, lhs_symbol); 1388 } while(act <= NUM_RULES); 1389 if (tempStackTop + 1 >= stackLength) 1390 return; 1391 max_pos = max_pos < tempStackTop ? max_pos : tempStackTop; 1392 tempStack[tempStackTop + 1] = act; 1393 act = Parser.tAction(act, tok); 1394 } 1395 1396 if (act != ERROR_ACTION) { 1403 int j, k; 1404 k = Parser.scope_prefix[i]; 1405 for (j = tempStackTop + 1; 1406 j >= (max_pos + 1) && 1407 Parser.in_symbol(tempStack[j]) == Parser.scope_rhs[k]; j--) { 1408 k++; 1409 } 1410 if (j == max_pos) { 1411 for (j = max_pos; 1412 j >= 1 && Parser.in_symbol(stck[j]) == Parser.scope_rhs[k]; 1413 j--) { 1414 k++; 1415 } 1416 } 1417 int marked_pos = (max_pos < stack_top ? max_pos + 1 : stack_top); 1426 if (Parser.scope_rhs[k] == 0 && j < marked_pos) { int stack_position = j; 1428 for (j = Parser.scope_state_set[i]; 1429 stck[stack_position] != Parser.scope_state[j] && 1430 Parser.scope_state[j] != 0; 1431 j++){} 1432 if (Parser.scope_state[j] != 0) { int previous_distance = repair.distance; 1441 int distance = parseCheck(stck, 1442 stack_position, 1443 Parser.scope_lhs[i]+NT_OFFSET, 1444 repair.bufferPosition); 1445 if ((distance - repair.bufferPosition + 1) < MIN_DISTANCE) { 1462 int top = stack_position; 1463 act = Parser.ntAction(stck[top], Parser.scope_lhs[i]); 1464 while(act <= NUM_RULES) { 1465 if(Parser.rules_compliance[act] > this.options.sourceLevel) { 1466 continue next; 1467 } 1468 top -= (Parser.rhs[act]-1); 1469 act = Parser.ntAction(stck[top], Parser.lhs[act]); 1470 } 1471 top++; 1472 1473 j = act; 1474 act = stck[top]; stck[top] = j; scopeTrialCheck(stck, top, repair, indx+1); 1477 stck[top] = act; } else if (distance > repair.distance) { 1479 scopeStackTop = indx; 1480 repair.distance = distance; 1481 } 1482 1483 if (lexStream.kind(buffer[repair.bufferPosition]) == EOFT_SYMBOL && 1484 repair.distance == previous_distance) { 1485 scopeStackTop = indx; 1486 repair.distance = MAX_DISTANCE; 1487 } 1488 1489 if (repair.distance > previous_distance) { 1498 scopeIndex[indx] = i; 1499 scopePosition[indx] = stack_position; 1500 return; 1501 } 1502 } 1503 } 1504 } 1505 } 1506 } 1507 private boolean secondaryCheck(int stck[], int stack_top, int buffer_position, int distance) { 1518 int top, j; 1519 1520 for (top = stack_top - 1; top >= 0; top--) { 1521 j = parseCheck(stck, top, 1522 lexStream.kind(buffer[buffer_position]), 1523 buffer_position + 1); 1524 if (((j - buffer_position + 1) > MIN_DISTANCE) && (j > distance)) 1525 return true; 1526 } 1527 1528 PrimaryRepairInfo repair = new PrimaryRepairInfo(); 1529 repair.bufferPosition = buffer_position + 1; 1530 repair.distance = distance; 1531 repair = scopeTrial(stck, stack_top, repair); 1532 if ((repair.distance - buffer_position) > MIN_DISTANCE && repair.distance > distance) 1533 return true; 1534 return false; 1535 } 1536 1537 1538 private RepairCandidate secondaryPhase(int error_token) { 1549 SecondaryRepairInfo repair = new SecondaryRepairInfo(); 1550 SecondaryRepairInfo misplaced = new SecondaryRepairInfo(); 1551 1552 RepairCandidate candidate = new RepairCandidate(); 1553 1554 int i, j, k, top; 1555 int next_last_index = 0; 1556 int last_index; 1557 1558 candidate.symbol = 0; 1559 1560 repair.code = 0; 1561 repair.distance = 0; 1562 repair.recoveryOnNextStack = false; 1563 1564 misplaced.distance = 0; 1565 misplaced.recoveryOnNextStack = false; 1566 1567 if (nextStackTop >= 0) { 1572 int save_location; 1573 1574 buffer[2] = error_token; 1575 buffer[1] = lexStream.previous(buffer[2]); 1576 buffer[0] = lexStream.previous(buffer[1]); 1577 1578 for (k = 3; k < BUFF_UBOUND; k++) 1579 buffer[k] = lexStream.next(buffer[k - 1]); 1580 1581 buffer[BUFF_UBOUND] = lexStream.badtoken(); 1583 for (next_last_index = MAX_DISTANCE - 1; 1589 next_last_index >= 1 && 1590 lexStream.kind(buffer[next_last_index]) == EOFT_SYMBOL; 1591 next_last_index--){} 1592 next_last_index = next_last_index + 1; 1593 1594 save_location = locationStack[nextStackTop]; 1595 int save_location_start = locationStartStack[nextStackTop]; 1596 locationStack[nextStackTop] = buffer[2]; 1597 locationStartStack[nextStackTop] = lexStream.start(buffer[2]); 1598 misplaced.numDeletions = nextStackTop; 1599 misplaced = misplacementRecovery(nextStack, nextStackTop, 1600 next_last_index, 1601 misplaced, true); 1602 if (misplaced.recoveryOnNextStack) 1603 misplaced.distance++; 1604 1605 repair.numDeletions = nextStackTop + BUFF_UBOUND; 1606 repair = secondaryRecovery(nextStack, nextStackTop, 1607 next_last_index, 1608 repair, true); 1609 if (repair.recoveryOnNextStack) 1610 repair.distance++; 1611 1612 locationStack[nextStackTop] = save_location; 1613 locationStartStack[nextStackTop] = save_location_start; 1614 } else { misplaced.numDeletions = stateStackTop; 1616 repair.numDeletions = stateStackTop + BUFF_UBOUND; 1617 } 1618 1619 buffer[3] = error_token; 1623 1624 buffer[2] = lexStream.previous(buffer[3]); 1625 buffer[1] = lexStream.previous(buffer[2]); 1626 buffer[0] = lexStream.previous(buffer[1]); 1627 1628 for (k = 4; k < BUFF_SIZE; k++) 1629 buffer[k] = lexStream.next(buffer[k - 1]); 1630 1631 for (last_index = MAX_DISTANCE - 1; 1632 last_index >= 1 && lexStream.kind(buffer[last_index]) == EOFT_SYMBOL; 1633 last_index--){} 1634 last_index++; 1635 1636 misplaced = misplacementRecovery(stack, stateStackTop, 1637 last_index, 1638 misplaced, false); 1639 1640 repair = secondaryRecovery(stack, stateStackTop, 1641 last_index, repair, false); 1642 1643 if (misplaced.distance > MIN_DISTANCE) { 1650 if (misplaced.numDeletions <= repair.numDeletions || 1651 (misplaced.distance - misplaced.numDeletions) >= 1652 (repair.distance - repair.numDeletions)) { 1653 repair.code = MISPLACED_CODE; 1654 repair.stackPosition = misplaced.stackPosition; 1655 repair.bufferPosition = 2; 1656 repair.numDeletions = misplaced.numDeletions; 1657 repair.distance = misplaced.distance; 1658 repair.recoveryOnNextStack = misplaced.recoveryOnNextStack; 1659 } 1660 } 1661 1662 if (repair.recoveryOnNextStack) { 1667 stateStackTop = nextStackTop; 1668 for (i = 0; i <= stateStackTop; i++) 1669 stack[i] = nextStack[i]; 1670 1671 buffer[2] = error_token; 1672 buffer[1] = lexStream.previous(buffer[2]); 1673 buffer[0] = lexStream.previous(buffer[1]); 1674 1675 for (k = 3; k < BUFF_UBOUND; k++) 1676 buffer[k] = lexStream.next(buffer[k - 1]); 1677 1678 buffer[BUFF_UBOUND] = lexStream.badtoken(); 1680 locationStack[nextStackTop] = buffer[2]; 1681 locationStartStack[nextStackTop] = lexStream.start(buffer[2]); 1682 last_index = next_last_index; 1683 } 1684 1685 if (repair.code == SECONDARY_CODE || repair.code == DELETION_CODE) { 1690 PrimaryRepairInfo scope_repair = new PrimaryRepairInfo(); 1691 1692 scope_repair.distance = 0; 1693 for (scope_repair.bufferPosition = 2; 1694 scope_repair.bufferPosition <= repair.bufferPosition && 1695 repair.code != SCOPE_CODE; scope_repair.bufferPosition++) { 1696 scope_repair = scopeTrial(stack, stateStackTop, scope_repair); 1697 j = (scope_repair.distance == MAX_DISTANCE 1698 ? last_index 1699 : scope_repair.distance); 1700 k = scope_repair.bufferPosition - 1; 1701 if ((j - k) > MIN_DISTANCE && (j - k) > (repair.distance - repair.numDeletions)) { 1702 repair.code = SCOPE_CODE; 1703 i = scopeIndex[scopeStackTop]; repair.symbol = Parser.scope_lhs[i] + NT_OFFSET; 1705 repair.stackPosition = stateStackTop; 1706 repair.bufferPosition = scope_repair.bufferPosition; 1707 } 1708 } 1709 } 1710 1711 if (repair.code == 0 && lexStream.kind(buffer[last_index]) == EOFT_SYMBOL) { 1718 PrimaryRepairInfo scope_repair = new PrimaryRepairInfo(); 1719 1720 scope_repair.bufferPosition = last_index; 1721 scope_repair.distance = 0; 1722 for (top = stateStackTop; 1723 top >= 0 && repair.code == 0; top--) 1724 { 1725 scope_repair = scopeTrial(stack, top, scope_repair); 1726 if (scope_repair.distance > 0) 1727 { 1728 repair.code = SCOPE_CODE; 1729 i = scopeIndex[scopeStackTop]; repair.symbol = Parser.scope_lhs[i] + NT_OFFSET; 1731 repair.stackPosition = top; 1732 repair.bufferPosition = scope_repair.bufferPosition; 1733 } 1734 } 1735 } 1736 1737 if (repair.code == 0) 1742 return candidate; 1743 1744 secondaryDiagnosis(repair); 1745 1746 switch(repair.code) { 1750 case MISPLACED_CODE: 1751 candidate.location = buffer[2]; 1752 candidate.symbol = lexStream.kind(buffer[2]); 1753 lexStream.reset(lexStream.next(buffer[2])); 1754 1755 break; 1756 1757 case DELETION_CODE: 1758 candidate.location = buffer[repair.bufferPosition]; 1759 candidate.symbol = 1760 lexStream.kind(buffer[repair.bufferPosition]); 1761 lexStream.reset(lexStream.next(buffer[repair.bufferPosition])); 1762 1763 break; 1764 1765 default: candidate.symbol = repair.symbol; 1767 candidate.location = buffer[repair.bufferPosition]; 1768 lexStream.reset(buffer[repair.bufferPosition]); 1769 1770 break; 1771 } 1772 1773 return candidate; 1774 } 1775 1776 1777 private SecondaryRepairInfo misplacementRecovery(int stck[], int stack_top, int last_index, SecondaryRepairInfo repair, boolean stack_flag) { 1783 int previous_loc = buffer[2]; 1784 int stack_deletions = 0; 1785 1786 for (int top = stack_top - 1; top >= 0; top--) { 1787 if (locationStack[top] < previous_loc) { 1788 stack_deletions++; 1789 } 1790 previous_loc = locationStack[top]; 1791 1792 int j = parseCheck(stck, top, lexStream.kind(buffer[2]), 3); 1793 if (j == MAX_DISTANCE) { 1794 j = last_index; 1795 } 1796 if ((j > MIN_DISTANCE) && (j - stack_deletions) > (repair.distance - repair.numDeletions)) { 1797 repair.stackPosition = top; 1798 repair.distance = j; 1799 repair.numDeletions = stack_deletions; 1800 repair.recoveryOnNextStack = stack_flag; 1801 } 1802 } 1803 1804 return repair; 1805 } 1806 1807 1808 private SecondaryRepairInfo secondaryRecovery(int stck[],int stack_top, int last_index, SecondaryRepairInfo repair, boolean stack_flag) { 1814 int previous_loc; 1815 int stack_deletions = 0; 1816 1817 previous_loc = buffer[2]; 1818 for (int top = stack_top; top >= 0 && repair.numDeletions >= stack_deletions; top--) { 1819 if (locationStack[top] < previous_loc) { 1820 stack_deletions++; 1821 } 1822 previous_loc = locationStack[top]; 1823 1824 for (int i = 2; 1825 i <= (last_index - MIN_DISTANCE + 1) && 1826 (repair.numDeletions >= (stack_deletions + i - 1)); i++) { 1827 int j = parseCheck(stck, top, lexStream.kind(buffer[i]), i + 1); 1828 1829 if (j == MAX_DISTANCE) { 1830 j = last_index; 1831 } 1832 if ((j - i + 1) > MIN_DISTANCE) { 1833 int k = stack_deletions + i - 1; 1834 if ((k < repair.numDeletions) || 1835 (j - k) > (repair.distance - repair.numDeletions) || 1836 ((repair.code == SECONDARY_CODE) && (j - k) == (repair.distance - repair.numDeletions))) { 1837 repair.code = DELETION_CODE; 1838 repair.distance = j; 1839 repair.stackPosition = top; 1840 repair.bufferPosition = i; 1841 repair.numDeletions = k; 1842 repair.recoveryOnNextStack = stack_flag; 1843 } 1844 } 1845 1846 for (int l = Parser.nasi(stck[top]); l >= 0 && Parser.nasr[l] != 0; l++) { 1847 int symbol = Parser.nasr[l] + NT_OFFSET; 1848 j = parseCheck(stck, top, symbol, i); 1849 if (j == MAX_DISTANCE) { 1850 j = last_index; 1851 } 1852 if ((j - i + 1) > MIN_DISTANCE) { 1853 int k = stack_deletions + i - 1; 1854 if (k < repair.numDeletions || (j - k) > (repair.distance - repair.numDeletions)) { 1855 repair.code = SECONDARY_CODE; 1856 repair.symbol = symbol; 1857 repair.distance = j; 1858 repair.stackPosition = top; 1859 repair.bufferPosition = i; 1860 repair.numDeletions = k; 1861 repair.recoveryOnNextStack = stack_flag; 1862 } 1863 } 1864 } 1865 } 1866 } 1867 1868 return repair; 1869 } 1870 1871 1872 private void secondaryDiagnosis(SecondaryRepairInfo repair) { 1879 switch(repair.code) { 1880 case SCOPE_CODE: { 1881 if (repair.stackPosition < stateStackTop) { 1882 reportError(DELETION_CODE, 1883 Parser.terminal_index[ERROR_SYMBOL], 1884 locationStack[repair.stackPosition], 1885 buffer[1]); 1886 } 1887 for (int i = 0; i < scopeStackTop; i++) { 1888 reportError(SCOPE_CODE, 1889 -scopeIndex[i], 1890 locationStack[scopePosition[i]], 1891 buffer[1], 1892 Parser.non_terminal_index[Parser.scope_lhs[scopeIndex[i]]]); 1893 } 1894 1895 repair.symbol = Parser.scope_lhs[scopeIndex[scopeStackTop]] + NT_OFFSET; 1896 stateStackTop = scopePosition[scopeStackTop]; 1897 reportError(SCOPE_CODE, 1898 -scopeIndex[scopeStackTop], 1899 locationStack[scopePosition[scopeStackTop]], 1900 buffer[1], 1901 getNtermIndex(stack[stateStackTop], 1902 repair.symbol, 1903 repair.bufferPosition) 1904 ); 1905 break; 1906 } 1907 default: { 1908 reportError(repair.code, 1909 (repair.code == SECONDARY_CODE 1910 ? getNtermIndex(stack[repair.stackPosition], 1911 repair.symbol, 1912 repair.bufferPosition) 1913 : Parser.terminal_index[ERROR_SYMBOL]), 1914 locationStack[repair.stackPosition], 1915 buffer[repair.bufferPosition - 1]); 1916 stateStackTop = repair.stackPosition; 1917 } 1918 } 1919 } 1920 1921 1922 1923 1924 private int parseCheck(int stck[], int stack_top, int first_token, int buffer_position) { 1930 int max_pos; 1931 int indx; 1932 int ct; 1933 int act; 1934 1935 act = stck[stack_top]; 1940 if (first_token > NT_OFFSET) { 1941 tempStackTop = stack_top; 1942 if(DEBUG_PARSECHECK) { 1943 System.out.println(tempStackTop); 1944 } 1945 max_pos = stack_top; 1946 indx = buffer_position; 1947 ct = lexStream.kind(buffer[indx]); 1948 lexStream.reset(lexStream.next(buffer[indx])); 1949 int lhs_symbol = first_token - NT_OFFSET; 1950 act = Parser.ntAction(act, lhs_symbol); 1951 if (act <= NUM_RULES) { 1952 do { 1954 tempStackTop -= (Parser.rhs[act]-1); 1955 1956 if(DEBUG_PARSECHECK) { 1957 System.out.print(tempStackTop); 1958 System.out.print(" ("); System.out.print(-(Parser.rhs[act]-1)); 1960 System.out.print(") [max:"); System.out.print(max_pos); 1962 System.out.print("]\tprocess_non_terminal\t"); System.out.print(act); 1964 System.out.print("\t"); System.out.print(Parser.name[Parser.non_terminal_index[Parser.lhs[act]]]); 1966 System.out.println(); 1967 } 1968 1969 if(Parser.rules_compliance[act] > this.options.sourceLevel) { 1970 return 0; 1971 } 1972 lhs_symbol = Parser.lhs[act]; 1973 act = (tempStackTop > max_pos 1974 ? tempStack[tempStackTop] 1975 : stck[tempStackTop]); 1976 act = Parser.ntAction(act, lhs_symbol); 1977 } while(act <= NUM_RULES); 1978 1979 max_pos = max_pos < tempStackTop ? max_pos : tempStackTop; 1980 } 1981 } else { 1982 tempStackTop = stack_top - 1; 1983 1984 if(DEBUG_PARSECHECK) { 1985 System.out.println(tempStackTop); 1986 } 1987 1988 max_pos = tempStackTop; 1989 indx = buffer_position - 1; 1990 ct = first_token; 1991 lexStream.reset(buffer[buffer_position]); 1992 } 1993 1994 process_terminal: for (;;) { 1995 if(DEBUG_PARSECHECK) { 1996 System.out.print(tempStackTop + 1); 1997 System.out.print(" (+1) [max:"); System.out.print(max_pos); 1999 System.out.print("]\tprocess_terminal \t"); System.out.print(ct); 2001 System.out.print("\t"); System.out.print(Parser.name[Parser.terminal_index[ct]]); 2003 System.out.println(); 2004 } 2005 2006 if (++tempStackTop >= stackLength) return indx; 2008 tempStack[tempStackTop] = act; 2009 2010 act = Parser.tAction(act, ct); 2011 2012 if (act <= NUM_RULES) { tempStackTop--; 2014 2015 if(DEBUG_PARSECHECK) { 2016 System.out.print(tempStackTop); 2017 System.out.print(" (-1) [max:"); System.out.print(max_pos); 2019 System.out.print("]\treduce"); System.out.println(); 2021 } 2022 } else if (act < ACCEPT_ACTION || act > ERROR_ACTION) { if (indx == MAX_DISTANCE) 2025 return indx; 2026 indx++; 2027 ct = lexStream.kind(buffer[indx]); 2028 lexStream.reset(lexStream.next(buffer[indx])); 2029 if (act > ERROR_ACTION) { 2030 act -= ERROR_ACTION; 2031 2032 if(DEBUG_PARSECHECK) { 2033 System.out.print(tempStackTop); 2034 System.out.print("\tshift reduce"); System.out.println(); 2036 } 2037 } else { 2038 if(DEBUG_PARSECHECK) { 2039 System.out.println("\tshift"); } 2041 continue process_terminal; 2042 } 2043 } else if (act == ACCEPT_ACTION) { return MAX_DISTANCE; 2045 } else { 2046 return indx; } 2048 2049 do { 2052 tempStackTop -= (Parser.rhs[act]-1); 2053 2054 if(DEBUG_PARSECHECK) { 2055 System.out.print(tempStackTop); 2056 System.out.print(" ("); System.out.print(-(Parser.rhs[act]-1)); 2058 System.out.print(") [max:"); System.out.print(max_pos); 2060 System.out.print("]\tprocess_non_terminal\t"); System.out.print(act); 2062 System.out.print("\t"); System.out.print(Parser.name[Parser.non_terminal_index[Parser.lhs[act]]]); 2064 System.out.println(); 2065 } 2066 2067 if(act <= NUM_RULES) { 2068 if(Parser.rules_compliance[act] > this.options.sourceLevel) { 2069 return 0; 2070 } 2071 } 2072 int lhs_symbol = Parser.lhs[act]; 2073 act = (tempStackTop > max_pos 2074 ? tempStack[tempStackTop] 2075 : stck[tempStackTop]); 2076 act = Parser.ntAction(act, lhs_symbol); 2077 } while(act <= NUM_RULES); 2078 2079 max_pos = max_pos < tempStackTop ? max_pos : tempStackTop; 2080 } } 2082 private void reportError(int msgCode, int nameIndex, int leftToken, int rightToken) { 2083 reportError(msgCode, nameIndex, leftToken, rightToken, 0); 2084 } 2085 2086 private void reportError(int msgCode, int nameIndex, int leftToken, int rightToken, int scopeNameIndex) { 2087 int lToken = (leftToken > rightToken ? rightToken : leftToken); 2088 2089 if (lToken < rightToken) { 2090 reportSecondaryError(msgCode, nameIndex, lToken, rightToken, scopeNameIndex); 2091 } else { 2092 reportPrimaryError(msgCode, nameIndex, rightToken, scopeNameIndex); 2093 } 2094 } 2095 private void reportPrimaryError(int msgCode, int nameIndex, int token, int scopeNameIndex) { 2096 String name; 2097 if (nameIndex >= 0) { 2098 name = Parser.readableName[nameIndex]; 2099 } else { 2100 name = Util.EMPTY_STRING; 2101 } 2102 2103 int errorStart = lexStream.start(token); 2104 int errorEnd = lexStream.end(token); 2105 int currentKind = lexStream.kind(token); 2106 String errorTokenName = Parser.name[Parser.terminal_index[lexStream.kind(token)]]; 2107 char[] errorTokenSource = lexStream.name(token); 2108 2109 int addedToken = -1; 2110 if(recoveryScanner != null) { 2111 if (nameIndex >= 0) { 2112 addedToken = Parser.reverse_index[nameIndex]; 2113 } 2114 } 2115 switch(msgCode) { 2116 case BEFORE_CODE: 2117 if(recoveryScanner != null) { 2118 if(addedToken > -1) { 2119 recoveryScanner.insertToken(addedToken, -1, errorStart); 2120 } else { 2121 int[] template = getNTermTemplate(-addedToken); 2122 if(template != null) { 2123 recoveryScanner.insertTokens(template, -1, errorStart); 2124 } 2125 } 2126 } 2127 if(this.reportProblem) problemReporter().parseErrorInsertBeforeToken( 2128 errorStart, 2129 errorEnd, 2130 currentKind, 2131 errorTokenSource, 2132 errorTokenName, 2133 name); 2134 break; 2135 case INSERTION_CODE: 2136 if(recoveryScanner != null) { 2137 if(addedToken > -1) { 2138 recoveryScanner.insertToken(addedToken, -1, errorEnd); 2139 } else { 2140 int[] template = getNTermTemplate(-addedToken); 2141 if(template != null) { 2142 recoveryScanner.insertTokens(template, -1, errorEnd); 2143 } 2144 } 2145 } 2146 if(this.reportProblem) problemReporter().parseErrorInsertAfterToken( 2147 errorStart, 2148 errorEnd, 2149 currentKind, 2150 errorTokenSource, 2151 errorTokenName, 2152 name); 2153 break; 2154 case DELETION_CODE: 2155 if(recoveryScanner != null) { 2156 recoveryScanner.removeTokens(errorStart, errorEnd); 2157 } 2158 if(this.reportProblem) problemReporter().parseErrorDeleteToken( 2159 errorStart, 2160 errorEnd, 2161 currentKind, 2162 errorTokenSource, 2163 errorTokenName); 2164 break; 2165 case INVALID_CODE: 2166 if (name.length() == 0) { 2167 if(recoveryScanner != null) { 2168 recoveryScanner.removeTokens(errorStart, errorEnd); 2169 } 2170 if(this.reportProblem) problemReporter().parseErrorReplaceToken( 2171 errorStart, 2172 errorEnd, 2173 currentKind, 2174 errorTokenSource, 2175 errorTokenName, 2176 name); 2177 } else { 2178 if(recoveryScanner != null) { 2179 if(addedToken > -1) { 2180 recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); 2181 } else { 2182 int[] template = getNTermTemplate(-addedToken); 2183 if(template != null) { 2184 recoveryScanner.replaceTokens(template, errorStart, errorEnd); 2185 } 2186 } 2187 } 2188 if(this.reportProblem) problemReporter().parseErrorInvalidToken( 2189 errorStart, 2190 errorEnd, 2191 currentKind, 2192 errorTokenSource, 2193 errorTokenName, 2194 name); 2195 } 2196 break; 2197 case SUBSTITUTION_CODE: 2198 if(recoveryScanner != null) { 2199 if(addedToken > -1) { 2200 recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); 2201 } else { 2202 int[] template = getNTermTemplate(-addedToken); 2203 if(template != null) { 2204 recoveryScanner.replaceTokens(template, errorStart, errorEnd); 2205 } 2206 } 2207 } 2208 if(this.reportProblem) problemReporter().parseErrorReplaceToken( 2209 errorStart, 2210 errorEnd, 2211 currentKind, 2212 errorTokenSource, 2213 errorTokenName, 2214 name); 2215 break; 2216 case SCOPE_CODE: 2217 StringBuffer buf = new StringBuffer (); 2218 2219 int[] addedTokens = null; 2220 int addedTokenCount = 0; 2221 if(this.recoveryScanner != null) { 2222 addedTokens = new int[Parser.scope_rhs.length - Parser.scope_suffix[- nameIndex]]; 2223 } 2224 2225 for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) { 2226 buf.append(Parser.readableName[Parser.scope_rhs[i]]); 2227 if (Parser.scope_rhs[i + 1] != 0) buf.append(' '); 2229 2230 if(addedTokens != null) { 2231 int tmpAddedToken = Parser.reverse_index[Parser.scope_rhs[i]]; 2232 if (tmpAddedToken > -1) { 2233 int length = addedTokens.length; 2234 if(addedTokenCount == length) { 2235 System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); 2236 } 2237 addedTokens[addedTokenCount++] = tmpAddedToken; 2238 } else { 2239 int[] template = getNTermTemplate(-tmpAddedToken); 2240 if(template != null) { 2241 for (int j = 0; j < template.length; j++) { 2242 int length = addedTokens.length; 2243 if(addedTokenCount == length) { 2244 System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); 2245 } 2246 addedTokens[addedTokenCount++] = template[j]; 2247 } 2248 } else { 2249 addedTokenCount = 0; 2250 addedTokens = null; 2251 } 2252 } 2253 } 2254 } 2255 2256 if(addedTokenCount > 0) { 2257 System.arraycopy(addedTokens, 0, addedTokens = new int[addedTokenCount], 0, addedTokenCount); 2258 2259 int completedToken = -1; 2260 if(scopeNameIndex != 0) { 2261 completedToken = -Parser.reverse_index[scopeNameIndex]; 2262 } 2263 this.recoveryScanner.insertTokens(addedTokens, completedToken, errorEnd); 2264 } 2265 2266 if (scopeNameIndex != 0) { 2267 if(this.reportProblem) problemReporter().parseErrorInsertToComplete( 2268 errorStart, 2269 errorEnd, 2270 buf.toString(), 2271 Parser.readableName[scopeNameIndex]); 2272 } else { 2273 if(this.reportProblem) problemReporter().parseErrorInsertToCompleteScope( 2274 errorStart, 2275 errorEnd, 2276 buf.toString()); 2277 } 2278 2279 break; 2280 case EOF_CODE: 2281 if(this.reportProblem) problemReporter().parseErrorUnexpectedEnd( 2282 errorStart, 2283 errorEnd); 2284 break; 2285 case MERGE_CODE: 2286 if(recoveryScanner != null) { 2287 if(addedToken > -1) { 2288 recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); 2289 } else { 2290 int[] template = getNTermTemplate(-addedToken); 2291 if(template != null) { 2292 recoveryScanner.replaceTokens(template, errorStart, errorEnd); 2293 } 2294 } 2295 } 2296 if(this.reportProblem) problemReporter().parseErrorMergeTokens( 2297 errorStart, 2298 errorEnd, 2299 name); 2300 break; 2301 case MISPLACED_CODE: 2302 if(recoveryScanner != null) { 2303 recoveryScanner.removeTokens(errorStart, errorEnd); 2304 } 2305 if(this.reportProblem) problemReporter().parseErrorMisplacedConstruct( 2306 errorStart, 2307 errorEnd); 2308 break; 2309 default: 2310 if (name.length() == 0) { 2311 if(recoveryScanner != null) { 2312 recoveryScanner.removeTokens(errorStart, errorEnd); 2313 } 2314 if(this.reportProblem) problemReporter().parseErrorNoSuggestion( 2315 errorStart, 2316 errorEnd, 2317 currentKind, 2318 errorTokenSource, 2319 errorTokenName); 2320 } else { 2321 if(recoveryScanner != null) { 2322 if(addedToken > -1) { 2323 recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); 2324 } else { 2325 int[] template = getNTermTemplate(-addedToken); 2326 if(template != null) { 2327 recoveryScanner.replaceTokens(template, errorStart, errorEnd); 2328 } 2329 } 2330 } 2331 if(this.reportProblem) problemReporter().parseErrorReplaceToken( 2332 errorStart, 2333 errorEnd, 2334 currentKind, 2335 errorTokenSource, 2336 errorTokenName, 2337 name); 2338 } 2339 break; 2340 } 2341 } 2342 2343 private void reportSecondaryError(int msgCode, int nameIndex, int leftToken, int rightToken, int scopeNameIndex) { 2344 String name; 2345 if (nameIndex >= 0) { 2346 name = Parser.readableName[nameIndex]; 2347 } else { 2348 name = Util.EMPTY_STRING; 2349 } 2350 2351 int errorStart = -1; 2352 if(lexStream.isInsideStream(leftToken)) { 2353 if(leftToken == 0) { 2354 errorStart = lexStream.start(leftToken + 1); 2355 } else { 2356 errorStart = lexStream.start(leftToken); 2357 } 2358 } else { 2359 if(leftToken == errorToken) { 2360 errorStart = errorTokenStart; 2361 } else { 2362 for (int i = 0; i <= stateStackTop; i++) { 2363 if(locationStack[i] == leftToken) { 2364 errorStart = locationStartStack[i]; 2365 } 2366 } 2367 } 2368 if(errorStart == -1) { 2369 errorStart = lexStream.start(rightToken); 2370 } 2371 } 2372 int errorEnd = lexStream.end(rightToken); 2373 2374 int addedToken = -1; 2375 if(recoveryScanner != null) { 2376 if (nameIndex >= 0) { 2377 addedToken = Parser.reverse_index[nameIndex]; 2378 } 2379 } 2380 2381 switch(msgCode) { 2382 case MISPLACED_CODE: 2383 if(recoveryScanner != null) { 2384 recoveryScanner.removeTokens(errorStart, errorEnd); 2385 } 2386 if(this.reportProblem) problemReporter().parseErrorMisplacedConstruct( 2387 errorStart, 2388 errorEnd); 2389 break; 2390 case SCOPE_CODE: 2391 errorStart = lexStream.start(rightToken); 2393 2394 StringBuffer buf = new StringBuffer (); 2395 2396 int[] addedTokens = null; 2397 int addedTokenCount = 0; 2398 if(this.recoveryScanner != null) { 2399 addedTokens = new int[Parser.scope_rhs.length - Parser.scope_suffix[- nameIndex]]; 2400 } 2401 2402 for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) { 2403 2404 buf.append(Parser.readableName[Parser.scope_rhs[i]]); 2405 if (Parser.scope_rhs[i+1] != 0) 2406 buf.append(' '); 2407 2408 if(addedTokens != null) { 2409 int tmpAddedToken = Parser.reverse_index[Parser.scope_rhs[i]]; 2410 if (tmpAddedToken > -1) { 2411 int length = addedTokens.length; 2412 if(addedTokenCount == length) { 2413 System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); 2414 } 2415 addedTokens[addedTokenCount++] = tmpAddedToken; 2416 } else { 2417 int[] template = getNTermTemplate(-tmpAddedToken); 2418 if(template != null) { 2419 for (int j = 0; j < template.length; j++) { 2420 int length = addedTokens.length; 2421 if(addedTokenCount == length) { 2422 System.arraycopy(addedTokens, 0, addedTokens = new int[length * 2], 0, length); 2423 } 2424 addedTokens[addedTokenCount++] = template[j]; 2425 } 2426 } else { 2427 addedTokenCount = 0; 2428 addedTokens = null; 2429 } 2430 } 2431 } 2432 } 2433 if(addedTokenCount > 0) { 2434 System.arraycopy(addedTokens, 0, addedTokens = new int[addedTokenCount], 0, addedTokenCount); 2435 int completedToken = -1; 2436 if(scopeNameIndex != 0) { 2437 completedToken = -Parser.reverse_index[scopeNameIndex]; 2438 } 2439 this.recoveryScanner.insertTokens(addedTokens, completedToken, errorEnd); 2440 } 2441 if (scopeNameIndex != 0) { 2442 if(this.reportProblem) problemReporter().parseErrorInsertToComplete( 2443 errorStart, 2444 errorEnd, 2445 buf.toString(), 2446 Parser.readableName[scopeNameIndex]); 2447 } else { 2448 if(this.reportProblem) problemReporter().parseErrorInsertToCompletePhrase( 2449 errorStart, 2450 errorEnd, 2451 buf.toString()); 2452 } 2453 break; 2454 case MERGE_CODE: 2455 if(recoveryScanner != null) { 2456 if(addedToken > -1) { 2457 recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); 2458 } else { 2459 int[] template = getNTermTemplate(-addedToken); 2460 if(template != null) { 2461 recoveryScanner.replaceTokens(template, errorStart, errorEnd); 2462 } 2463 } 2464 } 2465 if(this.reportProblem) problemReporter().parseErrorMergeTokens( 2466 errorStart, 2467 errorEnd, 2468 name); 2469 break; 2470 case DELETION_CODE: 2471 if(recoveryScanner != null) { 2472 recoveryScanner.removeTokens(errorStart, errorEnd); 2473 } 2474 if(this.reportProblem) problemReporter().parseErrorDeleteTokens( 2475 errorStart, 2476 errorEnd); 2477 break; 2478 default: 2479 if (name.length() == 0) { 2480 if(recoveryScanner != null) { 2481 recoveryScanner.removeTokens(errorStart, errorEnd); 2482 } 2483 if(this.reportProblem) problemReporter().parseErrorNoSuggestionForTokens( 2484 errorStart, 2485 errorEnd); 2486 } else { 2487 if(recoveryScanner != null) { 2488 if(addedToken > -1) { 2489 recoveryScanner.replaceTokens(addedToken, errorStart, errorEnd); 2490 } else { 2491 int[] template = getNTermTemplate(-addedToken); 2492 if(template != null) { 2493 recoveryScanner.replaceTokens(template, errorStart, errorEnd); 2494 } 2495 } 2496 } 2497 if(this.reportProblem) problemReporter().parseErrorReplaceTokens( 2498 errorStart, 2499 errorEnd, 2500 name); 2501 } 2502 } 2503 return; 2504 } 2505 2506 private int[] getNTermTemplate(int sym) { 2507 int templateIndex = Parser.recovery_templates_index[sym]; 2508 if(templateIndex > 0) { 2509 int[] result = new int[Parser.recovery_templates.length]; 2510 int count = 0; 2511 for(int j = templateIndex; Parser.recovery_templates[j] != 0; j++) { 2512 result[count++] = Parser.recovery_templates[j]; 2513 } 2514 System.arraycopy(result, 0, result = new int[count], 0, count); 2515 return result; 2516 } else { 2517 return null; 2518 } 2519 } 2520 2521 public String toString() { 2522 StringBuffer res = new StringBuffer (); 2523 2524 res.append(lexStream.toString()); 2525 2526 return res.toString(); 2527 } 2528} 2529 | Popular Tags |