| /* |
| * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package jdk.nashorn.internal.parser; |
| |
| /** |
| * |
| */ |
| |
| /** |
| * Handles streaming of tokens between lexer and parser. |
| * |
| */ |
| public class TokenStream { |
| /** Initial buffer size. */ |
| private static final int INITIAL_SIZE = 256; |
| |
| /** Token buffer. */ |
| private long[] buffer; |
| |
| /** Token count. */ |
| private int count; |
| |
| /** Cursor to write position in buffer */ |
| private int in; |
| |
| /** Cursor to read position in buffer */ |
| private int out; |
| |
| /** Base index in buffer */ |
| private int base; |
| |
| /** |
| * Constructor. |
| */ |
| public TokenStream() { |
| buffer = new long[INITIAL_SIZE]; |
| count = 0; |
| in = 0; |
| out = 0; |
| base = 0; |
| } |
| |
| /** |
| * Get the next position in the buffer. |
| * @param position Current position in buffer. |
| * @return Next position in buffer. |
| */ |
| private int next(final int position) { |
| // Next position. |
| int next = position + 1; |
| |
| // If exceeds buffer length. |
| if (next >= buffer.length) { |
| // Wrap around. |
| next = 0; |
| } |
| |
| return next; |
| } |
| |
| /** |
| * Get the index position in the buffer. |
| * @param k Seek position. |
| * @return Position in buffer. |
| */ |
| private int index(final int k) { |
| // Bias k. |
| int index = k - (base - out); |
| |
| // If wrap around. |
| if (index >= buffer.length) { |
| index -= buffer.length; |
| } |
| |
| return index; |
| } |
| |
| /** |
| * Test to see if stream is empty. |
| * @return True if stream is empty. |
| */ |
| public boolean isEmpty() { |
| return count == 0; |
| } |
| |
| /** |
| * Test to see if stream is full. |
| * @return True if stream is full. |
| */ |
| public boolean isFull() { |
| return count == buffer.length; |
| } |
| |
| /** |
| * Get the number of tokens in the buffer. |
| * @return Number of tokens. |
| */ |
| public int count() { |
| return count; |
| } |
| |
| /** |
| * Get the index of the first token in the stream. |
| * @return Index of first buffered token in the stream. |
| */ |
| public int first() { |
| return base; |
| } |
| |
| /** |
| * Get the index of the last token in the stream. |
| * @return Index of last buffered token in the stream. |
| */ |
| public int last() { |
| return base + count - 1; |
| } |
| |
| /** |
| * Remove the last token in the stream. |
| */ |
| public void removeLast() { |
| if (count != 0) { |
| count--; |
| in--; |
| |
| if (in < 0) { |
| in = buffer.length - 1; |
| } |
| } |
| } |
| |
| /** |
| * Put a token descriptor to the stream. |
| * @param token Token descriptor to add. |
| */ |
| public void put(final long token) { |
| if (count == buffer.length) { |
| grow(); |
| } |
| |
| buffer[in] = token; |
| count++; |
| in = next(in); |
| } |
| |
| /** |
| * Get the kth token descriptor from the stream. |
| * @param k index |
| * @return Token descriptor. |
| */ |
| public long get(final int k) { |
| return buffer[index(k)]; |
| } |
| |
| /** |
| * Advances the base of the stream. |
| * @param k Position of token to be the new base. |
| */ |
| public void commit(final int k) { |
| // Advance out. |
| out = index(k); |
| // Adjust count. |
| count -= k - base; |
| // Set base. |
| base = k; |
| } |
| |
| /** |
| * Grow the buffer to accommodate more token descriptors. |
| */ |
| public void grow() { |
| // Allocate new buffer. |
| final long[] newBuffer = new long[buffer.length * 2]; |
| |
| // If single chunk. |
| if (in > out) { |
| System.arraycopy(buffer, out, newBuffer, 0, count); |
| } else { |
| final int portion = buffer.length - out; |
| System.arraycopy(buffer, out, newBuffer, 0, portion); |
| System.arraycopy(buffer, 0, newBuffer, portion, count - portion); |
| } |
| |
| // Update buffer and indices. |
| out = 0; |
| in = count; |
| buffer = newBuffer; |
| } |
| |
| void reset() { |
| in = out = count = base = 0; |
| } |
| } |