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}