blob: 4f7f2dddea5e90b398705ea717e7278f28972c48 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.lang.pratt;
import com.intellij.lang.LighterASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import java.util.LinkedList;
/**
* @author peter
*/
public class MutableMarker {
enum Mode { READY, DROPPED, COMMITTED, ERROR }
private final PsiBuilder.Marker myStartMarker;
private IElementType myResultType;
private final int myInitialPathLength;
private final LinkedList<IElementType> myPath;
private Mode myMode;
public MutableMarker(final LinkedList<IElementType> path, final PsiBuilder.Marker startMarker, final int initialPathLength) {
myPath = path;
myStartMarker = startMarker;
myInitialPathLength = initialPathLength;
myMode = startMarker instanceof LighterASTNode && ((LighterASTNode)startMarker).getTokenType() != null? Mode.COMMITTED : Mode.READY;
}
// for easier transition only
public MutableMarker(final LinkedList<IElementType> path, final PsiBuilder builder) {
myPath = path;
myStartMarker = (PsiBuilder.Marker)builder.getLatestDoneMarker();
myInitialPathLength = path.size();
myResultType = myStartMarker instanceof LighterASTNode? ((LighterASTNode)myStartMarker).getTokenType() : null;
myMode = myResultType != null ? Mode.COMMITTED : Mode.READY;
}
public boolean isCommitted() {
return myMode == Mode.COMMITTED;
}
public boolean isDropped() {
return myMode == Mode.DROPPED;
}
public boolean isError() {
return myMode == Mode.ERROR;
}
public boolean isReady() {
return myMode == Mode.READY;
}
public MutableMarker setResultType(final IElementType resultType) {
myResultType = resultType;
return this;
}
public IElementType getResultType() {
return myResultType;
}
public void finish() {
if (myMode == Mode.READY) {
if (myResultType == null) {
myMode = Mode.DROPPED;
myStartMarker.drop();
}
else {
myMode = Mode.COMMITTED;
myStartMarker.done(myResultType);
restorePath();
myPath.addLast(myResultType);
}
}
}
private void restorePath() {
while (myPath.size() > myInitialPathLength) {
myPath.removeLast();
}
}
public MutableMarker precede() {
return new MutableMarker(myPath, myStartMarker.precede(), myInitialPathLength);
}
public void finish(final IElementType type) {
setResultType(type);
finish();
}
public void drop() {
assert myMode == Mode.READY : myMode;
myMode = Mode.DROPPED;
myStartMarker.drop();
}
public void rollback() {
assert myMode == Mode.READY : myMode;
myMode = Mode.DROPPED;
restorePath();
myStartMarker.rollbackTo();
}
public void error(final String message) {
assert myMode == Mode.READY : myMode;
myMode = Mode.ERROR;
myStartMarker.error(message);
}
}