/*
 * [The "BSD licence"]
 * Copyright (c) 2005-2008 Terence Parr
 * All rights reserved.
 *
 * Conversion to C#:
 * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

namespace Antlr.Runtime {
    using System.Collections.Generic;

    using ArgumentNullException = System.ArgumentNullException;
    using Array = System.Array;
    using Conditional = System.Diagnostics.ConditionalAttribute;
    using Exception = System.Exception;
    using IDebugEventListener = Antlr.Runtime.Debug.IDebugEventListener;
    using MethodBase = System.Reflection.MethodBase;
    using NotSupportedException = System.NotSupportedException;
    using Regex = System.Text.RegularExpressions.Regex;
    using StackFrame = System.Diagnostics.StackFrame;
    using StackTrace = System.Diagnostics.StackTrace;
    using TextWriter = System.IO.TextWriter;
    using Type = System.Type;

    /** <summary>
     *  A generic recognizer that can handle recognizers generated from
     *  lexer, parser, and tree grammars.  This is all the parsing
     *  support code essentially; most of it is error recovery stuff and
     *  backtracking.
     *  </summary>
     */
    public abstract class BaseRecognizer {
        public const int MemoRuleFailed = -2;
        public const int MemoRuleUnknown = -1;
        public const int InitialFollowStackSize = 100;

        // copies from Token object for convenience in actions
        public const int DefaultTokenChannel = TokenChannels.Default;
        public const int Hidden = TokenChannels.Hidden;

        public const string NextTokenRuleName = "nextToken";

        /** <summary>
         *  State of a lexer, parser, or tree parser are collected into a state
         *  object so the state can be shared.  This sharing is needed to
         *  have one grammar import others and share same error variables
         *  and other state variables.  It's a kind of explicit multiple
         *  inheritance via delegation of methods and shared state.
         *  </summary>
         */
        protected internal RecognizerSharedState state;

        public BaseRecognizer()
            : this(new RecognizerSharedState()) {
        }

        public BaseRecognizer(RecognizerSharedState state) {
            if (state == null) {
                state = new RecognizerSharedState();
            }
            this.state = state;
            InitDFAs();
        }

        public TextWriter TraceDestination {
            get;
            set;
        }

        protected virtual void InitDFAs() {
        }

        /** <summary>reset the parser's state; subclasses must rewinds the input stream</summary> */
        public virtual void Reset() {
            // wack everything related to error recovery
            if (state == null) {
                return; // no shared state work to do
            }
            state._fsp = -1;
            state.errorRecovery = false;
            state.lastErrorIndex = -1;
            state.failed = false;
            state.syntaxErrors = 0;
            // wack everything related to backtracking and memoization
            state.backtracking = 0;
            for (int i = 0; state.ruleMemo != null && i < state.ruleMemo.Length; i++) { // wipe cache
                state.ruleMemo[i] = null;
            }
        }


        /** <summary>
         *  Match current input symbol against ttype.  Attempt
         *  single token insertion or deletion error recovery.  If
         *  that fails, throw MismatchedTokenException.
         *  </summary>
         *
         *  <remarks>
         *  To turn off single token insertion or deletion error
         *  recovery, override recoverFromMismatchedToken() and have it
         *  throw an exception. See TreeParser.recoverFromMismatchedToken().
         *  This way any error in a rule will cause an exception and
         *  immediate exit from rule.  Rule would recover by resynchronizing
         *  to the set of symbols that can follow rule ref.
         *  </remarks>
         */
        public virtual object Match(IIntStream input, int ttype, BitSet follow) {
            //System.out.println("match "+((TokenStream)input).LT(1));
            object matchedSymbol = GetCurrentInputSymbol(input);
            if (input.LA(1) == ttype) {
                input.Consume();
                state.errorRecovery = false;
                state.failed = false;
                return matchedSymbol;
            }
            if (state.backtracking > 0) {
                state.failed = true;
                return matchedSymbol;
            }
            matchedSymbol = RecoverFromMismatchedToken(input, ttype, follow);
            return matchedSymbol;
        }

        /** <summary>Match the wildcard: in a symbol</summary> */
        public virtual void MatchAny(IIntStream input) {
            state.errorRecovery = false;
            state.failed = false;
            input.Consume();
        }

        public virtual bool MismatchIsUnwantedToken(IIntStream input, int ttype) {
            return input.LA(2) == ttype;
        }

        public virtual bool MismatchIsMissingToken(IIntStream input, BitSet follow) {
            if (follow == null) {
                // we have no information about the follow; we can only consume
                // a single token and hope for the best
                return false;
            }
            // compute what can follow this grammar element reference
            if (follow.Member(TokenTypes.EndOfRule)) {
                BitSet viableTokensFollowingThisRule = ComputeContextSensitiveRuleFOLLOW();
                follow = follow.Or(viableTokensFollowingThisRule);
                if (state._fsp >= 0) { // remove EOR if we're not the start symbol
                    follow.Remove(TokenTypes.EndOfRule);
                }
            }
            // if current token is consistent with what could come after set
            // then we know we're missing a token; error recovery is free to
            // "insert" the missing token

            //System.out.println("viable tokens="+follow.toString(getTokenNames()));
            //System.out.println("LT(1)="+((TokenStream)input).LT(1));

            // BitSet cannot handle negative numbers like -1 (EOF) so I leave EOR
            // in follow set to indicate that the fall of the start symbol is
            // in the set (EOF can follow).
            if (follow.Member(input.LA(1)) || follow.Member(TokenTypes.EndOfRule)) {
                //System.out.println("LT(1)=="+((TokenStream)input).LT(1)+" is consistent with what follows; inserting...");
                return true;
            }
            return false;
        }

        /** <summary>Report a recognition problem.</summary>
         *
         *  <remarks>
         *  This method sets errorRecovery to indicate the parser is recovering
         *  not parsing.  Once in recovery mode, no errors are generated.
         *  To get out of recovery mode, the parser must successfully match
         *  a token (after a resync).  So it will go:
         *
         * 		1. error occurs
         * 		2. enter recovery mode, report error
         * 		3. consume until token found in resynch set
         * 		4. try to resume parsing
         * 		5. next match() will reset errorRecovery mode
         *
         *  If you override, make sure to update syntaxErrors if you care about that.
         *  </remarks>
         */
        public virtual void ReportError(RecognitionException e) {
            // if we've already reported an error and have not matched a token
            // yet successfully, don't report any errors.
            if (state.errorRecovery) {
                //System.err.print("[SPURIOUS] ");
                return;
            }
            state.syntaxErrors++; // don't count spurious
            state.errorRecovery = true;

            DisplayRecognitionError(this.TokenNames, e);
        }

        public virtual void DisplayRecognitionError(string[] tokenNames,
                                            RecognitionException e) {
            string hdr = GetErrorHeader(e);
            string msg = GetErrorMessage(e, tokenNames);
            EmitErrorMessage(hdr + " " + msg);
        }

        /** <summary>What error message should be generated for the various exception types?</summary>
         *
         *  <remarks>
         *  Not very object-oriented code, but I like having all error message
         *  generation within one method rather than spread among all of the
         *  exception classes. This also makes it much easier for the exception
         *  handling because the exception classes do not have to have pointers back
         *  to this object to access utility routines and so on. Also, changing
         *  the message for an exception type would be difficult because you
         *  would have to subclassing exception, but then somehow get ANTLR
         *  to make those kinds of exception objects instead of the default.
         *  This looks weird, but trust me--it makes the most sense in terms
         *  of flexibility.
         *
         *  For grammar debugging, you will want to override this to add
         *  more information such as the stack frame with
         *  getRuleInvocationStack(e, this.getClass().getName()) and,
         *  for no viable alts, the decision description and state etc...
         *
         *  Override this to change the message generated for one or more
         *  exception types.
         *  </remarks>
         */
        public virtual string GetErrorMessage(RecognitionException e, string[] tokenNames) {
            string msg = e.Message;
            if (e is UnwantedTokenException) {
                UnwantedTokenException ute = (UnwantedTokenException)e;
                string tokenName = "<unknown>";
                if (ute.Expecting == TokenTypes.EndOfFile) {
                    tokenName = "EndOfFile";
                } else {
                    tokenName = tokenNames[ute.Expecting];
                }
                msg = "extraneous input " + GetTokenErrorDisplay(ute.UnexpectedToken) +
                    " expecting " + tokenName;
            } else if (e is MissingTokenException) {
                MissingTokenException mte = (MissingTokenException)e;
                string tokenName = "<unknown>";
                if (mte.Expecting == TokenTypes.EndOfFile) {
                    tokenName = "EndOfFile";
                } else {
                    tokenName = tokenNames[mte.Expecting];
                }
                msg = "missing " + tokenName + " at " + GetTokenErrorDisplay(e.Token);
            } else if (e is MismatchedTokenException) {
                MismatchedTokenException mte = (MismatchedTokenException)e;
                string tokenName = "<unknown>";
                if (mte.Expecting == TokenTypes.EndOfFile) {
                    tokenName = "EndOfFile";
                } else {
                    tokenName = tokenNames[mte.Expecting];
                }
                msg = "mismatched input " + GetTokenErrorDisplay(e.Token) +
                    " expecting " + tokenName;
            } else if (e is MismatchedTreeNodeException) {
                MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e;
                string tokenName = "<unknown>";
                if (mtne.Expecting == TokenTypes.EndOfFile) {
                    tokenName = "EndOfFile";
                } else {
                    tokenName = tokenNames[mtne.Expecting];
                }
                // workaround for a .NET framework bug (NullReferenceException)
                string nodeText = (mtne.Node != null) ? mtne.Node.ToString() ?? string.Empty : string.Empty;
                msg = "mismatched tree node: " + nodeText + " expecting " + tokenName;
            } else if (e is NoViableAltException) {
                //NoViableAltException nvae = (NoViableAltException)e;
                // for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>"
                // and "(decision="+nvae.decisionNumber+") and
                // "state "+nvae.stateNumber
                msg = "no viable alternative at input " + GetTokenErrorDisplay(e.Token);
            } else if (e is EarlyExitException) {
                //EarlyExitException eee = (EarlyExitException)e;
                // for development, can add "(decision="+eee.decisionNumber+")"
                msg = "required (...)+ loop did not match anything at input " +
                    GetTokenErrorDisplay(e.Token);
            } else if (e is MismatchedSetException) {
                MismatchedSetException mse = (MismatchedSetException)e;
                msg = "mismatched input " + GetTokenErrorDisplay(e.Token) +
                    " expecting set " + mse.Expecting;
            } else if (e is MismatchedNotSetException) {
                MismatchedNotSetException mse = (MismatchedNotSetException)e;
                msg = "mismatched input " + GetTokenErrorDisplay(e.Token) +
                    " expecting set " + mse.Expecting;
            } else if (e is FailedPredicateException) {
                FailedPredicateException fpe = (FailedPredicateException)e;
                msg = "rule " + fpe.RuleName + " failed predicate: {" +
                    fpe.PredicateText + "}?";
            }
            return msg;
        }

        /** <summary>
         *  Get number of recognition errors (lexer, parser, tree parser).  Each
         *  recognizer tracks its own number.  So parser and lexer each have
         *  separate count.  Does not count the spurious errors found between
         *  an error and next valid token match
         *  </summary>
         *
         *  <seealso cref="reportError()"/>
         */
        public virtual int NumberOfSyntaxErrors {
            get {
                return state.syntaxErrors;
            }
        }

        /** <summary>What is the error header, normally line/character position information?</summary> */
        public virtual string GetErrorHeader(RecognitionException e) {
            return "line " + e.Line + ":" + (e.CharPositionInLine + 1);
        }

        /** <summary>
         *  How should a token be displayed in an error message? The default
         *  is to display just the text, but during development you might
         *  want to have a lot of information spit out.  Override in that case
         *  to use t.ToString() (which, for CommonToken, dumps everything about
         *  the token). This is better than forcing you to override a method in
         *  your token objects because you don't have to go modify your lexer
         *  so that it creates a new Java type.
         *  </summary>
         */
        public virtual string GetTokenErrorDisplay(IToken t) {
            string s = t.Text;
            if (s == null) {
                if (t.Type == TokenTypes.EndOfFile) {
                    s = "<EOF>";
                } else {
                    s = "<" + t.Type + ">";
                }
            }
            s = Regex.Replace(s, "\n", "\\\\n");
            s = Regex.Replace(s, "\r", "\\\\r");
            s = Regex.Replace(s, "\t", "\\\\t");
            return "'" + s + "'";
        }

        /** <summary>Override this method to change where error messages go</summary> */
        public virtual void EmitErrorMessage(string msg) {
            if (TraceDestination != null)
                TraceDestination.WriteLine(msg);
        }

        /** <summary>
         *  Recover from an error found on the input stream.  This is
         *  for NoViableAlt and mismatched symbol exceptions.  If you enable
         *  single token insertion and deletion, this will usually not
         *  handle mismatched symbol exceptions but there could be a mismatched
         *  token that the match() routine could not recover from.
         *  </summary>
         */
        public virtual void Recover(IIntStream input, RecognitionException re) {
            if (state.lastErrorIndex == input.Index) {
                // uh oh, another error at same token index; must be a case
                // where LT(1) is in the recovery token set so nothing is
                // consumed; consume a single token so at least to prevent
                // an infinite loop; this is a failsafe.
                input.Consume();
            }
            state.lastErrorIndex = input.Index;
            BitSet followSet = ComputeErrorRecoverySet();
            BeginResync();
            ConsumeUntil(input, followSet);
            EndResync();
        }

        /** <summary>
         *  A hook to listen in on the token consumption during error recovery.
         *  The DebugParser subclasses this to fire events to the listenter.
         *  </summary>
         */
        public virtual void BeginResync() {
        }

        public virtual void EndResync() {
        }

        /*  Compute the error recovery set for the current rule.  During
         *  rule invocation, the parser pushes the set of tokens that can
         *  follow that rule reference on the stack; this amounts to
         *  computing FIRST of what follows the rule reference in the
         *  enclosing rule. This local follow set only includes tokens
         *  from within the rule; i.e., the FIRST computation done by
         *  ANTLR stops at the end of a rule.
         *
         *  EXAMPLE
         *
         *  When you find a "no viable alt exception", the input is not
         *  consistent with any of the alternatives for rule r.  The best
         *  thing to do is to consume tokens until you see something that
         *  can legally follow a call to r *or* any rule that called r.
         *  You don't want the exact set of viable next tokens because the
         *  input might just be missing a token--you might consume the
         *  rest of the input looking for one of the missing tokens.
         *
         *  Consider grammar:
         *
         *  a : '[' b ']'
         *    | '(' b ')'
         *    ;
         *  b : c '^' INT ;
         *  c : ID
         *    | INT
         *    ;
         *
         *  At each rule invocation, the set of tokens that could follow
         *  that rule is pushed on a stack.  Here are the various "local"
         *  follow sets:
         *
         *  FOLLOW(b1_in_a) = FIRST(']') = ']'
         *  FOLLOW(b2_in_a) = FIRST(')') = ')'
         *  FOLLOW(c_in_b) = FIRST('^') = '^'
         *
         *  Upon erroneous input "[]", the call chain is
         *
         *  a -> b -> c
         *
         *  and, hence, the follow context stack is:
         *
         *  depth  local follow set     after call to rule
         *    0         <EOF>                    a (from main())
         *    1          ']'                     b
         *    3          '^'                     c
         *
         *  Notice that ')' is not included, because b would have to have
         *  been called from a different context in rule a for ')' to be
         *  included.
         *
         *  For error recovery, we cannot consider FOLLOW(c)
         *  (context-sensitive or otherwise).  We need the combined set of
         *  all context-sensitive FOLLOW sets--the set of all tokens that
         *  could follow any reference in the call chain.  We need to
         *  resync to one of those tokens.  Note that FOLLOW(c)='^' and if
         *  we resync'd to that token, we'd consume until EOF.  We need to
         *  sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}.
         *  In this case, for input "[]", LA(1) is in this set so we would
         *  not consume anything and after printing an error rule c would
         *  return normally.  It would not find the required '^' though.
         *  At this point, it gets a mismatched token error and throws an
         *  exception (since LA(1) is not in the viable following token
         *  set).  The rule exception handler tries to recover, but finds
         *  the same recovery set and doesn't consume anything.  Rule b
         *  exits normally returning to rule a.  Now it finds the ']' (and
         *  with the successful match exits errorRecovery mode).
         *
         *  So, you cna see that the parser walks up call chain looking
         *  for the token that was a member of the recovery set.
         *
         *  Errors are not generated in errorRecovery mode.
         *
         *  ANTLR's error recovery mechanism is based upon original ideas:
         *
         *  "Algorithms + Data Structures = Programs" by Niklaus Wirth
         *
         *  and
         *
         *  "A note on error recovery in recursive descent parsers":
         *  http://portal.acm.org/citation.cfm?id=947902.947905
         *
         *  Later, Josef Grosch had some good ideas:
         *
         *  "Efficient and Comfortable Error Recovery in Recursive Descent
         *  Parsers":
         *  ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip
         *
         *  Like Grosch I implemented local FOLLOW sets that are combined
         *  at run-time upon error to avoid overhead during parsing.
         */
        protected virtual BitSet ComputeErrorRecoverySet() {
            return CombineFollows(false);
        }

        /** <summary>
         *  Compute the context-sensitive FOLLOW set for current rule.
         *  This is set of token types that can follow a specific rule
         *  reference given a specific call chain.  You get the set of
         *  viable tokens that can possibly come next (lookahead depth 1)
         *  given the current call chain.  Contrast this with the
         *  definition of plain FOLLOW for rule r:
         *  </summary>
         *
         *   FOLLOW(r)={x | S=>*alpha r beta in G and x in FIRST(beta)}
         *
         *  where x in T* and alpha, beta in V*; T is set of terminals and
         *  V is the set of terminals and nonterminals.  In other words,
         *  FOLLOW(r) is the set of all tokens that can possibly follow
         *  references to r in *any* sentential form (context).  At
         *  runtime, however, we know precisely which context applies as
         *  we have the call chain.  We may compute the exact (rather
         *  than covering superset) set of following tokens.
         *
         *  For example, consider grammar:
         *
         *  stat : ID '=' expr ';'      // FOLLOW(stat)=={EOF}
         *       | "return" expr '.'
         *       ;
         *  expr : atom ('+' atom)* ;   // FOLLOW(expr)=={';','.',')'}
         *  atom : INT                  // FOLLOW(atom)=={'+',')',';','.'}
         *       | '(' expr ')'
         *       ;
         *
         *  The FOLLOW sets are all inclusive whereas context-sensitive
         *  FOLLOW sets are precisely what could follow a rule reference.
         *  For input input "i=(3);", here is the derivation:
         *
         *  stat => ID '=' expr ';'
         *       => ID '=' atom ('+' atom)* ';'
         *       => ID '=' '(' expr ')' ('+' atom)* ';'
         *       => ID '=' '(' atom ')' ('+' atom)* ';'
         *       => ID '=' '(' INT ')' ('+' atom)* ';'
         *       => ID '=' '(' INT ')' ';'
         *
         *  At the "3" token, you'd have a call chain of
         *
         *    stat -> expr -> atom -> expr -> atom
         *
         *  What can follow that specific nested ref to atom?  Exactly ')'
         *  as you can see by looking at the derivation of this specific
         *  input.  Contrast this with the FOLLOW(atom)={'+',')',';','.'}.
         *
         *  You want the exact viable token set when recovering from a
         *  token mismatch.  Upon token mismatch, if LA(1) is member of
         *  the viable next token set, then you know there is most likely
         *  a missing token in the input stream.  "Insert" one by just not
         *  throwing an exception.
         */
        protected virtual BitSet ComputeContextSensitiveRuleFOLLOW() {
            return CombineFollows(true);
        }

        // what is exact? it seems to only add sets from above on stack
        // if EOR is in set i.  When it sees a set w/o EOR, it stops adding.
        // Why would we ever want them all?  Maybe no viable alt instead of
        // mismatched token?
        protected virtual BitSet CombineFollows(bool exact) {
            int top = state._fsp;
            BitSet followSet = new BitSet();
            for (int i = top; i >= 0; i--) {
                BitSet localFollowSet = (BitSet)state.following[i];
                /*
                System.out.println("local follow depth "+i+"="+
                                   localFollowSet.toString(getTokenNames())+")");
                 */
                followSet.OrInPlace(localFollowSet);
                if (exact) {
                    // can we see end of rule?
                    if (localFollowSet.Member(TokenTypes.EndOfRule)) {
                        // Only leave EOR in set if at top (start rule); this lets
                        // us know if have to include follow(start rule); i.e., EOF
                        if (i > 0) {
                            followSet.Remove(TokenTypes.EndOfRule);
                        }
                    } else { // can't see end of rule, quit
                        break;
                    }
                }
            }
            return followSet;
        }

        /** <summary>Attempt to recover from a single missing or extra token.</summary>
         *
         *  EXTRA TOKEN
         *
         *  LA(1) is not what we are looking for.  If LA(2) has the right token,
         *  however, then assume LA(1) is some extra spurious token.  Delete it
         *  and LA(2) as if we were doing a normal match(), which advances the
         *  input.
         *
         *  MISSING TOKEN
         *
         *  If current token is consistent with what could come after
         *  ttype then it is ok to "insert" the missing token, else throw
         *  exception For example, Input "i=(3;" is clearly missing the
         *  ')'.  When the parser returns from the nested call to expr, it
         *  will have call chain:
         *
         *    stat -> expr -> atom
         *
         *  and it will be trying to match the ')' at this point in the
         *  derivation:
         *
         *       => ID '=' '(' INT ')' ('+' atom)* ';'
         *                          ^
         *  match() will see that ';' doesn't match ')' and report a
         *  mismatched token error.  To recover, it sees that LA(1)==';'
         *  is in the set of tokens that can follow the ')' token
         *  reference in rule atom.  It can assume that you forgot the ')'.
         */
        protected virtual object RecoverFromMismatchedToken(IIntStream input, int ttype, BitSet follow) {
            RecognitionException e = null;
            // if next token is what we are looking for then "delete" this token
            if (MismatchIsUnwantedToken(input, ttype)) {
                e = new UnwantedTokenException(ttype, input, TokenNames);
                /*
                System.err.println("recoverFromMismatchedToken deleting "+
                                   ((TokenStream)input).LT(1)+
                                   " since "+((TokenStream)input).LT(2)+" is what we want");
                 */
                BeginResync();
                input.Consume(); // simply delete extra token
                EndResync();
                ReportError(e);  // report after consuming so AW sees the token in the exception
                // we want to return the token we're actually matching
                object matchedSymbol = GetCurrentInputSymbol(input);
                input.Consume(); // move past ttype token as if all were ok
                return matchedSymbol;
            }
            // can't recover with single token deletion, try insertion
            if (MismatchIsMissingToken(input, follow)) {
                object inserted = GetMissingSymbol(input, e, ttype, follow);
                e = new MissingTokenException(ttype, input, inserted);
                ReportError(e);  // report after inserting so AW sees the token in the exception
                return inserted;
            }
            // even that didn't work; must throw the exception
            e = new MismatchedTokenException(ttype, input, TokenNames);
            throw e;
        }

        /** Not currently used */
        public virtual object RecoverFromMismatchedSet(IIntStream input,
                                               RecognitionException e,
                                               BitSet follow) {
            if (MismatchIsMissingToken(input, follow)) {
                // System.out.println("missing token");
                ReportError(e);
                // we don't know how to conjure up a token for sets yet
                return GetMissingSymbol(input, e, TokenTypes.Invalid, follow);
            }
            // TODO do single token deletion like above for Token mismatch
            throw e;
        }

        /** <summary>
         *  Match needs to return the current input symbol, which gets put
         *  into the label for the associated token ref; e.g., x=ID.  Token
         *  and tree parsers need to return different objects. Rather than test
         *  for input stream type or change the IntStream interface, I use
         *  a simple method to ask the recognizer to tell me what the current
         *  input symbol is.
         *  </summary>
         *
         *  <remarks>This is ignored for lexers.</remarks>
         */
        protected virtual object GetCurrentInputSymbol(IIntStream input) {
            return null;
        }

        /** <summary>Conjure up a missing token during error recovery.</summary>
         *
         *  <remarks>
         *  The recognizer attempts to recover from single missing
         *  symbols. But, actions might refer to that missing symbol.
         *  For example, x=ID {f($x);}. The action clearly assumes
         *  that there has been an identifier matched previously and that
         *  $x points at that token. If that token is missing, but
         *  the next token in the stream is what we want we assume that
         *  this token is missing and we keep going. Because we
         *  have to return some token to replace the missing token,
         *  we have to conjure one up. This method gives the user control
         *  over the tokens returned for missing tokens. Mostly,
         *  you will want to create something special for identifier
         *  tokens. For literals such as '{' and ',', the default
         *  action in the parser or tree parser works. It simply creates
         *  a CommonToken of the appropriate type. The text will be the token.
         *  If you change what tokens must be created by the lexer,
         *  override this method to create the appropriate tokens.
         *  </remarks>
         */
        protected virtual object GetMissingSymbol(IIntStream input,
                                          RecognitionException e,
                                          int expectedTokenType,
                                          BitSet follow) {
            return null;
        }

        public virtual void ConsumeUntil(IIntStream input, int tokenType) {
            //System.out.println("consumeUntil "+tokenType);
            int ttype = input.LA(1);
            while (ttype != TokenTypes.EndOfFile && ttype != tokenType) {
                input.Consume();
                ttype = input.LA(1);
            }
        }

        /** <summary>Consume tokens until one matches the given token set</summary> */
        public virtual void ConsumeUntil(IIntStream input, BitSet set) {
            //System.out.println("consumeUntil("+set.toString(getTokenNames())+")");
            int ttype = input.LA(1);
            while (ttype != TokenTypes.EndOfFile && !set.Member(ttype)) {
                //System.out.println("consume during recover LA(1)="+getTokenNames()[input.LA(1)]);
                input.Consume();
                ttype = input.LA(1);
            }
        }

        /** <summary>Push a rule's follow set using our own hardcoded stack</summary> */
        protected void PushFollow(BitSet fset) {
            if ((state._fsp + 1) >= state.following.Length) {
                Array.Resize(ref state.following, state.following.Length * 2);
            }
            state.following[++state._fsp] = fset;
        }

        protected void PopFollow() {
            state._fsp--;
        }

        /** <summary>
         *  Return List<String> of the rules in your parser instance
         *  leading up to a call to this method.  You could override if
         *  you want more details such as the file/line info of where
         *  in the parser java code a rule is invoked.
         *  </summary>
         *
         *  <remarks>
         *  This is very useful for error messages and for context-sensitive
         *  error recovery.
         *  </remarks>
         */
        public virtual IList<string> GetRuleInvocationStack() {
            return GetRuleInvocationStack(new StackTrace(true));
        }

        /** <summary>
         *  A more general version of GetRuleInvocationStack where you can
         *  pass in the StackTrace of, for example, a RecognitionException
         *  to get it's rule stack trace.
         *  </summary>
         */
        public static IList<string> GetRuleInvocationStack(StackTrace trace) {
            if (trace == null)
                throw new ArgumentNullException("trace");

            List<string> rules = new List<string>();
            StackFrame[] stack = trace.GetFrames() ?? new StackFrame[0];

            for (int i = stack.Length - 1; i >= 0; i--) {
                StackFrame frame = stack[i];
                MethodBase method = frame.GetMethod();
                GrammarRuleAttribute[] attributes = (GrammarRuleAttribute[])method.GetCustomAttributes(typeof(GrammarRuleAttribute), true);
                if (attributes != null && attributes.Length > 0)
                    rules.Add(attributes[0].Name);
            }

            return rules;
        }

        public virtual int BacktrackingLevel {
            get {
                return state.backtracking;
            }
            set {
                state.backtracking = value;
            }
        }

        /** <summary>Return whether or not a backtracking attempt failed.</summary> */
        public virtual bool Failed {
            get {
                return state.failed;
            }
        }

        /** <summary>
         *  Used to print out token names like ID during debugging and
         *  error reporting.  The generated parsers implement a method
         *  that overrides this to point to their String[] tokenNames.
         *  </summary>
         */
        public virtual string[] TokenNames {
            get {
                return null;
            }
        }

        /** <summary>
         *  For debugging and other purposes, might want the grammar name.
         *  Have ANTLR generate an implementation for this method.
         *  </summary>
         */
        public virtual string GrammarFileName {
            get {
                return null;
            }
        }

        public abstract string SourceName {
            get;
        }

        /** <summary>
         *  A convenience method for use most often with template rewrites.
         *  Convert a List<Token> to List<String>
         *  </summary>
         */
        public virtual List<string> ToStrings(ICollection<IToken> tokens) {
            if (tokens == null)
                return null;

            List<string> strings = new List<string>(tokens.Count);
            foreach (IToken token in tokens) {
                strings.Add(token.Text);
            }

            return strings;
        }

        /** <summary>
         *  Given a rule number and a start token index number, return
         *  MEMO_RULE_UNKNOWN if the rule has not parsed input starting from
         *  start index.  If this rule has parsed input starting from the
         *  start index before, then return where the rule stopped parsing.
         *  It returns the index of the last token matched by the rule.
         *  </summary>
         *
         *  <remarks>
         *  For now we use a hashtable and just the slow Object-based one.
         *  Later, we can make a special one for ints and also one that
         *  tosses out data after we commit past input position i.
         *  </remarks>
         */
        public virtual int GetRuleMemoization(int ruleIndex, int ruleStartIndex) {
            if (state.ruleMemo[ruleIndex] == null) {
                state.ruleMemo[ruleIndex] = new Dictionary<int, int>();
            }

            int stopIndex;
            if (!state.ruleMemo[ruleIndex].TryGetValue(ruleStartIndex, out stopIndex))
                return MemoRuleUnknown;

            return stopIndex;
        }

        /** <summary>
         *  Has this rule already parsed input at the current index in the
         *  input stream?  Return the stop token index or MEMO_RULE_UNKNOWN.
         *  If we attempted but failed to parse properly before, return
         *  MEMO_RULE_FAILED.
         *  </summary>
         *
         *  <remarks>
         *  This method has a side-effect: if we have seen this input for
         *  this rule and successfully parsed before, then seek ahead to
         *  1 past the stop token matched for this rule last time.
         *  </remarks>
         */
        public virtual bool AlreadyParsedRule(IIntStream input, int ruleIndex) {
            int stopIndex = GetRuleMemoization(ruleIndex, input.Index);
            if (stopIndex == MemoRuleUnknown) {
                return false;
            }
            if (stopIndex == MemoRuleFailed) {
                //System.out.println("rule "+ruleIndex+" will never succeed");
                state.failed = true;
            } else {
                //System.out.println("seen rule "+ruleIndex+" before; skipping ahead to @"+(stopIndex+1)+" failed="+state.failed);
                input.Seek(stopIndex + 1); // jump to one past stop token
            }
            return true;
        }

        /** <summary>
         *  Record whether or not this rule parsed the input at this position
         *  successfully.  Use a standard java hashtable for now.
         *  </summary>
         */
        public virtual void Memoize(IIntStream input,
                            int ruleIndex,
                            int ruleStartIndex) {
            int stopTokenIndex = state.failed ? MemoRuleFailed : input.Index - 1;
            if (state.ruleMemo == null) {
                if (TraceDestination != null)
                    TraceDestination.WriteLine("!!!!!!!!! memo array is null for " + GrammarFileName);
            }
            if (ruleIndex >= state.ruleMemo.Length) {
                if (TraceDestination != null)
                    TraceDestination.WriteLine("!!!!!!!!! memo size is " + state.ruleMemo.Length + ", but rule index is " + ruleIndex);
            }
            if (state.ruleMemo[ruleIndex] != null) {
                state.ruleMemo[ruleIndex][ruleStartIndex] = stopTokenIndex;
            }
        }

        /** <summary>return how many rule/input-index pairs there are in total.</summary>
         *  TODO: this includes synpreds. :(
         */
        public virtual int GetRuleMemoizationCacheSize() {
            int n = 0;
            for (int i = 0; state.ruleMemo != null && i < state.ruleMemo.Length; i++) {
                var ruleMap = state.ruleMemo[i];
                if (ruleMap != null) {
                    n += ruleMap.Count; // how many input indexes are recorded?
                }
            }
            return n;
        }

        [Conditional("ANTLR_TRACE")]
        public virtual void TraceIn(string ruleName, int ruleIndex, object inputSymbol) {
            if (TraceDestination == null)
                return;

            TraceDestination.Write("enter " + ruleName + " " + inputSymbol);
            if (state.backtracking > 0) {
                TraceDestination.Write(" backtracking=" + state.backtracking);
            }
            TraceDestination.WriteLine();
        }

        [Conditional("ANTLR_TRACE")]
        public virtual void TraceOut(string ruleName, int ruleIndex, object inputSymbol) {
            if (TraceDestination == null)
                return;

            TraceDestination.Write("exit " + ruleName + " " + inputSymbol);
            if (state.backtracking > 0) {
                TraceDestination.Write(" backtracking=" + state.backtracking);
                if (state.failed)
                    TraceDestination.Write(" failed");
                else
                    TraceDestination.Write(" succeeded");
            }
            TraceDestination.WriteLine();
        }

        #region Debugging support
        public virtual IDebugEventListener DebugListener {
            get {
                return null;
            }
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugEnterRule(string grammarFileName, string ruleName) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.EnterRule(grammarFileName, ruleName);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugExitRule(string grammarFileName, string ruleName) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.ExitRule(grammarFileName, ruleName);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugEnterSubRule(int decisionNumber) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.EnterSubRule(decisionNumber);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugExitSubRule(int decisionNumber) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.ExitSubRule(decisionNumber);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugEnterAlt(int alt) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.EnterAlt(alt);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugEnterDecision(int decisionNumber, bool couldBacktrack) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.EnterDecision(decisionNumber, couldBacktrack);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugExitDecision(int decisionNumber) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.ExitDecision(decisionNumber);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugLocation(int line, int charPositionInLine) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.Location(line, charPositionInLine);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugSemanticPredicate(bool result, string predicate) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.SemanticPredicate(result, predicate);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugBeginBacktrack(int level) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.BeginBacktrack(level);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugEndBacktrack(int level, bool successful) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.EndBacktrack(level, successful);
        }

        [Conditional("ANTLR_DEBUG")]
        protected virtual void DebugRecognitionException(RecognitionException ex) {
            IDebugEventListener dbg = DebugListener;
            if (dbg != null)
                dbg.RecognitionException(ex);
        }
        #endregion
    }
}
