| /* |
| * [The "BSD licence"] |
| * 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.Debug |
| { |
| using ITreeAdaptor = Antlr.Runtime.Tree.ITreeAdaptor; |
| |
| /** <summary> |
| * A TreeAdaptor proxy that fires debugging events to a DebugEventListener |
| * delegate and uses the TreeAdaptor delegate to do the actual work. All |
| * AST events are triggered by this adaptor; no code gen changes are needed |
| * in generated rules. Debugging events are triggered *after* invoking |
| * tree adaptor routines. |
| * </summary> |
| * |
| * <remarks> |
| * Trees created with actions in rewrite actions like "-> ^(ADD {foo} {bar})" |
| * cannot be tracked as they might not use the adaptor to create foo, bar. |
| * The debug listener has to deal with tree node IDs for which it did |
| * not see a createNode event. A single <unknown> node is sufficient even |
| * if it represents a whole tree. |
| * </remarks> |
| */ |
| public class DebugTreeAdaptor : ITreeAdaptor |
| { |
| protected IDebugEventListener dbg; |
| protected ITreeAdaptor adaptor; |
| |
| public DebugTreeAdaptor( IDebugEventListener dbg, ITreeAdaptor adaptor ) |
| { |
| this.dbg = dbg; |
| this.adaptor = adaptor; |
| } |
| |
| public virtual object Create( IToken payload ) |
| { |
| if ( payload.TokenIndex < 0 ) |
| { |
| // could be token conjured up during error recovery |
| return Create( payload.Type, payload.Text ); |
| } |
| object node = adaptor.Create( payload ); |
| dbg.CreateNode( node, payload ); |
| return node; |
| } |
| |
| public virtual object ErrorNode( ITokenStream input, IToken start, IToken stop, |
| RecognitionException e ) |
| { |
| object node = adaptor.ErrorNode( input, start, stop, e ); |
| if ( node != null ) |
| { |
| dbg.ErrorNode( node ); |
| } |
| return node; |
| } |
| |
| public virtual object DupTree( object tree ) |
| { |
| object t = adaptor.DupTree( tree ); |
| // walk the tree and emit create and add child events |
| // to simulate what dupTree has done. dupTree does not call this debug |
| // adapter so I must simulate. |
| SimulateTreeConstruction( t ); |
| return t; |
| } |
| |
| /** <summary>^(A B C): emit create A, create B, add child, ...</summary> */ |
| protected virtual void SimulateTreeConstruction( object t ) |
| { |
| dbg.CreateNode( t ); |
| int n = adaptor.GetChildCount( t ); |
| for ( int i = 0; i < n; i++ ) |
| { |
| object child = adaptor.GetChild( t, i ); |
| SimulateTreeConstruction( child ); |
| dbg.AddChild( t, child ); |
| } |
| } |
| |
| public virtual object DupNode( object treeNode ) |
| { |
| object d = adaptor.DupNode( treeNode ); |
| dbg.CreateNode( d ); |
| return d; |
| } |
| |
| public object DupNode(int type, object treeNode) |
| { |
| object d = adaptor.DupNode(type, treeNode); |
| dbg.CreateNode(d); |
| return d; |
| } |
| |
| public object DupNode(object treeNode, string text) |
| { |
| object d = adaptor.DupNode(treeNode, text); |
| dbg.CreateNode(d); |
| return d; |
| } |
| |
| public object DupNode(int type, object treeNode, string text) |
| { |
| object d = adaptor.DupNode(type, treeNode, text); |
| dbg.CreateNode(d); |
| return d; |
| } |
| |
| public virtual object Nil() |
| { |
| object node = adaptor.Nil(); |
| dbg.NilNode( node ); |
| return node; |
| } |
| |
| public virtual bool IsNil( object tree ) |
| { |
| return adaptor.IsNil( tree ); |
| } |
| |
| public virtual void AddChild( object t, object child ) |
| { |
| if ( t == null || child == null ) |
| { |
| return; |
| } |
| adaptor.AddChild( t, child ); |
| dbg.AddChild( t, child ); |
| } |
| |
| public virtual object BecomeRoot( object newRoot, object oldRoot ) |
| { |
| object n = adaptor.BecomeRoot( newRoot, oldRoot ); |
| dbg.BecomeRoot( newRoot, oldRoot ); |
| return n; |
| } |
| |
| public virtual object RulePostProcessing( object root ) |
| { |
| return adaptor.RulePostProcessing( root ); |
| } |
| |
| public virtual void AddChild( object t, IToken child ) |
| { |
| object n = this.Create( child ); |
| this.AddChild( t, n ); |
| } |
| |
| public virtual object BecomeRoot( IToken newRoot, object oldRoot ) |
| { |
| object n = this.Create( newRoot ); |
| adaptor.BecomeRoot( n, oldRoot ); |
| dbg.BecomeRoot( newRoot, oldRoot ); |
| return n; |
| } |
| |
| public virtual object Create( int tokenType, IToken fromToken ) |
| { |
| object node = adaptor.Create( tokenType, fromToken ); |
| dbg.CreateNode( node ); |
| return node; |
| } |
| |
| public virtual object Create( int tokenType, IToken fromToken, string text ) |
| { |
| object node = adaptor.Create( tokenType, fromToken, text ); |
| dbg.CreateNode( node ); |
| return node; |
| } |
| |
| public virtual object Create( int tokenType, string text ) |
| { |
| object node = adaptor.Create( tokenType, text ); |
| dbg.CreateNode( node ); |
| return node; |
| } |
| |
| public object Create(IToken fromToken, string text) |
| { |
| object node = adaptor.Create(fromToken, text); |
| dbg.CreateNode(node); |
| return node; |
| } |
| |
| public virtual int GetType( object t ) |
| { |
| return adaptor.GetType( t ); |
| } |
| |
| public virtual void SetType( object t, int type ) |
| { |
| adaptor.SetType( t, type ); |
| } |
| |
| public virtual string GetText( object t ) |
| { |
| return adaptor.GetText( t ); |
| } |
| |
| public virtual void SetText( object t, string text ) |
| { |
| adaptor.SetText( t, text ); |
| } |
| |
| public virtual IToken GetToken( object t ) |
| { |
| return adaptor.GetToken( t ); |
| } |
| |
| public virtual void SetTokenBoundaries( object t, IToken startToken, IToken stopToken ) |
| { |
| adaptor.SetTokenBoundaries( t, startToken, stopToken ); |
| if ( t != null && startToken != null && stopToken != null ) |
| { |
| dbg.SetTokenBoundaries( |
| t, startToken.TokenIndex, |
| stopToken.TokenIndex ); |
| } |
| } |
| |
| public virtual int GetTokenStartIndex( object t ) |
| { |
| return adaptor.GetTokenStartIndex( t ); |
| } |
| |
| public virtual int GetTokenStopIndex( object t ) |
| { |
| return adaptor.GetTokenStopIndex( t ); |
| } |
| |
| public virtual object GetChild( object t, int i ) |
| { |
| return adaptor.GetChild( t, i ); |
| } |
| |
| public virtual void SetChild( object t, int i, object child ) |
| { |
| adaptor.SetChild( t, i, child ); |
| } |
| |
| public virtual object DeleteChild( object t, int i ) |
| { |
| return DeleteChild( t, i ); |
| } |
| |
| public virtual int GetChildCount( object t ) |
| { |
| return adaptor.GetChildCount( t ); |
| } |
| |
| public virtual int GetUniqueID( object node ) |
| { |
| return adaptor.GetUniqueID( node ); |
| } |
| |
| public virtual object GetParent( object t ) |
| { |
| return adaptor.GetParent( t ); |
| } |
| |
| public virtual int GetChildIndex( object t ) |
| { |
| return adaptor.GetChildIndex( t ); |
| } |
| |
| public virtual void SetParent( object t, object parent ) |
| { |
| adaptor.SetParent( t, parent ); |
| } |
| |
| public virtual void SetChildIndex( object t, int index ) |
| { |
| adaptor.SetChildIndex( t, index ); |
| } |
| |
| public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t ) |
| { |
| adaptor.ReplaceChildren( parent, startChildIndex, stopChildIndex, t ); |
| } |
| |
| #region support |
| |
| public virtual IDebugEventListener GetDebugListener() |
| { |
| return dbg; |
| } |
| |
| public virtual void SetDebugListener( IDebugEventListener dbg ) |
| { |
| this.dbg = dbg; |
| } |
| |
| public virtual ITreeAdaptor GetTreeAdaptor() |
| { |
| return adaptor; |
| } |
| |
| #endregion |
| } |
| } |