001/*
002 * Anarres C Preprocessor
003 * Copyright (c) 2007-2015, Shevek
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
014 * or implied.  See the License for the specific language governing
015 * permissions and limitations under the License.
016 */
017package org.anarres.cpp;
018
019import java.io.IOException;
020import java.util.Iterator;
021import java.util.NoSuchElementException;
022import javax.annotation.Nonnull;
023import static org.anarres.cpp.Token.EOF;
024
025/**
026 * An Iterator for {@link Source Sources},
027 * returning {@link Token Tokens}.
028 */
029public class SourceIterator implements Iterator<Token> {
030
031    private final Source source;
032    private Token tok;
033
034    public SourceIterator(@Nonnull Source s) {
035        this.source = s;
036        this.tok = null;
037    }
038
039    /**
040     * Rethrows IOException inside IllegalStateException.
041     */
042    private void advance() {
043        try {
044            if (tok == null)
045                tok = source.token();
046        } catch (LexerException e) {
047            throw new IllegalStateException(e);
048        } catch (IOException e) {
049            throw new IllegalStateException(e);
050        }
051    }
052
053    /**
054     * Returns true if the enclosed Source has more tokens.
055     *
056     * The EOF token is never returned by the iterator.
057     * @throws IllegalStateException if the Source
058     *          throws a LexerException or IOException
059     */
060    @Override
061    public boolean hasNext() {
062        advance();
063        return tok.getType() != EOF;
064    }
065
066    /**
067     * Returns the next token from the enclosed Source.
068     *
069     * The EOF token is never returned by the iterator.
070     * @throws IllegalStateException if the Source
071     *          throws a LexerException or IOException
072     */
073    @Override
074    public Token next() {
075        if (!hasNext())
076            throw new NoSuchElementException();
077        Token t = this.tok;
078        this.tok = null;
079        return t;
080    }
081
082    /**
083     * Not supported.
084     *
085     * @throws UnsupportedOperationException unconditionally.
086     */
087    @Override
088    public void remove() {
089        throw new UnsupportedOperationException();
090    }
091}