1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/* 2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * [The "BSD licence"] 3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Copyright (c) 2005-2008 Terence Parr 4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * All rights reserved. 5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Conversion to C#: 7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. 8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * All rights reserved. 9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Redistribution and use in source and binary forms, with or without 11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * modification, are permitted provided that the following conditions 12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * are met: 13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 1. Redistributions of source code must retain the above copyright 14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * notice, this list of conditions and the following disclaimer. 15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 2. Redistributions in binary form must reproduce the above copyright 16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * notice, this list of conditions and the following disclaimer in the 17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * documentation and/or other materials provided with the distribution. 18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 3. The name of the author may not be used to endorse or promote products 19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * derived from this software without specific prior written permission. 20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvernamespace Antlr.Runtime 34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver{ 35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using System.Collections.Generic; 36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using ArgumentNullException = System.ArgumentNullException; 38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using Array = System.Array; 39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using Conditional = System.Diagnostics.ConditionalAttribute; 40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using Exception = System.Exception; 41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using IDebugEventListener = Antlr.Runtime.Debug.IDebugEventListener; 42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using MethodBase = System.Reflection.MethodBase; 43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using NotSupportedException = System.NotSupportedException; 44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using Regex = System.Text.RegularExpressions.Regex; 45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using StackFrame = System.Diagnostics.StackFrame; 46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using StackTrace = System.Diagnostics.StackTrace; 47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using TextWriter = System.IO.TextWriter; 48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver using Type = System.Type; 49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * A generic recognizer that can handle recognizers generated from 52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * lexer, parser, and tree grammars. This is all the parsing 53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * support code essentially; most of it is error recovery stuff and 54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * backtracking. 55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public abstract class BaseRecognizer 58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public const int MemoRuleFailed = -2; 60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public const int MemoRuleUnknown = -1; 61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public const int InitialFollowStackSize = 100; 62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // copies from Token object for convenience in actions 64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public const int DefaultTokenChannel = TokenChannels.Default; 65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public const int Hidden = TokenChannels.Hidden; 66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public const string NextTokenRuleName = "nextToken"; 68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * State of a lexer, parser, or tree parser are collected into a state 71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * object so the state can be shared. This sharing is needed to 72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * have one grammar import others and share same error variables 73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * and other state variables. It's a kind of explicit multiple 74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * inheritance via delegation of methods and shared state. 75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected internal RecognizerSharedState state; 78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public BaseRecognizer() 80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver : this(new RecognizerSharedState()) 81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public BaseRecognizer( RecognizerSharedState state ) 85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( state == null ) 87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state = new RecognizerSharedState(); 89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver this.state = state; 91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver InitDFAs(); 92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public TextWriter TraceDestination 95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver get; 97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver set; 98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void InitDFAs() 101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>reset the parser's state; subclasses must rewinds the input stream</summary> */ 105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Reset() 106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // wack everything related to error recovery 108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( state == null ) 109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return; // no shared state work to do 111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state._fsp = -1; 113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.errorRecovery = false; 114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.lastErrorIndex = -1; 115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.failed = false; 116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.syntaxErrors = 0; 117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // wack everything related to backtracking and memoization 118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.backtracking = 0; 119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int i = 0; state.ruleMemo != null && i < state.ruleMemo.Length; i++ ) 120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { // wipe cache 121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.ruleMemo[i] = null; 122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Match current input symbol against ttype. Attempt 128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * single token insertion or deletion error recovery. If 129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * that fails, throw MismatchedTokenException. 130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * <remarks> 133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * To turn off single token insertion or deletion error 134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * recovery, override recoverFromMismatchedToken() and have it 135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * throw an exception. See TreeParser.recoverFromMismatchedToken(). 136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * This way any error in a rule will cause an exception and 137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * immediate exit from rule. Rule would recover by resynchronizing 138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * to the set of symbols that can follow rule ref. 139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </remarks> 140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual object Match( IIntStream input, int ttype, BitSet follow ) 142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("match "+((TokenStream)input).LT(1)); 144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver object matchedSymbol = GetCurrentInputSymbol( input ); 145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( input.LA( 1 ) == ttype ) 146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver input.Consume(); 148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.errorRecovery = false; 149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.failed = false; 150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return matchedSymbol; 151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( state.backtracking > 0 ) 153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.failed = true; 155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return matchedSymbol; 156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver matchedSymbol = RecoverFromMismatchedToken( input, ttype, follow ); 158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return matchedSymbol; 159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Match the wildcard: in a symbol</summary> */ 162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void MatchAny( IIntStream input ) 163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.errorRecovery = false; 165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.failed = false; 166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver input.Consume(); 167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual bool MismatchIsUnwantedToken( IIntStream input, int ttype ) 170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return input.LA( 2 ) == ttype; 172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual bool MismatchIsMissingToken( IIntStream input, BitSet follow ) 175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( follow == null ) 177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // we have no information about the follow; we can only consume 179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // a single token and hope for the best 180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return false; 181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // compute what can follow this grammar element reference 183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( follow.Member( TokenTypes.EndOfRule ) ) 184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver BitSet viableTokensFollowingThisRule = ComputeContextSensitiveRuleFOLLOW(); 186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver follow = follow.Or( viableTokensFollowingThisRule ); 187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( state._fsp >= 0 ) 188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { // remove EOR if we're not the start symbol 189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver follow.Remove( TokenTypes.EndOfRule ); 190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // if current token is consistent with what could come after set 193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // then we know we're missing a token; error recovery is free to 194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // "insert" the missing token 195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("viable tokens="+follow.toString(getTokenNames())); 197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("LT(1)="+((TokenStream)input).LT(1)); 198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // BitSet cannot handle negative numbers like -1 (EOF) so I leave EOR 200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // in follow set to indicate that the fall of the start symbol is 201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // in the set (EOF can follow). 202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( follow.Member( input.LA( 1 ) ) || follow.Member( TokenTypes.EndOfRule ) ) 203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("LT(1)=="+((TokenStream)input).LT(1)+" is consistent with what follows; inserting..."); 205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return true; 206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return false; 208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Report a recognition problem.</summary> 211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * <remarks> 213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * This method sets errorRecovery to indicate the parser is recovering 214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * not parsing. Once in recovery mode, no errors are generated. 215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * To get out of recovery mode, the parser must successfully match 216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * a token (after a resync). So it will go: 217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 1. error occurs 219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 2. enter recovery mode, report error 220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 3. consume until token found in resynch set 221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 4. try to resume parsing 222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 5. next match() will reset errorRecovery mode 223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * If you override, make sure to update syntaxErrors if you care about that. 225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </remarks> 226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void ReportError( RecognitionException e ) 228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // if we've already reported an error and have not matched a token 230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // yet successfully, don't report any errors. 231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( state.errorRecovery ) 232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.err.print("[SPURIOUS] "); 234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return; 235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.syntaxErrors++; // don't count spurious 237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.errorRecovery = true; 238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver DisplayRecognitionError( this.TokenNames, e ); 240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void DisplayRecognitionError( string[] tokenNames, 243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RecognitionException e ) 244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string hdr = GetErrorHeader( e ); 246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string msg = GetErrorMessage( e, tokenNames ); 247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver EmitErrorMessage( hdr + " " + msg ); 248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>What error message should be generated for the various exception types?</summary> 251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * <remarks> 253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Not very object-oriented code, but I like having all error message 254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * generation within one method rather than spread among all of the 255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * exception classes. This also makes it much easier for the exception 256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * handling because the exception classes do not have to have pointers back 257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * to this object to access utility routines and so on. Also, changing 258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the message for an exception type would be difficult because you 259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * would have to subclassing exception, but then somehow get ANTLR 260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * to make those kinds of exception objects instead of the default. 261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * This looks weird, but trust me--it makes the most sense in terms 262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * of flexibility. 263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * For grammar debugging, you will want to override this to add 265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * more information such as the stack frame with 266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * getRuleInvocationStack(e, this.getClass().getName()) and, 267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * for no viable alts, the decision description and state etc... 268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Override this to change the message generated for one or more 270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * exception types. 271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </remarks> 272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string GetErrorMessage( RecognitionException e, string[] tokenNames ) 274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string msg = e.Message; 276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( e is UnwantedTokenException ) 277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver UnwantedTokenException ute = (UnwantedTokenException)e; 279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string tokenName = "<unknown>"; 280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( ute.Expecting == TokenTypes.EndOfFile ) 281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokenName = "EndOfFile"; 283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokenName = tokenNames[ute.Expecting]; 287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver msg = "extraneous input " + GetTokenErrorDisplay( ute.UnexpectedToken ) + 289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver " expecting " + tokenName; 290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else if ( e is MissingTokenException ) 292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver MissingTokenException mte = (MissingTokenException)e; 294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string tokenName = "<unknown>"; 295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( mte.Expecting == TokenTypes.EndOfFile ) 296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokenName = "EndOfFile"; 298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokenName = tokenNames[mte.Expecting]; 302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver msg = "missing " + tokenName + " at " + GetTokenErrorDisplay( e.Token ); 304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else if ( e is MismatchedTokenException ) 306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver MismatchedTokenException mte = (MismatchedTokenException)e; 308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string tokenName = "<unknown>"; 309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( mte.Expecting == TokenTypes.EndOfFile ) 310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokenName = "EndOfFile"; 312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokenName = tokenNames[mte.Expecting]; 316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver msg = "mismatched input " + GetTokenErrorDisplay( e.Token ) + 318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver " expecting " + tokenName; 319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else if ( e is MismatchedTreeNodeException ) 321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e; 323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string tokenName = "<unknown>"; 324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( mtne.Expecting == TokenTypes.EndOfFile ) 325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokenName = "EndOfFile"; 327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver tokenName = tokenNames[mtne.Expecting]; 331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // workaround for a .NET framework bug (NullReferenceException) 333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string nodeText = ( mtne.Node != null ) ? mtne.Node.ToString() ?? string.Empty : string.Empty; 334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver msg = "mismatched tree node: " + nodeText + " expecting " + tokenName; 335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else if ( e is NoViableAltException ) 337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //NoViableAltException nvae = (NoViableAltException)e; 339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>" 340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // and "(decision="+nvae.decisionNumber+") and 341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // "state "+nvae.stateNumber 342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver msg = "no viable alternative at input " + GetTokenErrorDisplay( e.Token ); 343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else if ( e is EarlyExitException ) 345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //EarlyExitException eee = (EarlyExitException)e; 347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // for development, can add "(decision="+eee.decisionNumber+")" 348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver msg = "required (...)+ loop did not match anything at input " + 349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver GetTokenErrorDisplay( e.Token ); 350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else if ( e is MismatchedSetException ) 352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver MismatchedSetException mse = (MismatchedSetException)e; 354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver msg = "mismatched input " + GetTokenErrorDisplay( e.Token ) + 355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver " expecting set " + mse.Expecting; 356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else if ( e is MismatchedNotSetException ) 358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver MismatchedNotSetException mse = (MismatchedNotSetException)e; 360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver msg = "mismatched input " + GetTokenErrorDisplay( e.Token ) + 361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver " expecting set " + mse.Expecting; 362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else if ( e is FailedPredicateException ) 364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver FailedPredicateException fpe = (FailedPredicateException)e; 366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver msg = "rule " + fpe.RuleName + " failed predicate: {" + 367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver fpe.PredicateText + "}?"; 368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return msg; 370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Get number of recognition errors (lexer, parser, tree parser). Each 374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * recognizer tracks its own number. So parser and lexer each have 375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * separate count. Does not count the spurious errors found between 376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * an error and next valid token match 377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * <seealso cref="reportError()"/> 380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual int NumberOfSyntaxErrors 382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver get 384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return state.syntaxErrors; 386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>What is the error header, normally line/character position information?</summary> */ 390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string GetErrorHeader( RecognitionException e ) 391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string prefix = SourceName ?? string.Empty; 393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (prefix.Length > 0) 394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver prefix += ' '; 395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return string.Format("{0}line {1}:{2}", prefix, e.Line, e.CharPositionInLine + 1); 397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * How should a token be displayed in an error message? The default 401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * is to display just the text, but during development you might 402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * want to have a lot of information spit out. Override in that case 403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * to use t.ToString() (which, for CommonToken, dumps everything about 404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the token). This is better than forcing you to override a method in 405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * your token objects because you don't have to go modify your lexer 406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * so that it creates a new Java type. 407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string GetTokenErrorDisplay( IToken t ) 410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver string s = t.Text; 412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( s == null ) 413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( t.Type == TokenTypes.EndOfFile ) 415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver s = "<EOF>"; 417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver s = "<" + t.Type + ">"; 421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver s = Regex.Replace( s, "\n", "\\\\n" ); 424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver s = Regex.Replace( s, "\r", "\\\\r" ); 425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver s = Regex.Replace( s, "\t", "\\\\t" ); 426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return "'" + s + "'"; 427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Override this method to change where error messages go</summary> */ 430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void EmitErrorMessage( string msg ) 431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (TraceDestination != null) 433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.WriteLine( msg ); 434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Recover from an error found on the input stream. This is 438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * for NoViableAlt and mismatched symbol exceptions. If you enable 439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * single token insertion and deletion, this will usually not 440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * handle mismatched symbol exceptions but there could be a mismatched 441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * token that the match() routine could not recover from. 442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Recover( IIntStream input, RecognitionException re ) 445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( state.lastErrorIndex == input.Index ) 447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // uh oh, another error at same token index; must be a case 449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // where LT(1) is in the recovery token set so nothing is 450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // consumed; consume a single token so at least to prevent 451324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // an infinite loop; this is a failsafe. 452324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver input.Consume(); 453324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 454324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.lastErrorIndex = input.Index; 455324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver BitSet followSet = ComputeErrorRecoverySet(); 456324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver BeginResync(); 457324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ConsumeUntil( input, followSet ); 458324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver EndResync(); 459324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 460324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 461324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 462324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * A hook to listen in on the token consumption during error recovery. 463324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * The DebugParser subclasses this to fire events to the listenter. 464324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 465324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 466324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void BeginResync() 467324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 468324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 469324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 470324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void EndResync() 471324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 472324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 473324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 474324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /* Compute the error recovery set for the current rule. During 475324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * rule invocation, the parser pushes the set of tokens that can 476324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * follow that rule reference on the stack; this amounts to 477324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * computing FIRST of what follows the rule reference in the 478324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * enclosing rule. This local follow set only includes tokens 479324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * from within the rule; i.e., the FIRST computation done by 480324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ANTLR stops at the end of a rule. 481324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 482324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * EXAMPLE 483324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 484324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * When you find a "no viable alt exception", the input is not 485324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * consistent with any of the alternatives for rule r. The best 486324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * thing to do is to consume tokens until you see something that 487324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * can legally follow a call to r *or* any rule that called r. 488324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * You don't want the exact set of viable next tokens because the 489324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * input might just be missing a token--you might consume the 490324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * rest of the input looking for one of the missing tokens. 491324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 492324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Consider grammar: 493324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 494324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * a : '[' b ']' 495324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * | '(' b ')' 496324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ; 497324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * b : c '^' INT ; 498324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * c : ID 499324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * | INT 500324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ; 501324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 502324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * At each rule invocation, the set of tokens that could follow 503324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * that rule is pushed on a stack. Here are the various "local" 504324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * follow sets: 505324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 506324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * FOLLOW(b1_in_a) = FIRST(']') = ']' 507324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * FOLLOW(b2_in_a) = FIRST(')') = ')' 508324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * FOLLOW(c_in_b) = FIRST('^') = '^' 509324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 510324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Upon erroneous input "[]", the call chain is 511324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 512324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * a -> b -> c 513324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 514324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * and, hence, the follow context stack is: 515324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 516324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * depth local follow set after call to rule 517324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 0 <EOF> a (from main()) 518324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 1 ']' b 519324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 3 '^' c 520324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 521324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Notice that ')' is not included, because b would have to have 522324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * been called from a different context in rule a for ')' to be 523324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * included. 524324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 525324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * For error recovery, we cannot consider FOLLOW(c) 526324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * (context-sensitive or otherwise). We need the combined set of 527324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * all context-sensitive FOLLOW sets--the set of all tokens that 528324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * could follow any reference in the call chain. We need to 529324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * resync to one of those tokens. Note that FOLLOW(c)='^' and if 530324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * we resync'd to that token, we'd consume until EOF. We need to 531324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}. 532324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * In this case, for input "[]", LA(1) is in this set so we would 533324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * not consume anything and after printing an error rule c would 534324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * return normally. It would not find the required '^' though. 535324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * At this point, it gets a mismatched token error and throws an 536324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * exception (since LA(1) is not in the viable following token 537324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * set). The rule exception handler tries to recover, but finds 538324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the same recovery set and doesn't consume anything. Rule b 539324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * exits normally returning to rule a. Now it finds the ']' (and 540324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * with the successful match exits errorRecovery mode). 541324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 542324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * So, you cna see that the parser walks up call chain looking 543324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * for the token that was a member of the recovery set. 544324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 545324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Errors are not generated in errorRecovery mode. 546324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 547324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ANTLR's error recovery mechanism is based upon original ideas: 548324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 549324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * "Algorithms + Data Structures = Programs" by Niklaus Wirth 550324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 551324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * and 552324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 553324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * "A note on error recovery in recursive descent parsers": 554324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * http://portal.acm.org/citation.cfm?id=947902.947905 555324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 556324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Later, Josef Grosch had some good ideas: 557324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 558324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * "Efficient and Comfortable Error Recovery in Recursive Descent 559324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Parsers": 560324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip 561324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 562324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Like Grosch I implemented local FOLLOW sets that are combined 563324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * at run-time upon error to avoid overhead during parsing. 564324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 565324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual BitSet ComputeErrorRecoverySet() 566324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 567324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return CombineFollows( false ); 568324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 569324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 570324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 571324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Compute the context-sensitive FOLLOW set for current rule. 572324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * This is set of token types that can follow a specific rule 573324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * reference given a specific call chain. You get the set of 574324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * viable tokens that can possibly come next (lookahead depth 1) 575324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * given the current call chain. Contrast this with the 576324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * definition of plain FOLLOW for rule r: 577324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 578324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 579324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * FOLLOW(r)={x | S=>*alpha r beta in G and x in FIRST(beta)} 580324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 581324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * where x in T* and alpha, beta in V*; T is set of terminals and 582324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * V is the set of terminals and nonterminals. In other words, 583324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * FOLLOW(r) is the set of all tokens that can possibly follow 584324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * references to r in *any* sentential form (context). At 585324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * runtime, however, we know precisely which context applies as 586324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * we have the call chain. We may compute the exact (rather 587324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * than covering superset) set of following tokens. 588324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 589324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * For example, consider grammar: 590324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 591324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * stat : ID '=' expr ';' // FOLLOW(stat)=={EOF} 592324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * | "return" expr '.' 593324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ; 594324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * expr : atom ('+' atom)* ; // FOLLOW(expr)=={';','.',')'} 595324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * atom : INT // FOLLOW(atom)=={'+',')',';','.'} 596324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * | '(' expr ')' 597324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ; 598324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 599324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * The FOLLOW sets are all inclusive whereas context-sensitive 600324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * FOLLOW sets are precisely what could follow a rule reference. 601324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * For input input "i=(3);", here is the derivation: 602324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 603324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * stat => ID '=' expr ';' 604324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * => ID '=' atom ('+' atom)* ';' 605324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * => ID '=' '(' expr ')' ('+' atom)* ';' 606324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * => ID '=' '(' atom ')' ('+' atom)* ';' 607324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * => ID '=' '(' INT ')' ('+' atom)* ';' 608324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * => ID '=' '(' INT ')' ';' 609324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 610324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * At the "3" token, you'd have a call chain of 611324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 612324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * stat -> expr -> atom -> expr -> atom 613324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 614324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * What can follow that specific nested ref to atom? Exactly ')' 615324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * as you can see by looking at the derivation of this specific 616324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * input. Contrast this with the FOLLOW(atom)={'+',')',';','.'}. 617324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 618324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * You want the exact viable token set when recovering from a 619324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * token mismatch. Upon token mismatch, if LA(1) is member of 620324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the viable next token set, then you know there is most likely 621324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * a missing token in the input stream. "Insert" one by just not 622324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * throwing an exception. 623324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 624324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual BitSet ComputeContextSensitiveRuleFOLLOW() 625324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 626324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return CombineFollows( true ); 627324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 628324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 629324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // what is exact? it seems to only add sets from above on stack 630324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // if EOR is in set i. When it sees a set w/o EOR, it stops adding. 631324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Why would we ever want them all? Maybe no viable alt instead of 632324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // mismatched token? 633324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual BitSet CombineFollows(bool exact) 634324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 635324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int top = state._fsp; 636324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver BitSet followSet = new BitSet(); 637324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int i = top; i >= 0; i-- ) 638324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 639324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver BitSet localFollowSet = (BitSet)state.following[i]; 640324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /* 641324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver System.out.println("local follow depth "+i+"="+ 642324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver localFollowSet.toString(getTokenNames())+")"); 643324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 644324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver followSet.OrInPlace( localFollowSet ); 645324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( exact ) 646324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 647324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // can we see end of rule? 648324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( localFollowSet.Member( TokenTypes.EndOfRule ) ) 649324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 650324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // Only leave EOR in set if at top (start rule); this lets 651324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // us know if have to include follow(start rule); i.e., EOF 652324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( i > 0 ) 653324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 654324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver followSet.Remove( TokenTypes.EndOfRule ); 655324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 656324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 657324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 658324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { // can't see end of rule, quit 659324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver break; 660324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 661324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 662324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 663324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return followSet; 664324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 665324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 666324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Attempt to recover from a single missing or extra token.</summary> 667324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 668324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * EXTRA TOKEN 669324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 670324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * LA(1) is not what we are looking for. If LA(2) has the right token, 671324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * however, then assume LA(1) is some extra spurious token. Delete it 672324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * and LA(2) as if we were doing a normal match(), which advances the 673324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * input. 674324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 675324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * MISSING TOKEN 676324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 677324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * If current token is consistent with what could come after 678324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ttype then it is ok to "insert" the missing token, else throw 679324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * exception For example, Input "i=(3;" is clearly missing the 680324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ')'. When the parser returns from the nested call to expr, it 681324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * will have call chain: 682324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 683324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * stat -> expr -> atom 684324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 685324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * and it will be trying to match the ')' at this point in the 686324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * derivation: 687324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 688324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * => ID '=' '(' INT ')' ('+' atom)* ';' 689324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * ^ 690324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * match() will see that ';' doesn't match ')' and report a 691324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * mismatched token error. To recover, it sees that LA(1)==';' 692324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * is in the set of tokens that can follow the ')' token 693324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * reference in rule atom. It can assume that you forgot the ')'. 694324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 695324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual object RecoverFromMismatchedToken( IIntStream input, int ttype, BitSet follow ) 696324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 697324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RecognitionException e = null; 698324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // if next token is what we are looking for then "delete" this token 699324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( MismatchIsUnwantedToken( input, ttype ) ) 700324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 701324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver e = new UnwantedTokenException( ttype, input, TokenNames ); 702324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /* 703324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver System.err.println("recoverFromMismatchedToken deleting "+ 704324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ((TokenStream)input).LT(1)+ 705324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver " since "+((TokenStream)input).LT(2)+" is what we want"); 706324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 707324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver BeginResync(); 708324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver input.Consume(); // simply delete extra token 709324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver EndResync(); 710324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ReportError( e ); // report after consuming so AW sees the token in the exception 711324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // we want to return the token we're actually matching 712324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver object matchedSymbol = GetCurrentInputSymbol( input ); 713324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver input.Consume(); // move past ttype token as if all were ok 714324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return matchedSymbol; 715324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 716324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // can't recover with single token deletion, try insertion 717324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( MismatchIsMissingToken( input, follow ) ) 718324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 719324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver object inserted = GetMissingSymbol( input, e, ttype, follow ); 720324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver e = new MissingTokenException( ttype, input, inserted ); 721324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ReportError( e ); // report after inserting so AW sees the token in the exception 722324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return inserted; 723324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 724324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // even that didn't work; must throw the exception 725324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver e = new MismatchedTokenException(ttype, input, TokenNames); 726324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw e; 727324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 728324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 729324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** Not currently used */ 730324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual object RecoverFromMismatchedSet( IIntStream input, 731324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RecognitionException e, 732324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver BitSet follow ) 733324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 734324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( MismatchIsMissingToken( input, follow ) ) 735324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 736324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // System.out.println("missing token"); 737324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ReportError( e ); 738324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // we don't know how to conjure up a token for sets yet 739324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return GetMissingSymbol( input, e, TokenTypes.Invalid, follow ); 740324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 741324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver // TODO do single token deletion like above for Token mismatch 742324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw e; 743324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 744324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 745324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 746324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Match needs to return the current input symbol, which gets put 747324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * into the label for the associated token ref; e.g., x=ID. Token 748324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * and tree parsers need to return different objects. Rather than test 749324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * for input stream type or change the IntStream interface, I use 750324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * a simple method to ask the recognizer to tell me what the current 751324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * input symbol is. 752324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 753324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 754324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * <remarks>This is ignored for lexers.</remarks> 755324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 756324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual object GetCurrentInputSymbol( IIntStream input ) 757324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 758324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return null; 759324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 760324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 761324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Conjure up a missing token during error recovery.</summary> 762324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 763324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * <remarks> 764324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * The recognizer attempts to recover from single missing 765324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * symbols. But, actions might refer to that missing symbol. 766324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * For example, x=ID {f($x);}. The action clearly assumes 767324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * that there has been an identifier matched previously and that 768324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * $x points at that token. If that token is missing, but 769324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * the next token in the stream is what we want we assume that 770324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * this token is missing and we keep going. Because we 771324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * have to return some token to replace the missing token, 772324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * we have to conjure one up. This method gives the user control 773324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * over the tokens returned for missing tokens. Mostly, 774324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * you will want to create something special for identifier 775324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * tokens. For literals such as '{' and ',', the default 776324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * action in the parser or tree parser works. It simply creates 777324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * a CommonToken of the appropriate type. The text will be the token. 778324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * If you change what tokens must be created by the lexer, 779324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * override this method to create the appropriate tokens. 780324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </remarks> 781324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 782324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual object GetMissingSymbol( IIntStream input, 783324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver RecognitionException e, 784324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int expectedTokenType, 785324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver BitSet follow ) 786324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 787324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return null; 788324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 789324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 790324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void ConsumeUntil( IIntStream input, int tokenType ) 791324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 792324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("consumeUntil "+tokenType); 793324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int ttype = input.LA( 1 ); 794324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver while ( ttype != TokenTypes.EndOfFile && ttype != tokenType ) 795324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 796324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver input.Consume(); 797324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ttype = input.LA( 1 ); 798324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 799324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 800324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 801324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Consume tokens until one matches the given token set</summary> */ 802324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void ConsumeUntil( IIntStream input, BitSet set ) 803324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 804324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("consumeUntil("+set.toString(getTokenNames())+")"); 805324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int ttype = input.LA( 1 ); 806324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver while ( ttype != TokenTypes.EndOfFile && !set.Member( ttype ) ) 807324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 808324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("consume during recover LA(1)="+getTokenNames()[input.LA(1)]); 809324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver input.Consume(); 810324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver ttype = input.LA( 1 ); 811324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 812324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 813324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 814324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Push a rule's follow set using our own hardcoded stack</summary> */ 815324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected void PushFollow( BitSet fset ) 816324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 817324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( ( state._fsp + 1 ) >= state.following.Length ) 818324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 819324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver Array.Resize(ref state.following, state.following.Length * 2); 820324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 821324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.following[++state._fsp] = fset; 822324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 823324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 824324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected void PopFollow() 825324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 826324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state._fsp--; 827324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 828324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 829324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 830324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Return List<String> of the rules in your parser instance 831324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * leading up to a call to this method. You could override if 832324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * you want more details such as the file/line info of where 833324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * in the parser java code a rule is invoked. 834324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 835324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 836324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * <remarks> 837324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * This is very useful for error messages and for context-sensitive 838324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * error recovery. 839324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </remarks> 840324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 841324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual IList<string> GetRuleInvocationStack() 842324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 843324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return GetRuleInvocationStack( new StackTrace(true) ); 844324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 845324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 846324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 847324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * A more general version of GetRuleInvocationStack where you can 848324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * pass in the StackTrace of, for example, a RecognitionException 849324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * to get it's rule stack trace. 850324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 851324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 852324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public static IList<string> GetRuleInvocationStack(StackTrace trace) 853324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 854324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (trace == null) 855324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver throw new ArgumentNullException("trace"); 856324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 857324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver List<string> rules = new List<string>(); 858324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver StackFrame[] stack = trace.GetFrames() ?? new StackFrame[0]; 859324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 860324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for (int i = stack.Length - 1; i >= 0; i--) 861324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 862324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver StackFrame frame = stack[i]; 863324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver MethodBase method = frame.GetMethod(); 864324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver GrammarRuleAttribute[] attributes = (GrammarRuleAttribute[])method.GetCustomAttributes(typeof(GrammarRuleAttribute), true); 865324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (attributes != null && attributes.Length > 0) 866324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver rules.Add(attributes[0].Name); 867324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 868324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 869324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return rules; 870324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 871324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 872324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual int BacktrackingLevel 873324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 874324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver get 875324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 876324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return state.backtracking; 877324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 878324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver set 879324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 880324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.backtracking = value; 881324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 882324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 883324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 884324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>Return whether or not a backtracking attempt failed.</summary> */ 885324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual bool Failed 886324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 887324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver get 888324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 889324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return state.failed; 890324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 891324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 892324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 893324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 894324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Used to print out token names like ID during debugging and 895324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * error reporting. The generated parsers implement a method 896324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * that overrides this to point to their String[] tokenNames. 897324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 898324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 899324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string[] TokenNames 900324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 901324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver get 902324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 903324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return null; 904324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 905324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 906324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 907324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 908324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * For debugging and other purposes, might want the grammar name. 909324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Have ANTLR generate an implementation for this method. 910324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 911324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 912324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual string GrammarFileName 913324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 914324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver get 915324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 916324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return null; 917324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 918324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 919324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 920324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public abstract string SourceName 921324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 922324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver get; 923324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 924324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 925324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 926324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * A convenience method for use most often with template rewrites. 927324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Convert a List<Token> to List<String> 928324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 929324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 930324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual List<string> ToStrings( ICollection<IToken> tokens ) 931324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 932324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( tokens == null ) 933324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return null; 934324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 935324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver List<string> strings = new List<string>( tokens.Count ); 936324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver foreach ( IToken token in tokens ) 937324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 938324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver strings.Add( token.Text ); 939324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 940324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 941324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return strings; 942324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 943324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 944324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 945324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Given a rule number and a start token index number, return 946324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * MEMO_RULE_UNKNOWN if the rule has not parsed input starting from 947324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * start index. If this rule has parsed input starting from the 948324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * start index before, then return where the rule stopped parsing. 949324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * It returns the index of the last token matched by the rule. 950324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 951324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 952324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * <remarks> 953324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * For now we use a hashtable and just the slow Object-based one. 954324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Later, we can make a special one for ints and also one that 955324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * tosses out data after we commit past input position i. 956324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </remarks> 957324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 958324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual int GetRuleMemoization( int ruleIndex, int ruleStartIndex ) 959324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 960324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( state.ruleMemo[ruleIndex] == null ) 961324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 962324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.ruleMemo[ruleIndex] = new Dictionary<int, int>(); 963324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 964324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 965324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int stopIndex; 966324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( !state.ruleMemo[ruleIndex].TryGetValue( ruleStartIndex, out stopIndex ) ) 967324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return MemoRuleUnknown; 968324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 969324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return stopIndex; 970324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 971324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 972324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 973324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Has this rule already parsed input at the current index in the 974324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * input stream? Return the stop token index or MEMO_RULE_UNKNOWN. 975324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * If we attempted but failed to parse properly before, return 976324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * MEMO_RULE_FAILED. 977324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 978324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 979324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * <remarks> 980324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * This method has a side-effect: if we have seen this input for 981324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * this rule and successfully parsed before, then seek ahead to 982324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * 1 past the stop token matched for this rule last time. 983324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </remarks> 984324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 985324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual bool AlreadyParsedRule( IIntStream input, int ruleIndex ) 986324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 987324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int stopIndex = GetRuleMemoization( ruleIndex, input.Index ); 988324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( stopIndex == MemoRuleUnknown ) 989324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 990324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return false; 991324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 992324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( stopIndex == MemoRuleFailed ) 993324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 994324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("rule "+ruleIndex+" will never succeed"); 995324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.failed = true; 996324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 997324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 998324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 999324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver //System.out.println("seen rule "+ruleIndex+" before; skipping ahead to @"+(stopIndex+1)+" failed="+state.failed); 1000324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver input.Seek( stopIndex + 1 ); // jump to one past stop token 1001324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1002324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return true; 1003324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1004324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1005324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary> 1006324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * Record whether or not this rule parsed the input at this position 1007324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * successfully. Use a standard java hashtable for now. 1008324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * </summary> 1009324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 1010324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void Memoize( IIntStream input, 1011324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int ruleIndex, 1012324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int ruleStartIndex ) 1013324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1014324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int stopTokenIndex = state.failed ? MemoRuleFailed : input.Index - 1; 1015324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( state.ruleMemo == null ) 1016324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1017324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (TraceDestination != null) 1018324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.WriteLine( "!!!!!!!!! memo array is null for " + GrammarFileName ); 1019324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1020324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( ruleIndex >= state.ruleMemo.Length ) 1021324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1022324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (TraceDestination != null) 1023324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.WriteLine("!!!!!!!!! memo size is " + state.ruleMemo.Length + ", but rule index is " + ruleIndex); 1024324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1025324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( state.ruleMemo[ruleIndex] != null ) 1026324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1027324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver state.ruleMemo[ruleIndex][ruleStartIndex] = stopTokenIndex; 1028324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1029324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1030324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1031324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver /** <summary>return how many rule/input-index pairs there are in total.</summary> 1032324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * TODO: this includes synpreds. :( 1033324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */ 1034324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual int GetRuleMemoizationCacheSize() 1035324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1036324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver int n = 0; 1037324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver for ( int i = 0; state.ruleMemo != null && i < state.ruleMemo.Length; i++ ) 1038324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1039324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver var ruleMap = state.ruleMemo[i]; 1040324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if ( ruleMap != null ) 1041324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1042324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver n += ruleMap.Count; // how many input indexes are recorded? 1043324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1044324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1045324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return n; 1046324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1047324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1048324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void TraceIn(string ruleName, int ruleIndex, object inputSymbol) 1049324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1050324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (TraceDestination == null) 1051324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return; 1052324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1053324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.Write("enter " + ruleName + " " + inputSymbol); 1054324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (state.backtracking > 0) 1055324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1056324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.Write(" backtracking=" + state.backtracking); 1057324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1058324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.WriteLine(); 1059324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1060324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1061324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual void TraceOut(string ruleName, int ruleIndex, object inputSymbol) 1062324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1063324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (TraceDestination == null) 1064324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return; 1065324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1066324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.Write("exit " + ruleName + " " + inputSymbol); 1067324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (state.backtracking > 0) 1068324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1069324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.Write(" backtracking=" + state.backtracking); 1070324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (state.failed) 1071324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.Write(" failed"); 1072324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver else 1073324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.Write(" succeeded"); 1074324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1075324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver TraceDestination.WriteLine(); 1076324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1077324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1078324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver #region Debugging support 1079324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver public virtual IDebugEventListener DebugListener 1080324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1081324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver get 1082324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1083324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver return null; 1084324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1085324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1086324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1087324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1088324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugEnterRule(string grammarFileName, string ruleName) 1089324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1090324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1091324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1092324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.EnterRule(grammarFileName, ruleName); 1093324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1094324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1095324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1096324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugExitRule(string grammarFileName, string ruleName) 1097324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1098324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1099324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.ExitRule(grammarFileName, ruleName); 1101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugEnterSubRule(int decisionNumber) 1105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.EnterSubRule(decisionNumber); 1109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugExitSubRule(int decisionNumber) 1113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.ExitSubRule(decisionNumber); 1117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugEnterAlt(int alt) 1121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.EnterAlt(alt); 1125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugEnterDecision(int decisionNumber, bool couldBacktrack) 1129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.EnterDecision(decisionNumber, couldBacktrack); 1133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugExitDecision(int decisionNumber) 1137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.ExitDecision(decisionNumber); 1141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugLocation(int line, int charPositionInLine) 1145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.Location(line, charPositionInLine); 1149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugSemanticPredicate(bool result, string predicate) 1153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.SemanticPredicate(result, predicate); 1157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugBeginBacktrack(int level) 1161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.BeginBacktrack(level); 1165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugEndBacktrack(int level, bool successful) 1169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.EndBacktrack(level, successful); 1173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 1175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver [Conditional("ANTLR_DEBUG")] 1176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver protected virtual void DebugRecognitionException(RecognitionException ex) 1177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver { 1178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver IDebugEventListener dbg = DebugListener; 1179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver if (dbg != null) 1180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver dbg.RecognitionException(ex); 1181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver #endregion 1183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver } 1184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver} 1185