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