diff options
Diffstat (limited to 'runtime/CSharp3/Sources/Antlr3.Runtime/Debug/IDebugEventListener.cs')
-rw-r--r-- | runtime/CSharp3/Sources/Antlr3.Runtime/Debug/IDebugEventListener.cs | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Debug/IDebugEventListener.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Debug/IDebugEventListener.cs new file mode 100644 index 0000000..0f5d2c5 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Debug/IDebugEventListener.cs @@ -0,0 +1,387 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +namespace Antlr.Runtime.Debug +{ + + /** <summary>All debugging events that a recognizer can trigger.</summary> + * + * <remarks> + * I did not create a separate AST debugging interface as it would create + * lots of extra classes and DebugParser has a dbg var defined, which makes + * it hard to change to ASTDebugEventListener. I looked hard at this issue + * and it is easier to understand as one monolithic event interface for all + * possible events. Hopefully, adding ST debugging stuff won't be bad. Leave + * for future. 4/26/2006. + * </remarks> + */ + public interface IDebugEventListener + { + void Initialize(); + + /** <summary> + * The parser has just entered a rule. No decision has been made about + * which alt is predicted. This is fired AFTER init actions have been + * executed. Attributes are defined and available etc... + * The grammarFileName allows composite grammars to jump around among + * multiple grammar files. + * </summary> + */ + void EnterRule( string grammarFileName, string ruleName ); + + /** <summary> + * Because rules can have lots of alternatives, it is very useful to + * know which alt you are entering. This is 1..n for n alts. + * </summary> + */ + void EnterAlt( int alt ); + + /** <summary> + * This is the last thing executed before leaving a rule. It is + * executed even if an exception is thrown. This is triggered after + * error reporting and recovery have occurred (unless the exception is + * not caught in this rule). This implies an "exitAlt" event. + * The grammarFileName allows composite grammars to jump around among + * multiple grammar files. + * </summary> + */ + void ExitRule( string grammarFileName, string ruleName ); + + /** <summary>Track entry into any (...) subrule other EBNF construct</summary> */ + void EnterSubRule( int decisionNumber ); + + void ExitSubRule( int decisionNumber ); + + /** <summary> + * Every decision, fixed k or arbitrary, has an enter/exit event + * so that a GUI can easily track what LT/consume events are + * associated with prediction. You will see a single enter/exit + * subrule but multiple enter/exit decision events, one for each + * loop iteration. + * </summary> + */ + void EnterDecision(int decisionNumber, bool couldBacktrack); + + void ExitDecision( int decisionNumber ); + + /** <summary> + * An input token was consumed; matched by any kind of element. + * Trigger after the token was matched by things like match(), matchAny(). + * </summary> + */ + void ConsumeToken( IToken t ); + + /** <summary> + * An off-channel input token was consumed. + * Trigger after the token was matched by things like match(), matchAny(). + * (unless of course the hidden token is first stuff in the input stream). + * </summary> + */ + void ConsumeHiddenToken( IToken t ); + + /** <summary> + * Somebody (anybody) looked ahead. Note that this actually gets + * triggered by both LA and LT calls. The debugger will want to know + * which Token object was examined. Like consumeToken, this indicates + * what token was seen at that depth. A remote debugger cannot look + * ahead into a file it doesn't have so LT events must pass the token + * even if the info is redundant. + * </summary> + */ + void LT( int i, IToken t ); + + /** <summary> + * The parser is going to look arbitrarily ahead; mark this location, + * the token stream's marker is sent in case you need it. + * </summary> + */ + void Mark( int marker ); + + /** <summary> + * After an arbitrairly long lookahead as with a cyclic DFA (or with + * any backtrack), this informs the debugger that stream should be + * rewound to the position associated with marker. + * </summary> + */ + void Rewind( int marker ); + + /** <summary> + * Rewind to the input position of the last marker. + * Used currently only after a cyclic DFA and just + * before starting a sem/syn predicate to get the + * input position back to the start of the decision. + * Do not "pop" the marker off the state. mark(i) + * and rewind(i) should balance still. + * </summary> + */ + void Rewind(); + + void BeginBacktrack( int level ); + + void EndBacktrack( int level, bool successful ); + + /** <summary> + * To watch a parser move through the grammar, the parser needs to + * inform the debugger what line/charPos it is passing in the grammar. + * For now, this does not know how to switch from one grammar to the + * other and back for island grammars etc... + * </summary> + * + * <remarks> + * This should also allow breakpoints because the debugger can stop + * the parser whenever it hits this line/pos. + * </remarks> + */ + void Location( int line, int pos ); + + /** <summary> + * A recognition exception occurred such as NoViableAltException. I made + * this a generic event so that I can alter the exception hierachy later + * without having to alter all the debug objects. + * </summary> + * + * <remarks> + * Upon error, the stack of enter rule/subrule must be properly unwound. + * If no viable alt occurs it is within an enter/exit decision, which + * also must be rewound. Even the rewind for each mark must be unwount. + * In the Java target this is pretty easy using try/finally, if a bit + * ugly in the generated code. The rewind is generated in DFA.predict() + * actually so no code needs to be generated for that. For languages + * w/o this "finally" feature (C++?), the target implementor will have + * to build an event stack or something. + * + * Across a socket for remote debugging, only the RecognitionException + * data fields are transmitted. The token object or whatever that + * caused the problem was the last object referenced by LT. The + * immediately preceding LT event should hold the unexpected Token or + * char. + * + * Here is a sample event trace for grammar: + * + * b : C ({;}A|B) // {;} is there to prevent A|B becoming a set + * | D + * ; + * + * The sequence for this rule (with no viable alt in the subrule) for + * input 'c c' (there are 3 tokens) is: + * + * commence + * LT(1) + * enterRule b + * location 7 1 + * enter decision 3 + * LT(1) + * exit decision 3 + * enterAlt1 + * location 7 5 + * LT(1) + * consumeToken [c/<4>,1:0] + * location 7 7 + * enterSubRule 2 + * enter decision 2 + * LT(1) + * LT(1) + * recognitionException NoViableAltException 2 1 2 + * exit decision 2 + * exitSubRule 2 + * beginResync + * LT(1) + * consumeToken [c/<4>,1:1] + * LT(1) + * endResync + * LT(-1) + * exitRule b + * terminate + * </remarks> + */ + void RecognitionException( RecognitionException e ); + + /** <summary> + * Indicates the recognizer is about to consume tokens to resynchronize + * the parser. Any consume events from here until the recovered event + * are not part of the parse--they are dead tokens. + * </summary> + */ + void BeginResync(); + + /** <summary> + * Indicates that the recognizer has finished consuming tokens in order + * to resychronize. There may be multiple beginResync/endResync pairs + * before the recognizer comes out of errorRecovery mode (in which + * multiple errors are suppressed). This will be useful + * in a gui where you want to probably grey out tokens that are consumed + * but not matched to anything in grammar. Anything between + * a beginResync/endResync pair was tossed out by the parser. + * </summary> + */ + void EndResync(); + + /** <summary>A semantic predicate was evaluate with this result and action text</summary> */ + void SemanticPredicate( bool result, string predicate ); + + /** <summary> + * Announce that parsing has begun. Not technically useful except for + * sending events over a socket. A GUI for example will launch a thread + * to connect and communicate with a remote parser. The thread will want + * to notify the GUI when a connection is made. ANTLR parsers + * trigger this upon entry to the first rule (the ruleLevel is used to + * figure this out). + * </summary> + */ + void Commence(); + + /** <summary> + * Parsing is over; successfully or not. Mostly useful for telling + * remote debugging listeners that it's time to quit. When the rule + * invocation level goes to zero at the end of a rule, we are done + * parsing. + * </summary> + */ + void Terminate(); + + + #region Tree Parsing + + /** <summary> + * Input for a tree parser is an AST, but we know nothing for sure + * about a node except its type and text (obtained from the adaptor). + * This is the analog of the consumeToken method. Again, the ID is + * the hashCode usually of the node so it only works if hashCode is + * not implemented. If the type is UP or DOWN, then + * the ID is not really meaningful as it's fixed--there is + * just one UP node and one DOWN navigation node. + * </summary> + * + * <param name="t" /> + */ + void ConsumeNode( object t ); + + /** <summary> + * The tree parser lookedahead. If the type is UP or DOWN, + * then the ID is not really meaningful as it's fixed--there is + * just one UP node and one DOWN navigation node. + * </summary> + */ + void LT( int i, object t ); + + #endregion + + + #region AST Events + + /** <summary> + * A nil was created (even nil nodes have a unique ID... + * they are not "null" per se). As of 4/28/2006, this + * seems to be uniquely triggered when starting a new subtree + * such as when entering a subrule in automatic mode and when + * building a tree in rewrite mode. + * </summary> + * + * <remarks> + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only t.ID is set. + * </remarks> + */ + void NilNode( object t ); + + /** <summary> + * Upon syntax error, recognizers bracket the error with an error node + * if they are building ASTs. + * </summary> + * + * <param name="t"/> + */ + void ErrorNode( object t ); + + /** <summary>Announce a new node built from token elements such as type etc...</summary> + * + * <remarks> + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only t.ID, type, text are + * set. + * </remarks> + */ + void CreateNode( object t ); + + /** <summary>Announce a new node built from an existing token.</summary> + * + * <remarks> + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only node.ID and token.tokenIndex + * are set. + * </remarks> + */ + void CreateNode( object node, IToken token ); + + /** <summary>Make a node the new root of an existing root. See</summary> + * + * <remarks> + * Note: the newRootID parameter is possibly different + * than the TreeAdaptor.becomeRoot() newRoot parameter. + * In our case, it will always be the result of calling + * TreeAdaptor.becomeRoot() and not root_n or whatever. + * + * The listener should assume that this event occurs + * only when the current subrule (or rule) subtree is + * being reset to newRootID. + * + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only IDs are set. + * </remarks> + * + * <seealso cref="Antlr.Runtime.Tree.TreeAdaptor.becomeRoot()"/> + */ + void BecomeRoot( object newRoot, object oldRoot ); + + /** <summary>Make childID a child of rootID.</summary> + * + * <remarks> + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only IDs are set. + * </remarks> + * + * <seealso cref="Antlr.Runtime.Tree.TreeAdaptor.addChild()"/> + */ + void AddChild( object root, object child ); + + /** <summary>Set the token start/stop token index for a subtree root or node.</summary> + * + * <remarks> + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only t.ID is set. + * </remarks> + */ + void SetTokenBoundaries( object t, int tokenStartIndex, int tokenStopIndex ); + + #endregion + } +} |