1 /*
2  * [The "BSD license"]
3  *  Copyright (c) 2016 Terence Parr
4  *  Copyright (c) 2016 Sam Harwell
5  *  All rights reserved.
6  *
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions
9  *  are met:
10  *
11  *  1. Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *  2. Redistributions in binary form must reproduce the above copyright
14  *     notice, this list of conditions and the following disclaimer in the
15  *     documentation and/or other materials provided with the distribution.
16  *  3. The name of the author may not be used to endorse or promote products
17  *     derived from this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 module antlr.v4.runtime.atn.ATNState;
32 
33 import std.stdio;
34 import std.conv;
35 import std.array;
36 import antlr.v4.runtime.atn.StateNames;
37 import antlr.v4.runtime.atn.Transition;
38 import antlr.v4.runtime.atn.ATN;
39 import antlr.v4.runtime.misc.IntervalSet;
40 import std.algorithm.mutation: remove;
41 
42 // Class ATNState
43 /**
44  * The following images show the relation of states and
45  * {@link ATNState#transitions} for various grammar constructs.
46  */
47 abstract class ATNState
48 {
49 
50     public static immutable int INITIAL_NUM_TRANSITIONS = 4;
51 
52     public static immutable int INVALID_STATE_NUMBER = -1;
53 
54     /**
55      * @uml
56      * Which ATN are we in?
57      */
58     public ATN atn = null;
59 
60     public int stateNumber = INVALID_STATE_NUMBER;
61 
62     /**
63      * @uml
64      * at runtime, we don't have Rule objects
65      */
66     public int ruleIndex;
67 
68     public bool epsilonOnlyTransitions = false;
69 
70     /**
71      * @uml
72      * Track the transitions emanating from this ATN state.
73      */
74     public Transition[] transitions;
75 
76     /**
77      * @uml
78      * Used to cache lookahead during parsing, not used during construction
79      */
80     public IntervalSet nextTokenWithinRule;
81 
82     /**
83      * @uml
84      * @read
85      * @write
86      */
87     private Transition[] optimizedTransitions_;
88 
89     /**
90      * @uml
91      * @pure
92      * @safe
93      */
94     public int hashCode() @safe pure
95     {
96         return stateNumber;
97     }
98 
99     /**
100      * @uml
101      * @pure
102      * @safe
103      */
104     public bool equals(Object o) @safe pure
105     {
106         return stateNumber==(cast(ATNState)o).stateNumber;
107     }
108 
109     /**
110      * @uml
111      * @pure
112      * @safe
113      */
114     public bool isNonGreedyExitState() @safe pure
115     {
116         return false;
117     }
118 
119     /**
120      * @uml
121      * @pure
122      * @safe
123      * @override
124      */
125     public override string toString() @safe pure
126     {
127         return to!string(stateNumber);
128     }
129 
130     /**
131      * @uml
132      * @pure
133      * @safe
134      */
135     public Transition[] getTransitions() @safe pure
136     {
137         return transitions.dup;
138     }
139 
140     /**
141      * @uml
142      * @pure
143      * @safe
144      */
145     public int getNumberOfTransitions() @safe pure
146     {
147         return to!int(transitions.length);
148     }
149 
150     public void addTransition(Transition e)
151     {
152         if (transitions.length == 0) {
153             epsilonOnlyTransitions = e.isEpsilon;
154         }
155         else
156             if (epsilonOnlyTransitions != e.isEpsilon()) {
157                 stderr.writefln("ATN state %1$s has both epsilon and non-epsilon transitions.\n", stateNumber);
158                 epsilonOnlyTransitions = false;
159             }
160         transitions ~= e;
161     }
162 
163     public Transition transition(int i)
164     {
165         return transitions[i];
166     }
167 
168     public void setTransition(int i, Transition e)
169     {
170         transitions[i] = e;
171     }
172 
173     public Transition removeTransition(int index)
174     {
175         auto t = transitions[index];
176         transitions = transitions[0..index] ~ transitions[index+1..$];
177         return t;
178     }
179 
180     abstract public int getStateType();
181 
182     public bool onlyHasEpsilonTransitions()
183     {
184         return epsilonOnlyTransitions;
185     }
186 
187     public void setRuleIndex(int ruleIndex)
188     {
189         this.ruleIndex = ruleIndex;
190     }
191 
192     public bool isOptimized()
193     {
194         return optimizedTransitions != transitions;
195     }
196 
197     public size_t numberOfOptimizedTransitions()
198     {
199         return optimizedTransitions.length;
200     }
201 
202     public Transition getOptimizedTransition(size_t i)
203     {
204         return optimizedTransitions[i];
205     }
206 
207     public void addOptimizedTransition(Transition e)
208     {
209         if (!isOptimized)
210             {
211                 optimizedTransitions_.length = 0;
212             }
213             optimizedTransitions_ ~= e;
214     }
215 
216     public void setOptimizedTransition(size_t i, Transition e)
217     {
218         if (!isOptimized)
219             {
220                 assert(false, "InvalidOperationException");
221             }
222             optimizedTransitions_[i] = e;
223     }
224 
225     public void removeOptimizedTransition(size_t i)
226     {
227         if (!isOptimized)
228             {
229                 assert(false, "InvalidOperationException");
230             }
231             optimizedTransitions_ = optimizedTransitions_.remove(i);
232     }
233 
234     public this()
235     {
236         optimizedTransitions = transitions.dup;
237     }
238 
239     public final Transition[] optimizedTransitions()
240     {
241         return this.optimizedTransitions_.dup;
242     }
243 
244     public final void optimizedTransitions(Transition[] optimizedTransitions)
245     {
246         this.optimizedTransitions_ = optimizedTransitions.dup;
247     }
248 
249 }