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