| /* |
| * 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); |
| } |
| } |