/* * [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.Tree { using System.Collections.Generic; using Antlr.Runtime.Misc; using StringBuilder = System.Text.StringBuilder; using NotSupportedException = System.NotSupportedException; [System.Serializable] public class CommonTreeNodeStream : LookaheadStream, ITreeNodeStream { public const int DEFAULT_INITIAL_BUFFER_SIZE = 100; public const int INITIAL_CALL_STACK_SIZE = 10; /** Pull nodes from which tree? */ object _root; /** If this tree (root) was created from a token stream, track it. */ protected ITokenStream tokens; /** What tree adaptor was used to build these trees */ [System.NonSerialized] ITreeAdaptor _adaptor; /** The tree iterator we are using */ TreeIterator _it; /** Stack of indexes used for push/pop calls */ Stack _calls; /** Tree (nil A B C) trees like flat A B C streams */ bool _hasNilRoot = false; /** Tracks tree depth. Level=0 means we're at root node level. */ int _level = 0; 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 virtual void Reset() { base.Clear(); _it.Reset(); _hasNilRoot = false; _level = 0; 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 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(); } _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; } #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"; } /** For debugging; destructive: moves tree iterator to end. */ 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(); } } }