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