@@ -91,11 +91,16 @@ func (l *LexerATNSimulator) Match(input CharStream, mode int) int {
9191
9292 dfa := l .decisionToDFA [mode ]
9393
94- if dfa .getS0 () == nil {
94+ var s0 * DFAState
95+ l .atn .stateMu .RLock ()
96+ s0 = dfa .getS0 ()
97+ l .atn .stateMu .RUnlock ()
98+
99+ if s0 == nil {
95100 return l .MatchATN (input )
96101 }
97102
98- return l .execATN (input , dfa . getS0 () )
103+ return l .execATN (input , s0 )
99104}
100105
101106func (l * LexerATNSimulator ) reset () {
@@ -117,11 +122,7 @@ func (l *LexerATNSimulator) MatchATN(input CharStream) int {
117122 suppressEdge := s0Closure .hasSemanticContext
118123 s0Closure .hasSemanticContext = false
119124
120- next := l .addDFAState (s0Closure )
121-
122- if ! suppressEdge {
123- l .decisionToDFA [l .mode ].setS0 (next )
124- }
125+ next := l .addDFAState (s0Closure , suppressEdge )
125126
126127 predict := l .execATN (input , next )
127128
@@ -203,10 +204,15 @@ func (l *LexerATNSimulator) execATN(input CharStream, ds0 *DFAState) int {
203204// {@code t}, or {@code nil} if the target state for l edge is not
204205// already cached
205206func (l * LexerATNSimulator ) getExistingTargetState (s * DFAState , t int ) * DFAState {
206- if s . getEdges () == nil || t < LexerATNSimulatorMinDFAEdge || t > LexerATNSimulatorMaxDFAEdge {
207+ if t < LexerATNSimulatorMinDFAEdge || t > LexerATNSimulatorMaxDFAEdge {
207208 return nil
208209 }
209210
211+ l .atn .edgeMu .RLock ()
212+ defer l .atn .edgeMu .RUnlock ()
213+ if s .getEdges () == nil {
214+ return nil
215+ }
210216 target := s .getIthEdge (t - LexerATNSimulatorMinDFAEdge )
211217 if LexerATNSimulatorDebug && target != nil {
212218 fmt .Println ("reuse state " + strconv .Itoa (s .stateNumber ) + " edge to " + strconv .Itoa (target .stateNumber ))
@@ -537,7 +543,7 @@ func (l *LexerATNSimulator) addDFAEdge(from *DFAState, tk int, to *DFAState, cfg
537543 suppressEdge := cfgs .HasSemanticContext ()
538544 cfgs .SetHasSemanticContext (false )
539545
540- to = l .addDFAState (cfgs )
546+ to = l .addDFAState (cfgs , true )
541547
542548 if suppressEdge {
543549 return to
@@ -551,6 +557,8 @@ func (l *LexerATNSimulator) addDFAEdge(from *DFAState, tk int, to *DFAState, cfg
551557 if LexerATNSimulatorDebug {
552558 fmt .Println ("EDGE " + from .String () + " -> " + to .String () + " upon " + strconv .Itoa (tk ))
553559 }
560+ l .atn .edgeMu .Lock ()
561+ defer l .atn .edgeMu .Unlock ()
554562 if from .getEdges () == nil {
555563 // make room for tokens 1..n and -1 masquerading as index 0
556564 from .setEdges (make ([]* DFAState , LexerATNSimulatorMaxDFAEdge - LexerATNSimulatorMinDFAEdge + 1 ))
@@ -564,7 +572,7 @@ func (l *LexerATNSimulator) addDFAEdge(from *DFAState, tk int, to *DFAState, cfg
564572// configurations already. This method also detects the first
565573// configuration containing an ATN rule stop state. Later, when
566574// traversing the DFA, we will know which rule to accept.
567- func (l * LexerATNSimulator ) addDFAState (configs ATNConfigSet ) * DFAState {
575+ func (l * LexerATNSimulator ) addDFAState (configs ATNConfigSet , suppressEdge bool ) * DFAState {
568576
569577 proposed := NewDFAState (- 1 , configs )
570578 var firstConfigWithRuleStopState ATNConfig
@@ -585,16 +593,22 @@ func (l *LexerATNSimulator) addDFAState(configs ATNConfigSet) *DFAState {
585593 }
586594 hash := proposed .hash ()
587595 dfa := l .decisionToDFA [l .mode ]
596+
597+ l .atn .stateMu .Lock ()
598+ defer l .atn .stateMu .Unlock ()
588599 existing , ok := dfa .getState (hash )
589600 if ok {
590- return existing
591- }
592- newState := proposed
593- newState .stateNumber = dfa .numStates ()
594- configs .SetReadOnly (true )
595- newState .configs = configs
596- dfa .setState (hash , newState )
597- return newState
601+ proposed = existing
602+ } else {
603+ proposed .stateNumber = dfa .numStates ()
604+ configs .SetReadOnly (true )
605+ proposed .configs = configs
606+ dfa .setState (hash , proposed )
607+ }
608+ if ! suppressEdge {
609+ dfa .setS0 (proposed )
610+ }
611+ return proposed
598612}
599613
600614func (l * LexerATNSimulator ) getDFA (mode int ) * DFA {
0 commit comments