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