File size: 7,663 Bytes
1d777c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#
# Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
# Use of this file is governed by the BSD 3-clause license that
# can be found in the LICENSE.txt file in the project root.
#

# The following images show the relation of states and
# {@link ATNState#transitions} for various grammar constructs.
#
# <ul>
#
# <li>Solid edges marked with an &#0949; indicate a required
# {@link EpsilonTransition}.</li>
#
# <li>Dashed edges indicate locations where any transition derived from
# {@link Transition} might appear.</li>
#
# <li>Dashed nodes are place holders for either a sequence of linked
# {@link BasicState} states or the inclusion of a block representing a nested
# construct in one of the forms below.</li>
#
# <li>Nodes showing multiple outgoing alternatives with a {@code ...} support
# any number of alternatives (one or more). Nodes without the {@code ...} only
# support the exact number of alternatives shown in the diagram.</li>
#
# </ul>
#
# <h2>Basic Blocks</h2>
#
# <h3>Rule</h3>
#
# <embed src="images/Rule.svg" type="image/svg+xml"/>
#
# <h3>Block of 1 or more alternatives</h3>
#
# <embed src="images/Block.svg" type="image/svg+xml"/>
#
# <h2>Greedy Loops</h2>
#
# <h3>Greedy Closure: {@code (...)*}</h3>
#
# <embed src="images/ClosureGreedy.svg" type="image/svg+xml"/>
#
# <h3>Greedy Positive Closure: {@code (...)+}</h3>
#
# <embed src="images/PositiveClosureGreedy.svg" type="image/svg+xml"/>
#
# <h3>Greedy Optional: {@code (...)?}</h3>
#
# <embed src="images/OptionalGreedy.svg" type="image/svg+xml"/>
#
# <h2>Non-Greedy Loops</h2>
#
# <h3>Non-Greedy Closure: {@code (...)*?}</h3>
#
# <embed src="images/ClosureNonGreedy.svg" type="image/svg+xml"/>
#
# <h3>Non-Greedy Positive Closure: {@code (...)+?}</h3>
#
# <embed src="images/PositiveClosureNonGreedy.svg" type="image/svg+xml"/>
#
# <h3>Non-Greedy Optional: {@code (...)??}</h3>
#
# <embed src="images/OptionalNonGreedy.svg" type="image/svg+xml"/>
#

from antlr4.atn.Transition import Transition

INITIAL_NUM_TRANSITIONS = 4

class ATNState(object):
    __slots__ = (
        'atn', 'stateNumber', 'stateType', 'ruleIndex', 'epsilonOnlyTransitions',
        'transitions', 'nextTokenWithinRule',
    )

    # constants for serialization
    INVALID_TYPE = 0
    BASIC = 1
    RULE_START = 2
    BLOCK_START = 3
    PLUS_BLOCK_START = 4
    STAR_BLOCK_START = 5
    TOKEN_START = 6
    RULE_STOP = 7
    BLOCK_END = 8
    STAR_LOOP_BACK = 9
    STAR_LOOP_ENTRY = 10
    PLUS_LOOP_BACK = 11
    LOOP_END = 12

    serializationNames = [
            "INVALID",
            "BASIC",
            "RULE_START",
            "BLOCK_START",
            "PLUS_BLOCK_START",
            "STAR_BLOCK_START",
            "TOKEN_START",
            "RULE_STOP",
            "BLOCK_END",
            "STAR_LOOP_BACK",
            "STAR_LOOP_ENTRY",
            "PLUS_LOOP_BACK",
            "LOOP_END" ]

    INVALID_STATE_NUMBER = -1

    def __init__(self):
        # Which ATN are we in?
        self.atn = None
        self.stateNumber = ATNState.INVALID_STATE_NUMBER
        self.stateType = None
        self.ruleIndex = 0 # at runtime, we don't have Rule objects
        self.epsilonOnlyTransitions = False
        # Track the transitions emanating from this ATN state.
        self.transitions = []
        # Used to cache lookahead during parsing, not used during construction
        self.nextTokenWithinRule = None

    def __hash__(self):
        return self.stateNumber

    def __eq__(self, other):
        return isinstance(other, ATNState) and self.stateNumber==other.stateNumber

    def onlyHasEpsilonTransitions(self):
        return self.epsilonOnlyTransitions

    def isNonGreedyExitState(self):
        return False

    def __str__(self):
        return str(self.stateNumber)

    def addTransition(self, trans:Transition, index:int=-1):
        if len(self.transitions)==0:
            self.epsilonOnlyTransitions = trans.isEpsilon
        elif self.epsilonOnlyTransitions != trans.isEpsilon:
            self.epsilonOnlyTransitions = False
            # TODO System.err.format(Locale.getDefault(), "ATN state %d has both epsilon and non-epsilon transitions.\n", stateNumber);
        if index==-1:
            self.transitions.append(trans)
        else:
            self.transitions.insert(index, trans)

