• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * [The "BSD licence"]
3  * Copyright (c) 2005-2008 Terence Parr
4  * All rights reserved.
5  *
6  * Conversion to C#:
7  * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 namespace Antlr.Runtime {
34     using ConditionalAttribute = System.Diagnostics.ConditionalAttribute;
35     using Console = System.Console;
36     using IDebugEventListener = Antlr.Runtime.Debug.IDebugEventListener;
37 
SpecialStateTransitionHandler(DFA dfa, int s, IIntStream input)38     public delegate int SpecialStateTransitionHandler(DFA dfa, int s, IIntStream input);
39 
40     /** <summary>A DFA implemented as a set of transition tables.</summary>
41      *
42      *  <remarks>
43      *  Any state that has a semantic predicate edge is special; those states
44      *  are generated with if-then-else structures in a specialStateTransition()
45      *  which is generated by cyclicDFA template.
46      *
47      *  There are at most 32767 states (16-bit signed short).
48      *  Could get away with byte sometimes but would have to generate different
49      *  types and the simulation code too.  For a point of reference, the Java
50      *  lexer's Tokens rule DFA has 326 states roughly.
51      *  </remarks>
52      */
53     public class DFA {
DFA()54         public DFA()
55             : this(new SpecialStateTransitionHandler(SpecialStateTransitionDefault)) {
56         }
DFA(SpecialStateTransitionHandler specialStateTransition)57         public DFA(SpecialStateTransitionHandler specialStateTransition) {
58             this.SpecialStateTransition = specialStateTransition ?? new SpecialStateTransitionHandler(SpecialStateTransitionDefault);
59         }
60 
61         protected short[] eot;
62         protected short[] eof;
63         protected char[] min;
64         protected char[] max;
65         protected short[] accept;
66         protected short[] special;
67         protected short[][] transition;
68 
69         protected int decisionNumber;
70 
71         /** <summary>Which recognizer encloses this DFA?  Needed to check backtracking</summary> */
72         protected BaseRecognizer recognizer;
73 
74         public readonly bool debug = false;
75 
76         /** <summary>
77          *  From the input stream, predict what alternative will succeed
78          *  using this DFA (representing the covering regular approximation
79          *  to the underlying CFL).  Return an alternative number 1..n.  Throw
80          *  an exception upon error.
81          *  </summary>
82          */
Predict(IIntStream input)83         public virtual int Predict(IIntStream input) {
84             if (debug) {
85                 Console.Error.WriteLine("Enter DFA.predict for decision " + decisionNumber);
86             }
87             int mark = input.Mark(); // remember where decision started in input
88             int s = 0; // we always start at s0
89             try {
90                 for (; ; ) {
91                     if (debug)
92                         Console.Error.WriteLine("DFA " + decisionNumber + " state " + s + " LA(1)=" + (char)input.LA(1) + "(" + input.LA(1) +
93                                            "), index=" + input.Index);
94                     int specialState = special[s];
95                     if (specialState >= 0) {
96                         if (debug) {
97                             Console.Error.WriteLine("DFA " + decisionNumber +
98                                 " state " + s + " is special state " + specialState);
99                         }
100                         s = SpecialStateTransition(this, specialState, input);
101                         if (debug) {
102                             Console.Error.WriteLine("DFA " + decisionNumber +
103                                 " returns from special state " + specialState + " to " + s);
104                         }
105                         if (s == -1) {
106                             NoViableAlt(s, input);
107                             return 0;
108                         }
109                         input.Consume();
110                         continue;
111                     }
112                     if (accept[s] >= 1) {
113                         if (debug)
114                             Console.Error.WriteLine("accept; predict " + accept[s] + " from state " + s);
115                         return accept[s];
116                     }
117                     // look for a normal char transition
118                     char c = (char)input.LA(1); // -1 == \uFFFF, all tokens fit in 65000 space
119                     if (c >= min[s] && c <= max[s]) {
120                         int snext = transition[s][c - min[s]]; // move to next state
121                         if (snext < 0) {
122                             // was in range but not a normal transition
123                             // must check EOT, which is like the else clause.
124                             // eot[s]>=0 indicates that an EOT edge goes to another
125                             // state.
126                             if (eot[s] >= 0) {  // EOT Transition to accept state?
127                                 if (debug)
128                                     Console.Error.WriteLine("EOT transition");
129                                 s = eot[s];
130                                 input.Consume();
131                                 // TODO: I had this as return accept[eot[s]]
132                                 // which assumed here that the EOT edge always
133                                 // went to an accept...faster to do this, but
134                                 // what about predicated edges coming from EOT
135                                 // target?
136                                 continue;
137                             }
138                             NoViableAlt(s, input);
139                             return 0;
140                         }
141                         s = snext;
142                         input.Consume();
143                         continue;
144                     }
145                     if (eot[s] >= 0) {  // EOT Transition?
146                         if (debug)
147                             Console.Error.WriteLine("EOT transition");
148                         s = eot[s];
149                         input.Consume();
150                         continue;
151                     }
152                     if (c == unchecked((char)TokenTypes.EndOfFile) && eof[s] >= 0) {  // EOF Transition to accept state?
153                         if (debug)
154                             Console.Error.WriteLine("accept via EOF; predict " + accept[eof[s]] + " from " + eof[s]);
155                         return accept[eof[s]];
156                     }
157                     // not in range and not EOF/EOT, must be invalid symbol
158                     if (debug) {
159                         Console.Error.WriteLine("min[" + s + "]=" + min[s]);
160                         Console.Error.WriteLine("max[" + s + "]=" + max[s]);
161                         Console.Error.WriteLine("eot[" + s + "]=" + eot[s]);
162                         Console.Error.WriteLine("eof[" + s + "]=" + eof[s]);
163                         for (int p = 0; p < transition[s].Length; p++) {
164                             Console.Error.Write(transition[s][p] + " ");
165                         }
166                         Console.Error.WriteLine();
167                     }
168                     NoViableAlt(s, input);
169                     return 0;
170                 }
171             } finally {
172                 input.Rewind(mark);
173             }
174         }
175 
NoViableAlt(int s, IIntStream input)176         protected virtual void NoViableAlt(int s, IIntStream input) {
177             if (recognizer.state.backtracking > 0) {
178                 recognizer.state.failed = true;
179                 return;
180             }
181             NoViableAltException nvae =
182                 new NoViableAltException(Description,
183                                          decisionNumber,
184                                          s,
185                                          input);
186             Error(nvae);
187             throw nvae;
188         }
189 
190         /** <summary>A hook for debugging interface</summary> */
Error(NoViableAltException nvae)191         public virtual void Error(NoViableAltException nvae) {
192         }
193 
194         public SpecialStateTransitionHandler SpecialStateTransition {
195             get;
196             private set;
197         }
198         //public virtual int specialStateTransition( int s, IntStream input )
199         //{
200         //    return -1;
201         //}
202 
SpecialStateTransitionDefault(DFA dfa, int s, IIntStream input)203         static int SpecialStateTransitionDefault(DFA dfa, int s, IIntStream input) {
204             return -1;
205         }
206 
207         public virtual string Description {
208             get {
209                 return "n/a";
210             }
211         }
212 
213         /** <summary>
214          *  Given a String that has a run-length-encoding of some unsigned shorts
215          *  like "\1\2\3\9", convert to short[] {2,9,9,9}.  We do this to avoid
216          *  static short[] which generates so much init code that the class won't
217          *  compile. :(
218          *  </summary>
219          */
UnpackEncodedString(string encodedString)220         public static short[] UnpackEncodedString(string encodedString) {
221             // walk first to find how big it is.
222             int size = 0;
223             for (int i = 0; i < encodedString.Length; i += 2) {
224                 size += encodedString[i];
225             }
226             short[] data = new short[size];
227             int di = 0;
228             for (int i = 0; i < encodedString.Length; i += 2) {
229                 char n = encodedString[i];
230                 char v = encodedString[i + 1];
231                 // add v n times to data
232                 for (int j = 1; j <= n; j++) {
233                     data[di++] = (short)v;
234                 }
235             }
236             return data;
237         }
238 
239         /** <summary>Hideous duplication of code, but I need different typed arrays out :(</summary> */
UnpackEncodedStringToUnsignedChars(string encodedString)240         public static char[] UnpackEncodedStringToUnsignedChars(string encodedString) {
241             // walk first to find how big it is.
242             int size = 0;
243             for (int i = 0; i < encodedString.Length; i += 2) {
244                 size += encodedString[i];
245             }
246             char[] data = new char[size];
247             int di = 0;
248             for (int i = 0; i < encodedString.Length; i += 2) {
249                 char n = encodedString[i];
250                 char v = encodedString[i + 1];
251                 // add v n times to data
252                 for (int j = 1; j <= n; j++) {
253                     data[di++] = v;
254                 }
255             }
256             return data;
257         }
258 
259         [Conditional("ANTLR_DEBUG")]
DebugRecognitionException(RecognitionException ex)260         protected virtual void DebugRecognitionException(RecognitionException ex) {
261             IDebugEventListener dbg = recognizer.DebugListener;
262             if (dbg != null)
263                 dbg.RecognitionException(ex);
264         }
265     }
266 }
267