aboutsummaryrefslogtreecommitdiff
path: root/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs')
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs234
1 files changed, 234 insertions, 0 deletions
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs
new file mode 100644
index 0000000..24dc0cb
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs
@@ -0,0 +1,234 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Misc
+{
+ using ArgumentException = System.ArgumentException;
+ using InvalidOperationException = System.InvalidOperationException;
+
+ /** <summary>
+ * A lookahead queue that knows how to mark/release locations
+ * in the buffer for backtracking purposes. Any markers force the FastQueue
+ * superclass to keep all tokens until no more markers; then can reset
+ * to avoid growing a huge buffer.
+ * </summary>
+ */
+ public abstract class LookaheadStream<T>
+ : FastQueue<T>
+ where T : class
+ {
+ /** Absolute token index. It's the index of the symbol about to be
+ * read via LT(1). Goes from 0 to numtokens.
+ */
+ private int _currentElementIndex = 0;
+
+ private T _previousElement;
+
+ /** Track object returned by nextElement upon end of stream;
+ * Return it later when they ask for LT passed end of input.
+ */
+ T _eof = null;
+
+ /** <summary>Track the last mark() call result value for use in rewind().</summary> */
+ int _lastMarker;
+
+ /** <summary>tracks how deep mark() calls are nested</summary> */
+ int _markDepth;
+
+ public T EndOfFile
+ {
+ get
+ {
+ return _eof;
+ }
+ protected set
+ {
+ _eof = value;
+ }
+ }
+
+ public T PreviousElement
+ {
+ get
+ {
+ return _previousElement;
+ }
+ }
+
+ public override void Clear()
+ {
+ base.Clear();
+ _currentElementIndex = 0;
+ _p = 0;
+ _previousElement = null;
+ }
+
+ /** <summary>
+ * Implement nextElement to supply a stream of elements to this
+ * lookahead buffer. Return eof upon end of the stream we're pulling from.
+ * </summary>
+ */
+ public abstract T NextElement();
+
+ public abstract bool IsEndOfFile(T o);
+
+ /** <summary>Get and remove first element in queue; override FastQueue.remove()</summary> */
+ public override T Dequeue()
+ {
+ T o = this[0];
+ _p++;
+ // have we hit end of buffer and not backtracking?
+ if ( _p == _data.Count && _markDepth == 0 )
+ {
+ // if so, it's an opportunity to start filling at index 0 again
+ Clear(); // size goes to 0, but retains memory
+ }
+ return o;
+ }
+
+ /** <summary>Make sure we have at least one element to remove, even if EOF</summary> */
+ public virtual void Consume()
+ {
+ SyncAhead(1);
+ _previousElement = Dequeue();
+ _currentElementIndex++;
+ }
+
+ /** <summary>
+ * Make sure we have 'need' elements from current position p. Last valid
+ * p index is data.size()-1. p+need-1 is the data index 'need' elements
+ * ahead. If we need 1 element, (p+1-1)==p must be &lt; data.size().
+ * </summary>
+ */
+ protected virtual void SyncAhead( int need )
+ {
+ int n = ( _p + need - 1 ) - _data.Count + 1; // how many more elements we need?
+ if ( n > 0 )
+ Fill( n ); // out of elements?
+ }
+
+ /** <summary>add n elements to buffer</summary> */
+ public virtual void Fill( int n )
+ {
+ for ( int i = 0; i < n; i++ )
+ {
+ T o = NextElement();
+ if ( IsEndOfFile(o) )
+ _eof = o;
+
+ _data.Add( o );
+ }
+ }
+
+ /** <summary>Size of entire stream is unknown; we only know buffer size from FastQueue</summary> */
+ public override int Count
+ {
+ get
+ {
+ throw new System.NotSupportedException( "streams are of unknown size" );
+ }
+ }
+
+ public virtual T LT( int k )
+ {
+ if ( k == 0 )
+ {
+ return null;
+ }
+ if ( k < 0 )
+ {
+ return LB(-k);
+ }
+
+ SyncAhead( k );
+ if ((_p + k - 1) > _data.Count)
+ return _eof;
+
+ return this[k - 1];
+ }
+
+ public virtual int Index
+ {
+ get
+ {
+ return _currentElementIndex;
+ }
+ }
+
+ public virtual int Mark()
+ {
+ _markDepth++;
+ _lastMarker = _p; // track where we are in buffer, not absolute token index
+ return _lastMarker;
+ }
+
+ public virtual void Release( int marker )
+ {
+ if (_markDepth == 0)
+ throw new InvalidOperationException();
+
+ _markDepth--;
+ }
+
+ public virtual void Rewind( int marker )
+ {
+ Seek( marker );
+ Release( marker );
+ }
+
+ public virtual void Rewind()
+ {
+ Rewind( _lastMarker );
+ }
+
+ /** <summary>
+ * Seek to a 0-indexed position within data buffer. Can't handle
+ * case where you seek beyond end of existing buffer. Normally used
+ * to seek backwards in the buffer. Does not force loading of nodes.
+ * Doesn't see to absolute position in input stream since this stream
+ * is unbuffered. Seeks only into our moving window of elements.
+ * </summary>
+ */
+ public virtual void Seek( int index )
+ {
+ _p = index;
+ }
+
+ protected virtual T LB(int k)
+ {
+ if (k == 1)
+ return _previousElement;
+
+ throw new ArgumentException("can't look backwards more than one token in this stream");
+ }
+ }
+}