You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
9.4 KiB
313 lines
9.4 KiB
/*
|
|
* [The "BSD license"]
|
|
* Copyright (c) 2011 Terence Parr
|
|
* All rights reserved.
|
|
*
|
|
* Conversion to C#:
|
|
* Copyright (c) 2011 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.Tree
|
|
{
|
|
using System.Collections.Generic;
|
|
using Antlr.Runtime.Misc;
|
|
|
|
using StringBuilder = System.Text.StringBuilder;
|
|
|
|
[System.Serializable]
|
|
public class CommonTreeNodeStream : LookaheadStream<object>, ITreeNodeStream, IPositionTrackingStream
|
|
{
|
|
public const int DEFAULT_INITIAL_BUFFER_SIZE = 100;
|
|
public const int INITIAL_CALL_STACK_SIZE = 10;
|
|
|
|
/** <summary>Pull nodes from which tree?</summary> */
|
|
private readonly object _root;
|
|
|
|
/** <summary>If this tree (root) was created from a token stream, track it.</summary> */
|
|
protected ITokenStream tokens;
|
|
|
|
/** <summary>What tree adaptor was used to build these trees</summary> */
|
|
[System.NonSerialized]
|
|
private ITreeAdaptor _adaptor;
|
|
|
|
/** The tree iterator we are using */
|
|
private readonly TreeIterator _it;
|
|
|
|
/** <summary>Stack of indexes used for push/pop calls</summary> */
|
|
private Stack<int> _calls;
|
|
|
|
/** <summary>Tree (nil A B C) trees like flat A B C streams</summary> */
|
|
private bool _hasNilRoot = false;
|
|
|
|
/** <summary>Tracks tree depth. Level=0 means we're at root node level.</summary> */
|
|
private int _level = 0;
|
|
|
|
/**
|
|
* Tracks the last node before the start of {@link #data} which contains
|
|
* position information to provide information for error reporting. This is
|
|
* tracked in addition to {@link #prevElement} which may or may not contain
|
|
* position information.
|
|
*
|
|
* @see #hasPositionInformation
|
|
* @see RecognitionException#extractInformationFromTreeNodeStream
|
|
*/
|
|
private object _previousLocationElement;
|
|
|
|
public CommonTreeNodeStream( object tree )
|
|
: this( new CommonTreeAdaptor(), tree )
|
|
{
|
|
}
|
|
|
|
public CommonTreeNodeStream( ITreeAdaptor adaptor, object tree )
|
|
{
|
|
this._root = tree;
|
|
this._adaptor = adaptor;
|
|
_it = new TreeIterator( adaptor, _root );
|
|
}
|
|
|
|
#region Properties
|
|
|
|
public virtual string SourceName
|
|
{
|
|
get
|
|
{
|
|
if ( TokenStream == null )
|
|
return null;
|
|
|
|
return TokenStream.SourceName;
|
|
}
|
|
}
|
|
|
|
public virtual ITokenStream TokenStream
|
|
{
|
|
get
|
|
{
|
|
return tokens;
|
|
}
|
|
|
|
set
|
|
{
|
|
tokens = value;
|
|
}
|
|
}
|
|
|
|
public virtual ITreeAdaptor TreeAdaptor
|
|
{
|
|
get
|
|
{
|
|
return _adaptor;
|
|
}
|
|
|
|
set
|
|
{
|
|
_adaptor = value;
|
|
}
|
|
}
|
|
|
|
public virtual object TreeSource
|
|
{
|
|
get
|
|
{
|
|
return _root;
|
|
}
|
|
}
|
|
|
|
public virtual bool UniqueNavigationNodes
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
|
|
set
|
|
{
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
public override void Reset()
|
|
{
|
|
base.Reset();
|
|
_it.Reset();
|
|
_hasNilRoot = false;
|
|
_level = 0;
|
|
_previousLocationElement = null;
|
|
if ( _calls != null )
|
|
_calls.Clear();
|
|
}
|
|
|
|
public override object NextElement()
|
|
{
|
|
_it.MoveNext();
|
|
object t = _it.Current;
|
|
//System.out.println("pulled "+adaptor.getType(t));
|
|
if ( t == _it.up )
|
|
{
|
|
_level--;
|
|
if ( _level == 0 && _hasNilRoot )
|
|
{
|
|
_it.MoveNext();
|
|
return _it.Current; // don't give last UP; get EOF
|
|
}
|
|
}
|
|
else if ( t == _it.down )
|
|
{
|
|
_level++;
|
|
}
|
|
|
|
if ( _level == 0 && TreeAdaptor.IsNil( t ) )
|
|
{
|
|
// if nil root, scarf nil, DOWN
|
|
_hasNilRoot = true;
|
|
_it.MoveNext();
|
|
t = _it.Current; // t is now DOWN, so get first real node next
|
|
_level++;
|
|
_it.MoveNext();
|
|
t = _it.Current;
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
public override object Dequeue()
|
|
{
|
|
object result = base.Dequeue();
|
|
if (_p == 0 && HasPositionInformation(PreviousElement))
|
|
_previousLocationElement = PreviousElement;
|
|
|
|
return result;
|
|
}
|
|
|
|
public override bool IsEndOfFile(object o)
|
|
{
|
|
return TreeAdaptor.GetType(o) == CharStreamConstants.EndOfFile;
|
|
}
|
|
|
|
public virtual int LA( int i )
|
|
{
|
|
return TreeAdaptor.GetType( LT( i ) );
|
|
}
|
|
|
|
/** Make stream jump to a new location, saving old location.
|
|
* Switch back with pop().
|
|
*/
|
|
public virtual void Push( int index )
|
|
{
|
|
if ( _calls == null )
|
|
_calls = new Stack<int>();
|
|
|
|
_calls.Push( _p ); // save current index
|
|
Seek( index );
|
|
}
|
|
|
|
/** Seek back to previous index saved during last push() call.
|
|
* Return top of stack (return index).
|
|
*/
|
|
public virtual int Pop()
|
|
{
|
|
int ret = _calls.Pop();
|
|
Seek( ret );
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Returns an element containing position information. If {@code allowApproximateLocation} is {@code false}, then
|
|
* this method will return the {@code LT(1)} element if it contains position information, and otherwise return {@code null}.
|
|
* If {@code allowApproximateLocation} is {@code true}, then this method will return the last known element containing position information.
|
|
*
|
|
* @see #hasPositionInformation
|
|
*/
|
|
public object GetKnownPositionElement(bool allowApproximateLocation)
|
|
{
|
|
object node = _data[_p];
|
|
if (HasPositionInformation(node))
|
|
return node;
|
|
|
|
if (!allowApproximateLocation)
|
|
return null;
|
|
|
|
for (int index = _p - 1; index >= 0; index--)
|
|
{
|
|
node = _data[index];
|
|
if (HasPositionInformation(node))
|
|
return node;
|
|
}
|
|
|
|
return _previousLocationElement;
|
|
}
|
|
|
|
public bool HasPositionInformation(object node)
|
|
{
|
|
IToken token = TreeAdaptor.GetToken(node);
|
|
if (token == null)
|
|
return false;
|
|
|
|
if (token.Line <= 0)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
#region Tree rewrite interface
|
|
|
|
public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t )
|
|
{
|
|
if ( parent != null )
|
|
{
|
|
TreeAdaptor.ReplaceChildren( parent, startChildIndex, stopChildIndex, t );
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
public virtual string ToString( object start, object stop )
|
|
{
|
|
// we'll have to walk from start to stop in tree; we're not keeping
|
|
// a complete node stream buffer
|
|
return "n/a";
|
|
}
|
|
|
|
/** <summary>For debugging; destructive: moves tree iterator to end.</summary> */
|
|
public virtual string ToTokenTypeString()
|
|
{
|
|
Reset();
|
|
StringBuilder buf = new StringBuilder();
|
|
object o = LT( 1 );
|
|
int type = TreeAdaptor.GetType( o );
|
|
while ( type != TokenTypes.EndOfFile )
|
|
{
|
|
buf.Append( " " );
|
|
buf.Append( type );
|
|
Consume();
|
|
o = LT( 1 );
|
|
type = TreeAdaptor.GetType( o );
|
|
}
|
|
return buf.ToString();
|
|
}
|
|
}
|
|
}
|