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 
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 {
Initialize()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          */
EnterRule(string grammarFileName, string ruleName)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          */
EnterAlt(int alt)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          */
ExitRule(string grammarFileName, string ruleName)75         void ExitRule(string grammarFileName, string ruleName);
76 
77         /** <summary>Track entry into any (...) subrule other EBNF construct</summary> */
EnterSubRule(int decisionNumber)78         void EnterSubRule(int decisionNumber);
79 
ExitSubRule(int decisionNumber)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          */
EnterDecision(int decisionNumber, bool couldBacktrack)90         void EnterDecision(int decisionNumber, bool couldBacktrack);
91 
ExitDecision(int decisionNumber)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          */
ConsumeToken(IToken t)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          */
ConsumeHiddenToken(IToken t)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          */
LT(int i, IToken t)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          */
Mark(int marker)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          */
Rewind(int marker)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          */
Rewind()144         void Rewind();
145 
BeginBacktrack(int level)146         void BeginBacktrack(int level);
147 
EndBacktrack(int level, bool successful)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          */
Location(int line, int pos)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          */
RecognitionException(RecognitionException e)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          */
BeginResync()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          */
EndResync()244         void EndResync();
245 
246         /** <summary>A semantic predicate was evaluate with this result and action text</summary> */
SemanticPredicate(bool result, string predicate)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          */
Commence()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          */
Terminate()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          */
ConsumeNode(object t)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          */
LT(int i, object t)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          */
NilNode(object t)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          */
ErrorNode(object t)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          */
CreateNode(object t)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          */
CreateNode(object node, IToken token)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          */
BecomeRoot(object newRoot, object oldRoot)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          */
AddChild(object root, object child)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          */
SetTokenBoundaries(object t, int tokenStartIndex, int tokenStopIndex)381         void SetTokenBoundaries(object t, int tokenStartIndex, int tokenStopIndex);
382 
383         #endregion
384     }
385 }
386