blob: 0000400164e152de2c2faa133bfdb65f74868f6c [file] [log] [blame]
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.smalidea;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilder.Marker;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.Token;
import org.antlr.runtime.TokenSource;
import org.antlr.runtime.TokenStream;
import org.jetbrains.annotations.Nullable;
import org.jf.smali.InvalidToken;
import org.jf.smali.smaliParser;
import javax.annotation.Nonnull;
import java.util.ArrayList;
public class PsiBuilderTokenStream implements TokenStream {
@Nonnull private PsiBuilder psiBuilder;
@Nullable private CommonToken currentToken = null;
@Nonnull private ArrayList<Marker> markers = new ArrayList<PsiBuilder.Marker>();
public PsiBuilderTokenStream(@Nonnull PsiBuilder psiBuilder) {
this.psiBuilder = psiBuilder;
}
@Override public Token LT(int k) {
if (k == 1) {
if (currentToken == null) {
buildCurrentToken();
}
return currentToken;
}
throw new UnsupportedOperationException();
}
@Override public int range() {
return currentToken==null?0:1;
}
@Override public Token get(int i) {
throw new UnsupportedOperationException();
}
@Override public TokenSource getTokenSource() {
throw new UnsupportedOperationException();
}
@Override public String toString(int start, int stop) {
throw new UnsupportedOperationException();
}
@Override public String toString(Token start, Token stop) {
throw new UnsupportedOperationException();
}
@Override public void consume() {
psiBuilder.advanceLexer();
buildCurrentToken();
}
private void buildCurrentToken() {
IElementType element = psiBuilder.getTokenType();
if (element != null) {
if (element instanceof SmaliLexicalElementType) {
SmaliLexicalElementType elementType = (SmaliLexicalElementType)element;
currentToken = new CommonToken(elementType.tokenId, psiBuilder.getTokenText());
} else if (element == TokenType.BAD_CHARACTER) {
currentToken = new InvalidToken("", psiBuilder.getTokenText());
} else {
throw new UnsupportedOperationException();
}
} else {
currentToken = new CommonToken(Token.EOF);
}
}
@Override public int LA(int i) {
IElementType elementType = psiBuilder.lookAhead(i-1);
if (elementType == null) {
return -1;
} else if (elementType instanceof SmaliLexicalElementType) {
return ((SmaliLexicalElementType)elementType).tokenId;
} else if (elementType == TokenType.BAD_CHARACTER) {
return smaliParser.INVALID_TOKEN;
}
throw new UnsupportedOperationException();
}
@Override public int mark() {
int ret = markers.size();
markers.add(psiBuilder.mark());
return ret;
}
@Override public int index() {
return psiBuilder.getCurrentOffset();
}
@Override public void rewind(int markerIndex) {
PsiBuilder.Marker marker = markers.get(markerIndex);
marker.rollbackTo();
while (markerIndex < markers.size()) {
markers.remove(markerIndex);
}
}
@Override public void rewind() {
rewind(markers.size()-1);
mark();
}
@Override public void release(int markerIndex) {
while (markerIndex < markers.size()) {
markers.remove(markerIndex).drop();
}
}
@Override public void seek(int index) {
if (index < psiBuilder.getCurrentOffset()) {
throw new UnsupportedOperationException();
}
while (index > psiBuilder.getCurrentOffset()) {
consume();
}
}
@Override public int size() {
throw new UnsupportedOperationException();
}
@Override public String getSourceName() {
return null;
}
}