blob: 94bd6db7fde1a2473a7c4e1d7d2e3398cb3a324d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2015 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* 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<>();
/**
* 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();
}
@Override
public void setActiveRule(Rule<RULE_DATA> rule) {
activeRule = rule;
}
@Override
public Rule<RULE_DATA> getActiveRule() {
return activeRule;
}
@Override
public final boolean trialAction(int rule_number) {
return ruleAction[rule_number].doTrial(this, parserAction);
}
@Override
public final void undoAction(int rule_number) {
ruleAction[rule_number].doUndo(this, parserAction);
}
@Override
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<>();
}
@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;
}
}