001/*-----------------------------------------------------------------------+
002 | org.conqat.engine.index.incubator
003 |                                                                       |
004   $Id$            
005 |                                                                       |
006 | Copyright (c)  2009-2013 CQSE GmbH                                 |
007 +-----------------------------------------------------------------------*/
008package eu.cqse.check.framework.util.tokens;
009
010import java.util.List;
011
012import eu.cqse.check.framework.scanner.IToken;
013
014/**
015 * Wraps a list of tokens for easier parsing.
016 */
017public class TokenStream {
018
019        /** The parsed tokens. */
020        private final List<IToken> tokens;
021
022        /** The current position in the stream. */
023        private int position;
024
025        /** Constructor. */
026        public TokenStream(List<IToken> tokens, int position) {
027                this.tokens = tokens;
028                this.position = position;
029        }
030
031        /** @see #tokens */
032        public List<IToken> getTokens() {
033                return tokens;
034        }
035
036        /**
037         * Sets the position of the stream to the given one.
038         */
039        public void setPosition(int position) {
040                this.position = position;
041        }
042
043        /**
044         * Advances the position of the stream by the given increment.
045         */
046        public void advancePosition(int increment) {
047                this.position += increment;
048        }
049
050        /**
051         * Returns <code>true</code> if the steam is positioned on the first token.
052         */
053        public boolean isAtBeginning() {
054                return position == 0;
055        }
056
057        /**
058         * Returns true if the stream is positioned past the last token.
059         */
060        public boolean isExhausted() {
061                return position >= tokens.size();
062        }
063
064        /**
065         * Returns a view of the tokens in between the given position (inclusive) and
066         * the current position (exclusive).
067         */
068        public List<IToken> getTokensSince(int startPosition) {
069                return tokens.subList(startPosition, position);
070        }
071
072        /**
073         * Advances the stream by one token.
074         * 
075         * @return The token the stream was positioned on before advancing or
076         *         <code>null</code> if the stream was already exhausted at that time.
077         */
078        public IToken next() {
079                if (position >= tokens.size()) {
080                        return null;
081                }
082                position += 1;
083                return getAtPosition(position - 1);
084        }
085
086        /**
087         * Returns the token at the given position or <code>null</code> if the position
088         * is out of bounds.
089         */
090        private IToken getAtPosition(int position) {
091                if (position >= tokens.size() || position < 0) {
092                        return null;
093                }
094                return tokens.get(position);
095        }
096
097        /**
098         * Returns the token before the current one or <code>null</code> if the stream
099         * is at the beginning.
100         */
101        public IToken peekBackward() {
102                return getAtPosition(position - 1);
103        }
104
105        /**
106         * Returns the current token or <code>null</code> if the stream is exhausted.
107         */
108        public IToken peekCurrent() {
109                return getAtPosition(position);
110        }
111
112        /**
113         * Returns the current position in the stream. May be used to reset the stream
114         * to that position at a later time using {@link #setPosition(int)}.
115         */
116        public int getPosition() {
117                return position;
118        }
119
120        /**
121         * Moves the stream's position back by one token and returns the token at that
122         * position or <code>null</code> if the stream was already at the beginning.
123         */
124        public IToken moveBack() {
125                if (position <= 0) {
126                        return null;
127                }
128                position -= 1;
129                return peekCurrent();
130        }
131}