diff options
Diffstat (limited to 'runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs')
-rw-r--r-- | runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs | 234 |
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 < 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"); + } + } +} |