IDebugEventListener.cs revision 324c4644fee44b9898524c09511bd33c3f12e2df
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
35    /** <summary>All debugging events that a recognizer can trigger.</summary>
36     *
37     *  <remarks>
38     *  I did not create a separate AST debugging interface as it would create
39     *  lots of extra classes and DebugParser has a dbg var defined, which makes
40     *  it hard to change to ASTDebugEventListener.  I looked hard at this issue
41     *  and it is easier to understand as one monolithic event interface for all
42     *  possible events.  Hopefully, adding ST debugging stuff won't be bad.  Leave
43     *  for future. 4/26/2006.
44     *  </remarks>
45     */
46    public interface IDebugEventListener {
47        void Initialize();
48
49        /** <summary>
50         *  The parser has just entered a rule.  No decision has been made about
51         *  which alt is predicted.  This is fired AFTER init actions have been
52         *  executed.  Attributes are defined and available etc...
53         *  The grammarFileName allows composite grammars to jump around among
54         *  multiple grammar files.
55         *  </summary>
56         */
57        void EnterRule(string grammarFileName, string ruleName);
58
59        /** <summary>
60         *  Because rules can have lots of alternatives, it is very useful to
61         *  know which alt you are entering.  This is 1..n for n alts.
62         *  </summary>
63         */
64        void EnterAlt(int alt);
65
66        /** <summary>
67         *  This is the last thing executed before leaving a rule.  It is
68         *  executed even if an exception is thrown.  This is triggered after
69         *  error reporting and recovery have occurred (unless the exception is
70         *  not caught in this rule).  This implies an "exitAlt" event.
71         *  The grammarFileName allows composite grammars to jump around among
72         *  multiple grammar files.
73         *  </summary>
74         */
75        void ExitRule(string grammarFileName, string ruleName);
76
77        /** <summary>Track entry into any (...) subrule other EBNF construct</summary> */
78        void EnterSubRule(int decisionNumber);
79
80        void ExitSubRule(int decisionNumber);
81
82        /** <summary>
83         *  Every decision, fixed k or arbitrary, has an enter/exit event
84         *  so that a GUI can easily track what LT/consume events are
85         *  associated with prediction.  You will see a single enter/exit
86         *  subrule but multiple enter/exit decision events, one for each
87         *  loop iteration.
88         *  </summary>
89         */
90        void EnterDecision(int decisionNumber, bool couldBacktrack);
91
92        void ExitDecision(int decisionNumber);
93
94        /** <summary>
95         *  An input token was consumed; matched by any kind of element.
96         *  Trigger after the token was matched by things like match(), matchAny().
97         *  </summary>
98         */
99        void ConsumeToken(IToken t);
100
101        /** <summary>
102         *  An off-channel input token was consumed.
103         *  Trigger after the token was matched by things like match(), matchAny().
104         *  (unless of course the hidden token is first stuff in the input stream).
105         *  </summary>
106         */
107        void ConsumeHiddenToken(IToken t);
108
109        /** <summary>
110         *  Somebody (anybody) looked ahead.  Note that this actually gets
111         *  triggered by both LA and LT calls.  The debugger will want to know
112         *  which Token object was examined.  Like consumeToken, this indicates
113         *  what token was seen at that depth.  A remote debugger cannot look
114         *  ahead into a file it doesn't have so LT events must pass the token
115         *  even if the info is redundant.
116         *  </summary>
117         */
118        void LT(int i, IToken t);
119
120        /** <summary>
121         *  The parser is going to look arbitrarily ahead; mark this location,
122         *  the token stream's marker is sent in case you need it.
123         *  </summary>
124         */
125        void Mark(int marker);
126
127        /** <summary>
128         *  After an arbitrairly long lookahead as with a cyclic DFA (or with
129         *  any backtrack), this informs the debugger that stream should be
130         *  rewound to the position associated with marker.
131         *  </summary>
132         */
133        void Rewind(int marker);
134
135        /** <summary>
136         *  Rewind to the input position of the last marker.
137         *  Used currently only after a cyclic DFA and just
138         *  before starting a sem/syn predicate to get the
139         *  input position back to the start of the decision.
140         *  Do not "pop" the marker off the state.  mark(i)
141         *  and rewind(i) should balance still.
142         *  </summary>
143         */
144        void Rewind();
145
146        void BeginBacktrack(int level);
147
148        void EndBacktrack(int level, bool successful);
149
150        /** <summary>
151         *  To watch a parser move through the grammar, the parser needs to
152         *  inform the debugger what line/charPos it is passing in the grammar.
153         *  For now, this does not know how to switch from one grammar to the
154         *  other and back for island grammars etc...
155         *  </summary>
156         *
157         *  <remarks>
158         *  This should also allow breakpoints because the debugger can stop
159         *  the parser whenever it hits this line/pos.
160         *  </remarks>
161         */
162        void Location(int line, int pos);
163
164        /** <summary>
165         *  A recognition exception occurred such as NoViableAltException.  I made
166         *  this a generic event so that I can alter the exception hierachy later
167         *  without having to alter all the debug objects.
168         *  </summary>
169         *
170         *  <remarks>
171         *  Upon error, the stack of enter rule/subrule must be properly unwound.
172         *  If no viable alt occurs it is within an enter/exit decision, which
173         *  also must be rewound.  Even the rewind for each mark must be unwount.
174         *  In the Java target this is pretty easy using try/finally, if a bit
175         *  ugly in the generated code.  The rewind is generated in DFA.predict()
176         *  actually so no code needs to be generated for that.  For languages
177         *  w/o this "finally" feature (C++?), the target implementor will have
178         *  to build an event stack or something.
179         *
180         *  Across a socket for remote debugging, only the RecognitionException
181         *  data fields are transmitted.  The token object or whatever that
182         *  caused the problem was the last object referenced by LT.  The
183         *  immediately preceding LT event should hold the unexpected Token or
184         *  char.
185         *
186         *  Here is a sample event trace for grammar:
187         *
188         *  b : C ({;}A|B) // {;} is there to prevent A|B becoming a set
189         *    | D
190         *    ;
191         *
192         *  The sequence for this rule (with no viable alt in the subrule) for
193         *  input 'c c' (there are 3 tokens) is:
194         *
195         *		commence
196         *		LT(1)
197         *		enterRule b
198         *		location 7 1
199         *		enter decision 3
200         *		LT(1)
201         *		exit decision 3
202         *		enterAlt1
203         *		location 7 5
204         *		LT(1)
205         *		consumeToken [c/<4>,1:0]
206         *		location 7 7
207         *		enterSubRule 2
208         *		enter decision 2
209         *		LT(1)
210         *		LT(1)
211         *		recognitionException NoViableAltException 2 1 2
212         *		exit decision 2
213         *		exitSubRule 2
214         *		beginResync
215         *		LT(1)
216         *		consumeToken [c/<4>,1:1]
217         *		LT(1)
218         *		endResync
219         *		LT(-1)
220         *		exitRule b
221         *		terminate
222         *  </remarks>
223         */
224        void RecognitionException(RecognitionException e);
225
226        /** <summary>
227         *  Indicates the recognizer is about to consume tokens to resynchronize
228         *  the parser.  Any consume events from here until the recovered event
229         *  are not part of the parse--they are dead tokens.
230         *  </summary>
231         */
232        void BeginResync();
233
234        /** <summary>
235         *  Indicates that the recognizer has finished consuming tokens in order
236         *  to resychronize.  There may be multiple beginResync/endResync pairs
237         *  before the recognizer comes out of errorRecovery mode (in which
238         *  multiple errors are suppressed).  This will be useful
239         *  in a gui where you want to probably grey out tokens that are consumed
240         *  but not matched to anything in grammar.  Anything between
241         *  a beginResync/endResync pair was tossed out by the parser.
242         *  </summary>
243         */
244        void EndResync();
245
246        /** <summary>A semantic predicate was evaluate with this result and action text</summary> */
247        void SemanticPredicate(bool result, string predicate);
248
249        /** <summary>
250         *  Announce that parsing has begun.  Not technically useful except for
251         *  sending events over a socket.  A GUI for example will launch a thread
252         *  to connect and communicate with a remote parser.  The thread will want
253         *  to notify the GUI when a connection is made.  ANTLR parsers
254         *  trigger this upon entry to the first rule (the ruleLevel is used to
255         *  figure this out).
256         *  </summary>
257         */
258        void Commence();
259
260        /** <summary>
261         *  Parsing is over; successfully or not.  Mostly useful for telling
262         *  remote debugging listeners that it's time to quit.  When the rule
263         *  invocation level goes to zero at the end of a rule, we are done
264         *  parsing.
265         *  </summary>
266         */
267        void Terminate();
268
269
270        #region Tree Parsing
271
272        /** <summary>
273         *  Input for a tree parser is an AST, but we know nothing for sure
274         *  about a node except its type and text (obtained from the adaptor).
275         *  This is the analog of the consumeToken method.  Again, the ID is
276         *  the hashCode usually of the node so it only works if hashCode is
277         *  not implemented.  If the type is UP or DOWN, then
278         *  the ID is not really meaningful as it's fixed--there is
279         *  just one UP node and one DOWN navigation node.
280         *  </summary>
281         *
282         *  <param name="t" />
283         */
284        void ConsumeNode(object t);
285
286        /** <summary>
287         *  The tree parser lookedahead.  If the type is UP or DOWN,
288         *  then the ID is not really meaningful as it's fixed--there is
289         *  just one UP node and one DOWN navigation node.
290         *  </summary>
291         */
292        void LT(int i, object t);
293
294        #endregion
295
296
297        #region AST Events
298
299        /** <summary>
300         *  A nil was created (even nil nodes have a unique ID...
301         *  they are not "null" per se).  As of 4/28/2006, this
302         *  seems to be uniquely triggered when starting a new subtree
303         *  such as when entering a subrule in automatic mode and when
304         *  building a tree in rewrite mode.
305         *  </summary>
306         *
307         *  <remarks>
308         *  If you are receiving this event over a socket via
309         *  RemoteDebugEventSocketListener then only t.ID is set.
310         *  </remarks>
311         */
312        void NilNode(object t);
313
314        /** <summary>
315         *  Upon syntax error, recognizers bracket the error with an error node
316         *  if they are building ASTs.
317         *  </summary>
318         *
319         *  <param name="t"/>
320         */
321        void ErrorNode(object t);
322
323        /** <summary>Announce a new node built from token elements such as type etc...</summary>
324         *
325         *  <remarks>
326         *  If you are receiving this event over a socket via
327         *  RemoteDebugEventSocketListener then only t.ID, type, text are
328         *  set.
329         *  </remarks>
330         */
331        void CreateNode(object t);
332
333        /** <summary>Announce a new node built from an existing token.</summary>
334         *
335         *  <remarks>
336         *  If you are receiving this event over a socket via
337         *  RemoteDebugEventSocketListener then only node.ID and token.tokenIndex
338         *  are set.
339         *  </remarks>
340         */
341        void CreateNode(object node, IToken token);
342
343        /** <summary>Make a node the new root of an existing root.  See</summary>
344         *
345         *  <remarks>
346         *  Note: the newRootID parameter is possibly different
347         *  than the TreeAdaptor.becomeRoot() newRoot parameter.
348         *  In our case, it will always be the result of calling
349         *  TreeAdaptor.becomeRoot() and not root_n or whatever.
350         *
351         *  The listener should assume that this event occurs
352         *  only when the current subrule (or rule) subtree is
353         *  being reset to newRootID.
354         *
355         *  If you are receiving this event over a socket via
356         *  RemoteDebugEventSocketListener then only IDs are set.
357         *  </remarks>
358         *
359         *  <seealso cref="Antlr.Runtime.Tree.TreeAdaptor.becomeRoot()"/>
360         */
361        void BecomeRoot(object newRoot, object oldRoot);
362
363        /** <summary>Make childID a child of rootID.</summary>
364         *
365         *  <remarks>
366         *  If you are receiving this event over a socket via
367         *  RemoteDebugEventSocketListener then only IDs are set.
368         *  </remarks>
369         *
370         *  <seealso cref="Antlr.Runtime.Tree.TreeAdaptor.addChild()"/>
371         */
372        void AddChild(object root, object child);
373
374        /** <summary>Set the token start/stop token index for a subtree root or node.</summary>
375         *
376         *  <remarks>
377         *  If you are receiving this event over a socket via
378         *  RemoteDebugEventSocketListener then only t.ID is set.
379         *  </remarks>
380         */
381        void SetTokenBoundaries(object t, int tokenStartIndex, int tokenStopIndex);
382
383        #endregion
384    }
385}
386