// // Parse input allowing up to max_error_count Error token recoveries. // When max_error_count is 0, no Error token recoveries occur. // When max_error is > 0, it limits the number of Error token recoveries. // When max_error is < 0, the number of error token recoveries is unlimited. // Also, such recoveries only require one token to be parsed beyond the // recovery point. // (normally two tokens beyond the recovery point must be parsed) // Thus, a negative max_error_count should be used when error productions // are used to // skip tokens. // public Object parse(int max_error_count) throws BadParseException { state = new ParserState(START_STATE, tokStream); skipTokens = max_error_count < 0; state.pendingCommits = new LinkedList(); backtrackRequested = false; state.trialActionCount = 0; // Next "start" token state.repair_token = 0; int start_token_index = tokStream.peek(); int start_action_index = 0; // Last commit point int[] temp_stack = new int[1]; temp_stack[0] = START_STATE; state.reallocateOtherStacks(start_token_index); int initial_error_token = backtrackParse(state.repair_token); for (int error_token = initial_error_token, count = 0; error_token != 0; error_token = backtrackParse(state.repair_token), count++) { if (count == max_error_count) throw new BadParseException(initial_error_token); state.actionCount = start_action_index; tokStream.reset(start_token_index); state.stateStackTop = temp_stack.length - 1; System.arraycopy(temp_stack, 0, state.stateStack, 0, temp_stack.length); state.reallocateOtherStacks(start_token_index); backtrackParseUpToError(state.repair_token, error_token); for (state.stateStackTop = findRecoveryStateIndex(state.stateStackTop); state.stateStackTop >= 0; state.stateStackTop = findRecoveryStateIndex(state.stateStackTop - 1)) { int recovery_token = state.tokens.get(state.locationStack[state.stateStackTop] - 1); state.repair_token = errorRepair( (recovery_token >= start_token_index ? recovery_token : error_token), error_token); if (state.repair_token != 0) break; } if (state.stateStackTop < 0) throw new BadParseException(initial_error_token); temp_stack = new int[state.stateStackTop + 1]; System.arraycopy(state.stateStack, 0, temp_stack, 0, temp_stack.length); start_action_index = state.actionCount; start_token_index = tokStream.peek(); } if (state.repair_token != 0) state.tokens.add(state.repair_token); int t; for (t = start_token_index; tokStream.getKind(t) != EOFT_SYMBOL; t = tokStream.getNext(t)) state.tokens.add(t); state.tokens.add(t); return null; }
// // Process reductions and continue... // private int process_repair_reductions(int act) { do { System.out.println("process_repair_reductions: " + act); state.stateStackTop -= (prs.rhs(act) - 1); act = prs.ntAction(state.stateStack[state.stateStackTop], prs.lhs(act)); } while (act <= NUM_RULES); return act; }
// // Process reductions and continue... // private int process_backtrack_reductions(int act) { do { state.stateStackTop -= (prs.rhs(act) - 1); trialAction(act); if (backtrackRequested) { backtrackRequested = false; return ERROR_ACTION; } act = prs.ntAction(state.stateStack[state.stateStackTop], prs.lhs(act)); } while (act <= NUM_RULES); return act; }
private int errorRepair(int recovery_token, int error_token) { int temp_stack[] = new int[state.stateStackTop + 1]; System.arraycopy(state.stateStack, 0, temp_stack, 0, temp_stack.length); for (; tokStream.getKind(recovery_token) != EOFT_SYMBOL; recovery_token = tokStream.getNext(recovery_token)) { System.out.println("recovery token: " + tokStream.getKind(recovery_token)); // $NON-NLS-1$ tokStream.reset(recovery_token); if (repairable(error_token)) break; state.stateStackTop = temp_stack.length - 1; System.arraycopy(temp_stack, 0, state.stateStack, 0, temp_stack.length); } if (tokStream.getKind(recovery_token) == EOFT_SYMBOL) { tokStream.reset(recovery_token); if (!repairable(error_token)) { state.stateStackTop = temp_stack.length - 1; System.arraycopy(temp_stack, 0, state.stateStack, 0, temp_stack.length); return 0; } } state.stateStackTop = temp_stack.length - 1; System.arraycopy(temp_stack, 0, state.stateStack, 0, temp_stack.length); undoActions(state.undoStack[state.stateStackTop]); tokStream.reset(recovery_token); state.tokens.reset(state.locationStack[state.stateStackTop] - 1); state.actionCount = state.actionStack[state.stateStackTop]; state.trialActionCount = state.undoStack[state.stateStackTop]; return tokStream.makeErrorToken( state.tokens.get(state.locationStack[state.stateStackTop] - 1), tokStream.getPrevious(recovery_token), error_token, ERROR_SYMBOL); }
private boolean repairable(int error_token) { // // Allocate configuration stack. // ConfigurationStack configuration_stack = new ConfigurationStack(prs); // // Keep parsing until we successfully reach the end of file or // an error is encountered. The list of actions executed will // be stored in the "action" tuple. // int start_token = tokStream.peek(); int final_token = tokStream.getStreamLength(); // unreachable int curtok = 0; int current_kind = ERROR_SYMBOL; int act = tAction(state.stateStack[state.stateStackTop], current_kind); for (; ; ) { if (act <= NUM_RULES) { state.stateStackTop--; act = process_repair_reductions(act); } else if (act > ERROR_ACTION) { curtok = tokStream.getToken(); if (curtok > final_token) return true; current_kind = tokStream.getKind(curtok); act = process_repair_reductions(act - ERROR_ACTION); } else if (act < ACCEPT_ACTION) { curtok = tokStream.getToken(); if (curtok > final_token) return true; current_kind = tokStream.getKind(curtok); } else if (act == ERROR_ACTION) { ConfigurationElement configuration = configuration_stack.pop(); if (configuration == null) act = ERROR_ACTION; else { state.stateStackTop = configuration.stack_top; configuration.retrieveStack(state.stateStack); act = configuration.act; curtok = configuration.curtok; if (curtok == 0) { current_kind = ERROR_SYMBOL; tokStream.reset(start_token); } else { current_kind = tokStream.getKind(curtok); tokStream.reset(tokStream.getNext(curtok)); } continue; } break; } else if (act > ACCEPT_ACTION) { if (configuration_stack.findConfiguration(state.stateStack, state.stateStackTop, curtok)) act = ERROR_ACTION; else { configuration_stack.push(state.stateStack, state.stateStackTop, act + 1, curtok, 0); act = prs.baseAction(act); } continue; } else break; // assert(act == ACCEPT_ACTION); try { // // We consider a configuration to be acceptable for recovery // if we are able to consume enough symbols in the remaining // tokens to reach another potential recovery point past the // original error token. // if ((curtok > error_token) && (final_token == tokStream.getStreamLength())) { // // If the ERROR_SYMBOL is a valid Action Adjunct in the // state // "act" then we set the terminating token as the successor // of // the current token. I.e., we have to be able to parse at // least // two tokens past the re-synch point before we claim // victory. // if (recoverableState(act)) final_token = skipTokens ? curtok : tokStream.getNext(curtok); } state.stateStack[++state.stateStackTop] = act; } catch (IndexOutOfBoundsException e) { state.reallocateStateStack(); state.stateStack[state.stateStackTop] = act; } act = tAction(act, current_kind); } // // If we can reach the end of the input successfully, we claim victory. // return (act == ACCEPT_ACTION); }
private void backtrackParseUpToError(int initial_token, int error_token) { // // Allocate configuration stack. // state.configurationStack = new ConfigurationStack(prs); state.trialActionStack = new LinkedList<Integer>(); state.trialActionStack.add(Integer.valueOf(state.trialActionCount)); // // Keep parsing until we successfully reach the end of file or // an error is encountered. The list of actions executed will // be stored in the "action" tuple. // // tokStream.reset(initial_token); int start_token = tokStream.peek(); state.curtok = (initial_token > 0 ? initial_token : tokStream.getToken()); int current_kind = tokStream.getKind(state.curtok); state.act = tAction(state.stateStack[state.stateStackTop], current_kind); state.tokens.add(state.curtok); state.locationStack[state.stateStackTop] = state.tokens.size(); state.actionStack[state.stateStackTop] = state.actionCount; state.undoStack[state.stateStackTop] = state.trialActionCount; for (; ; ) { // // if the parser needs to stop processing, // it may do so here. // if (monitor != null && monitor.isCancelled()) return; state.parserLocationStack[state.stateStackTop] = state.curtok; if (state.act <= NUM_RULES) { state.actionCount++; state.stateStackTop--; state.act = process_backtrack_reductions(state.act); } else if (state.act > ERROR_ACTION) { state.actionCount++; state.lastToken = state.curtok; state.curtok = tokStream.getToken(); current_kind = tokStream.getKind(state.curtok); state.tokens.add(state.curtok); state.act = process_backtrack_reductions(state.act - ERROR_ACTION); } else if (state.act < ACCEPT_ACTION) { state.actionCount++; state.lastToken = state.curtok; state.curtok = tokStream.getToken(); current_kind = tokStream.getKind(state.curtok); state.tokens.add(state.curtok); } else if (state.act == ERROR_ACTION) { if (state.curtok != error_token) { ConfigurationElement configuration = state.configurationStack.pop(); if (configuration == null) state.act = ERROR_ACTION; else { boolean shouldPop = prs.baseAction(configuration.conflict_index) == 0; undoActions(shouldPop); state.actionCount = configuration.action_length; state.act = configuration.act; int next_token_index = configuration.curtok; state.tokens.reset(next_token_index); state.curtok = state.tokens.get(next_token_index - 1); current_kind = tokStream.getKind(state.curtok); tokStream.reset( state.curtok == initial_token ? start_token : tokStream.getNext(state.curtok)); state.stateStackTop = configuration.stack_top; configuration.retrieveStack(state.stateStack); state.locationStack[state.stateStackTop] = state.tokens.size(); state.actionStack[state.stateStackTop] = state.actionCount; state.undoStack[state.stateStackTop] = state.trialActionCount; continue; } } break; } else if (state.act > ACCEPT_ACTION) { if (state.configurationStack.findConfiguration( state.stateStack, state.stateStackTop, state.tokens.size())) state.act = ERROR_ACTION; else { state.configurationStack.push( state.stateStack, state.stateStackTop, state.act + 1, state.tokens.size(), state.actionCount); state.trialActionStack.add(Integer.valueOf(state.trialActionCount)); state.act = prs.baseAction(state.act); } continue; } else break; // assert(act == ACCEPT_ACTION); state.stateStack[++state.stateStackTop] = state.act; // no need // to check // if out of // bounds state.locationStack[state.stateStackTop] = state.tokens.size(); state.actionStack[state.stateStackTop] = state.actionCount; state.undoStack[state.stateStackTop] = state.trialActionCount; state.act = tAction(state.act, current_kind); } // assert(curtok == error_token); return; }
// // Parse the input until either the parse completes successfully or // an error is encountered. This function returns an integer that // represents the last action that was executed by the parser. If // the parse was succesful, then the tuple "action" contains the // successful sequence of actions that was executed. // private int backtrackParse(int initial_token) { // // Allocate configuration stack. // state.configurationStack = new ConfigurationStack(prs); state.trialActionStack = new LinkedList<Integer>(); state.trialActionStack.add(Integer.valueOf(state.trialActionCount)); // // Keep parsing until we successfully reach the end of file or // an error is encountered. The list of actions executed will // be stored in the "action" tuple. // int error_token = 0; int maxStackTop = state.stateStackTop; int start_token = tokStream.peek(); state.curtok = (initial_token > 0 ? initial_token : tokStream.getToken()); int current_kind = tokStream.getKind(state.curtok); state.act = tAction(state.stateStack[state.stateStackTop], current_kind); // // The main driver loop // for (; ; ) { // // if the parser needs to stop processing, // it may do so here. // if (monitor != null && monitor.isCancelled()) return 0; state.parserLocationStack[state.stateStackTop] = state.curtok; if (state.act <= NUM_RULES) { state.actionCount++; state.stateStackTop--; state.act = process_backtrack_reductions(state.act); } else if (state.act > ERROR_ACTION) { state.actionCount++; state.lastToken = state.curtok; state.curtok = tokStream.getToken(); current_kind = tokStream.getKind(state.curtok); state.act = process_backtrack_reductions(state.act - ERROR_ACTION); } else if (state.act < ACCEPT_ACTION) { state.actionCount++; state.lastToken = state.curtok; state.curtok = tokStream.getToken(); current_kind = tokStream.getKind(state.curtok); } if (state.act == ERROR_ACTION) { error_token = (error_token > state.curtok ? error_token : state.curtok); ConfigurationElement configuration = state.configurationStack.pop(); if (configuration == null) state.act = ERROR_ACTION; else { boolean shouldPop = prs.baseAction(configuration.conflict_index) == 0; undoActions(shouldPop); state.actionCount = configuration.action_length; state.act = configuration.act; state.curtok = configuration.curtok; current_kind = tokStream.getKind(state.curtok); tokStream.reset( state.curtok == initial_token ? start_token : tokStream.getNext(state.curtok)); state.stateStackTop = configuration.stack_top; configuration.retrieveStack(state.stateStack); continue; } break; } if (state.act > ACCEPT_ACTION && state.act != ERROR_ACTION) { if (state.configurationStack.findConfiguration( state.stateStack, state.stateStackTop, state.curtok)) state.act = ERROR_ACTION; else { state.configurationStack.push( state.stateStack, state.stateStackTop, state.act + 1, state.curtok, state.actionCount); state.trialActionStack.add(Integer.valueOf(state.trialActionCount)); state.act = prs.baseAction(state.act); maxStackTop = state.stateStackTop > maxStackTop ? state.stateStackTop : maxStackTop; } continue; } else if (state.act == ACCEPT_ACTION) { break; } try { state.stateStack[++state.stateStackTop] = state.act; } catch (IndexOutOfBoundsException e) { state.reallocateStateStack(); state.stateStack[state.stateStackTop] = state.act; } state.act = tAction(state.act, current_kind); } // System.out.println("****Number of configurations: " + // configuration_stack.configurationSize()); // System.out.println("****Number of elements in stack tree: " + // configuration_stack.numStateElements()); // System.out.println("****Number of elements in stacks: " + // configuration_stack.stacksSize()); // System.out.println("****Number of actions: " + action.size()); // System.out.println("****Max Stack Size = " + maxStackTop); // System.out.flush(); return (state.act == ERROR_ACTION ? error_token : 0); }