/*******************************************************************************
* Copyright (c) 2013, 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:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package dtool.parser.common;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue;
import java.util.AbstractList;
import java.util.List;
import dtool.parser.DeeTokens;
/**
* A list-like indexed source of {@link LexElement}'s.
* Supports backtracking by means of saving and restoring state.
*/
public class LexElementSource {
public static final LexElement START_TOKEN = new LexElement(DeeTokens.EOF, "", 0, 0, null);
public final AbstractList<LexElement> lexElementList; // Immutable
protected LexElement lastLexElement = START_TOKEN;
protected int lexElementPosition = 0;
protected int sourcePosition = 0;
public LexElementSource(AbstractList<LexElement> lexElementList) {
this.lexElementList = lexElementList;
}
public List<LexElement> getLexElementList() {
return lexElementList;
}
public final LexElement lastLexElement() {
return lastLexElement;
}
public final int getLexElementPosition() {
return lexElementPosition;
}
public final int getSourcePosition() {
return sourcePosition;
}
public final void setSourcePosition(int sourcePosition) {
this.sourcePosition = sourcePosition;
}
public LexElement lookAheadElement(int laIndex) {
assertTrue(laIndex >= 0);
int listIndex = Math.min(lexElementPosition + laIndex, lexElementList.size() - 1);
return lexElementList.get(listIndex);
}
public LexElementSource saveState() {
LexElementSource savedState = new LexElementSource(lexElementList);
savedState.lastLexElement = lastLexElement;
savedState.lexElementPosition = lexElementPosition;
savedState.sourcePosition = sourcePosition;
return savedState;
}
public void resetState(LexElementSource savedState) {
assertTrue(savedState.lexElementList == lexElementList);
lastLexElement = savedState.lastLexElement;
lexElementPosition = savedState.lexElementPosition;
sourcePosition = savedState.sourcePosition;
}
public final LexElement consumeInput() {
lastLexElement = lookAheadElement(0);
lexElementPosition++;
sourcePosition = lastLexElement.getEndPos();
return lastLexElement;
}
public final void advanceSubChannelTokens() {
setSourcePosition(lookAheadElement(0).getStartPos());
}
}