1 // [The "BSD licence"] 2 // Copyright (c) 2006-2007 Kay Roepke 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. The name of the author may not be used to endorse or promote products 14 // derived from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #import <Foundation/Foundation.h> 28 #import "Token.h" 29 #import "RecognitionException.h" 30 31 @protocol DebugEventListener 32 33 #define DebugProtocolVersion 1 34 35 /** The parser has just entered a rule. No decision has been made about 36 * which alt is predicted. This is fired AFTER init actions have been 37 * executed. Attributes are defined and available etc... 38 */ 39 - (void) enterRule:(NSString *)ruleName; 40 41 /** Because rules can have lots of alternatives, it is very useful to 42 * know which alt you are entering. This is 1..n for n alts. 43 */ 44 - (void) enterAlt:(NSInteger)alt; 45 46 /** This is the last thing executed before leaving a rule. It is 47 * executed even if an exception is thrown. This is triggered after 48 * error reporting and recovery have occurred (unless the exception is 49 * not caught in this rule). This implies an "exitAlt" event. 50 */ 51 - (void) exitRule:(NSString *)ruleName; 52 53 /** Track entry into any (...) subrule other EBNF construct */ 54 - (void) enterSubRule:(NSInteger)decisionNumber; 55 56 - (void) exitSubRule:(NSInteger)decisionNumber; 57 58 /** Every decision, fixed k or arbitrary, has an enter/exit event 59 * so that a GUI can easily track what LT/consume events are 60 * associated with prediction. You will see a single enter/exit 61 * subrule but multiple enter/exit decision events, one for each 62 * loop iteration. 63 */ 64 - (void) enterDecision:(NSInteger)decisionNumber; 65 66 - (void) exitDecision:(NSInteger)decisionNumber; 67 68 /** An input token was consumed; matched by any kind of element. 69 * Trigger after the token was matched by things like match(), matchAny(). 70 */ 71 - (void) consumeToken:(id<Token>)t; 72 73 /** An off-channel input token was consumed. 74 * Trigger after the token was matched by things like match(), matchAny(). 75 * (unless of course the hidden token is first stuff in the input stream). 76 */ 77 - (void) consumeHiddenToken:(id<Token>)t; 78 79 /** Somebody (anybody) looked ahead. Note that this actually gets 80 * triggered by both LA and LT calls. The debugger will want to know 81 * which Token object was examined. Like consumeToken, this indicates 82 * what token was seen at that depth. A remote debugger cannot look 83 * ahead into a file it doesn't have so LT events must pass the token 84 * even if the info is redundant. 85 */ 86 - (void) LT:(NSInteger)i foundToken:(id<Token>)t; 87 88 /** The parser is going to look arbitrarily ahead; mark this location, 89 * the token stream's marker is sent in case you need it. 90 */ 91 - (void) mark:(NSInteger)marker; 92 93 /** After an arbitrairly long lookahead as with a cyclic DFA (or with 94 * any backtrack), this informs the debugger that stream should be 95 * rewound to the position associated with marker. 96 */ 97 - (void) rewind:(NSInteger)marker; 98 99 /** Rewind to the input position of the last marker. 100 * Used currently only after a cyclic DFA and just 101 * before starting a sem/syn predicate to get the 102 * input position back to the start of the decision. 103 * Do not "pop" the marker off the state. mark(i) 104 * and rewind(i) should balance still. 105 */ 106 - (void) rewind; 107 108 - (void) beginBacktrack:(NSInteger)level; 109 110 - (void) endBacktrack:(NSInteger)level wasSuccessful:(BOOL)successful; 111 112 /** To watch a parser move through the grammar, the parser needs to 113 * inform the debugger what line/charPos it is passing in the grammar. 114 * For now, this does not know how to switch from one grammar to the 115 * other and back for island grammars etc... 116 * 117 * This should also allow breakpoints because the debugger can stop 118 * the parser whenever it hits this line/pos. 119 */ 120 - (void) locationLine:(NSInteger)line column:(NSInteger)pos; 121 122 /** A recognition exception occurred such as NoViableAltException. I made 123 * this a generic event so that I can alter the exception hierachy later 124 * without having to alter all the debug objects. 125 * 126 * Upon error, the stack of enter rule/subrule must be properly unwound. 127 * If no viable alt occurs it is within an enter/exit decision, which 128 * also must be rewound. Even the rewind for each mark must be unwount. 129 * In the Java target this is pretty easy using try/finally, if a bit 130 * ugly in the generated code. The rewind is generated in DFA.predict() 131 * actually so no code needs to be generated for that. For languages 132 * w/o this "finally" feature (C++?), the target implementor will have 133 * to build an event stack or something. 134 * 135 * Across a socket for remote debugging, only the RecognitionException 136 * data fields are transmitted. The token object or whatever that 137 * caused the problem was the last object referenced by LT. The 138 * immediately preceding LT event should hold the unexpected Token or 139 * char. 140 * 141 * Here is a sample event trace for grammar: 142 * 143 * b : C ({;}A|B) // {;} is there to prevent A|B becoming a set 144 * | D 145 * ; 146 * 147 * The sequence for this rule (with no viable alt in the subrule) for 148 * input 'c c' (there are 3 tokens) is: 149 * 150 * commence 151 * LT(1) 152 * enterRule b 153 * location 7 1 154 * enter decision 3 155 * LT(1) 156 * exit decision 3 157 * enterAlt1 158 * location 7 5 159 * LT(1) 160 * consumeToken [c/<4>,1:0] 161 * location 7 7 162 * enterSubRule 2 163 * enter decision 2 164 * LT(1) 165 * LT(1) 166 * recognitionException NoViableAltException 2 1 2 167 * exit decision 2 168 * exitSubRule 2 169 * beginResync 170 * LT(1) 171 * consumeToken [c/<4>,1:1] 172 * LT(1) 173 * endResync 174 * LT(-1) 175 * exitRule b 176 * terminate 177 */ 178 - (void) recognitionException:(RecognitionException *)e; 179 180 /** Indicates the recognizer is about to consume tokens to resynchronize 181 * the parser. Any consume events from here until the recovered event 182 * are not part of the parse--they are dead tokens. 183 */ 184 - (void) beginResync; 185 186 /** Indicates that the recognizer has finished consuming tokens in order 187 * to resychronize. There may be multiple beginResync/endResync pairs 188 * before the recognizer comes out of errorRecovery mode (in which 189 * multiple errors are suppressed). This will be useful 190 * in a gui where you want to probably grey out tokens that are consumed 191 * but not matched to anything in grammar. Anything between 192 * a beginResync/endResync pair was tossed out by the parser. 193 */ 194 - (void) endResync; 195 196 /** A semantic predicate was evaluate with this result and action text */ 197 - (void) semanticPredicate:(NSString *)predicate matched:(BOOL)result; 198 199 /** Announce that parsing has begun. Not technically useful except for 200 * sending events over a socket. A GUI for example will launch a thread 201 * to connect and communicate with a remote parser. The thread will want 202 * to notify the GUI when a connection is made. ANTLR parsers 203 * trigger this upon entry to the first rule (the ruleLevel is used to 204 * figure this out). 205 */ 206 - (void) commence; 207 208 /** Parsing is over; successfully or not. Mostly useful for telling 209 * remote debugging listeners that it's time to quit. When the rule 210 * invocation level goes to zero at the end of a rule, we are done 211 * parsing. 212 */ 213 - (void) terminate; 214 215 216 // T r e e P a r s i n g 217 218 /** Input for a tree parser is an AST, but we know nothing for sure 219 * about a node except its type and text (obtained from the adaptor). 220 * This is the analog of the consumeToken method. Again, the ID is 221 * the hashCode usually of the node so it only works if hashCode is 222 * not implemented. If the type is UP or DOWN, then 223 * the ID is not really meaningful as it's fixed--there is 224 * just one UP node and one DOWN navigation node. 225 */ 226 - (void) consumeNode:(NSInteger)nodeHash ofType:(NSInteger)type text:(NSString *)text; 227 228 /** The tree parser lookedahead. If the type is UP or DOWN, 229 * then the ID is not really meaningful as it's fixed--there is 230 * just one UP node and one DOWN navigation node. 231 */ 232 - (void) LT:(NSInteger)i foundNode:(unsigned)nodeHash ofType:(NSInteger)type text:(NSString *)text; 233 234 235 // A S T E v e n t s 236 237 /** A nil was created (even nil nodes have a unique ID... 238 * they are not "null" per se). As of 4/28/2006, this 239 * seems to be uniquely triggered when starting a new subtree 240 * such as when entering a subrule in automatic mode and when 241 * building a tree in rewrite mode. 242 */ 243 - (void) createNilNode:(unsigned)hash; 244 245 /** Announce a new node built from text */ 246 - (void) createNode:(unsigned)hash text:(NSString *)text type:(NSInteger)type; 247 248 /** Announce a new node built from an existing token */ 249 - (void) createNode:(unsigned)hash fromTokenAtIndex:(NSInteger)tokenIndex; 250 251 /** Make a node the new root of an existing root. See 252 * 253 * Note: the newRootID parameter is possibly different 254 * than the TreeAdaptor.becomeRoot() newRoot parameter. 255 * In our case, it will always be the result of calling 256 * TreeAdaptor.becomeRoot() and not root_n or whatever. 257 * 258 * The listener should assume that this event occurs 259 * only when the current subrule (or rule) subtree is 260 * being reset to newRootID. 261 * 262 */ 263 - (void) makeNode:(unsigned)newRootHash parentOf:(unsigned)oldRootHash; 264 265 /** Make childID a child of rootID. 266 * @see org.antlr.runtime.tree.TreeAdaptor.addChild() 267 */ 268 - (void) addChild:(unsigned)childHash toTree:(unsigned)treeHash; 269 270 /** Set the token start/stop token index for a subtree root or node */ 271 - (void) setTokenBoundariesForTree:(unsigned)nodeHash From:(NSUInteger)tokenStartIndex To:(NSUInteger)tokenStopIndex; 272 273 - (void) waitForDebuggerConnection; 274 275 @end 276