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
33namespace Antlr.Runtime.Debug {
34    using System.Collections.Generic;
35
36    /** <summary>
37     *  Broadcast debug events to multiple listeners.  Lets you debug and still
38     *  use the event mechanism to build parse trees etc...  Not thread-safe.
39     *  Don't add events in one thread while parser fires events in another.
40     *  </summary>
41     *
42     *  <seealso cref="DebugEventRepeater"/>
43     */
44    public class DebugEventHub : IDebugEventListener {
45        List<IDebugEventListener> _listeners = new List<IDebugEventListener>();
46
47        public DebugEventHub(params IDebugEventListener[] listeners) {
48            _listeners = new List<IDebugEventListener>(listeners);
49        }
50
51        public virtual void Initialize() {
52        }
53
54        /** <summary>
55         *  Add another listener to broadcast events too.  Not thread-safe.
56         *  Don't add events in one thread while parser fires events in another.
57         *  </summary>
58         */
59        public virtual void AddListener(IDebugEventListener listener) {
60            _listeners.Add(listener);
61        }
62
63        /* To avoid a mess like this:
64            public void enterRule(final String ruleName) {
65                broadcast(new Code(){
66                    public void exec(DebugEventListener listener) {listener.enterRule(ruleName);}}
67                    );
68            }
69            I am dup'ing the for-loop in each.  Where are Java closures!? blech!
70         */
71
72        public virtual void EnterRule(string grammarFileName, string ruleName) {
73            for (int i = 0; i < _listeners.Count; i++) {
74                IDebugEventListener listener = _listeners[i];
75                listener.EnterRule(grammarFileName, ruleName);
76            }
77        }
78
79        public virtual void ExitRule(string grammarFileName, string ruleName) {
80            for (int i = 0; i < _listeners.Count; i++) {
81                IDebugEventListener listener = _listeners[i];
82                listener.ExitRule(grammarFileName, ruleName);
83            }
84        }
85
86        public virtual void EnterAlt(int alt) {
87            for (int i = 0; i < _listeners.Count; i++) {
88                IDebugEventListener listener = _listeners[i];
89                listener.EnterAlt(alt);
90            }
91        }
92
93        public virtual void EnterSubRule(int decisionNumber) {
94            for (int i = 0; i < _listeners.Count; i++) {
95                IDebugEventListener listener = _listeners[i];
96                listener.EnterSubRule(decisionNumber);
97            }
98        }
99
100        public virtual void ExitSubRule(int decisionNumber) {
101            for (int i = 0; i < _listeners.Count; i++) {
102                IDebugEventListener listener = _listeners[i];
103                listener.ExitSubRule(decisionNumber);
104            }
105        }
106
107        public virtual void EnterDecision(int decisionNumber, bool couldBacktrack) {
108            for (int i = 0; i < _listeners.Count; i++) {
109                IDebugEventListener listener = _listeners[i];
110                listener.EnterDecision(decisionNumber, couldBacktrack);
111            }
112        }
113
114        public virtual void ExitDecision(int decisionNumber) {
115            for (int i = 0; i < _listeners.Count; i++) {
116                IDebugEventListener listener = _listeners[i];
117                listener.ExitDecision(decisionNumber);
118            }
119        }
120
121        public virtual void Location(int line, int pos) {
122            for (int i = 0; i < _listeners.Count; i++) {
123                IDebugEventListener listener = _listeners[i];
124                listener.Location(line, pos);
125            }
126        }
127
128        public virtual void ConsumeToken(IToken token) {
129            for (int i = 0; i < _listeners.Count; i++) {
130                IDebugEventListener listener = _listeners[i];
131                listener.ConsumeToken(token);
132            }
133        }
134
135        public virtual void ConsumeHiddenToken(IToken token) {
136            for (int i = 0; i < _listeners.Count; i++) {
137                IDebugEventListener listener = _listeners[i];
138                listener.ConsumeHiddenToken(token);
139            }
140        }
141
142        public virtual void LT(int index, IToken t) {
143            for (int i = 0; i < _listeners.Count; i++) {
144                IDebugEventListener listener = _listeners[i];
145                listener.LT(index, t);
146            }
147        }
148
149        public virtual void Mark(int index) {
150            for (int i = 0; i < _listeners.Count; i++) {
151                IDebugEventListener listener = _listeners[i];
152                listener.Mark(index);
153            }
154        }
155
156        public virtual void Rewind(int index) {
157            for (int i = 0; i < _listeners.Count; i++) {
158                IDebugEventListener listener = _listeners[i];
159                listener.Rewind(index);
160            }
161        }
162
163        public virtual void Rewind() {
164            for (int i = 0; i < _listeners.Count; i++) {
165                IDebugEventListener listener = _listeners[i];
166                listener.Rewind();
167            }
168        }
169
170        public virtual void BeginBacktrack(int level) {
171            for (int i = 0; i < _listeners.Count; i++) {
172                IDebugEventListener listener = _listeners[i];
173                listener.BeginBacktrack(level);
174            }
175        }
176
177        public virtual void EndBacktrack(int level, bool successful) {
178            for (int i = 0; i < _listeners.Count; i++) {
179                IDebugEventListener listener = _listeners[i];
180                listener.EndBacktrack(level, successful);
181            }
182        }
183
184        public virtual void RecognitionException(RecognitionException e) {
185            for (int i = 0; i < _listeners.Count; i++) {
186                IDebugEventListener listener = _listeners[i];
187                listener.RecognitionException(e);
188            }
189        }
190
191        public virtual void BeginResync() {
192            for (int i = 0; i < _listeners.Count; i++) {
193                IDebugEventListener listener = _listeners[i];
194                listener.BeginResync();
195            }
196        }
197
198        public virtual void EndResync() {
199            for (int i = 0; i < _listeners.Count; i++) {
200                IDebugEventListener listener = _listeners[i];
201                listener.EndResync();
202            }
203        }
204
205        public virtual void SemanticPredicate(bool result, string predicate) {
206            for (int i = 0; i < _listeners.Count; i++) {
207                IDebugEventListener listener = _listeners[i];
208                listener.SemanticPredicate(result, predicate);
209            }
210        }
211
212        public virtual void Commence() {
213            for (int i = 0; i < _listeners.Count; i++) {
214                IDebugEventListener listener = _listeners[i];
215                listener.Commence();
216            }
217        }
218
219        public virtual void Terminate() {
220            for (int i = 0; i < _listeners.Count; i++) {
221                IDebugEventListener listener = _listeners[i];
222                listener.Terminate();
223            }
224        }
225
226
227        #region Tree parsing stuff
228
229        public virtual void ConsumeNode(object t) {
230            for (int i = 0; i < _listeners.Count; i++) {
231                IDebugEventListener listener = _listeners[i];
232                listener.ConsumeNode(t);
233            }
234        }
235
236        public virtual void LT(int index, object t) {
237            for (int i = 0; i < _listeners.Count; i++) {
238                IDebugEventListener listener = _listeners[i];
239                listener.LT(index, t);
240            }
241        }
242
243        #endregion
244
245
246        #region AST Stuff
247
248        public virtual void NilNode(object t) {
249            for (int i = 0; i < _listeners.Count; i++) {
250                IDebugEventListener listener = _listeners[i];
251                listener.NilNode(t);
252            }
253        }
254
255        public virtual void ErrorNode(object t) {
256            for (int i = 0; i < _listeners.Count; i++) {
257                IDebugEventListener listener = _listeners[i];
258                listener.ErrorNode(t);
259            }
260        }
261
262        public virtual void CreateNode(object t) {
263            for (int i = 0; i < _listeners.Count; i++) {
264                IDebugEventListener listener = _listeners[i];
265                listener.CreateNode(t);
266            }
267        }
268
269        public virtual void CreateNode(object node, IToken token) {
270            for (int i = 0; i < _listeners.Count; i++) {
271                IDebugEventListener listener = _listeners[i];
272                listener.CreateNode(node, token);
273            }
274        }
275
276        public virtual void BecomeRoot(object newRoot, object oldRoot) {
277            for (int i = 0; i < _listeners.Count; i++) {
278                IDebugEventListener listener = _listeners[i];
279                listener.BecomeRoot(newRoot, oldRoot);
280            }
281        }
282
283        public virtual void AddChild(object root, object child) {
284            for (int i = 0; i < _listeners.Count; i++) {
285                IDebugEventListener listener = _listeners[i];
286                listener.AddChild(root, child);
287            }
288        }
289
290        public virtual void SetTokenBoundaries(object t, int tokenStartIndex, int tokenStopIndex) {
291            for (int i = 0; i < _listeners.Count; i++) {
292                IDebugEventListener listener = _listeners[i];
293                listener.SetTokenBoundaries(t, tokenStartIndex, tokenStopIndex);
294            }
295        }
296
297        #endregion
298    }
299}
300