001: /*
002: [The "BSD licence"]
003: Copyright (c) 2005-2006 Terence Parr
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in the
013: documentation and/or other materials provided with the distribution.
014: 3. The name of the author may not be used to endorse or promote products
015: derived from this software without specific prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
018: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
019: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
020: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
021: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028: package org.antlr.runtime.debug;
029:
030: import org.antlr.runtime.RecognitionException;
031: import org.antlr.runtime.Token;
032:
033: /** All debugging events that a recognizer can trigger.
034: *
035: * I did not create a separate AST debugging interface as it would create
036: * lots of extra classes and DebugParser has a dbg var defined, which makes
037: * it hard to change to ASTDebugEventListener. I looked hard at this issue
038: * and it is easier to understand as one monolithic event interface for all
039: * possible events. Hopefully, adding ST debugging stuff won't be bad. Leave
040: * for future. 4/26/2006.
041: */
042: public interface DebugEventListener {
043: public static final String PROTOCOL_VERSION = "1";
044:
045: /** serialized version of true */
046: public static final int TRUE = 1;
047: public static final int FALSE = 0;
048:
049: /** The parser has just entered a rule. No decision has been made about
050: * which alt is predicted. This is fired AFTER init actions have been
051: * executed. Attributes are defined and available etc...
052: */
053: public void enterRule(String ruleName);
054:
055: /** Because rules can have lots of alternatives, it is very useful to
056: * know which alt you are entering. This is 1..n for n alts.
057: */
058: public void enterAlt(int alt);
059:
060: /** This is the last thing executed before leaving a rule. It is
061: * executed even if an exception is thrown. This is triggered after
062: * error reporting and recovery have occurred (unless the exception is
063: * not caught in this rule). This implies an "exitAlt" event.
064: */
065: public void exitRule(String ruleName);
066:
067: /** Track entry into any (...) subrule other EBNF construct */
068: public void enterSubRule(int decisionNumber);
069:
070: public void exitSubRule(int decisionNumber);
071:
072: /** Every decision, fixed k or arbitrary, has an enter/exit event
073: * so that a GUI can easily track what LT/consume events are
074: * associated with prediction. You will see a single enter/exit
075: * subrule but multiple enter/exit decision events, one for each
076: * loop iteration.
077: */
078: public void enterDecision(int decisionNumber);
079:
080: public void exitDecision(int decisionNumber);
081:
082: /** An input token was consumed; matched by any kind of element.
083: * Trigger after the token was matched by things like match(), matchAny().
084: */
085: public void consumeToken(Token t);
086:
087: /** An off-channel input token was consumed.
088: * Trigger after the token was matched by things like match(), matchAny().
089: * (unless of course the hidden token is first stuff in the input stream).
090: */
091: public void consumeHiddenToken(Token t);
092:
093: /** Somebody (anybody) looked ahead. Note that this actually gets
094: * triggered by both LA and LT calls. The debugger will want to know
095: * which Token object was examined. Like consumeToken, this indicates
096: * what token was seen at that depth. A remote debugger cannot look
097: * ahead into a file it doesn't have so LT events must pass the token
098: * even if the info is redundant.
099: */
100: public void LT(int i, Token t);
101:
102: /** The parser is going to look arbitrarily ahead; mark this location,
103: * the token stream's marker is sent in case you need it.
104: */
105: public void mark(int marker);
106:
107: /** After an arbitrairly long lookahead as with a cyclic DFA (or with
108: * any backtrack), this informs the debugger that stream should be
109: * rewound to the position associated with marker.
110: */
111: public void rewind(int marker);
112:
113: /** Rewind to the input position of the last marker.
114: * Used currently only after a cyclic DFA and just
115: * before starting a sem/syn predicate to get the
116: * input position back to the start of the decision.
117: * Do not "pop" the marker off the state. mark(i)
118: * and rewind(i) should balance still.
119: */
120: public void rewind();
121:
122: public void beginBacktrack(int level);
123:
124: public void endBacktrack(int level, boolean successful);
125:
126: /** To watch a parser move through the grammar, the parser needs to
127: * inform the debugger what line/charPos it is passing in the grammar.
128: * For now, this does not know how to switch from one grammar to the
129: * other and back for island grammars etc...
130: *
131: * This should also allow breakpoints because the debugger can stop
132: * the parser whenever it hits this line/pos.
133: */
134: public void location(int line, int pos);
135:
136: /** A recognition exception occurred such as NoViableAltException. I made
137: * this a generic event so that I can alter the exception hierachy later
138: * without having to alter all the debug objects.
139: *
140: * Upon error, the stack of enter rule/subrule must be properly unwound.
141: * If no viable alt occurs it is within an enter/exit decision, which
142: * also must be rewound. Even the rewind for each mark must be unwount.
143: * In the Java target this is pretty easy using try/finally, if a bit
144: * ugly in the generated code. The rewind is generated in DFA.predict()
145: * actually so no code needs to be generated for that. For languages
146: * w/o this "finally" feature (C++?), the target implementor will have
147: * to build an event stack or something.
148: *
149: * Across a socket for remote debugging, only the RecognitionException
150: * data fields are transmitted. The token object or whatever that
151: * caused the problem was the last object referenced by LT. The
152: * immediately preceding LT event should hold the unexpected Token or
153: * char.
154: *
155: * Here is a sample event trace for grammar:
156: *
157: * b : C ({;}A|B) // {;} is there to prevent A|B becoming a set
158: * | D
159: * ;
160: *
161: * The sequence for this rule (with no viable alt in the subrule) for
162: * input 'c c' (there are 3 tokens) is:
163: *
164: * commence
165: * LT(1)
166: * enterRule b
167: * location 7 1
168: * enter decision 3
169: * LT(1)
170: * exit decision 3
171: * enterAlt1
172: * location 7 5
173: * LT(1)
174: * consumeToken [c/<4>,1:0]
175: * location 7 7
176: * enterSubRule 2
177: * enter decision 2
178: * LT(1)
179: * LT(1)
180: * recognitionException NoViableAltException 2 1 2
181: * exit decision 2
182: * exitSubRule 2
183: * beginResync
184: * LT(1)
185: * consumeToken [c/<4>,1:1]
186: * LT(1)
187: * endResync
188: * LT(-1)
189: * exitRule b
190: * terminate
191: */
192: public void recognitionException(RecognitionException e);
193:
194: /** Indicates the recognizer is about to consume tokens to resynchronize
195: * the parser. Any consume events from here until the recovered event
196: * are not part of the parse--they are dead tokens.
197: */
198: public void beginResync();
199:
200: /** Indicates that the recognizer has finished consuming tokens in order
201: * to resychronize. There may be multiple beginResync/endResync pairs
202: * before the recognizer comes out of errorRecovery mode (in which
203: * multiple errors are suppressed). This will be useful
204: * in a gui where you want to probably grey out tokens that are consumed
205: * but not matched to anything in grammar. Anything between
206: * a beginResync/endResync pair was tossed out by the parser.
207: */
208: public void endResync();
209:
210: /** A semantic predicate was evaluate with this result and action text */
211: public void semanticPredicate(boolean result, String predicate);
212:
213: /** Announce that parsing has begun. Not technically useful except for
214: * sending events over a socket. A GUI for example will launch a thread
215: * to connect and communicate with a remote parser. The thread will want
216: * to notify the GUI when a connection is made. ANTLR parsers
217: * trigger this upon entry to the first rule (the ruleLevel is used to
218: * figure this out).
219: */
220: public void commence();
221:
222: /** Parsing is over; successfully or not. Mostly useful for telling
223: * remote debugging listeners that it's time to quit. When the rule
224: * invocation level goes to zero at the end of a rule, we are done
225: * parsing.
226: */
227: public void terminate();
228:
229: // T r e e P a r s i n g
230:
231: /** Input for a tree parser is an AST, but we know nothing for sure
232: * about a node except its type and text (obtained from the adaptor).
233: * This is the analog of the consumeToken method. Again, the ID is
234: * the hashCode usually of the node so it only works if hashCode is
235: * not implemented. If the type is UP or DOWN, then
236: * the ID is not really meaningful as it's fixed--there is
237: * just one UP node and one DOWN navigation node.
238: * @param t
239: */
240: public void consumeNode(Object t);
241:
242: /** The tree parser lookedahead. If the type is UP or DOWN,
243: * then the ID is not really meaningful as it's fixed--there is
244: * just one UP node and one DOWN navigation node.
245: */
246: public void LT(int i, Object t);
247:
248: // A S T E v e n t s
249:
250: /** A nil was created (even nil nodes have a unique ID...
251: * they are not "null" per se). As of 4/28/2006, this
252: * seems to be uniquely triggered when starting a new subtree
253: * such as when entering a subrule in automatic mode and when
254: * building a tree in rewrite mode.
255: *
256: * If you are receiving this event over a socket via
257: * RemoteDebugEventSocketListener then only t.ID is set.
258: */
259: public void nilNode(Object t);
260:
261: /** Announce a new node built from token elements such as type etc...
262: *
263: * If you are receiving this event over a socket via
264: * RemoteDebugEventSocketListener then only t.ID, type, text are
265: * set.
266: */
267: public void createNode(Object t);
268:
269: /** Announce a new node built from an existing token.
270: *
271: * If you are receiving this event over a socket via
272: * RemoteDebugEventSocketListener then only node.ID and token.tokenIndex
273: * are set.
274: */
275: public void createNode(Object node, Token token);
276:
277: /** Make a node the new root of an existing root. See
278: *
279: * Note: the newRootID parameter is possibly different
280: * than the TreeAdaptor.becomeRoot() newRoot parameter.
281: * In our case, it will always be the result of calling
282: * TreeAdaptor.becomeRoot() and not root_n or whatever.
283: *
284: * The listener should assume that this event occurs
285: * only when the current subrule (or rule) subtree is
286: * being reset to newRootID.
287: *
288: * If you are receiving this event over a socket via
289: * RemoteDebugEventSocketListener then only IDs are set.
290: *
291: * @see org.antlr.runtime.tree.TreeAdaptor.becomeRoot()
292: */
293: public void becomeRoot(Object newRoot, Object oldRoot);
294:
295: /** Make childID a child of rootID.
296: *
297: * If you are receiving this event over a socket via
298: * RemoteDebugEventSocketListener then only IDs are set.
299: *
300: * @see org.antlr.runtime.tree.TreeAdaptor.addChild()
301: */
302: public void addChild(Object root, Object child);
303:
304: /** Set the token start/stop token index for a subtree root or node.
305: *
306: * If you are receiving this event over a socket via
307: * RemoteDebugEventSocketListener then only t.ID is set.
308: */
309: public void setTokenBoundaries(Object t, int tokenStartIndex,
310: int tokenStopIndex);
311: }
|