removed Makefile; lifted repo/org.ibex.tool/src/ to src/
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / parser / diagnose / DiagnoseParser.java
diff --git a/src/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java b/src/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
new file mode 100644 (file)
index 0000000..58e0506
--- /dev/null
@@ -0,0 +1,2216 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser.diagnose;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.parser.ParserBasicInformation;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+
+public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
+       private static final boolean DEBUG = false;
+       
+       private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+       private static final int STACK_INCREMENT = 256;
+       
+//     private static final int ERROR_CODE = 1;
+       private static final int BEFORE_CODE = 2;
+       private static final int INSERTION_CODE = 3;
+       private static final int INVALID_CODE = 4;
+       private static final int SUBSTITUTION_CODE = 5;
+       private static final int DELETION_CODE = 6;
+       private static final int MERGE_CODE = 7;
+       private static final int MISPLACED_CODE = 8;
+       private static final int SCOPE_CODE = 9;
+       private static final int SECONDARY_CODE = 10;
+       private static final int EOF_CODE = 11;
+
+       private static final int BUFF_UBOUND  = 31;
+       private static final int BUFF_SIZE    = 32;
+       private static final int MAX_DISTANCE = 30;
+       private static final int MIN_DISTANCE = 3;
+       
+       private LexStream lexStream;
+       private int errorToken;
+       private int errorTokenStart;
+       
+       private int currentToken = 0;
+       
+       private int stackLength;
+       private int stateStackTop;
+       private int[] stack;
+       
+       private int[] locationStack;
+       private int[] locationStartStack;
+       
+       private int tempStackTop;
+       private int[] tempStack;
+       
+       private int prevStackTop;
+       private int[] prevStack;
+       private int nextStackTop;
+       private int[] nextStack;
+       
+       private int scopeStackTop;
+    private int[] scopeIndex;
+    private int[] scopePosition;
+       
+       int[] list = new int[NUM_SYMBOLS + 1];
+       int[] buffer = new int[BUFF_SIZE];
+       
+       private static final int NIL = -1;
+       int[] stateSeen;
+       
+       int statePoolTop;
+       StateInfo[] statePool;
+       
+       private Parser parser;
+       
+       private class RepairCandidate {
+               public int symbol;
+               public int location;
+               
+               public RepairCandidate(){
+                       this.symbol = 0;
+                       this.location = 0;
+               }
+       }
+       
+       private class PrimaryRepairInfo {
+               public int distance;
+               public int misspellIndex;
+               public int code;
+               public int bufferPosition;
+               public int symbol;
+               
+               public PrimaryRepairInfo(){
+                       this.distance = 0;
+                       this.misspellIndex = 0;
+                       this.code = 0;
+                       this.bufferPosition = 0;
+                       this.symbol = 0;
+               }
+               
+               public PrimaryRepairInfo copy(){
+                       PrimaryRepairInfo c = new PrimaryRepairInfo();
+                       c.distance = this.distance;
+                       c.misspellIndex = this.misspellIndex;
+                       c.code = this.code;
+                       c.bufferPosition = this .bufferPosition;
+                       c.symbol = this.symbol;
+                       return c;
+                       
+               }
+       }
+       
+       private class SecondaryRepairInfo {
+               public int code;
+               public int distance;
+               public int bufferPosition;
+               public int stackPosition;
+               public int numDeletions;
+               public int symbol;
+
+               boolean recoveryOnNextStack;
+       } 
+       
+       private class StateInfo {
+           int state;
+           int next;
+           
+           public StateInfo(int state, int next){
+               this.state = state;
+               this.next = next;
+           }
+       }
+
+       public DiagnoseParser(Parser parser, int firstToken, int start, int end) {
+               this(parser, firstToken, start, end, new int[0], new int[0], new int[0]);
+       }
+
+       public DiagnoseParser(Parser parser, int firstToken, int start, int end, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip) {
+               this.parser = parser;
+               this.lexStream = new LexStream(BUFF_SIZE, parser.scanner, intervalStartToSkip, intervalEndToSkip, intervalFlagsToSkip, firstToken, start, end);
+       }
+       
+       private ProblemReporter problemReporter(){
+               return parser.problemReporter();
+       }
+
+       private void reallocateStacks() {
+               int old_stack_length = stackLength;
+
+               stackLength += STACK_INCREMENT;
+
+               if(old_stack_length == 0){
+                       stack = new int[stackLength];
+                       locationStack = new int[stackLength];
+                       locationStartStack = new int[stackLength];
+                       tempStack = new int[stackLength];
+                       prevStack = new int[stackLength];
+                       nextStack = new int[stackLength];
+                       scopeIndex = new int[stackLength];
+                       scopePosition = new int[stackLength];
+               } else {
+                       System.arraycopy(stack, 0, stack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(locationStack, 0, locationStack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(locationStartStack, 0, locationStartStack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(tempStack, 0, tempStack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(prevStack, 0, prevStack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(nextStack, 0, nextStack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(scopeIndex, 0, scopeIndex = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(scopePosition, 0, scopePosition = new int[stackLength], 0, old_stack_length);
+               }
+               return;
+       }
+
+
+       public void diagnoseParse() {
+               lexStream.reset();
+
+               currentToken = lexStream.getToken();
+
+               int prev_pos;
+               int pos;
+               int next_pos;
+               int act = START_STATE;
+
+               reallocateStacks();
+
+               //
+               // Start parsing
+               //
+               stateStackTop = 0;
+               stack[stateStackTop] = act;
+
+               int tok = lexStream.kind(currentToken);
+               locationStack[stateStackTop] = currentToken;
+               locationStartStack[stateStackTop] = lexStream.start(currentToken);
+               
+               boolean forceRecoveryAfterLBracketMissing = false;
+//             int forceRecoveryToken = -1;
+
+               //
+               // Process a terminal
+               //
+               do {
+                       //
+                       // Synchronize state stacks and update the location stack
+                       //
+                       prev_pos = -1;
+                       prevStackTop = -1;
+
+                       next_pos = -1;
+                       nextStackTop = -1;
+
+                       pos = stateStackTop;
+                       tempStackTop = stateStackTop - 1;
+                       for (int i = 0; i <= stateStackTop; i++)
+                               tempStack[i] = stack[i];
+
+                       act = Parser.tAction(act, tok);
+                       //
+                       // When a reduce action is encountered, we compute all REDUCE
+                       // and associated goto actions induced by the current token.
+                       // Eventually, a SHIFT, SHIFT-REDUCE, ACCEPT or ERROR action is
+                       // computed...
+                       //
+                       while (act <= NUM_RULES) {
+                               do {
+                                       tempStackTop -= (Parser.rhs[act]-1);
+                                       act = Parser.ntAction(tempStack[tempStackTop], Parser.lhs[act]);
+                               } while(act <= NUM_RULES);
+                               //
+                               // ... Update the maximum useful position of the
+                               // (STATE_)STACK, push goto state into stack, and
+                               // compute next action on current symbol ...
+                               //
+                               if (tempStackTop + 1 >= stackLength)
+                                       reallocateStacks();
+                               pos = pos < tempStackTop ? pos : tempStackTop;
+                               tempStack[tempStackTop + 1] = act;
+                               act = Parser.tAction(act, tok);
+                       }
+
+                       //
+                       // At this point, we have a shift, shift-reduce, accept or error
+                       // action.  STACK contains the configuration of the state stack
+                       // prior to executing any action on curtok. next_stack contains
+                       // the configuration of the state stack after executing all
+                       // reduce actions induced by curtok.  The variable pos indicates
+                       // the highest position in STACK that is still useful after the
+                       // reductions are executed.
+                       //
+                       while(act > ERROR_ACTION || act < ACCEPT_ACTION) { // SHIFT-REDUCE action or SHIFT action ?
+                               nextStackTop = tempStackTop + 1;
+                               for (int i = next_pos + 1; i <= nextStackTop; i++)
+                                       nextStack[i] = tempStack[i];
+
+                               for (int i = pos + 1; i <= nextStackTop; i++) {
+                                       locationStack[i] = locationStack[stateStackTop];
+                                       locationStartStack[i] = locationStartStack[stateStackTop];
+                               }
+
+                               //
+                               // If we have a shift-reduce, process it as well as
+                               // the goto-reduce actions that follow it.
+                               //
+                               if (act > ERROR_ACTION) {
+                                       act -= ERROR_ACTION;
+                                       do {
+                                               nextStackTop -= (Parser.rhs[act]-1);
+                                               act = Parser.ntAction(nextStack[nextStackTop], Parser.lhs[act]);
+                                       } while(act <= NUM_RULES);
+                                       pos = pos < nextStackTop ? pos : nextStackTop;
+                               }
+
+                               if (nextStackTop + 1 >= stackLength)
+                                       reallocateStacks();
+
+                               tempStackTop = nextStackTop;
+                               nextStack[++nextStackTop] = act;
+                               next_pos = nextStackTop;
+
+                               //
+                               // Simulate the parser through the next token without
+                               // destroying STACK or next_stack.
+                               //
+                               currentToken = lexStream.getToken();
+                               tok = lexStream.kind(currentToken);
+                               act = Parser.tAction(act, tok);
+                               while(act <= NUM_RULES) {
+                                       //
+                                       // ... Process all goto-reduce actions following
+                                       // reduction, until a goto action is computed ...
+                                       //
+                                       do {
+                                               int lhs_symbol = Parser.lhs[act];
+                                               if(DEBUG) {
+                                                       System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]);
+                                               }
+                                               tempStackTop -= (Parser.rhs[act]-1);
+                                               act = (tempStackTop > next_pos
+                                                                  ? tempStack[tempStackTop]
+                                                                  : nextStack[tempStackTop]);
+                                               act = Parser.ntAction(act, lhs_symbol);
+                                       }   while(act <= NUM_RULES);
+
+                                       //
+                                       // ... Update the maximum useful position of the
+                                       // (STATE_)STACK, push GOTO state into stack, and
+                                       // compute next action on current symbol ...
+                                       //
+                                       if (tempStackTop + 1 >= stackLength)
+                                               reallocateStacks();
+
+                                       next_pos = next_pos < tempStackTop ? next_pos : tempStackTop;
+                                       tempStack[tempStackTop + 1] = act;
+                                       act = Parser.tAction(act, tok);
+                               }
+
+//                             if((tok != TokenNameRBRACE || (forceRecoveryToken != currentToken && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0))
+//                                     && (lexStream.flags(currentToken) & LexStream.IS_AFTER_JUMP) !=0) {
+//                                     act = ERROR_ACTION;
+//                                     if(forceRecoveryToken != currentToken
+//                                             && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0) {
+//                                             forceRecoveryAfterLBracketMissing = true;
+//                                             forceRecoveryToken = currentToken;
+//                                     }
+//                             }
+                               
+                               //
+                               // No error was detected, Read next token into
+                               // PREVTOK element, advance CURTOK pointer and
+                               // update stacks.
+                               //
+                               if (act != ERROR_ACTION) {
+                                       prevStackTop = stateStackTop;
+                                       for (int i = prev_pos + 1; i <= prevStackTop; i++)
+                                               prevStack[i] = stack[i];
+                                       prev_pos = pos;
+
+                                       stateStackTop = nextStackTop;
+                                       for (int i = pos + 1; i <= stateStackTop; i++)
+                                               stack[i] = nextStack[i];
+                                       locationStack[stateStackTop] = currentToken;
+                                       locationStartStack[stateStackTop] = lexStream.start(currentToken);
+                                       pos = next_pos;
+                               }
+                       }
+
+                       //
+                       // At this stage, either we have an ACCEPT or an ERROR
+                       // action.
+                       //
+                       if (act == ERROR_ACTION) {
+                               //
+                               // An error was detected.
+                               //
+                               RepairCandidate candidate = errorRecovery(currentToken, forceRecoveryAfterLBracketMissing);
+                               
+                               forceRecoveryAfterLBracketMissing = false;
+                               
+                               if(parser.reportOnlyOneSyntaxError) {
+                                       return;
+                               }
+                               
+                               if(this.parser.problemReporter().options.maxProblemsPerUnit < this.parser.compilationUnit.compilationResult.problemCount) {
+                                       return;
+                               }
+
+                               act = stack[stateStackTop];
+
+                               //
+                               // If the recovery was successful on a nonterminal candidate,
+                               // parse through that candidate and "read" the next token.
+                               //
+                               if (candidate.symbol == 0) {
+                                       break;
+                               } else if (candidate.symbol > NT_OFFSET) {
+                                       int lhs_symbol = candidate.symbol - NT_OFFSET;
+                                       if(DEBUG) {
+                                               System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]);
+                                       }
+                                       act = Parser.ntAction(act, lhs_symbol);
+                                       while(act <= NUM_RULES) {
+                                               stateStackTop -= (Parser.rhs[act]-1);
+                                               act = Parser.ntAction(stack[stateStackTop], Parser.lhs[act]);
+                                       }
+                                       stack[++stateStackTop] = act;
+                                       currentToken = lexStream.getToken();
+                                       tok = lexStream.kind(currentToken);
+                                       locationStack[stateStackTop] = currentToken;
+                                       locationStartStack[stateStackTop] = lexStream.start(currentToken);
+                               } else {
+                                       tok = candidate.symbol;
+                                       locationStack[stateStackTop] = candidate.location;
+                                       locationStartStack[stateStackTop] = lexStream.start(candidate.location);
+                               }
+                       }
+               } while (act != ACCEPT_ACTION);
+
+               return;
+       }
+
+       //
+//             This routine is invoked when an error is encountered.  It
+//        tries to diagnose the error and recover from it.  If it is
+//        successful, the state stack, the current token and the buffer
+//        are readjusted; i.e., after a successful recovery,
+//        state_stack_top points to the location in the state stack
+//        that contains the state on which to recover; curtok
+//        identifies the symbol on which to recover.
+//
+//        Up to three configurations may be available when this routine
+//        is invoked. PREV_STACK may contain the sequence of states
+//        preceding any action on prevtok, STACK always contains the
+//        sequence of states preceding any action on curtok, and
+//        NEXT_STACK may contain the sequence of states preceding any
+//        action on the successor of curtok.
+//
+       private RepairCandidate errorRecovery(int error_token, boolean forcedError) {
+               this.errorToken = error_token;
+               this.errorTokenStart = lexStream.start(error_token);
+               
+               int prevtok = lexStream.previous(error_token);
+               int prevtokKind = lexStream.kind(prevtok);
+               
+               if(forcedError) {
+                       int name_index = Parser.terminal_index[TokenNameLBRACE];
+
+                       reportError(INSERTION_CODE, name_index, prevtok, prevtok);
+                       
+                       RepairCandidate candidate = new RepairCandidate();
+                       candidate.symbol = TokenNameLBRACE;
+                       candidate.location = error_token;
+                       lexStream.reset(error_token);
+                       
+                       stateStackTop = nextStackTop;
+                       for (int j = 0; j <= stateStackTop; j++) {
+                               stack[j] = nextStack[j];
+                       }
+                       locationStack[stateStackTop] = error_token;
+                       locationStartStack[stateStackTop] = lexStream.start(error_token);
+                       
+                       return candidate;
+               }
+
+               //
+               // Try primary phase recoveries. If not successful, try secondary
+               // phase recoveries.  If not successful and we are at end of the
+               // file, we issue the end-of-file error and quit. Otherwise, ...
+               //
+               RepairCandidate candidate = primaryPhase(error_token);
+               if (candidate.symbol != 0) {
+                       return candidate;
+               }
+
+               candidate = secondaryPhase(error_token);
+               if (candidate.symbol != 0) {
+                       return candidate;
+               }
+
+               if (lexStream.kind(error_token) == EOFT_SYMBOL) {
+                       reportError(EOF_CODE,
+                                               Parser.terminal_index[EOFT_SYMBOL],
+                                               prevtok,
+                                               prevtok);
+                       candidate.symbol = 0;
+                       candidate.location = error_token;
+                       return candidate;
+               }
+
+               //
+               // At this point, primary and (initial attempt at) secondary
+               // recovery did not work.  We will now get into "panic mode" and
+               // keep trying secondary phase recoveries until we either find
+               // a successful recovery or have consumed the remaining input
+               // tokens.
+               //
+               while(lexStream.kind(buffer[BUFF_UBOUND]) != EOFT_SYMBOL) {
+                       candidate = secondaryPhase(buffer[MAX_DISTANCE - MIN_DISTANCE + 2]);
+                       if (candidate.symbol != 0) {
+                               return candidate;
+                       }
+               }
+
+               //
+               // We reached the end of the file while panicking. Delete all
+               // remaining tokens in the input.
+               //
+               int i;
+               for (i = BUFF_UBOUND; lexStream.kind(buffer[i]) == EOFT_SYMBOL; i--){/*empty*/}
+
+               reportError(DELETION_CODE,
+                                       Parser.terminal_index[prevtokKind],//Parser.terminal_index[lexStream.kind(prevtok)],
+                                       error_token,
+                                       buffer[i]);
+
+               candidate.symbol = 0;
+               candidate.location = buffer[i];
+
+               return candidate;
+       }
+
+//
+//        This function tries primary and scope recovery on each
+//        available configuration.  If a successful recovery is found
+//        and no secondary phase recovery can do better, a diagnosis is
+//        issued, the configuration is updated and the function returns
+//        "true".  Otherwise, it returns "false".
+//
+       private RepairCandidate primaryPhase(int error_token) {
+               PrimaryRepairInfo repair = new PrimaryRepairInfo();
+               RepairCandidate candidate = new RepairCandidate();
+
+               //
+               // Initialize the buffer.
+               //
+               int i = (nextStackTop >= 0 ? 3 : 2);
+               buffer[i] = error_token;
+
+               for (int j = i; j > 0; j--)
+                       buffer[j - 1] = lexStream.previous(buffer[j]);
+
+               for (int k = i + 1; k < BUFF_SIZE; k++)
+                       buffer[k] = lexStream.next(buffer[k - 1]);
+
+               //
+               // If NEXT_STACK_TOP > 0 then the parse was successful on CURTOK
+               // and the error was detected on the successor of CURTOK. In
+               // that case, first check whether or not primary recovery is
+               // possible on next_stack ...
+               //
+               if (nextStackTop >= 0) {
+                       repair.bufferPosition = 3;
+                       repair = checkPrimaryDistance(nextStack, nextStackTop, repair);
+               }
+
+               //
+               // ... Next, try primary recovery on the current token...
+               //
+               PrimaryRepairInfo new_repair = repair.copy();
+
+               new_repair.bufferPosition = 2;
+               new_repair = checkPrimaryDistance(stack, stateStackTop, new_repair);
+               if (new_repair.distance > repair.distance || new_repair.misspellIndex > repair.misspellIndex) {
+                       repair = new_repair;
+               }
+
+               //
+               // Finally, if prev_stack_top >= 0 then try primary recovery on
+               // the prev_stack configuration.
+               //
+               
+               if (prevStackTop >= 0) {
+                       new_repair = repair.copy();
+                       new_repair.bufferPosition = 1;
+                       new_repair = checkPrimaryDistance(prevStack,prevStackTop, new_repair);
+                       if (new_repair.distance > repair.distance || new_repair.misspellIndex > repair.misspellIndex) {
+                               repair = new_repair;
+                       }
+               }
+
+               //
+               // Before accepting the best primary phase recovery obtained,
+               // ensure that we cannot do better with a similar secondary
+               // phase recovery.
+               //
+               if (nextStackTop >= 0) {// next_stack available
+                       if (secondaryCheck(nextStack,nextStackTop,3,repair.distance)) {
+                               return candidate;
+                       }
+               }
+               else if (secondaryCheck(stack, stateStackTop, 2, repair.distance)) {
+                       return candidate;
+               }
+
+               //
+               // First, adjust distance if the recovery is on the error token;
+               // it is important that the adjustment be made here and not at
+               // each primary trial to prevent the distance tests from being
+               // biased in favor of deferred recoveries which have access to
+               // more input tokens...
+               //
+               repair.distance = repair.distance - repair.bufferPosition + 1;
+
+               //
+               // ...Next, adjust the distance if the recovery is a deletion or
+               // (some form of) substitution...
+               //
+               if (repair.code == INVALID_CODE      ||
+                       repair.code == DELETION_CODE     ||
+                       repair.code == SUBSTITUTION_CODE ||
+                       repair.code == MERGE_CODE) {
+                        repair.distance--;
+               }
+
+               //
+               // ... After adjustment, check if the most successful primary
+               // recovery can be applied.  If not, continue with more radical
+               // recoveries...
+               //
+               if (repair.distance < MIN_DISTANCE) {
+                       return candidate;
+               }
+
+               //
+               // When processing an insertion error, if the token preceeding
+               // the error token is not available, we change the repair code
+               // into a BEFORE_CODE to instruct the reporting routine that it
+               // indicates that the repair symbol should be inserted before
+               // the error token.
+               //
+               if (repair.code == INSERTION_CODE) {
+                       if (buffer[repair.bufferPosition - 1] == 0) {
+                               repair.code = BEFORE_CODE;
+                       }
+               }
+
+               //
+               // Select the proper sequence of states on which to recover,
+               // update stack accordingly and call diagnostic routine.
+               //
+               if (repair.bufferPosition == 1) {
+                       stateStackTop = prevStackTop;
+                       for (int j = 0; j <= stateStackTop; j++) {
+                               stack[j] = prevStack[j];
+                       }
+               } else if (nextStackTop >= 0 && repair.bufferPosition >= 3) {
+                       stateStackTop = nextStackTop;
+                       for (int j = 0; j <= stateStackTop; j++) {
+                               stack[j] = nextStack[j];
+                       }
+                       locationStack[stateStackTop] = buffer[3];
+                       locationStartStack[stateStackTop] = lexStream.start(buffer[3]);
+               }
+
+               return primaryDiagnosis(repair);
+       }
+
+
+//
+//                This function checks whether or not a given state has a
+//        candidate, whose string representaion is a merging of the two
+//        tokens at positions buffer_position and buffer_position+1 in
+//        the buffer.  If so, it returns the candidate in question;
+//        otherwise it returns 0.
+//
+       private int mergeCandidate(int state, int buffer_position) {
+               char[] name1 = lexStream.name(buffer[buffer_position]);
+               char[] name2 = lexStream.name(buffer[buffer_position + 1]);
+               
+               int len  = name1.length + name2.length;
+
+               char[] str = CharOperation.concat(name1, name2);
+
+               for (int k = Parser.asi(state); Parser.asr[k] != 0; k++) {
+                       int l = Parser.terminal_index[Parser.asr[k]];
+
+                       if (len == Parser.name[l].length()) {
+                               char[] name = Parser.name[l].toCharArray();
+
+                               if (CharOperation.equals(str, name, false)) {
+                                       return Parser.asr[k];
+                               }
+                       }
+               }
+
+               return 0;
+       }
+
+
+//
+//        This procedure takes as arguments a parsing configuration
+//        consisting of a state stack (stack and stack_top) and a fixed
+//        number of input tokens (starting at buffer_position) in the
+//        input BUFFER; and some reference arguments: repair_code,
+//        distance, misspell_index, candidate, and stack_position
+//        which it sets based on the best possible recovery that it
+//        finds in the given configuration.  The effectiveness of a
+//        a repair is judged based on two criteria:
+//
+//              1) the number of tokens that can be parsed after the repair
+//                     is applied: distance.
+//              2) how close to perfection is the candidate that is chosen:
+//                     misspell_index.
+//        When this procedure is entered, distance, misspell_index and
+//        repair_code are assumed to be initialized.
+//
+       private PrimaryRepairInfo checkPrimaryDistance(int stck[], int stack_top, PrimaryRepairInfo repair) {
+               int i, j, k, next_state, max_pos, act, root, symbol, tok;
+
+               //
+           //  First, try scope and manual recovery.
+           //
+           PrimaryRepairInfo scope_repair = scopeTrial(stck, stack_top, repair.copy());
+           if (scope_repair.distance > repair.distance)
+               repair = scope_repair;
+               
+               //
+               //  Next, try merging the error token with its successor.
+               //
+           if(buffer[repair.bufferPosition] != 0 && buffer[repair.bufferPosition + 1] != 0) {// do not merge the first token
+                       symbol = mergeCandidate(stck[stack_top], repair.bufferPosition);
+                       if (symbol != 0) {
+                               j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+2);
+                               if ((j > repair.distance) || (j == repair.distance && repair.misspellIndex < 10)) {
+                                       repair.misspellIndex = 10;
+                                       repair.symbol = symbol;
+                                       repair.distance = j;
+                                       repair.code = MERGE_CODE;
+                               }
+                       }
+           }
+
+               //
+               // Next, try deletion of the error token.
+               //
+               j = parseCheck(
+                               stck,
+                               stack_top,
+                               lexStream.kind(buffer[repair.bufferPosition + 1]),
+                               repair.bufferPosition + 2);
+               if (lexStream.kind(buffer[repair.bufferPosition]) == EOLT_SYMBOL &&
+                       lexStream.afterEol(buffer[repair.bufferPosition+1])) {
+                        k = 10;
+               } else {
+                       k = 0;
+               }
+               if (j > repair.distance || (j == repair.distance && k > repair.misspellIndex)) {
+                       repair.misspellIndex = k;
+                       repair.code = DELETION_CODE;
+                       repair.distance = j;
+               }
+
+               //
+               // Update the error configuration by simulating all reduce and
+               // goto actions induced by the error token. Then assign the top
+               // most state of the new configuration to next_state.
+               //
+               next_state = stck[stack_top];
+               max_pos = stack_top;
+               tempStackTop = stack_top - 1;
+
+               tok = lexStream.kind(buffer[repair.bufferPosition]);
+               lexStream.reset(buffer[repair.bufferPosition + 1]);
+               act = Parser.tAction(next_state, tok);
+               while(act <= NUM_RULES) {
+                       do {
+                               tempStackTop -= (Parser.rhs[act]-1);
+                               symbol = Parser.lhs[act];
+                               act = (tempStackTop > max_pos
+                                                                         ? tempStack[tempStackTop]
+                                                                         : stck[tempStackTop]);
+                               act = Parser.ntAction(act, symbol);
+                       } while(act <= NUM_RULES);
+                       max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+                       tempStack[tempStackTop + 1] = act;
+                       next_state = act;
+                       act = Parser.tAction(next_state, tok);
+               }
+
+               //
+               //  Next, place the list of candidates in proper order.
+               //
+               root = 0;
+               for (i = Parser.asi(next_state); Parser.asr[i] != 0; i++) {
+                       symbol = Parser.asr[i];
+                       if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL) {
+                               if (root == 0) {
+                                       list[symbol] = symbol;
+                               } else {
+                                       list[symbol] = list[root];
+                                       list[root] = symbol;
+                               }
+                               root = symbol;
+                       }
+               }
+
+               if (stck[stack_top] != next_state) {
+                       for (i = Parser.asi(stck[stack_top]); Parser.asr[i] != 0; i++) {
+                               symbol = Parser.asr[i];
+                               if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL && list[symbol] == 0) {
+                                       if (root == 0) {
+                                               list[symbol] = symbol;
+                                       } else {
+                                               list[symbol] = list[root];
+                                               list[root] = symbol;
+                                       }
+                                       root = symbol;
+                               }
+                       }
+               }
+
+               i = list[root];
+               list[root] = 0;
+               root = i;
+
+               //
+               //  Next, try insertion for each possible candidate available in
+               // the current state, except EOFT and ERROR_SYMBOL.
+               //
+               symbol = root;
+               while(symbol != 0) {
+                       if (symbol == EOLT_SYMBOL && lexStream.afterEol(buffer[repair.bufferPosition])) {
+                               k = 10;
+                       } else {
+                               k = 0;
+                       }
+                       j = parseCheck(stck, stack_top, symbol, repair.bufferPosition);
+                       if (j > repair.distance) {
+                               repair.misspellIndex = k;
+                               repair.distance = j;
+                               repair.symbol = symbol;
+                               repair.code = INSERTION_CODE;
+                       } else if (j == repair.distance && k > repair.misspellIndex) {
+                               repair.misspellIndex = k;
+                               repair.distance = j;
+                               repair.symbol = symbol;
+                               repair.code = INSERTION_CODE;
+                       } else if (j == repair.distance && k == repair.misspellIndex && isBetterSymbol(symbol, repair.symbol)) {
+                               repair.misspellIndex = k;
+                               repair.distance = j;
+                               repair.symbol = symbol;
+                               repair.code = INSERTION_CODE;
+                       }
+
+                       symbol = list[symbol];
+               }
+
+               //
+               //  Next, Try substitution for each possible candidate available
+               // in the current state, except EOFT and ERROR_SYMBOL.
+               //
+               symbol = root;
+               
+               if(buffer[repair.bufferPosition] != 0) {// do not replace the first token
+                       while(symbol != 0) {
+                               if (symbol == EOLT_SYMBOL && lexStream.afterEol(buffer[repair.bufferPosition+1])) {
+                                       k = 10;
+                               } else {
+                                       k = misspell(symbol, buffer[repair.bufferPosition]);
+                               }
+                               j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+1);
+                               if (j > repair.distance) {
+                                       repair.misspellIndex = k;
+                                       repair.distance = j;
+                                       repair.symbol = symbol;
+                                       repair.code = SUBSTITUTION_CODE;
+                               } else if (j == repair.distance && k > repair.misspellIndex) {
+                                       repair.misspellIndex = k;
+                                       repair.symbol = symbol;
+                                       repair.code = SUBSTITUTION_CODE;
+                               } else if (j == repair.distance && k > repair.misspellIndex && isBetterSymbol(symbol, repair.symbol)) {
+                                       repair.misspellIndex = k;
+                                       repair.symbol = symbol;
+                                       repair.code = SUBSTITUTION_CODE;
+                               }
+                               i = symbol;
+                               symbol = list[symbol];
+                               list[i] = 0;                             // reset element
+                       }
+               }
+
+
+               //
+               // Next, we try to insert a nonterminal candidate in front of the
+               // error token, or substituting a nonterminal candidate for the
+               // error token. Precedence is given to insertion.
+               //
+                for (i = Parser.nasi(stck[stack_top]); Parser.nasr[i] != 0; i++) {
+                        symbol = Parser.nasr[i] + NT_OFFSET;
+                        j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+1);
+                        if (j > repair.distance) {
+                                repair.misspellIndex = 0;
+                                repair.distance = j;
+                                repair.symbol = symbol;
+                                repair.code = INVALID_CODE;
+                        }
+
+                        j = parseCheck(stck, stack_top, symbol, repair.bufferPosition);
+                        if ((j > repair.distance) || (j == repair.distance && repair.code == INVALID_CODE)) {
+                                repair.misspellIndex = 0;
+                                repair.distance = j;
+                                repair.symbol = symbol;
+                                repair.code = INSERTION_CODE;
+                        }
+                }
+
+               return repair;
+       }
+
+
+//
+//        This procedure is invoked to issue a diagnostic message and
+//        adjust the input buffer.  The recovery in question is either
+//        the insertion of one or more scopes, the merging of the error
+//        token with its successor, the deletion of the error token,
+//        the insertion of a single token in front of the error token
+//        or the substitution of another token for the error token.
+//
+       private RepairCandidate primaryDiagnosis(PrimaryRepairInfo repair) {
+               int name_index;
+
+               //
+               //  Issue diagnostic.
+               //
+               int prevtok = buffer[repair.bufferPosition - 1];
+               int     curtok  = buffer[repair.bufferPosition];
+
+               switch(repair.code) {
+                       case INSERTION_CODE:
+                       case BEFORE_CODE: {
+                               if (repair.symbol > NT_OFFSET)
+                                        name_index = getNtermIndex(stack[stateStackTop],
+                                                                                               repair.symbol,
+                                                                                               repair.bufferPosition);
+                               else name_index = getTermIndex(stack,
+                                                                                          stateStackTop,
+                                                                                          repair.symbol,
+                                                                                          repair.bufferPosition);
+
+                               int t = (repair.code == INSERTION_CODE ? prevtok : curtok);
+                               reportError(repair.code, name_index, t, t);
+                               break;
+                       }
+                       case INVALID_CODE: {
+                               name_index = getNtermIndex(stack[stateStackTop],
+                                                                                  repair.symbol,
+                                                                                  repair.bufferPosition + 1);
+                               reportError(repair.code, name_index, curtok, curtok);
+                               break;
+                       }
+                       case SUBSTITUTION_CODE: {
+                               if (repair.misspellIndex >= 6)
+                                       name_index = Parser.terminal_index[repair.symbol];
+                               else
+                               {
+                                       name_index = getTermIndex(stack, stateStackTop,
+                                                                                         repair.symbol,
+                                                                                         repair.bufferPosition + 1);
+                                       if (name_index != Parser.terminal_index[repair.symbol])
+                                               repair.code = INVALID_CODE;
+                               }
+                               reportError(repair.code, name_index, curtok, curtok);
+                               break;
+                       }
+                       case MERGE_CODE: {
+                               reportError(repair.code,
+                                                        Parser.terminal_index[repair.symbol],
+                                                        curtok,
+                                                        lexStream.next(curtok));
+                               break;
+                       }
+                       case SCOPE_CODE: {
+                   for (int i = 0; i < scopeStackTop; i++) {
+                       reportError(repair.code,
+                                   -scopeIndex[i],
+                                   locationStack[scopePosition[i]],
+                                   prevtok,
+                                   Parser.non_terminal_index[Parser.scope_lhs[scopeIndex[i]]]);
+                   }
+       
+                   repair.symbol = Parser.scope_lhs[scopeIndex[scopeStackTop]] + NT_OFFSET;
+                   stateStackTop = scopePosition[scopeStackTop];
+                   reportError(repair.code,
+                               -scopeIndex[scopeStackTop],
+                               locationStack[scopePosition[scopeStackTop]],
+                               prevtok,
+                               getNtermIndex(stack[stateStackTop],
+                                             repair.symbol,
+                                             repair.bufferPosition)
+                              );
+                   break;
+               }
+                       default: {// deletion
+                               reportError(repair.code, Parser.terminal_index[ERROR_SYMBOL], curtok, curtok);
+                       }
+               }
+
+               //
+               //  Update buffer.
+               //
+               RepairCandidate candidate = new RepairCandidate();
+               switch (repair.code) {
+                       case INSERTION_CODE:
+                       case BEFORE_CODE:
+                       case SCOPE_CODE: {
+                               candidate.symbol = repair.symbol;
+                               candidate.location = buffer[repair.bufferPosition];
+                               lexStream.reset(buffer[repair.bufferPosition]);
+                               break;
+                       }
+                       case INVALID_CODE:
+                       case SUBSTITUTION_CODE: {
+                               candidate.symbol = repair.symbol;
+                               candidate.location = buffer[repair.bufferPosition];
+                               lexStream.reset(buffer[repair.bufferPosition + 1]);
+                               break;
+                       }
+                       case MERGE_CODE: {
+                               candidate.symbol = repair.symbol;
+                               candidate.location = buffer[repair.bufferPosition];
+                               lexStream.reset(buffer[repair.bufferPosition + 2]);
+                               break;
+                       }
+                       default: {// deletion
+                               candidate.location = buffer[repair.bufferPosition + 1];
+                               candidate.symbol =
+                                                 lexStream.kind(buffer[repair.bufferPosition + 1]);
+                               lexStream.reset(buffer[repair.bufferPosition + 2]);
+                               break;
+                       }
+               }
+
+               return candidate;
+       }
+
+
+//
+//        This function takes as parameter an integer STACK_TOP that
+//        points to a STACK element containing the state on which a
+//        primary recovery will be made; the terminal candidate on which
+//        to recover; and an integer: buffer_position, which points to
+//        the position of the next input token in the BUFFER.  The
+//        parser is simulated until a shift (or shift-reduce) action
+//        is computed on the candidate.  Then we proceed to compute the
+//        the name index of the highest level nonterminal that can
+//        directly or indirectly produce the candidate.
+//
+       private int getTermIndex(int stck[], int stack_top, int tok, int buffer_position) {
+               //
+               // Initialize stack index of temp_stack and initialize maximum
+               // position of state stack that is still useful.
+               //
+               int act = stck[stack_top],
+                       max_pos = stack_top,
+                       highest_symbol = tok;
+
+               tempStackTop = stack_top - 1;
+
+               //
+               // Compute all reduce and associated actions induced by the
+               // candidate until a SHIFT or SHIFT-REDUCE is computed. ERROR
+               // and ACCEPT actions cannot be computed on the candidate in
+               // this context, since we know that it is suitable for recovery.
+               //
+               lexStream.reset(buffer[buffer_position]);
+               act = Parser.tAction(act, tok);
+               while(act <= NUM_RULES) {
+                       //
+                       // Process all goto-reduce actions following reduction,
+                       // until a goto action is computed ...
+                       //
+                       do {
+                               tempStackTop -= (Parser.rhs[act]-1);
+                               int lhs_symbol = Parser.lhs[act];
+                               act = (tempStackTop > max_pos
+                                                                         ? tempStack[tempStackTop]
+                                                                         : stck[tempStackTop]);
+                               act = Parser.ntAction(act, lhs_symbol);
+                       } while(act <= NUM_RULES);
+
+                       //
+                       // Compute new maximum useful position of (STATE_)stack,
+                       // push goto state into the stack, and compute next
+                       // action on candidate ...
+                       //
+                       max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+                       tempStack[tempStackTop + 1] = act;
+                       act = Parser.tAction(act, tok);
+               }
+
+               //
+               // At this stage, we have simulated all actions induced by the
+               // candidate and we are ready to shift or shift-reduce it. First,
+               // set tok and next_ptr appropriately and identify the candidate
+               // as the initial highest_symbol. If a shift action was computed
+               // on the candidate, update the stack and compute the next
+               // action. Next, simulate all actions possible on the next input
+               // token until we either have to shift it or are about to reduce
+               // below the initial starting point in the stack (indicated by
+               // max_pos as computed in the previous loop).  At that point,
+               // return the highest_symbol computed.
+               //
+               tempStackTop++; // adjust top of stack to reflect last goto
+                                                 // next move is shift or shift-reduce.
+               int threshold = tempStackTop;
+
+               tok = lexStream.kind(buffer[buffer_position]);
+               lexStream.reset(buffer[buffer_position + 1]);
+
+               if (act > ERROR_ACTION) {  // shift-reduce on candidate?
+                       act -= ERROR_ACTION;
+               } else {
+                       tempStack[tempStackTop + 1] = act;
+                       act = Parser.tAction(act, tok);
+               }
+
+               while(act <= NUM_RULES) {
+                       //
+                       // Process all goto-reduce actions following reduction,
+                       // until a goto action is computed ...
+                       //
+                       do {
+                               tempStackTop -= (Parser.rhs[act]-1);
+
+                               if (tempStackTop < threshold) {
+                                       return (highest_symbol > NT_OFFSET
+                                                ? Parser.non_terminal_index[highest_symbol - NT_OFFSET]
+                                                : Parser.terminal_index[highest_symbol]);
+                               }
+
+                               int lhs_symbol = Parser.lhs[act];
+                               if (tempStackTop == threshold)
+                                       highest_symbol = lhs_symbol + NT_OFFSET;
+                               act = (tempStackTop > max_pos
+                                                                         ? tempStack[tempStackTop]
+                                                                         : stck[tempStackTop]);
+                               act = Parser.ntAction(act, lhs_symbol);
+                       } while(act <= NUM_RULES);
+
+                       tempStack[tempStackTop + 1] = act;
+                       act = Parser.tAction(act, tok);
+               }
+
+               return (highest_symbol > NT_OFFSET
+                                                        ? Parser.non_terminal_index[highest_symbol - NT_OFFSET]
+                                                        : Parser.terminal_index[highest_symbol]);
+       }
+
+//
+//        This function takes as parameter a starting state number:
+//        start, a nonterminal symbol, A (candidate), and an integer,
+//        buffer_position,  which points to the position of the next
+//        input token in the BUFFER.
+//        It returns the highest level non-terminal B such that
+//        B =>*rm A.  I.e., there does not exists a nonterminal C such
+//        that C =>+rm B. (Recall that for an LALR(k) grammar if
+//        C =>+rm B, it cannot be the case that B =>+rm C)
+//
+       private int getNtermIndex(int start, int sym, int buffer_position) {
+               int highest_symbol = sym - NT_OFFSET,
+                       tok = lexStream.kind(buffer[buffer_position]);
+               lexStream.reset(buffer[buffer_position + 1]);
+
+               //
+               // Initialize stack index of temp_stack and initialize maximum
+               // position of state stack that is still useful.
+               //
+               tempStackTop = 0;
+               tempStack[tempStackTop] = start;
+
+               int act = Parser.ntAction(start, highest_symbol);
+               if (act > NUM_RULES) { // goto action?
+                       tempStack[tempStackTop + 1] = act;
+                       act = Parser.tAction(act, tok);
+               }
+
+               while(act <= NUM_RULES) {
+                       //
+                       // Process all goto-reduce actions following reduction,
+                       // until a goto action is computed ...
+                       //
+                       do {
+                               tempStackTop -= (Parser.rhs[act]-1);
+                               if (tempStackTop < 0)
+                                       return Parser.non_terminal_index[highest_symbol];
+                               if (tempStackTop == 0)
+                                       highest_symbol = Parser.lhs[act];
+                               act = Parser.ntAction(tempStack[tempStackTop], Parser.lhs[act]);
+                       } while(act <= NUM_RULES);
+                       tempStack[tempStackTop + 1] = act;
+                       act = Parser.tAction(act, tok);
+               }
+
+               return Parser.non_terminal_index[highest_symbol];
+       }
+
+       private boolean isBetterSymbol(int symbol, int actualSymbol) {
+//             switch (actualSymbol) {
+//                     case TokenNameinterface :
+//                             if(symbol == TokenNameclass) {
+//                                     return true;
+//                             }
+//                             break;
+//             }
+               return false;
+       }
+
+//
+//                Check whether or not there is a high probability that a
+//        given string is a misspelling of another.
+//        Certain singleton symbols (such as ":" and ";") are also
+//        considered to be misspelling of each other.
+//
+       private int misspell(int sym, int tok) {
+               
+
+               //
+               //
+               //
+               char[] name = Parser.name[Parser.terminal_index[sym]].toCharArray();
+               int n = name.length;
+               char[] s1 = new char[n + 1];
+               for (int k = 0; k < n; k++) {
+                       char c = name[k];
+                       s1[k] = Character.toLowerCase(c);
+               }
+               s1[n] = '\0';
+
+               //
+               //
+               //
+               char[] tokenName = lexStream.name(tok);
+               int len = tokenName.length;
+               int m = len < MAX_NAME_LENGTH ? len : MAX_NAME_LENGTH;
+               char[] s2 = new char[m + 1];
+               for (int k = 0; k < m; k++) {
+                       char c = tokenName[k];
+                       s2[k] = Character.toLowerCase(c);
+               }
+               s2[m] = '\0';
+
+               //
+               //  Singleton mispellings:
+               //
+               //  ;      <---->     ,
+               //
+               //  ;      <---->     :
+               //
+               //  .      <---->     ,
+               //
+               //  '      <---->     "
+               //
+               //
+               if (n == 1  &&  m == 1) {
+                       if ((s1[0] == ';'  &&  s2[0] == ',')  ||
+                               (s1[0] == ','  &&  s2[0] == ';')  ||
+                               (s1[0] == ';'  &&  s2[0] == ':')  ||
+                               (s1[0] == ':'  &&  s2[0] == ';')  ||
+                               (s1[0] == '.'  &&  s2[0] == ',')  ||
+                               (s1[0] == ','  &&  s2[0] == '.')  ||
+                               (s1[0] == '\'' &&  s2[0] == '\"')  ||
+                               (s1[0] == '\"'  &&  s2[0] == '\'')) {
+                                       return 3;
+                       }
+               }
+
+               //
+               // Scan the two strings. Increment "match" count for each match.
+               // When a transposition is encountered, increase "match" count
+               // by two but count it as an error. When a typo is found, skip
+               // it and count it as an error. Otherwise we have a mismatch; if
+               // one of the strings is longer, increment its index, otherwise,
+               // increment both indices and continue.
+               //
+               // This algorithm is an adaptation of a boolean misspelling
+               // algorithm proposed by Juergen Uhl.
+               //
+               int count = 0;
+               int prefix_length = 0;
+               int num_errors = 0;
+
+               int i = 0;
+               int j = 0;
+               while ((i < n)  &&  (j < m)) {
+                       if (s1[i] == s2[j]) {
+                               count++;
+                               i++;
+                               j++;
+                               if (num_errors == 0) {
+                                       prefix_length++;
+                               }
+                       } else if (s1[i+1] == s2[j]  &&  s1[i] == s2[j+1]) {
+                               count += 2;
+                               i += 2;
+                               j += 2;
+                               num_errors++;
+                       } else if (s1[i+1] == s2[j+1]) {
+                               i++;
+                               j++;
+                               num_errors++;
+                       } else {
+                               if ((n - i) > (m - j)) {
+                                        i++;
+                               } else if ((m - j) > (n - i)) {
+                                        j++;
+                               } else {
+                                       i++;
+                                       j++;
+                               }
+                               num_errors++;
+                       }
+               }
+
+               if (i < n  ||  j < m)
+                       num_errors++;
+
+               if (num_errors > ((n < m ? n : m) / 6 + 1))
+                        count = prefix_length;
+
+               return(count * 10 / ((n < len ? len : n) + num_errors));
+       }
+       
+       private PrimaryRepairInfo scopeTrial(int stck[], int stack_top, PrimaryRepairInfo repair) {
+           stateSeen = new int[stackLength];
+           for (int i = 0; i < stackLength; i++)
+               stateSeen[i] = NIL;
+           
+           statePoolTop = 0;
+           statePool = new StateInfo[stackLength];
+       
+           scopeTrialCheck(stck, stack_top, repair, 0);
+       
+           stateSeen = null;
+           statePoolTop = 0;
+       
+           repair.code = SCOPE_CODE;
+           repair.misspellIndex = 10;
+       
+           return repair;
+       }
+       
+       private void scopeTrialCheck(int stck[], int stack_top, PrimaryRepairInfo repair, int indx) {
+               if(indx > 20) return; // avoid too much recursive call to improve performance
+               
+               int act = stck[stack_top];
+       
+           for (int i = stateSeen[stack_top]; i != NIL; i = statePool[i].next) {
+               if (statePool[i].state == act) return;
+           }
+
+           int old_state_pool_top = statePoolTop++;
+           if(statePoolTop >= statePool.length) {
+               System.arraycopy(statePool, 0, statePool = new StateInfo[statePoolTop * 2], 0, statePoolTop);
+           }
+           
+           statePool[old_state_pool_top] = new StateInfo(act, stateSeen[stack_top]);
+           stateSeen[stack_top] = old_state_pool_top;
+       
+           for (int i = 0; i < SCOPE_SIZE; i++) {
+               //
+               // Use the scope lookahead symbol to force all reductions
+               // inducible by that symbol.
+               //
+               act = stck[stack_top];
+               tempStackTop = stack_top - 1;
+               int max_pos = stack_top;
+               int tok = Parser.scope_la[i];
+               lexStream.reset(buffer[repair.bufferPosition]);
+               act = Parser.tAction(act, tok);
+               while(act <= NUM_RULES) {
+                   //
+                   // ... Process all goto-reduce actions following
+                   // reduction, until a goto action is computed ...
+                   //
+                   do  {
+                       tempStackTop -= (Parser.rhs[act]-1);
+                       int lhs_symbol = Parser.lhs[act];
+                       act =  (tempStackTop > max_pos
+                                   ?  tempStack[tempStackTop]
+                                   :  stck[tempStackTop]);
+                       act = Parser.ntAction(act, lhs_symbol);
+                   }  while(act <= NUM_RULES);
+                   if (tempStackTop + 1 >= stackLength)
+                       return;
+                   max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+                   tempStack[tempStackTop + 1] = act;
+                   act = Parser.tAction(act, tok);
+               }
+       
+               //
+               // If the lookahead symbol is parsable, then we check
+               // whether or not we have a match between the scope
+               // prefix and the transition symbols corresponding to
+               // the states on top of the stack.
+               //
+               if (act != ERROR_ACTION) {
+                       int j, k;
+                   k = Parser.scope_prefix[i];
+                   for (j = tempStackTop + 1;
+                        j >= (max_pos + 1) &&
+                        Parser.in_symbol(tempStack[j]) == Parser.scope_rhs[k]; j--) {
+                        k++;
+                   }
+                   if (j == max_pos) {
+                       for (j = max_pos;
+                            j >= 1 && Parser.in_symbol(stck[j]) == Parser.scope_rhs[k];
+                            j--) {
+                           k++;
+                       }
+                   }
+                   //
+                   // If the prefix matches, check whether the state
+                   // newly exposed on top of the stack, (after the
+                   // corresponding prefix states are popped from the
+                   // stack), is in the set of "source states" for the
+                   // scope in question and that it is at a position
+                   // below the threshold indicated by MARKED_POS.
+                   //
+                   int marked_pos = (max_pos < stack_top ? max_pos + 1 : stack_top);
+                   if (Parser.scope_rhs[k] == 0 && j < marked_pos) { // match?
+                       int stack_position = j;
+                       for (j = Parser.scope_state_set[i];
+                            stck[stack_position] != Parser.scope_state[j] &&
+                            Parser.scope_state[j] != 0;
+                            j++){/*empty*/}
+                       //
+                       // If the top state is valid for scope recovery,
+                       // the left-hand side of the scope is used as
+                       // starting symbol and we calculate how far the
+                       // parser can advance within the forward context
+                       // after parsing the left-hand symbol.
+                       //
+                       if (Parser.scope_state[j] != 0) {     // state was found
+                           int previous_distance = repair.distance;
+                           int distance = parseCheck(stck,
+                                                 stack_position,
+                                                 Parser.scope_lhs[i]+NT_OFFSET,
+                                                 repair.bufferPosition);
+                           //
+                           // if the recovery is not successful, we
+                           // update the stack with all actions induced
+                           // by the left-hand symbol, and recursively
+                           // call SCOPE_TRIAL_CHECK to try again.
+                           // Otherwise, the recovery is successful. If
+                           // the new distance is greater than the
+                           // initial SCOPE_DISTANCE, we update
+                           // SCOPE_DISTANCE and set scope_stack_top to INDX
+                           // to indicate the number of scopes that are
+                           // to be applied for a succesful  recovery.
+                           // NOTE that this procedure cannot get into
+                           // an infinite loop, since each prefix match
+                           // is guaranteed to take us to a lower point
+                           // within the stack.
+                           //
+                           if ((distance - repair.bufferPosition + 1) < MIN_DISTANCE) {
+                               int top = stack_position;
+                               act = Parser.ntAction(stck[top], Parser.scope_lhs[i]);
+                               while(act <= NUM_RULES) {
+                                   top -= (Parser.rhs[act]-1);
+                                   act = Parser.ntAction(stck[top], Parser.lhs[act]);
+                               }
+                               top++;
+       
+                               j = act;
+                               act = stck[top];  // save
+                               stck[top] = j;    // swap
+                               scopeTrialCheck(stck, top, repair, indx+1);
+                               stck[top] = act; // restore
+                           } else if (distance > repair.distance) {
+                               scopeStackTop = indx;
+                               repair.distance = distance;
+                           }
+       
+                           if (lexStream.kind(buffer[repair.bufferPosition]) == EOFT_SYMBOL &&
+                               repair.distance == previous_distance) {
+                               scopeStackTop = indx;
+                               repair.distance = MAX_DISTANCE;
+                           }
+       
+                           //
+                           // If this scope recovery has beaten the
+                           // previous distance, then we have found a
+                           // better recovery (or this recovery is one
+                           // of a list of scope recoveries). Record
+                           // its information at the proper location
+                           // (INDX) in SCOPE_INDEX and SCOPE_STACK.
+                           //
+                           if (repair.distance > previous_distance) {
+                               scopeIndex[indx] = i;
+                               scopePosition[indx] = stack_position;
+                               return;
+                           }
+                       }
+                   }
+               }
+           }
+       }
+//
+//        This function computes the ParseCheck distance for the best
+//        possible secondary recovery for a given configuration that
+//        either deletes none or only one symbol in the forward context.
+//        If the recovery found is more effective than the best primary
+//        recovery previously computed, then the function returns true.
+//        Only misplacement, scope and manual recoveries are attempted;
+//        simple insertion or substitution of a nonterminal are tried
+//        in CHECK_PRIMARY_DISTANCE as part of primary recovery.
+//
+       private boolean secondaryCheck(int stck[], int stack_top, int buffer_position, int distance) {
+               int top, j;
+
+               for (top = stack_top - 1; top >= 0; top--) {
+                       j = parseCheck(stck, top,
+                                                  lexStream.kind(buffer[buffer_position]),
+                                                  buffer_position + 1);
+                       if (((j - buffer_position + 1) > MIN_DISTANCE) && (j > distance))
+                               return true;
+               }
+               
+               PrimaryRepairInfo repair = new PrimaryRepairInfo();
+           repair.bufferPosition = buffer_position + 1;
+           repair.distance = distance;
+           repair = scopeTrial(stck, stack_top, repair);
+           if ((repair.distance - buffer_position) > MIN_DISTANCE && repair.distance > distance)
+                return true;
+               return false;
+       }
+
+
+//
+//        Secondary_phase is a boolean function that checks whether or
+//        not some form of secondary recovery is applicable to one of
+//        the error configurations. First, if "next_stack" is available,
+//        misplacement and secondary recoveries are attempted on it.
+//        Then, in any case, these recoveries are attempted on "stack".
+//        If a successful recovery is found, a diagnosis is issued, the
+//        configuration is updated and the function returns "true".
+//        Otherwise, the function returns false.
+//
+       private RepairCandidate secondaryPhase(int error_token) {
+               SecondaryRepairInfo repair = new SecondaryRepairInfo();
+               SecondaryRepairInfo misplaced = new SecondaryRepairInfo();
+
+               RepairCandidate candidate = new RepairCandidate();
+
+               int i, j, k, top;
+               int     next_last_index = 0;
+               int     last_index;
+
+               candidate.symbol = 0;
+
+               repair.code = 0;
+               repair.distance = 0;
+               repair.recoveryOnNextStack = false;
+
+               misplaced.distance = 0;
+               misplaced.recoveryOnNextStack = false;
+
+               //
+               // If the next_stack is available, try misplaced and secondary
+               // recovery on it first.
+               //
+               if (nextStackTop >= 0) {
+                       int  save_location;
+
+                       buffer[2] = error_token;
+                       buffer[1] = lexStream.previous(buffer[2]);
+                       buffer[0] = lexStream.previous(buffer[1]);
+
+                       for (k = 3; k < BUFF_UBOUND; k++)
+                               buffer[k] = lexStream.next(buffer[k - 1]);
+
+                       buffer[BUFF_UBOUND] = lexStream.badtoken();// elmt not available
+
+                       //
+                       // If we are at the end of the input stream, compute the
+                       // index position of the first EOFT symbol (last useful
+                       // index).
+                       //
+                       for (next_last_index = MAX_DISTANCE - 1;
+                                next_last_index >= 1 &&
+                                lexStream.kind(buffer[next_last_index]) == EOFT_SYMBOL;
+                                next_last_index--){/*empty*/}
+                       next_last_index = next_last_index + 1;
+
+                       save_location = locationStack[nextStackTop];
+                       int save_location_start = locationStartStack[nextStackTop];
+                       locationStack[nextStackTop] = buffer[2];
+                       locationStartStack[nextStackTop] = lexStream.start(buffer[2]);
+                       misplaced.numDeletions = nextStackTop;
+                       misplaced = misplacementRecovery(nextStack, nextStackTop,
+                                                                                        next_last_index,
+                                                                                        misplaced, true);
+                       if (misplaced.recoveryOnNextStack)
+                               misplaced.distance++;
+
+                       repair.numDeletions = nextStackTop + BUFF_UBOUND;
+                       repair = secondaryRecovery(nextStack, nextStackTop,
+                                                                          next_last_index,
+                                                                          repair, true);
+                       if (repair.recoveryOnNextStack)
+                               repair.distance++;
+
+                       locationStack[nextStackTop] = save_location;
+                       locationStartStack[nextStackTop] = save_location_start;
+               } else {            // next_stack not available, initialize ...
+                       misplaced.numDeletions = stateStackTop;
+                       repair.numDeletions = stateStackTop + BUFF_UBOUND;
+               }
+
+               //
+               // Try secondary recovery on the "stack" configuration.
+               //
+               buffer[3] = error_token;
+
+               buffer[2] = lexStream.previous(buffer[3]);
+               buffer[1] = lexStream.previous(buffer[2]);
+               buffer[0] = lexStream.previous(buffer[1]);
+
+               for (k = 4; k < BUFF_SIZE; k++)
+                       buffer[k] = lexStream.next(buffer[k - 1]);
+
+               for (last_index = MAX_DISTANCE - 1;
+                        last_index >= 1 && lexStream.kind(buffer[last_index]) == EOFT_SYMBOL;
+                        last_index--){/*empty*/}
+               last_index++;
+
+               misplaced = misplacementRecovery(stack, stateStackTop,
+                                                                                last_index,
+                                                                                misplaced, false);
+
+               repair = secondaryRecovery(stack, stateStackTop,
+                                                                  last_index, repair, false);
+
+               //
+               // If a successful misplaced recovery was found, compare it with
+               // the most successful secondary recovery.  If the misplaced
+               // recovery either deletes fewer symbols or parse-checks further
+               // then it is chosen.
+               //
+               if (misplaced.distance > MIN_DISTANCE) {
+                       if (misplaced.numDeletions <= repair.numDeletions ||
+                          (misplaced.distance - misplaced.numDeletions) >=
+                          (repair.distance - repair.numDeletions)) {
+                               repair.code = MISPLACED_CODE;
+                               repair.stackPosition = misplaced.stackPosition;
+                               repair.bufferPosition = 2;
+                               repair.numDeletions = misplaced.numDeletions;
+                               repair.distance = misplaced.distance;
+                               repair.recoveryOnNextStack = misplaced.recoveryOnNextStack;
+                       }
+               }
+
+               //
+               // If the successful recovery was on next_stack, update: stack,
+               // buffer, location_stack and last_index.
+               //
+               if (repair.recoveryOnNextStack) {
+                       stateStackTop = nextStackTop;
+                       for (i = 0; i <= stateStackTop; i++)
+                               stack[i] = nextStack[i];
+
+                       buffer[2] = error_token;
+                       buffer[1] = lexStream.previous(buffer[2]);
+                       buffer[0] = lexStream.previous(buffer[1]);
+
+                       for (k = 3; k < BUFF_UBOUND; k++)
+                               buffer[k] = lexStream.next(buffer[k - 1]);
+
+                       buffer[BUFF_UBOUND] = lexStream.badtoken();// elmt not available
+
+                       locationStack[nextStackTop] = buffer[2];
+                       locationStartStack[nextStackTop] = lexStream.start(buffer[2]);
+                       last_index = next_last_index;
+               }
+
+           //
+           // Next, try scope recoveries after deletion of one, two, three,
+           // four ... buffer_position tokens from the input stream.
+           //
+           if (repair.code == SECONDARY_CODE || repair.code == DELETION_CODE) {
+               PrimaryRepairInfo scope_repair = new PrimaryRepairInfo();
+       
+               scope_repair.distance = 0;
+               for (scope_repair.bufferPosition = 2;
+                    scope_repair.bufferPosition <= repair.bufferPosition &&
+                    repair.code != SCOPE_CODE; scope_repair.bufferPosition++) {
+                   scope_repair = scopeTrial(stack, stateStackTop, scope_repair);
+                   j = (scope_repair.distance == MAX_DISTANCE
+                                               ? last_index
+                                               : scope_repair.distance);
+                   k = scope_repair.bufferPosition - 1;
+                   if ((j - k) > MIN_DISTANCE && (j - k) > (repair.distance - repair.numDeletions)) {
+                       repair.code = SCOPE_CODE;
+                       i = scopeIndex[scopeStackTop];       // upper bound
+                       repair.symbol = Parser.scope_lhs[i] + NT_OFFSET;
+                       repair.stackPosition = stateStackTop;
+                       repair.bufferPosition = scope_repair.bufferPosition;
+                   }
+               }
+           }
+       
+           //
+           // If no successful recovery is found and we have reached the
+           // end of the file, check whether or not scope recovery is
+           // applicable at the end of the file after discarding some
+           // states.
+           //
+           if (repair.code == 0 && lexStream.kind(buffer[last_index]) == EOFT_SYMBOL) {
+               PrimaryRepairInfo scope_repair = new PrimaryRepairInfo();
+       
+               scope_repair.bufferPosition = last_index;
+               scope_repair.distance = 0;
+               for (top = stateStackTop;
+                    top >= 0 && repair.code == 0; top--)
+               {
+                   scope_repair = scopeTrial(stack, top, scope_repair);
+                   if (scope_repair.distance > 0)
+                   {
+                       repair.code = SCOPE_CODE;
+                       i = scopeIndex[scopeStackTop];    // upper bound
+                       repair.symbol = Parser.scope_lhs[i] + NT_OFFSET;
+                       repair.stackPosition = top;
+                       repair.bufferPosition = scope_repair.bufferPosition;
+                   }
+               }
+           }
+
+               //
+               // If a successful repair was not found, quit!  Otherwise, issue
+               // diagnosis and adjust configuration...
+               //
+               if (repair.code == 0)
+                       return candidate;
+
+               secondaryDiagnosis(repair);
+
+               //
+               // Update buffer based on number of elements that are deleted.
+               //
+               switch(repair.code) {
+                       case MISPLACED_CODE:
+                                candidate.location = buffer[2];
+                                candidate.symbol = lexStream.kind(buffer[2]);
+                                lexStream.reset(lexStream.next(buffer[2]));
+
+                                break;
+
+                       case DELETION_CODE:
+                                candidate.location = buffer[repair.bufferPosition];
+                                candidate.symbol =
+                                                  lexStream.kind(buffer[repair.bufferPosition]);
+                                lexStream.reset(lexStream.next(buffer[repair.bufferPosition]));
+
+                                break;
+
+               default: // SCOPE_CODE || SECONDARY_CODE
+                                candidate.symbol = repair.symbol;
+                                candidate.location = buffer[repair.bufferPosition];
+                                lexStream.reset(buffer[repair.bufferPosition]);
+
+                                break;
+               }
+
+               return candidate;
+       }
+
+
+//
+//        This boolean function checks whether or not a given
+//        configuration yields a better misplacement recovery than
+//        the best misplacement recovery computed previously.
+//
+       private SecondaryRepairInfo misplacementRecovery(int stck[], int stack_top, int last_index, SecondaryRepairInfo repair, boolean stack_flag) {
+               int  previous_loc = buffer[2];
+               int stack_deletions = 0;
+
+               for (int top = stack_top - 1; top >= 0; top--) {
+                       if (locationStack[top] < previous_loc) {
+                               stack_deletions++;
+                       }
+                       previous_loc = locationStack[top];
+
+                       int j = parseCheck(stck, top, lexStream.kind(buffer[2]), 3);
+                       if (j == MAX_DISTANCE) {
+                                j = last_index;
+                       }
+                       if ((j > MIN_DISTANCE) && (j - stack_deletions) > (repair.distance - repair.numDeletions)) {
+                               repair.stackPosition = top;
+                               repair.distance = j;
+                               repair.numDeletions = stack_deletions;
+                               repair.recoveryOnNextStack = stack_flag;
+                       }
+               }
+
+               return repair;
+       }
+
+
+//
+//        This boolean function checks whether or not a given
+//        configuration yields a better secondary recovery than the
+//        best misplacement recovery computed previously.
+//
+       private SecondaryRepairInfo secondaryRecovery(int stck[],int stack_top, int last_index, SecondaryRepairInfo repair, boolean stack_flag) {
+               int previous_loc;
+               int stack_deletions = 0;
+               
+               previous_loc = buffer[2];
+               for (int top = stack_top; top >= 0 && repair.numDeletions >= stack_deletions; top--) {
+                       if (locationStack[top] < previous_loc) {
+                               stack_deletions++;
+                       }
+                       previous_loc = locationStack[top];
+
+                       for (int i = 2;
+                                i <= (last_index - MIN_DISTANCE + 1) &&
+                                (repair.numDeletions >= (stack_deletions + i - 1)); i++) {
+                               int j = parseCheck(stck, top, lexStream.kind(buffer[i]), i + 1);
+
+                               if (j == MAX_DISTANCE) {
+                                        j = last_index;
+                               }
+                               if ((j - i + 1) > MIN_DISTANCE) {
+                                       int k = stack_deletions + i - 1;
+                                       if ((k < repair.numDeletions) ||
+                                               (j - k) > (repair.distance - repair.numDeletions) ||
+                                               ((repair.code == SECONDARY_CODE) && (j - k) == (repair.distance - repair.numDeletions))) {
+                                               repair.code = DELETION_CODE;
+                                               repair.distance = j;
+                                               repair.stackPosition = top;
+                                               repair.bufferPosition = i;
+                                               repair.numDeletions = k;
+                                               repair.recoveryOnNextStack = stack_flag;
+                                       }
+                               }
+
+                               for (int l = Parser.nasi(stck[top]); l >= 0 && Parser.nasr[l] != 0; l++) {
+                                       int symbol = Parser.nasr[l] + NT_OFFSET;
+                                       j = parseCheck(stck, top, symbol, i);
+                                       if (j == MAX_DISTANCE) {
+                                                j = last_index;
+                                       }
+                                       if ((j - i + 1) > MIN_DISTANCE) {
+                                               int k = stack_deletions + i - 1;
+                                               if (k < repair.numDeletions || (j - k) > (repair.distance - repair.numDeletions)) {
+                                                       repair.code = SECONDARY_CODE;
+                                                       repair.symbol = symbol;
+                                                       repair.distance = j;
+                                                       repair.stackPosition = top;
+                                                       repair.bufferPosition = i;
+                                                       repair.numDeletions = k;
+                                                       repair.recoveryOnNextStack = stack_flag;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return repair;
+       }
+
+
+//
+//        This procedure is invoked to issue a secondary diagnosis and
+//        adjust the input buffer.  The recovery in question is either
+//        an automatic scope recovery, a manual scope recovery, a
+//        secondary substitution or a secondary deletion.
+//
+       private void secondaryDiagnosis(SecondaryRepairInfo repair) {
+               switch(repair.code) {
+                       case SCOPE_CODE: {
+                   if (repair.stackPosition < stateStackTop) {
+                       reportError(DELETION_CODE,
+                                   Parser.terminal_index[ERROR_SYMBOL],
+                                   locationStack[repair.stackPosition],
+                                   buffer[1]);
+                   }
+                   for (int i = 0; i < scopeStackTop; i++) {
+                       reportError(SCOPE_CODE,
+                                   -scopeIndex[i],
+                                   locationStack[scopePosition[i]],
+                                   buffer[1],
+                                   Parser.non_terminal_index[Parser.scope_lhs[scopeIndex[i]]]);
+                   }
+       
+                   repair.symbol = Parser.scope_lhs[scopeIndex[scopeStackTop]] + NT_OFFSET;
+                   stateStackTop = scopePosition[scopeStackTop];
+                   reportError(SCOPE_CODE,
+                               -scopeIndex[scopeStackTop],
+                               locationStack[scopePosition[scopeStackTop]],
+                               buffer[1],
+                               getNtermIndex(stack[stateStackTop],
+                                             repair.symbol,
+                                             repair.bufferPosition)
+                              );
+                   break;
+               }
+                       default: {
+                               reportError(repair.code,
+                                                       (repair.code == SECONDARY_CODE
+                                                                                 ? getNtermIndex(stack[repair.stackPosition],
+                                                                                                                 repair.symbol,
+                                                                                                                 repair.bufferPosition)
+                                                                                 : Parser.terminal_index[ERROR_SYMBOL]),
+                                                       locationStack[repair.stackPosition],
+                                                       buffer[repair.bufferPosition - 1]);
+                               stateStackTop = repair.stackPosition;
+                       }
+               }
+       }
+
+
+
+
+//
+//        Try to parse until first_token and all tokens in BUFFER have
+//        been consumed, or an error is encountered. Return the number
+//        of tokens that were expended before the parse blocked.
+//
+       private int parseCheck(int stck[], int stack_top, int first_token, int buffer_position) {
+               int max_pos;
+               int indx;
+               int ct;
+               int act;
+
+               //
+               // Initialize pointer for temp_stack and initialize maximum
+               // position of state stack that is still useful.
+               //
+               act = stck[stack_top];
+               if (first_token > NT_OFFSET) {
+                       tempStackTop = stack_top;
+                       max_pos = stack_top;
+                       indx = buffer_position;
+                       ct = lexStream.kind(buffer[indx]);
+                       lexStream.reset(lexStream.next(buffer[indx]));
+                       int lhs_symbol = first_token - NT_OFFSET;
+                       act = Parser.ntAction(act, lhs_symbol);
+                       if (act <= NUM_RULES) {
+                               do {
+                                       tempStackTop -= (Parser.rhs[act]-1);
+                                       lhs_symbol = Parser.lhs[act];
+                                       act = (tempStackTop > max_pos
+                                                                                 ? tempStack[tempStackTop]
+                                                                                 : stck[tempStackTop]);
+                                       act = Parser.ntAction(act, lhs_symbol);
+                               } while(act <= NUM_RULES);
+       
+                               max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+                       }
+               } else {
+                       tempStackTop = stack_top - 1;
+                       max_pos = tempStackTop;
+                       indx = buffer_position - 1;
+                       ct = first_token;
+                       lexStream.reset(buffer[buffer_position]);
+               }
+
+               process_terminal: for (;;) {
+                       if (++tempStackTop >= stackLength)  // Stack overflow!!!
+                               return indx;
+                       tempStack[tempStackTop] = act;
+
+                       act = Parser.tAction(act, ct);
+
+                       if (act <= NUM_RULES) {               // reduce action
+                               tempStackTop--;
+                       } else if (act < ACCEPT_ACTION ||     // shift action
+                                        act > ERROR_ACTION) {        // shift-reduce action
+                               if (indx == MAX_DISTANCE)
+                                       return indx;
+                               indx++;
+                               ct = lexStream.kind(buffer[indx]);
+                               lexStream.reset(lexStream.next(buffer[indx]));
+                               if (act > ERROR_ACTION) {
+                                        act -= ERROR_ACTION;
+                               } else {
+                                       continue process_terminal;
+                               }
+                       } else if (act == ACCEPT_ACTION) {           // accept action
+                                return MAX_DISTANCE;
+                       } else {
+                               return indx;                         // error action
+                       }
+
+                       process_non_terminal:
+                       do {
+                               tempStackTop -= (Parser.rhs[act]-1);
+                               int lhs_symbol = Parser.lhs[act];
+                               act = (tempStackTop > max_pos
+                                                                         ? tempStack[tempStackTop]
+                                                                         : stck[tempStackTop]);
+                               act = Parser.ntAction(act, lhs_symbol);
+                       } while(act <= NUM_RULES);
+
+                       max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+               } // process_terminal;
+       }
+       private void reportError(int msgCode, int nameIndex, int leftToken, int rightToken) {
+               reportError(msgCode, nameIndex, leftToken, rightToken, 0);
+       }
+
+       private void reportError(int msgCode, int nameIndex, int leftToken, int rightToken, int scopeNameIndex) {
+               int lToken = (leftToken > rightToken ? rightToken : leftToken);
+
+               if (lToken < rightToken) {
+                       reportSecondaryError(msgCode, nameIndex, lToken, rightToken, scopeNameIndex);
+               } else {
+                       reportPrimaryError(msgCode, nameIndex, rightToken, scopeNameIndex);
+               }
+       }
+       private void reportPrimaryError(int msgCode, int nameIndex, int token, int scopeNameIndex) {
+               String name;
+               if (nameIndex >= 0) {
+                       name = Parser.readableName[nameIndex];
+               } else {
+                       name = EMPTY_STRING;
+               }
+
+               int errorStart = lexStream.start(token);
+               int errorEnd = lexStream.end(token);
+               int currentKind = lexStream.kind(token);
+               String errorTokenName = Parser.name[Parser.terminal_index[lexStream.kind(token)]];
+               char[] errorTokenSource = lexStream.name(token);
+
+               switch(msgCode) {
+                       case BEFORE_CODE:
+                               problemReporter().parseErrorInsertBeforeToken(
+                                       errorStart, 
+                                       errorEnd, 
+                                       currentKind,
+                                       errorTokenSource, 
+                                       errorTokenName, 
+                                       name);
+                                break;
+                       case INSERTION_CODE:
+                               problemReporter().parseErrorInsertAfterToken(
+                                       errorStart, 
+                                       errorEnd, 
+                                       currentKind,
+                                       errorTokenSource, 
+                                       errorTokenName, 
+                                       name);  
+                                break;
+                       case DELETION_CODE:
+                               problemReporter().parseErrorDeleteToken(
+                                       errorStart, 
+                                       errorEnd, 
+                                       currentKind,
+                                       errorTokenSource, 
+                                       errorTokenName);
+                               break;
+                       case INVALID_CODE:
+                               if (name.length() == 0) {
+                                       problemReporter().parseErrorReplaceToken(
+                                               errorStart, 
+                                               errorEnd, 
+                                               currentKind,
+                                               errorTokenSource, 
+                                               errorTokenName, 
+                                               name);
+                               } else {
+                                       problemReporter().parseErrorInvalidToken(
+                                               errorStart, 
+                                               errorEnd, 
+                                               currentKind,
+                                               errorTokenSource, 
+                                               errorTokenName, 
+                                               name);
+                               }
+                               break;
+                       case SUBSTITUTION_CODE:
+                               problemReporter().parseErrorReplaceToken(
+                                       errorStart, 
+                                       errorEnd, 
+                                       currentKind,
+                                       errorTokenSource, 
+                                       errorTokenName, 
+                                       name); 
+                                break;
+                       case SCOPE_CODE:
+                               StringBuffer buf = new StringBuffer();
+                               for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) {
+                                       buf.append(Parser.readableName[Parser.scope_rhs[i]]);
+                                       if (Parser.scope_rhs[i + 1] != 0) // any more symbols to print?
+                                               buf.append(' ');
+                                               
+                               }
+
+                               if (scopeNameIndex != 0) {
+                                       problemReporter().parseErrorInsertToComplete(
+                                               errorStart, 
+                                               errorEnd,
+                                               buf.toString(),
+                                               Parser.readableName[scopeNameIndex]);
+                               } else {
+                                       problemReporter().parseErrorInsertToCompleteScope(
+                                               errorStart, 
+                                               errorEnd,
+                                               buf.toString()); 
+                               }
+                               
+                               break;
+                       case EOF_CODE:
+                               problemReporter().parseErrorUnexpectedEnd(
+                                       errorStart, 
+                                       errorEnd); 
+                               break;
+                       case MERGE_CODE:
+                               problemReporter().parseErrorMergeTokens(
+                                       errorStart, 
+                                       errorEnd,
+                                       name);
+                               break;
+                       case MISPLACED_CODE:
+                               problemReporter().parseErrorMisplacedConstruct(
+                                       errorStart, 
+                                       errorEnd);
+                               break;
+                       default:
+                               if (name.length() == 0) {
+                                       problemReporter().parseErrorNoSuggestion(
+                                               errorStart, 
+                                               errorEnd, 
+                                               currentKind,
+                                               errorTokenSource, 
+                                               errorTokenName);
+                               } else {
+                                       problemReporter().parseErrorReplaceToken(
+                                               errorStart, 
+                                               errorEnd, 
+                                               currentKind,
+                                               errorTokenSource, 
+                                               errorTokenName, 
+                                               name); 
+                               }
+                               break;
+               }
+       }
+
+       private void reportSecondaryError(int msgCode,  int nameIndex,  int leftToken,  int rightToken, int scopeNameIndex) {
+               String name;
+               if (nameIndex >= 0) {
+                       name = Parser.readableName[nameIndex];
+               } else {
+                       name = EMPTY_STRING;    
+               }
+
+               int errorStart = -1;
+               if(lexStream.isInsideStream(leftToken)) {
+                       if(leftToken == 0) {
+                               errorStart = lexStream.start(leftToken + 1);
+                       } else {
+                               errorStart = lexStream.start(leftToken);
+                       }
+               } else {
+                       if(leftToken == errorToken) {
+                               errorStart = errorTokenStart;
+                       } else {
+                               for (int i = 0; i <= stateStackTop; i++) {
+                                       if(locationStack[i] == leftToken) {
+                                               errorStart = locationStartStack[i];
+                                       }
+                               }
+                       }
+                       if(errorStart == -1) {
+                               errorStart = lexStream.start(rightToken);
+                       }
+               }
+               int errorEnd = lexStream.end(rightToken);
+               
+               switch(msgCode) {
+                       case MISPLACED_CODE:
+                               problemReporter().parseErrorMisplacedConstruct(
+                                       errorStart, 
+                                       errorEnd); 
+                               break;
+                       case SCOPE_CODE:
+                               // error start is on the last token start
+                               errorStart = lexStream.start(rightToken);
+                       
+                   StringBuffer buf = new StringBuffer();
+                   for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) {
+                       buf.append(Parser.readableName[Parser.scope_rhs[i]]);
+                       if (Parser.scope_rhs[i+1] != 0)
+                            buf.append(' ');
+                   }
+                   if (scopeNameIndex != 0) {
+                       problemReporter().parseErrorInsertToComplete(
+                                               errorStart, 
+                                               errorEnd,
+                                               buf.toString(),
+                                               Parser.readableName[scopeNameIndex]);
+                   } else {
+                       problemReporter().parseErrorInsertToCompletePhrase(
+                                               errorStart, 
+                                               errorEnd,
+                                               buf.toString()); 
+                   }
+                   break;
+                       case MERGE_CODE:
+                               problemReporter().parseErrorMergeTokens(
+                                       errorStart, 
+                                       errorEnd,
+                                       name);
+                               break;
+                       case DELETION_CODE:
+                               problemReporter().parseErrorDeleteTokens(
+                                       errorStart, 
+                                       errorEnd);
+                               break;
+                       default:
+                               if (name.length() == 0) {
+                                       problemReporter().parseErrorNoSuggestionForTokens(
+                                               errorStart, 
+                                               errorEnd);
+                               } else {
+                                       problemReporter().parseErrorReplaceTokens(
+                                               errorStart, 
+                                               errorEnd,
+                                               name);
+                               }
+               }
+               return;
+       }
+
+       public String toString() {
+               StringBuffer res = new StringBuffer();
+               
+               res.append(lexStream.toString());
+               
+               return res.toString();
+       }
+}