class BasicState(ATNState):

    def __init__(self):
        super().__init__()
        self.stateType = self.BASIC


class DecisionState(ATNState):
    __slots__ = ('decision', 'nonGreedy')
    def __init__(self):
        super().__init__()
        self.decision = -1
        self.nonGreedy = False

#  The start of a regular {@code (...)} block.
class BlockStartState(DecisionState):
    __slots__ = 'endState'

    def __init__(self):
        super().__init__()
        self.endState = None

class BasicBlockStartState(BlockStartState):

    def __init__(self):
        super().__init__()
        self.stateType = self.BLOCK_START

# Terminal node of a simple {@code (a|b|c)} block.
class BlockEndState(ATNState):
    __slots__ = 'startState'

    def __init__(self):
        super().__init__()
        self.stateType = self.BLOCK_END
        self.startState = None

# The last node in the ATN for a rule, unless that rule is the start symbol.
#  In that case, there is one transition to EOF. Later, we might encode
#  references to all calls to this rule to compute FOLLOW sets for
#  error handling.
#
class RuleStopState(ATNState):

    def __init__(self):
        super().__init__()
        self.stateType = self.RULE_STOP

class RuleStartState(ATNState):
    __slots__ = ('stopState', 'isPrecedenceRule')

    def __init__(self):
        super().__init__()
        self.stateType = self.RULE_START
        self.stopState = None
        self.isPrecedenceRule = False

# Decision state for {@code A+} and {@code (A|B)+}.  It has two transitions:
#  one to the loop back to start of the block and one to exit.
#
class PlusLoopbackState(DecisionState):

    def __init__(self):
        super().__init__()
        self.stateType = self.PLUS_LOOP_BACK

# Start of {@code (A|B|...)+} loop. Technically a decision state, but
#  we don't use for code generation; somebody might need it, so I'm defining
#  it for completeness. In reality, the {@link PlusLoopbackState} node is the
#  real decision-making note for {@code A+}.
#
class PlusBlockStartState(BlockStartState):
    __slots__ = 'loopBackState'

    def __init__(self):
        super().__init__()
        self.stateType = self.PLUS_BLOCK_START
        self.loopBackState = None

# The block that begins a closure loop.
class StarBlockStartState(BlockStartState):

    def __init__(self):
        super().__init__()
        self.stateType = self.STAR_BLOCK_START

class StarLoopbackState(ATNState):

    def __init__(self):
        super().__init__()
        self.stateType = self.STAR_LOOP_BACK


class StarLoopEntryState(DecisionState):
    __slots__ = ('loopBackState', 'isPrecedenceDecision')

    def __init__(self):
        super().__init__()
        self.stateType = self.STAR_LOOP_ENTRY
        self.loopBackState = None
        # Indicates whether this state can benefit from a precedence DFA during SLL decision making.
        self.isPrecedenceDecision = None

# Mark the end of a * or + loop.
class LoopEndState(ATNState):
    __slots__ = 'loopBackState'

    def __init__(self):
        super().__init__()
        self.stateType = self.LOOP_END
        self.loopBackState = None

# The Tokens rule start state linking to each lexer rule start state */
class TokensStartState(DecisionState):

    def __init__(self):
        super().__init__()
        self.stateType = self.TOKEN_START