/runtime/CSharp2/Sources/Antlr3.Runtime/Antlr.Runtime.Tree/BufferedTreeNodeStream.cs
C# | 557 lines | 378 code | 69 blank | 110 comment | 86 complexity | 2b36766ae005ccf31b90026b8f21eb71 MD5 | raw file
- /*
- * [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 Console = System.Console;
- using IList = System.Collections.IList;
- using InvalidOperationException = System.InvalidOperationException;
- using StringBuilder = System.Text.StringBuilder;
- /** <summary>A buffered stream of tree nodes. Nodes can be from a tree of ANY kind.</summary>
- *
- * This node stream sucks all nodes out of the tree specified in
- * the constructor during construction and makes pointers into
- * the tree using an array of Object pointers. The stream necessarily
- * includes pointers to DOWN and UP and EOF nodes.
- *
- * This stream knows how to mark/release for backtracking.
- *
- * This stream is most suitable for tree interpreters that need to
- * jump around a lot or for tree parsers requiring speed (at cost of memory).
- * There is some duplicated functionality here with UnBufferedTreeNodeStream
- * but just in bookkeeping, not tree walking etc...
- *
- * TARGET DEVELOPERS:
- *
- * This is the old CommonTreeNodeStream that buffered up entire node stream.
- * No need to implement really as new CommonTreeNodeStream is much better
- * and covers what we need.
- *
- * @see CommonTreeNodeStream
- */
- public class BufferedTreeNodeStream : ITreeNodeStream, ITokenStreamInformation {
- public const int DEFAULT_INITIAL_BUFFER_SIZE = 100;
- public const int INITIAL_CALL_STACK_SIZE = 10;
- protected sealed class StreamIterator : IEnumerator<object> {
- BufferedTreeNodeStream _outer;
- int _index;
- public StreamIterator(BufferedTreeNodeStream outer) {
- _outer = outer;
- _index = -1;
- }
- #region IEnumerator<object> Members
- public object Current {
- get {
- if (_index < _outer.nodes.Count)
- return _outer.nodes[_index];
- return _outer.eof;
- }
- }
- #endregion
- #region IDisposable Members
- public void Dispose() {
- }
- #endregion
- #region IEnumerator Members
- public bool MoveNext() {
- if (_index < _outer.nodes.Count)
- _index++;
- return _index < _outer.nodes.Count;
- }
- public void Reset() {
- _index = -1;
- }
- #endregion
- }
- // all these navigation nodes are shared and hence they
- // cannot contain any line/column info
- protected object down;
- protected object up;
- protected object eof;
- /** <summary>The complete mapping from stream index to tree node.
- * This buffer includes pointers to DOWN, UP, and EOF nodes.
- * It is built upon ctor invocation. The elements are type
- * Object as we don't what the trees look like.</summary>
- *
- * Load upon first need of the buffer so we can set token types
- * of interest for reverseIndexing. Slows us down a wee bit to
- * do all of the if p==-1 testing everywhere though.
- */
- protected IList nodes;
- /** <summary>Pull nodes from which tree?</summary> */
- protected 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> */
- ITreeAdaptor adaptor;
- /** <summary>Reuse same DOWN, UP navigation nodes unless this is true</summary> */
- bool uniqueNavigationNodes = false;
- /** <summary>The index into the nodes list of the current node (next node
- * to consume). If -1, nodes array not filled yet.</summary>
- */
- protected int p = -1;
- /** <summary>Track the last mark() call result value for use in rewind().</summary> */
- protected int lastMarker;
- /** <summary>Stack of indexes used for push/pop calls</summary> */
- protected Stack<int> calls;
- public BufferedTreeNodeStream(object tree)
- : this(new CommonTreeAdaptor(), tree) {
- }
- public BufferedTreeNodeStream(ITreeAdaptor adaptor, object tree)
- : this(adaptor, tree, DEFAULT_INITIAL_BUFFER_SIZE) {
- }
- public BufferedTreeNodeStream(ITreeAdaptor adaptor, object tree, int initialBufferSize) {
- this.root = tree;
- this.adaptor = adaptor;
- nodes = new List<object>(initialBufferSize);
- down = adaptor.Create(TokenTypes.Down, "DOWN");
- up = adaptor.Create(TokenTypes.Up, "UP");
- eof = adaptor.Create(TokenTypes.EndOfFile, "EOF");
- }
- #region Properties
- public virtual int Count {
- get {
- if (p == -1) {
- throw new InvalidOperationException("Cannot determine the Count before the buffer is filled.");
- }
- return nodes.Count;
- }
- }
- public virtual object TreeSource {
- get {
- return root;
- }
- }
- public virtual string SourceName {
- get {
- 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 bool UniqueNavigationNodes {
- get {
- return uniqueNavigationNodes;
- }
- set {
- uniqueNavigationNodes = value;
- }
- }
- public virtual IToken LastToken {
- get {
- return TreeAdaptor.GetToken(LB(1));
- }
- }
- public virtual IToken LastRealToken {
- get {
- int i = 0;
- IToken token;
- do {
- i++;
- token = TreeAdaptor.GetToken(LB(i));
- } while (token != null && token.Line <= 0);
- return token;
- }
- }
- public virtual int MaxLookBehind {
- get {
- return int.MaxValue;
- }
- }
- #endregion
- /** Walk tree with depth-first-search and fill nodes buffer.
- * Don't do DOWN, UP nodes if its a list (t is isNil).
- */
- protected virtual void FillBuffer() {
- FillBuffer(root);
- //Console.Out.WriteLine( "revIndex=" + tokenTypeToStreamIndexesMap );
- p = 0; // buffer of nodes intialized now
- }
- public virtual void FillBuffer(object t) {
- bool nil = adaptor.IsNil(t);
- if (!nil) {
- nodes.Add(t); // add this node
- }
- // add DOWN node if t has children
- int n = adaptor.GetChildCount(t);
- if (!nil && n > 0) {
- AddNavigationNode(TokenTypes.Down);
- }
- // and now add all its children
- for (int c = 0; c < n; c++) {
- object child = adaptor.GetChild(t, c);
- FillBuffer(child);
- }
- // add UP node if t has children
- if (!nil && n > 0) {
- AddNavigationNode(TokenTypes.Up);
- }
- }
- /** What is the stream index for node? 0..n-1
- * Return -1 if node not found.
- */
- protected virtual int GetNodeIndex(object node) {
- if (p == -1) {
- FillBuffer();
- }
- for (int i = 0; i < nodes.Count; i++) {
- object t = nodes[i];
- if (t == node) {
- return i;
- }
- }
- return -1;
- }
- /** As we flatten the tree, we use UP, DOWN nodes to represent
- * the tree structure. When debugging we need unique nodes
- * so instantiate new ones when uniqueNavigationNodes is true.
- */
- protected virtual void AddNavigationNode(int ttype) {
- object navNode = null;
- if (ttype == TokenTypes.Down) {
- if (UniqueNavigationNodes) {
- navNode = adaptor.Create(TokenTypes.Down, "DOWN");
- } else {
- navNode = down;
- }
- } else {
- if (UniqueNavigationNodes) {
- navNode = adaptor.Create(TokenTypes.Up, "UP");
- } else {
- navNode = up;
- }
- }
- nodes.Add(navNode);
- }
- public virtual object this[int i] {
- get {
- if (p == -1) {
- throw new InvalidOperationException("Cannot get the node at index i before the buffer is filled.");
- }
- return nodes[i];
- }
- }
- public virtual object LT(int k) {
- if (p == -1) {
- FillBuffer();
- }
- if (k == 0) {
- return null;
- }
- if (k < 0) {
- return LB(-k);
- }
- //System.out.print("LT(p="+p+","+k+")=");
- if ((p + k - 1) >= nodes.Count) {
- return eof;
- }
- return nodes[p + k - 1];
- }
- public virtual object GetCurrentSymbol() {
- return LT(1);
- }
- #if false
- public virtual object getLastTreeNode()
- {
- int i = Index;
- if ( i >= size() )
- {
- i--; // if at EOF, have to start one back
- }
- Console.Out.WriteLine( "start last node: " + i + " size==" + nodes.Count );
- while ( i >= 0 &&
- ( adaptor.getType( this[i] ) == TokenTypes.EOF ||
- adaptor.getType( this[i] ) == TokenTypes.UP ||
- adaptor.getType( this[i] ) == TokenTypes.DOWN ) )
- {
- i--;
- }
- Console.Out.WriteLine( "stop at node: " + i + " " + nodes[i] );
- return nodes[i];
- }
- #endif
- /** <summary>Look backwards k nodes</summary> */
- protected virtual object LB(int k) {
- if (k == 0) {
- return null;
- }
- if ((p - k) < 0) {
- return null;
- }
- return nodes[p - k];
- }
- public virtual void Consume() {
- if (p == -1) {
- FillBuffer();
- }
- p++;
- }
- public virtual int LA(int i) {
- return adaptor.GetType(LT(i));
- }
- public virtual int Mark() {
- if (p == -1) {
- FillBuffer();
- }
- lastMarker = Index;
- return lastMarker;
- }
- public virtual void Release(int marker) {
- // no resources to release
- }
- public virtual int Index {
- get {
- return p;
- }
- }
- public virtual void Rewind(int marker) {
- Seek(marker);
- }
- public virtual void Rewind() {
- Seek(lastMarker);
- }
- public virtual void Seek(int index) {
- if (p == -1) {
- FillBuffer();
- }
- p = index;
- }
- /** <summary>
- * Make stream jump to a new location, saving old location.
- * Switch back with pop().
- * </summary>
- */
- public virtual void Push(int index) {
- if (calls == null) {
- calls = new Stack<int>();
- }
- calls.Push(p); // save current index
- Seek(index);
- }
- /** <summary>
- * Seek back to previous index saved during last push() call.
- * Return top of stack (return index).
- * </summary>
- */
- public virtual int Pop() {
- int ret = calls.Pop();
- Seek(ret);
- return ret;
- }
- public virtual void Reset() {
- p = 0;
- lastMarker = 0;
- if (calls != null) {
- calls.Clear();
- }
- }
- public virtual IEnumerator<object> Iterator() {
- if (p == -1) {
- FillBuffer();
- }
- return new StreamIterator(this);
- }
- // TREE REWRITE INTERFACE
- public virtual void ReplaceChildren(object parent, int startChildIndex, int stopChildIndex, object t) {
- if (parent != null) {
- adaptor.ReplaceChildren(parent, startChildIndex, stopChildIndex, t);
- }
- }
- /** <summary>Used for testing, just return the token type stream</summary> */
- public virtual string ToTokenTypeString() {
- if (p == -1) {
- FillBuffer();
- }
- StringBuilder buf = new StringBuilder();
- for (int i = 0; i < nodes.Count; i++) {
- object t = nodes[i];
- buf.Append(" ");
- buf.Append(adaptor.GetType(t));
- }
- return buf.ToString();
- }
- /** <summary>Debugging</summary> */
- public virtual string ToTokenString(int start, int stop) {
- if (p == -1) {
- FillBuffer();
- }
- StringBuilder buf = new StringBuilder();
- for (int i = start; i < nodes.Count && i <= stop; i++) {
- object t = nodes[i];
- buf.Append(" ");
- buf.Append(adaptor.GetToken(t));
- }
- return buf.ToString();
- }
- public virtual string ToString(object start, object stop) {
- Console.Out.WriteLine("toString");
- if (start == null || stop == null) {
- return null;
- }
- if (p == -1) {
- throw new InvalidOperationException("Buffer is not yet filled.");
- }
- //Console.Out.WriteLine( "stop: " + stop );
- if (start is CommonTree)
- Console.Out.Write("toString: " + ((CommonTree)start).Token + ", ");
- else
- Console.Out.WriteLine(start);
- if (stop is CommonTree)
- Console.Out.WriteLine(((CommonTree)stop).Token);
- else
- Console.Out.WriteLine(stop);
- // if we have the token stream, use that to dump text in order
- if (tokens != null) {
- int beginTokenIndex = adaptor.GetTokenStartIndex(start);
- int endTokenIndex = adaptor.GetTokenStopIndex(stop);
- // if it's a tree, use start/stop index from start node
- // else use token range from start/stop nodes
- if (adaptor.GetType(stop) == TokenTypes.Up) {
- endTokenIndex = adaptor.GetTokenStopIndex(start);
- } else if (adaptor.GetType(stop) == TokenTypes.EndOfFile) {
- endTokenIndex = Count - 2; // don't use EOF
- }
- return tokens.ToString(beginTokenIndex, endTokenIndex);
- }
- // walk nodes looking for start
- object t = null;
- int i = 0;
- for (; i < nodes.Count; i++) {
- t = nodes[i];
- if (t == start) {
- break;
- }
- }
- // now walk until we see stop, filling string buffer with text
- StringBuilder buf = new StringBuilder();
- t = nodes[i];
- while (t != stop) {
- string text = adaptor.GetText(t);
- if (text == null) {
- text = " " + adaptor.GetType(t).ToString();
- }
- buf.Append(text);
- i++;
- t = nodes[i];
- }
- // include stop node too
- string text2 = adaptor.GetText(stop);
- if (text2 == null) {
- text2 = " " + adaptor.GetType(stop).ToString();
- }
- buf.Append(text2);
- return buf.ToString();
- }
- }
- }