public static PredictionContext GetCachedContext(PredictionContext context, PredictionContextCache contextCache, PredictionContext.IdentityHashMap visited) { if (context.IsEmpty) { return(context); } PredictionContext existing = visited.Get(context); if (existing != null) { return(existing); } existing = contextCache.Get(context); if (existing != null) { visited.Put(context, existing); return(existing); } bool changed = false; PredictionContext[] parents = new PredictionContext[context.Size]; for (int i = 0; i < parents.Length; i++) { PredictionContext parent = GetCachedContext(context.GetParent(i), contextCache, visited); if (changed || parent != context.GetParent(i)) { if (!changed) { parents = new PredictionContext[context.Size]; for (int j = 0; j < context.Size; j++) { parents[j] = context.GetParent(j); } changed = true; } parents[i] = parent; } } if (!changed) { contextCache.Add(context); visited.Put(context, context); return(context); } PredictionContext updated; if (parents.Length == 0) { updated = EMPTY; } else if (parents.Length == 1) { updated = SingletonPredictionContext.Create(parents[0], context.GetReturnState(0)); } else { ArrayPredictionContext arrayPredictionContext = (ArrayPredictionContext)context; updated = new ArrayPredictionContext(parents, arrayPredictionContext.returnStates); } contextCache.Add(updated); visited.Put(updated, updated); visited.Put(context, updated); return(updated); }