diff options
Diffstat (limited to 'runtime/CSharp3/Sources/Antlr3.Runtime/Tree')
8 files changed, 219 insertions, 60 deletions
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BaseTree.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BaseTree.cs index 79f3d97..9327860 100644 --- a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BaseTree.cs +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BaseTree.cs @@ -1,10 +1,10 @@ /* - * [The "BSD licence"] + * [The "BSD license"] * Copyright (c) 2011 Terence Parr * All rights reserved. * * Conversion to C#: - * Copyright (c) 2011 Sam Harwell, Pixel Mine, Inc. + * Copyright (c) 2011 Sam Harwell, Tunnel Vision Laboratories, LLC * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -286,6 +286,30 @@ namespace Antlr.Runtime.Tree t.ChildIndex = i; } + /** Insert child t at child position i (0..n-1) by shifting children + * i+1..n-1 to the right one position. Set parent / indexes properly + * but does NOT collapse nil-rooted t's that come in here like addChild. + */ + public virtual void InsertChild(int i, ITree t) + { + if (i < 0) + throw new ArgumentOutOfRangeException("i"); + if (i > ChildCount) + throw new ArgumentException(); + + if (i == ChildCount) + { + AddChild(t); + return; + } + + Children.Insert(i, t); + + // walk others to increment their child indexes + // set index, parent of this one too + this.FreshenParentAndChildIndexes(i); + } + public virtual object DeleteChild( int i ) { if (i < 0) @@ -428,6 +452,25 @@ namespace Antlr.Runtime.Tree } } + public virtual void FreshenParentAndChildIndexesDeeply() + { + FreshenParentAndChildIndexesDeeply(0); + } + + public virtual void FreshenParentAndChildIndexesDeeply(int offset) + { + int n = ChildCount; + for (int c = offset; c < n; c++) + { + ITree child = GetChild(c); + child.ChildIndex = c; + child.Parent = this; + BaseTree baseTree = child as BaseTree; + if (baseTree != null) + baseTree.FreshenParentAndChildIndexesDeeply(); + } + } + public virtual void SanityCheckParentAndChildIndexes() { SanityCheckParentAndChildIndexes( null, -1 ); diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTreeNodeStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTreeNodeStream.cs index 45c46be..f9cb0a7 100644 --- a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTreeNodeStream.cs +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTreeNodeStream.cs @@ -1,10 +1,10 @@ /* - * [The "BSD licence"] - * Copyright (c) 2005-2008 Terence Parr + * [The "BSD license"] + * Copyright (c) 2011 Terence Parr * All rights reserved. * * Conversion to C#: - * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. + * Copyright (c) 2011 Sam Harwell, Pixel Mine, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,35 +36,45 @@ namespace Antlr.Runtime.Tree using Antlr.Runtime.Misc; using StringBuilder = System.Text.StringBuilder; - using NotSupportedException = System.NotSupportedException; [System.Serializable] - public class CommonTreeNodeStream : LookaheadStream<object>, ITreeNodeStream + 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> */ - object _root; + 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] - ITreeAdaptor _adaptor; + private ITreeAdaptor _adaptor; /** The tree iterator we are using */ - TreeIterator _it; + private readonly TreeIterator _it; /** <summary>Stack of indexes used for push/pop calls</summary> */ - Stack<int> _calls; + private Stack<int> _calls; /** <summary>Tree (nil A B C) trees like flat A B C streams</summary> */ - bool _hasNilRoot = false; + private bool _hasNilRoot = false; /** <summary>Tracks tree depth. Level=0 means we're at root node level.</summary> */ - int _level = 0; + 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 ) @@ -97,6 +107,7 @@ namespace Antlr.Runtime.Tree { return tokens; } + set { tokens = value; @@ -138,12 +149,13 @@ namespace Antlr.Runtime.Tree #endregion - public virtual void Reset() + public override void Reset() { - base.Clear(); + base.Reset(); _it.Reset(); _hasNilRoot = false; _level = 0; + _previousLocationElement = null; if ( _calls != null ) _calls.Clear(); } @@ -181,6 +193,15 @@ namespace Antlr.Runtime.Tree 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; @@ -197,9 +218,8 @@ namespace Antlr.Runtime.Tree public virtual void Push( int index ) { if ( _calls == null ) - { _calls = new Stack<int>(); - } + _calls.Push( _p ); // save current index Seek( index ); } @@ -214,6 +234,44 @@ namespace Antlr.Runtime.Tree 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 ) diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/IPositionTrackingStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/IPositionTrackingStream.cs new file mode 100644 index 0000000..8bc8945 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/IPositionTrackingStream.cs @@ -0,0 +1,59 @@ +/* + [The "BSD license"] + Copyright (c) 2012 Terence Parr + Copyright (c) 2012 Sam Harwell + 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 +{ + /** + * + * @author Sam Harwell + */ + public interface IPositionTrackingStream + { + /** + * Returns an element containing concrete information about the current + * position in the stream. + * + * @param allowApproximateLocation if {@code false}, this method returns + * {@code null} if an element containing exact information about the current + * position is not available + */ + object GetKnownPositionElement(bool allowApproximateLocation); + + /** + * Determines if the specified {@code element} contains concrete position + * information. + * + * @param element the element to check + * @return {@code true} if {@code element} contains concrete position + * information, otherwise {@code false} + */ + bool HasPositionInformation(object element); + + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeNodeStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeNodeStream.cs index b133f39..8f3f30a 100644 --- a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeNodeStream.cs +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeNodeStream.cs @@ -47,18 +47,18 @@ namespace Antlr.Runtime.Tree } /** <summary> - * Get tree node at current input pointer + i ahead where i=1 is next node. - * i<0 indicates nodes in the past. So LT(-1) is previous node, but - * implementations are not required to provide results for k < -1. - * LT(0) is undefined. For i>=n, return null. - * Return null for LT(0) and any index that results in an absolute address - * that is negative. + * Get tree node at current input pointer + {@code k} ahead where + * {@code k==1} is next node. {@code k<0} indicates nodes in the past. So + * {@code LT(-1)} is previous node, but implementations are not required to + * provide results for {@code k < -1}. {@code LT(0)} is undefined. For + * {@code k<=n}, return {@code null}. Return {@code null} for {@code LT(0)} + * and any index that results in an absolute address that is negative. * </summary> * * <remarks> - * This is analogus to the LT() method of the TokenStream, but this - * returns a tree node instead of a token. Makes code gen identical - * for both parser and tree grammars. :) + * This is analogous to {@link TokenStream#LT}, but this returns a tree node + * instead of a {@link Token}. Makes code generation identical for both + * parser and tree grammars. * </remarks> */ object LT( int k ); @@ -74,10 +74,11 @@ namespace Antlr.Runtime.Tree } /** <summary> - * If the tree associated with this stream was created from a TokenStream, - * you can specify it here. Used to do rule $text attribute in tree - * parser. Optional unless you use tree parser rule text attribute - * or output=template and rewrite=true options. + * If the tree associated with this stream was created from a + * {@link TokenStream}, you can specify it here. Used to do rule + * {@code $text} attribute in tree parser. Optional unless you use tree + * parser rule {@code $text} attribute or {@code output=template} and + * {@code rewrite=true} options. * </summary> */ ITokenStream TokenStream @@ -96,11 +97,11 @@ namespace Antlr.Runtime.Tree } /** <summary> - * As we flatten the tree, we use UP, DOWN nodes to represent - * the tree structure. When debugging we need unique nodes - * so we have to instantiate new ones. When doing normal tree - * parsing, it's slow and a waste of memory to create unique - * navigation nodes. Default should be false; + * As we flatten the tree, we use {@link Token#UP}, {@link Token#DOWN} nodes + * to represent the tree structure. When debugging we need unique nodes so + * we have to instantiate new ones. When doing normal tree parsing, it's + * slow and a waste of memory to create unique navigation nodes. Default + * should be {@code false}. * </summary> */ bool UniqueNavigationNodes @@ -110,11 +111,11 @@ namespace Antlr.Runtime.Tree } /** <summary> - * Return the text of all nodes from start to stop, inclusive. - * If the stream does not buffer all the nodes then it can still - * walk recursively from start until stop. You can always return - * null or "" too, but users should not access $ruleLabel.text in - * an action of course in that case. + * Return the text of all nodes from {@code start} to {@code stop}, + * inclusive. If the stream does not buffer all the nodes then it can still + * walk recursively from start until stop. You can always return + * {@code null} or {@code ""} too, but users should not access + * {@code $ruleLabel.text} in an action of course in that case. * </summary> */ string ToString( object start, object stop ); @@ -123,17 +124,18 @@ namespace Antlr.Runtime.Tree #region REWRITING TREES (used by tree parser) /** <summary> - * Replace from start to stop child index of parent with t, which might - * be a list. Number of children may be different - * after this call. The stream is notified because it is walking the - * tree and might need to know you are monkeying with the underlying - * tree. Also, it might be able to modify the node stream to avoid - * restreaming for future phases. + * Replace children of {@code parent} from index {@code startChildIndex} to + * {@code stopChildIndex} with {@code t}, which might be a list. Number of + * children may be different after this call. The stream is notified because + * it is walking the tree and might need to know you are monkeying with the + * underlying tree. Also, it might be able to modify the node stream to + * avoid restreaming for future phases. * </summary> * * <remarks> - * If parent is null, don't do anything; must be at root of overall tree. - * Can't replace whatever points to the parent externally. Do nothing. + * If {@code parent} is {@code null}, don't do anything; must be at root of + * overall tree. Can't replace whatever points to the parent externally. Do + * nothing. * </remarks> */ void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t ); diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleElementStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleElementStream.cs index 8e3d5b0..cb76ace 100644 --- a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleElementStream.cs +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleElementStream.cs @@ -71,10 +71,7 @@ namespace Antlr.Runtime.Tree /** <summary>Once a node / subtree has been used in a stream, it must be dup'd * from then on. Streams are reset after subrules so that the streams * can be reused in future subrules. So, reset must set a dirty bit. - * If dirty, then next() always returns a dup. - * - * I wanted to use "naughty bit" here, but couldn't think of a way - * to use "naughty". + * If dirty, then next() always returns a dup.</summary> */ protected bool dirty = false; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeFilter.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeFilter.cs index ef7b412..ba44e2d 100644 --- a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeFilter.cs +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeFilter.cs @@ -58,8 +58,8 @@ namespace Antlr.Runtime.Tree try { // share TreeParser object but not parsing-related state - state = new RecognizerSharedState(); - input = new CommonTreeNodeStream( originalAdaptor, t ); + SetState(new RecognizerSharedState()); + SetTreeNodeStream(new CommonTreeNodeStream(originalAdaptor, t)); ( (CommonTreeNodeStream)input ).TokenStream = originalTokenStream; BacktrackingLevel = 1; whichRule(); diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeParser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeParser.cs index 927ee23..f5a1508 100644 --- a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeParser.cs +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeParser.cs @@ -58,13 +58,13 @@ namespace Antlr.Runtime.Tree public TreeParser( ITreeNodeStream input ) : base() // highlight that we go to super to set state object { - SetTreeNodeStream( input ); + this.input = input; } public TreeParser( ITreeNodeStream input, RecognizerSharedState state ) : base( state ) // share the state object with another parser { - SetTreeNodeStream( input ); + this.input = input; } public override void Reset() diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeRewriter.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeRewriter.cs index b610c2c..16a38a2 100644 --- a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeRewriter.cs +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeRewriter.cs @@ -67,8 +67,8 @@ namespace Antlr.Runtime.Tree try { // share TreeParser object but not parsing-related state - state = new RecognizerSharedState(); - input = new CommonTreeNodeStream( originalAdaptor, t ); + SetState(new RecognizerSharedState()); + SetTreeNodeStream(new CommonTreeNodeStream(originalAdaptor, t)); ( (CommonTreeNodeStream)input ).TokenStream = originalTokenStream; BacktrackingLevel = 1; IAstRuleReturnScope r = whichRule(); @@ -119,12 +119,12 @@ namespace Antlr.Runtime.Tree // methods the downup strategy uses to do the up and down rules. // to override, just define tree grammar rule topdown and turn on // filter=true. - public virtual IAstRuleReturnScope Topdown() + protected virtual IAstRuleReturnScope Topdown() { return null; } - public virtual IAstRuleReturnScope Bottomup() + protected virtual IAstRuleReturnScope Bottomup() { return null; } |