Ejemplo n.º 1
0
        /**
         * Adding a new config means merging contexts with existing configs for
         * {@code (s, i, pi, _)}, where {@code s} is the
         * {@link ATNConfig#state}, {@code i} is the {@link ATNConfig#alt}, and
         * {@code pi} is the {@link ATNConfig#semanticContext}. We use
         * {@code (s,i,pi)} as key.
         *
         * <p>This method updates {@link #dipsIntoOuterContext} and
         * {@link #hasSemanticContext} when necessary.</p>
         */
        public bool Add(ATNConfig config, MergeCache mergeCache)
        {
            if (readOnly)
            {
                throw new Exception("This set is readonly");
            }
            if (config.semanticContext != SemanticContext.NONE)
            {
                hasSemanticContext = true;
            }
            if (config.OuterContextDepth > 0)
            {
                dipsIntoOuterContext = true;
            }
            ATNConfig existing = configLookup.GetOrAdd(config);

            if (existing == config)
            {                        // we added this new one
                cachedHashCode = -1;
                configs.Add(config); // track order here
                return(true);
            }
            // a previous (s,i,pi,_), merge with it and save result
            bool rootIsWildcard      = !fullCtx;
            PredictionContext merged = PredictionContext.Merge(existing.context, config.context, rootIsWildcard, mergeCache);

            // no need to check for existing.context, config.context in cache
            // since only way to create new graphs is "call rule" and here. We
            // cache at both places.
            existing.reachesIntoOuterContext = Math.Max(existing.reachesIntoOuterContext, config.reachesIntoOuterContext);

            // make sure to preserve the precedence filter suppression during the merge
            if (config.IsPrecedenceFilterSuppressed)
            {
                existing.SetPrecedenceFilterSuppressed(true);
            }

            existing.context = merged;             // replace context; no need to alt mapping
            return(true);
        }