package com.five35.dex;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
import java.util.List;
import javax.annotation.Nonnull;

/**
 * A parser for Dex code.
 */
public final class Parser {
	private final PeekingIterator<Token> tokens;

	private Parser(final String source) {
		final List<Token> tokenList = Tokenizer.tokenize(Preconditions.checkNotNull(source));

		this.tokens = Iterators.peekingIterator(tokenList.iterator());
	}

	/**
	 * Parse the supplied Dex source into an expression.
	 * 
	 * @param source The Dex source to parse.
	 * @return An expression representing the parsed source.
	 * @throws ParserException When the supplied source cannot be parsed as a
	 *         Dex expression.
	 */
	@Nonnull
	public static Expression parse(final String source) throws ParserException {
		return new Parser(Preconditions.checkNotNull(source)).getExpression(0);
	}

	@Nonnull
	Symbol advance(final Optional<Symbol> expected) throws ParserException {
		final Token oldToken = this.tokens.next();
		final Token token = this.tokens.peek();

		if (token == null) {
			throw new MissingSymbolException(oldToken.getIndex() + oldToken.toString().length(), expected, Optional.<Token>absent());
		}

		final Symbol symbol = Symbol.getSymbol(token);

		// There is only one instance of each symbol, so object equality really
		// is what we want.
		if (!expected.isPresent() || expected.get() == symbol) {
			return symbol;
		}

		throw new MissingSymbolException(token.getIndex(), expected, Optional.of(token));
	}

	@Nonnull
	Token getCurrentToken() {
		return this.tokens.peek();
	}

	@Nonnull
	Expression getExpression(final int bindingPower) throws ParserException {
		return null;
	}
}

@@ -316,16 +316,149 @@
 arser %7B%0A
+%09// Initialized with a dummy token to ensure empty source is handled%0A%09// correctly.%0A%09private Token currentToken = new Token(1, %22%22);%0A%0A
 %09private
@@ -1234,54 +1234,13 @@
 ken 
-oldToken = this.tokens.next();%0A%09%09final Token t
+nextT
 oken
@@ -1250,28 +1250,28 @@
 this.tokens.
-peek
+next
 ();%0A%0A%09%09if (t
@@ -1269,17 +1269,21 @@
 %0A%0A%09%09if (
-t
+nextT
 oken == 
@@ -1297,44 +1297,38 @@
 %0A%09%09%09
-throw new MissingSymbolException(old
+final int index = this.current
 Toke
@@ -1346,11 +1346,20 @@
 ) + 
-old
+this.current
 Toke
@@ -1379,16 +1379,60 @@
 length()
+;%0A%0A%09%09%09throw new MissingSymbolException(index
 , expect
@@ -1508,17 +1508,21 @@
 tSymbol(
-t
+nextT
 oken);%0A%0A
@@ -1676,16 +1676,51 @@
 mbol) %7B%0A
+%09%09%09this.currentToken = nextToken;%0A%0A
 %09%09%09retur
@@ -1769,17 +1769,21 @@
 ception(
-t
+nextT
 oken.get
@@ -1813,17 +1813,21 @@
 onal.of(
-t
+nextT
 oken));%0A
@@ -1885,21 +1885,20 @@
 his.
-tokens.peek()
+currentToken
 ;%0A%09%7D
@@ -2001,11 +2001,82 @@
 null;%0A%09%7D
+%0A%0A%09@Nonnull%0A%09Token previewNextToken() %7B%0A%09%09return this.tokens.peek();%0A%09%7D
 %0A%7D%0A

add proper current token tracking, so that the next token can be previewed