/******************************************************************************* * Copyright © 2011, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.compiler.core.ast; import java.util.Stack; import java_cup.runtime.Symbol; /** * @author winghong */ public class TerminalInsertionRecovery extends AbstractRecovery { private int parseCheckDistance; private int missingTerminal; public TerminalInsertionRecovery(ParseStack errorStack, Stack realStack, ITokenStream tokenStream, ISyntaxErrorRequestor problemRequestor) { super(errorStack, realStack, tokenStream, problemRequestor); } protected void performTrial() { short[] terminalCandidates = errorStack.getTerminalCandidates(errorStack.getCurrentState()); for(int i = 0; i < terminalCandidates.length; i++) { // Not a very good fix: // Sometimes the recovery will keep inserting or substituting LCURLY // because a lot of times, it will then be able to parse 3 tokens // This causes too many nested property settings and may eventually // lead to a stack overflow if(terminalCandidates[i] == NodeTypes.LCURLY) { continue; } Terminal terminal = new Terminal(terminalCandidates[i], -1, -1, -1); ParseStack trialStack = errorStack.createCopy(); trialStack.processLookAhead(terminal); int trialDistance = trialStack.parseCheck(tokenStream); if(trialDistance > parseCheckDistance) { parseCheckDistance = trialDistance; missingTerminal = terminalCandidates[i]; } } } public float getMisspellingIndex() { return 0; } public int getParseCheckDistance() { return parseCheckDistance; } public int performRecovery() { // Remember offset information for error message int errorOffset = tokenStream.getLookAhead().left; // Report error problemRequestor.missingTerminal(missingTerminal, tokenStream.getLookAhead().left, tokenStream.getLookAhead().right); // Compute construct root after the terminal has been inserted Terminal terminal = new Terminal(missingTerminal, errorOffset, errorOffset, -1); Symbol symbol = new Symbol(missingTerminal, errorOffset, errorOffset); symbol.parse_state = -2; tokenStream.rollBack(terminal, symbol); // Return 0 for the error node position. The true error node position will be // determined when the main parser shifts the artificially created terminal since // its parse_state is -2 return 0; } }