/* * [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; /** * 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. * * * * 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. * */ 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; } /** ^(A B C): emit create A, create B, add child, ... */ 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 } }