1 /*
2  * [The "BSD licence"]
3  * Copyright (c) 2005-2008 Terence Parr
4  * All rights reserved.
5  *
6  * Conversion to C#:
7  * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 namespace Antlr.Runtime.Debug {
34     using ITreeAdaptor = Antlr.Runtime.Tree.ITreeAdaptor;
35 
36     /** <summary>
37      *  A TreeAdaptor proxy that fires debugging events to a DebugEventListener
38      *  delegate and uses the TreeAdaptor delegate to do the actual work.  All
39      *  AST events are triggered by this adaptor; no code gen changes are needed
40      *  in generated rules.  Debugging events are triggered *after* invoking
41      *  tree adaptor routines.
42      *  </summary>
43      *
44      *  <remarks>
45      *  Trees created with actions in rewrite actions like "-&gt; ^(ADD {foo} {bar})"
46      *  cannot be tracked as they might not use the adaptor to create foo, bar.
47      *  The debug listener has to deal with tree node IDs for which it did
48      *  not see a createNode event.  A single &lt;unknown&gt; node is sufficient even
49      *  if it represents a whole tree.
50      *  </remarks>
51      */
52     public class DebugTreeAdaptor : ITreeAdaptor {
53         protected IDebugEventListener dbg;
54         protected ITreeAdaptor adaptor;
55 
DebugTreeAdaptor(IDebugEventListener dbg, ITreeAdaptor adaptor)56         public DebugTreeAdaptor(IDebugEventListener dbg, ITreeAdaptor adaptor) {
57             this.dbg = dbg;
58             this.adaptor = adaptor;
59         }
60 
Create(IToken payload)61         public virtual object Create(IToken payload) {
62             if (payload.TokenIndex < 0) {
63                 // could be token conjured up during error recovery
64                 return Create(payload.Type, payload.Text);
65             }
66             object node = adaptor.Create(payload);
67             dbg.CreateNode(node, payload);
68             return node;
69         }
70 
ErrorNode(ITokenStream input, IToken start, IToken stop, RecognitionException e)71         public virtual object ErrorNode(ITokenStream input, IToken start, IToken stop,
72                                 RecognitionException e) {
73             object node = adaptor.ErrorNode(input, start, stop, e);
74             if (node != null) {
75                 dbg.ErrorNode(node);
76             }
77             return node;
78         }
79 
DupTree(object tree)80         public virtual object DupTree(object tree) {
81             object t = adaptor.DupTree(tree);
82             // walk the tree and emit create and add child events
83             // to simulate what dupTree has done. dupTree does not call this debug
84             // adapter so I must simulate.
85             SimulateTreeConstruction(t);
86             return t;
87         }
88 
89         /** <summary>^(A B C): emit create A, create B, add child, ...</summary> */
SimulateTreeConstruction(object t)90         protected virtual void SimulateTreeConstruction(object t) {
91             dbg.CreateNode(t);
92             int n = adaptor.GetChildCount(t);
93             for (int i = 0; i < n; i++) {
94                 object child = adaptor.GetChild(t, i);
95                 SimulateTreeConstruction(child);
96                 dbg.AddChild(t, child);
97             }
98         }
99 
DupNode(object treeNode)100         public virtual object DupNode(object treeNode) {
101             object d = adaptor.DupNode(treeNode);
102             dbg.CreateNode(d);
103             return d;
104         }
105 
Nil()106         public virtual object Nil() {
107             object node = adaptor.Nil();
108             dbg.NilNode(node);
109             return node;
110         }
111 
IsNil(object tree)112         public virtual bool IsNil(object tree) {
113             return adaptor.IsNil(tree);
114         }
115 
AddChild(object t, object child)116         public virtual void AddChild(object t, object child) {
117             if (t == null || child == null) {
118                 return;
119             }
120             adaptor.AddChild(t, child);
121             dbg.AddChild(t, child);
122         }
123 
BecomeRoot(object newRoot, object oldRoot)124         public virtual object BecomeRoot(object newRoot, object oldRoot) {
125             object n = adaptor.BecomeRoot(newRoot, oldRoot);
126             dbg.BecomeRoot(newRoot, oldRoot);
127             return n;
128         }
129 
RulePostProcessing(object root)130         public virtual object RulePostProcessing(object root) {
131             return adaptor.RulePostProcessing(root);
132         }
133 
AddChild(object t, IToken child)134         public virtual void AddChild(object t, IToken child) {
135             object n = this.Create(child);
136             this.AddChild(t, n);
137         }
138 
BecomeRoot(IToken newRoot, object oldRoot)139         public virtual object BecomeRoot(IToken newRoot, object oldRoot) {
140             object n = this.Create(newRoot);
141             adaptor.BecomeRoot(n, oldRoot);
142             dbg.BecomeRoot(newRoot, oldRoot);
143             return n;
144         }
145 
Create(int tokenType, IToken fromToken)146         public virtual object Create(int tokenType, IToken fromToken) {
147             object node = adaptor.Create(tokenType, fromToken);
148             dbg.CreateNode(node);
149             return node;
150         }
151 
Create(int tokenType, IToken fromToken, string text)152         public virtual object Create(int tokenType, IToken fromToken, string text) {
153             object node = adaptor.Create(tokenType, fromToken, text);
154             dbg.CreateNode(node);
155             return node;
156         }
157 
Create(int tokenType, string text)158         public virtual object Create(int tokenType, string text) {
159             object node = adaptor.Create(tokenType, text);
160             dbg.CreateNode(node);
161             return node;
162         }
163 
GetType(object t)164         public virtual int GetType(object t) {
165             return adaptor.GetType(t);
166         }
167 
SetType(object t, int type)168         public virtual void SetType(object t, int type) {
169             adaptor.SetType(t, type);
170         }
171 
GetText(object t)172         public virtual string GetText(object t) {
173             return adaptor.GetText(t);
174         }
175 
SetText(object t, string text)176         public virtual void SetText(object t, string text) {
177             adaptor.SetText(t, text);
178         }
179 
GetToken(object t)180         public virtual IToken GetToken(object t) {
181             return adaptor.GetToken(t);
182         }
183 
SetTokenBoundaries(object t, IToken startToken, IToken stopToken)184         public virtual void SetTokenBoundaries(object t, IToken startToken, IToken stopToken) {
185             adaptor.SetTokenBoundaries(t, startToken, stopToken);
186             if (t != null && startToken != null && stopToken != null) {
187                 dbg.SetTokenBoundaries(
188                     t, startToken.TokenIndex,
189                     stopToken.TokenIndex);
190             }
191         }
192 
GetTokenStartIndex(object t)193         public virtual int GetTokenStartIndex(object t) {
194             return adaptor.GetTokenStartIndex(t);
195         }
196 
GetTokenStopIndex(object t)197         public virtual int GetTokenStopIndex(object t) {
198             return adaptor.GetTokenStopIndex(t);
199         }
200 
GetChild(object t, int i)201         public virtual object GetChild(object t, int i) {
202             return adaptor.GetChild(t, i);
203         }
204 
SetChild(object t, int i, object child)205         public virtual void SetChild(object t, int i, object child) {
206             adaptor.SetChild(t, i, child);
207         }
208 
DeleteChild(object t, int i)209         public virtual object DeleteChild(object t, int i) {
210             return DeleteChild(t, i);
211         }
212 
GetChildCount(object t)213         public virtual int GetChildCount(object t) {
214             return adaptor.GetChildCount(t);
215         }
216 
GetUniqueID(object node)217         public virtual int GetUniqueID(object node) {
218             return adaptor.GetUniqueID(node);
219         }
220 
GetParent(object t)221         public virtual object GetParent(object t) {
222             return adaptor.GetParent(t);
223         }
224 
GetChildIndex(object t)225         public virtual int GetChildIndex(object t) {
226             return adaptor.GetChildIndex(t);
227         }
228 
SetParent(object t, object parent)229         public virtual void SetParent(object t, object parent) {
230             adaptor.SetParent(t, parent);
231         }
232 
SetChildIndex(object t, int index)233         public virtual void SetChildIndex(object t, int index) {
234             adaptor.SetChildIndex(t, index);
235         }
236 
ReplaceChildren(object parent, int startChildIndex, int stopChildIndex, object t)237         public virtual void ReplaceChildren(object parent, int startChildIndex, int stopChildIndex, object t) {
238             adaptor.ReplaceChildren(parent, startChildIndex, stopChildIndex, t);
239         }
240 
241         #region support
242 
GetDebugListener()243         public virtual IDebugEventListener GetDebugListener() {
244             return dbg;
245         }
246 
SetDebugListener(IDebugEventListener dbg)247         public virtual void SetDebugListener(IDebugEventListener dbg) {
248             this.dbg = dbg;
249         }
250 
GetTreeAdaptor()251         public virtual ITreeAdaptor GetTreeAdaptor() {
252             return adaptor;
253         }
254 
255         #endregion
256     }
257 }
258