public static Antlr4.Runtime.Atn.PredictionContext GetCachedContext(Antlr4.Runtime.Atn.PredictionContext context, Sharpen.ConcurrentDictionary <Antlr4.Runtime.Atn.PredictionContext, Antlr4.Runtime.Atn.PredictionContext> contextCache, PredictionContext.IdentityHashMap visited) { if (context.IsEmpty) { return(context); } Antlr4.Runtime.Atn.PredictionContext existing; if (visited.TryGetValue(context, out existing)) { return(existing); } if (contextCache.TryGetValue(context, out existing)) { visited[context] = existing; return(existing); } bool changed = false; Antlr4.Runtime.Atn.PredictionContext[] parents = new Antlr4.Runtime.Atn.PredictionContext[context.Size]; for (int i = 0; i < parents.Length; i++) { Antlr4.Runtime.Atn.PredictionContext parent = GetCachedContext(context.GetParent(i), contextCache, visited); if (changed || parent != context.GetParent(i)) { if (!changed) { parents = new Antlr4.Runtime.Atn.PredictionContext[context.Size]; for (int j = 0; j < context.Size; j++) { parents[j] = context.GetParent(j); } changed = true; } parents[i] = parent; } } if (!changed) { existing = contextCache.GetOrAdd(context, context); visited[context] = existing; return(context); } // We know parents.length>0 because context.isEmpty() is checked at the beginning of the method. Antlr4.Runtime.Atn.PredictionContext updated; if (parents.Length == 1) { updated = new SingletonPredictionContext(parents[0], context.GetReturnState(0)); } else { ArrayPredictionContext arrayPredictionContext = (ArrayPredictionContext)context; updated = new ArrayPredictionContext(parents, arrayPredictionContext.returnStates, context.cachedHashCode); } existing = contextCache.GetOrAdd(updated, updated); visited[updated] = existing; visited[context] = existing; return(updated); }