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    using ConditionalAttribute = System.Diagnostics.ConditionalAttribute;
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /** <summary>
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *  A lexer is recognizer that draws input symbols from a character stream.
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *  lexer grammars result in a subclass of this object. A Lexer object
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *  uses simplified match() and error recovery mechanisms in the interest
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *  of speed.
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *  </summary>
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     */
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public abstract class Lexer : BaseRecognizer, ITokenSource {
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        /** <summary>Where is the lexer drawing characters from?</summary> */
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        protected ICharStream input;
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public Lexer() {
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public Lexer(ICharStream input) {
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            this.input = input;
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public Lexer(ICharStream input, RecognizerSharedState state)
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            : base(state) {
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            this.input = input;
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #region Properties
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public string Text {
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            /** <summary>Return the text matched so far for the current token or any text override.</summary> */
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            get {
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                if (state.text != null) {
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    return state.text;
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                }
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return input.Substring(state.tokenStartCharIndex, CharIndex - state.tokenStartCharIndex);
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            /** <summary>Set the complete text of this token; it wipes any previous changes to the text.</summary> */
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            set {
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                state.text = value;
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public int Line {
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            get {
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return input.Line;
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            set {
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                input.Line = value;
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public int CharPositionInLine {
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            get {
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return input.CharPositionInLine;
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            set {
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                input.CharPositionInLine = value;
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        #endregion
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public override void Reset() {
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            base.Reset(); // reset all recognizer state variables
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            // wack Lexer state variables
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if (input != null) {
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                input.Seek(0); // rewind the input
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if (state == null) {
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return; // no shared state work to do
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.token = null;
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.type = TokenTypes.Invalid;
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.channel = TokenChannels.Default;
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.tokenStartCharIndex = -1;
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.tokenStartCharPositionInLine = -1;
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.tokenStartLine = -1;
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.text = null;
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        /** <summary>Return a token from this source; i.e., match a token on the char stream.</summary> */
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual IToken NextToken() {
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            for (; ; ) {
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                state.token = null;
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                state.channel = TokenChannels.Default;
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                state.tokenStartCharIndex = input.Index;
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                state.tokenStartCharPositionInLine = input.CharPositionInLine;
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                state.tokenStartLine = input.Line;
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                state.text = null;
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                if (input.LA(1) == CharStreamConstants.EndOfFile) {
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    IToken eof = new CommonToken((ICharStream)input, CharStreamConstants.EndOfFile, TokenChannels.Default, input.Index, input.Index);
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    eof.Line = Line;
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    eof.CharPositionInLine = CharPositionInLine;
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    return eof;
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                }
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                try {
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    mTokens();
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    if (state.token == null) {
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                        Emit();
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    } else if (state.token == Tokens.Skip) {
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                        continue;
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    }
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    return state.token;
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                } catch (NoViableAltException nva) {
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    ReportError(nva);
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    Recover(nva); // throw out current char and try again
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                } catch (RecognitionException re) {
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    ReportError(re);
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    // match() routine has already called recover()
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                }
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        /** <summary>
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  Instruct the lexer to skip creating a token for current lexer rule
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  and look for another token.  nextToken() knows to keep looking when
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  a lexer rule finishes with token set to SKIP_TOKEN.  Recall that
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  if token==null at end of any token rule, it creates one for you
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  and emits it.
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  </summary>
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         */
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual void Skip() {
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.token = Tokens.Skip;
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        /** <summary>This is the lexer entry point that sets instance var 'token'</summary> */
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public abstract void mTokens();
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual ICharStream CharStream {
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            get {
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return input;
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            /** <summary>Set the char stream and reset the lexer</summary> */
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            set {
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                input = null;
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                Reset();
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                input = value;
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public override string SourceName {
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            get {
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return input.SourceName;
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        /** <summary>
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  Currently does not support multiple emits per nextToken invocation
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  for efficiency reasons.  Subclass and override this method and
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  nextToken (to push tokens into a list and pull from that list rather
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  than a single variable as this implementation does).
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  </summary>
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         */
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual void Emit(IToken token) {
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.token = token;
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        /** <summary>
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  The standard method called to automatically emit a token at the
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  outermost lexical rule.  The token object should point into the
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  char buffer start..stop.  If there is a text override in 'text',
190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  use that to set the token's text.  Override this method to emit
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  custom Token objects.
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  </summary>
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  <remarks>
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  If you are building trees, then you should also override
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  Parser or TreeParser.getMissingSymbol().
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  </remarks>
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         */
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual IToken Emit() {
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            IToken t = new CommonToken(input, state.type, state.channel, state.tokenStartCharIndex, CharIndex - 1);
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            t.Line = state.tokenStartLine;
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            t.Text = state.text;
203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            t.CharPositionInLine = state.tokenStartCharPositionInLine;
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            Emit(t);
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return t;
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual void Match(string s) {
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            int i = 0;
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            while (i < s.Length) {
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                if (input.LA(1) != s[i]) {
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    if (state.backtracking > 0) {
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                        state.failed = true;
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                        return;
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    }
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    MismatchedTokenException mte = new MismatchedTokenException(s[i], input, TokenNames);
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    Recover(mte);
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    throw mte;
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                }
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                i++;
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                input.Consume();
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                state.failed = false;
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual void MatchAny() {
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            input.Consume();
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual void Match(int c) {
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if (input.LA(1) != c) {
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                if (state.backtracking > 0) {
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    state.failed = true;
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    return;
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                }
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                MismatchedTokenException mte = new MismatchedTokenException(c, input, TokenNames);
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                Recover(mte);  // don't really recover; just consume in lexer
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                throw mte;
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            input.Consume();
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.failed = false;
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual void MatchRange(int a, int b) {
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if (input.LA(1) < a || input.LA(1) > b) {
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                if (state.backtracking > 0) {
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    state.failed = true;
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    return;
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                }
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                MismatchedRangeException mre = new MismatchedRangeException(a, b, input);
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                Recover(mre);
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                throw mre;
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            input.Consume();
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            state.failed = false;
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        /** <summary>What is the index of the current character of lookahead?</summary> */
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual int CharIndex {
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            get {
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return input.Index;
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public override void ReportError(RecognitionException e) {
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            /** TODO: not thought about recovery in lexer yet.
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver             *
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            // if we've already reported an error and have not matched a token
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            // yet successfully, don't report any errors.
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if ( errorRecovery ) {
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                //System.err.print("[SPURIOUS] ");
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                return;
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            errorRecovery = true;
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver             */
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            DisplayRecognitionError(this.TokenNames, e);
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public override string GetErrorMessage(RecognitionException e, string[] tokenNames) {
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            string msg = null;
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            if (e is MismatchedTokenException) {
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                MismatchedTokenException mte = (MismatchedTokenException)e;
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                msg = "mismatched character " + GetCharErrorDisplay(e.Character) + " expecting " + GetCharErrorDisplay(mte.Expecting);
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            } else if (e is NoViableAltException) {
286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                NoViableAltException nvae = (NoViableAltException)e;
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                // for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>"
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                // and "(decision="+nvae.decisionNumber+") and
289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                // "state "+nvae.stateNumber
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                msg = "no viable alternative at character " + GetCharErrorDisplay(e.Character);
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            } else if (e is EarlyExitException) {
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                EarlyExitException eee = (EarlyExitException)e;
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                // for development, can add "(decision="+eee.decisionNumber+")"
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                msg = "required (...)+ loop did not match anything at character " + GetCharErrorDisplay(e.Character);
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            } else if (e is MismatchedNotSetException) {
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                MismatchedNotSetException mse = (MismatchedNotSetException)e;
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                msg = "mismatched character " + GetCharErrorDisplay(e.Character) + " expecting set " + mse.Expecting;
298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            } else if (e is MismatchedSetException) {
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                MismatchedSetException mse = (MismatchedSetException)e;
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                msg = "mismatched character " + GetCharErrorDisplay(e.Character) + " expecting set " + mse.Expecting;
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            } else if (e is MismatchedRangeException) {
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                MismatchedRangeException mre = (MismatchedRangeException)e;
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                msg = "mismatched character " + GetCharErrorDisplay(e.Character) + " expecting set " +
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                      GetCharErrorDisplay(mre.A) + ".." + GetCharErrorDisplay(mre.B);
305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            } else {
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                msg = base.GetErrorMessage(e, tokenNames);
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return msg;
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual string GetCharErrorDisplay(int c) {
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            string s = ((char)c).ToString();
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            switch (c) {
314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                case TokenTypes.EndOfFile:
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    s = "<EOF>";
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    break;
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                case '\n':
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    s = "\\n";
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    break;
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                case '\t':
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    s = "\\t";
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    break;
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                case '\r':
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    s = "\\r";
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    break;
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return "'" + s + "'";
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        /** <summary>
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  Lexers can normally match any char in it's vocabulary after matching
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  a token, so do the easy thing and just kill a character and hope
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  it all works out.  You can instead use the rule invocation stack
334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  to do sophisticated error recovery if you are in a fragment rule.
335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         *  </summary>
336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver         */
337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual void Recover(RecognitionException re) {
338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            //System.out.println("consuming char "+(char)input.LA(1)+" during recovery");
339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            //re.printStackTrace();
340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            input.Consume();
341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        [Conditional("ANTLR_TRACE")]
344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual void TraceIn(string ruleName, int ruleIndex) {
345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            string inputSymbol = ((char)input.LT(1)) + " line=" + Line + ":" + CharPositionInLine;
346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            base.TraceIn(ruleName, ruleIndex, inputSymbol);
347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        [Conditional("ANTLR_TRACE")]
350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        public virtual void TraceOut(string ruleName, int ruleIndex) {
351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            string inputSymbol = ((char)input.LT(1)) + " line=" + Line + ":" + CharPositionInLine;
352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            base.TraceOut(ruleName, ruleIndex, inputSymbol);
353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
356