/* * Copyright (c) 2005, 2009 Sven Efftinge 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: * Sven Efftinge - Initial API and implementation */ package org.eclipse.gmf.internal.xpand.expression.codeassist; import lpg.runtime.IToken; import lpg.runtime.PrsStream; import org.eclipse.gmf.internal.xpand.parser.XpandLexer; import org.eclipse.gmf.internal.xpand.parser.XpandParsersym; @SuppressWarnings("restriction") public class ReverseScanner { private String internal; private int offset; public ReverseScanner(final String s) { internal = s; offset = internal.length(); } public int getOffset() { return offset; } public IToken previousToken() { int os = offset - 1; if (os < 0) { return null; } IToken t = null; while (os >= 0) { final String temp = internal.substring(os--, offset); if (isEndOfString(temp)) { final String wholeString = getString(internal.substring(0, offset)); if (wholeString == null) { // incorrect string return null; } offset = internal.substring(0, offset).lastIndexOf(wholeString); return lexToTokenStream(wholeString).getTokenAt(1); } else if (temp.trim().length() > 0) { final PrsStream tokenStream = lexToTokenStream(temp); final IToken tempToken = tokenStream.getTokenAt(1); if (tempToken.getKind() == 0) { //bad token offset = os + 2; return t; } if ((t == null) || (tempToken.toString().length() > t.toString().length())) { t = tempToken; } else { offset = os + 2; return t; } } } offset = 0; return t; } /** * is public only for testing purposes */ public String getString(final String string) { final String t = string.trim(); if (t.length() > 0) { if (t.endsWith("\"")) { int i = t.substring(0, t.length() - 1).lastIndexOf('"'); while ((i > 0) && (t.charAt(i - 1) == '\\')) { i = t.substring(0, t.length() - i).lastIndexOf('"'); } return string.substring(i); } else if (t.endsWith("'")) { int i = t.substring(0, t.length() - 1).lastIndexOf('\''); while ((i > 0) && (t.charAt(i - 1) == '\\')) { i = t.substring(0, i).lastIndexOf('\''); } if (i >= 0) { return t.substring(i); } } } // passed string is either empty or incorrect string return null; } private boolean isEndOfString(final String temp) { final String t = temp.trim(); return (t.length() > 0) && ((t.charAt(t.length() - 1) == '"') || (t.charAt(t.length() - 1) == '\'')); } public IToken nextToken() { final String temp = internal.substring(offset); final IToken tempToken = lexToTokenStream(temp).getTokenAt(1); if (tempToken.getKind() == XpandParsersym.TK_EOF_TOKEN) { return null; } final String tokenText = tempToken.toString(); offset = temp.indexOf(tokenText) + tokenText.length() + offset; return tempToken; } private static PrsStream lexToTokenStream(String sequence) { XpandLexer scanner = new XpandLexer(sequence.toCharArray(), "nofile"); scanner.lexer(new PrsStream(scanner)); // there are at least bad token in the head and eof in the tail assert scanner.getPrsStream().getSize() >= 2; return scanner.getPrsStream(); } }