/******************************************************************************* * Copyright (c) 2006, 2008 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.cdt.core.dom.lrparser.lpgextensions; import java.util.Collections; import java.util.List; import lpg.lpgjavaruntime.IToken; import lpg.lpgjavaruntime.LexStream; import lpg.lpgjavaruntime.PrsStream; /** * Base class for parser action classes which support trial, undo and * final actions. */ public abstract class AbstractTrialUndoActionProvider<ACT, RULE_DATA> extends PrsStream implements ITrialUndoActionProvider<RULE_DATA> { /** * An action that does nothing. */ public static final Action<Object, Object> EMPTY_ACTION = new Action<Object, Object>(); /** * The parser table interpreter. */ protected TrialUndoParser btParser; public AbstractTrialUndoActionProvider() { super(); } public AbstractTrialUndoActionProvider(LexStream lexStream) { super(lexStream); } /** * Actions for reduction rules. */ protected Action<ACT, RULE_DATA>[] ruleAction; protected ACT parserAction; public void setParserAction(ACT parserAction) { this.parserAction = parserAction; } /** * The reduction rule which is currently being processed. */ protected Rule<RULE_DATA> activeRule; /** * Returns the number of tokens in the rule being reduced. */ public int getRuleTokenCount() { return activeRule.getEndTokenOffset() - activeRule.getStartTokenOffset() + 1; } /** * Returns the tokens in the rule being reduced. */ @SuppressWarnings("unchecked") public List<IToken> getRuleTokens() { return Collections.unmodifiableList(getTokens().subList(getFirstRealToken(activeRule.getStartTokenOffset()), activeRule.getEndTokenOffset() + 1)); } public void backtrack() { btParser.backtrack(); } public void setActiveRule(Rule<RULE_DATA> rule) { activeRule = rule; } public Rule<RULE_DATA> getActiveRule() { return activeRule; } public final boolean trialAction(int rule_number) { return ruleAction[rule_number].doTrial(this, parserAction); } public final void undoAction(int rule_number) { ruleAction[rule_number].doUndo(this, parserAction); } public final void finalAction(int rule_number) { //System.out.println("finalAction: " + rule_number); //$NON-NLS-1$ ruleAction[rule_number].doFinal(this, parserAction); } public TrialUndoParser getParser() { return btParser; } /** * Returns the offset of the leftmost token of the * rule being reduced. */ private int getLeftSpan() { return getFirstRealToken(activeRule.getStartTokenOffset()); } /** * Returns the leftmost token of the rule being reduced. */ public IToken getLeftIToken() { return super.getIToken(getLeftSpan()); } /** * Returns the offset of the rightmost token of the * rule being reduced. */ private int getRightSpan() { return activeRule.getEndTokenOffset(); } /** * Returns the rightmost token of the rule being reduced. */ public IToken getRightIToken() { return super.getIToken(getRightSpan()); } public static <ACT, RULE_DATA> Action<ACT, RULE_DATA> emptyAction() { return new Action<ACT, RULE_DATA>(); } @SuppressWarnings("unused") public static class Action<ACT, RULE_DATA> { public void doFinal(ITrialUndoActionProvider<RULE_DATA> provider, ACT action) { // convenience method, can be overridden } public boolean doTrial(ITrialUndoActionProvider<RULE_DATA> provider, ACT action) { //System.out.println(provider.getActiveRule()); //System.out.println(Rules.lookup(provider.getActiveRule().getRuleNumber())); return false; } public void doUndo(ITrialUndoActionProvider<RULE_DATA> provider, ACT action) { //System.out.println(provider.getActiveRule() + " - undo"); // convenience method, can be overridden } } public static class DeclaredAction<ACT, RULE_DATA> extends Action<ACT, RULE_DATA> { protected boolean hasUndo = false; @Override @SuppressWarnings("unused") public boolean doTrial(ITrialUndoActionProvider<RULE_DATA> provider, ACT action) { return true; } } /** * Action for a null rule */ static final class NullAction<ACT, RULE_DATA> extends Action<ACT, RULE_DATA> { @Override @SuppressWarnings("unused") public void doFinal(ITrialUndoActionProvider<RULE_DATA> provider, ACT action) { // do nothing } } static final class BadAction<ACT, RULE_DATA> extends Action<ACT, RULE_DATA> { @Override @SuppressWarnings("unused") public void doFinal(ITrialUndoActionProvider<RULE_DATA> provider, ACT action) { throw new Error(new BadActionException()); } @Override @SuppressWarnings("unused") public boolean doTrial(ITrialUndoActionProvider<RULE_DATA> provider, ACT action) { throw new Error(new BadActionException()); } @Override @SuppressWarnings("unused") public void doUndo(ITrialUndoActionProvider<RULE_DATA> provider, ACT action) { throw new Error(new BadActionException()); } } static public class BadActionException extends Exception { private static final long serialVersionUID = 1L; } }