コード例 #1
0
ファイル: PredictionContext.cs プロジェクト: Lbsl/antlr4cs
        public static Antlr4.Runtime.Atn.PredictionContext GetCachedContext(Antlr4.Runtime.Atn.PredictionContext context, 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);
        }
コード例 #2
0
 public override bool Equals(object o)
 {
     if (o == this)
     {
         return(true);
     }
     else
     {
         if (!(o is Antlr4.Runtime.Atn.SingletonPredictionContext))
         {
             return(false);
         }
     }
     Antlr4.Runtime.Atn.SingletonPredictionContext other = (Antlr4.Runtime.Atn.SingletonPredictionContext)o;
     if (this.GetHashCode() != other.GetHashCode())
     {
         return(false);
     }
     return(returnState == other.returnState && parent.Equals(other.parent));
 }
コード例 #3
0
 public static PredictionContext MergeRoot(SingletonPredictionContext a,
                                           SingletonPredictionContext b,
                                           bool rootIsWildcard)
 {
     if (rootIsWildcard)
     {
         if (a == PredictionContext.EMPTY)
         {
             return(PredictionContext.EMPTY);                     // * + b = *
         }
         if (b == PredictionContext.EMPTY)
         {
             return(PredictionContext.EMPTY);                     // a + * = *
         }
     }
     else
     {
         if (a == EMPTY && b == EMPTY)
         {
             return(EMPTY);                                          // $ + $ = $
         }
         if (a == EMPTY)
         {                 // $ + x = [$,x]
             int[] payloads = { b.returnState, EMPTY_RETURN_STATE };
             PredictionContext[] parents = { b.parent, null };
             PredictionContext   joined  =
                 new ArrayPredictionContext(parents, payloads);
             return(joined);
         }
         if (b == EMPTY)
         {                 // x + $ = [$,x] ($ is always first if present)
             int[] payloads = { a.returnState, EMPTY_RETURN_STATE };
             PredictionContext[] parents = { a.parent, null };
             PredictionContext   joined  =
                 new ArrayPredictionContext(parents, payloads);
             return(joined);
         }
     }
     return(null);
 }
コード例 #4
0
 private static PredictionContext AppendContext(PredictionContext context, PredictionContext suffix, PredictionContext.IdentityHashMap visited)
 {
     if (suffix.IsEmpty)
     {
         if (IsEmptyLocal(suffix))
         {
             if (context.HasEmpty)
             {
                 return EmptyLocal;
             }
             throw new NotSupportedException("what to do here?");
         }
         return context;
     }
     if (suffix.Size != 1)
     {
         throw new NotSupportedException("Appending a tree suffix is not yet supported.");
     }
     PredictionContext result;
     if (!visited.TryGetValue(context, out result))
     {
         if (context.IsEmpty)
         {
             result = suffix;
         }
         else
         {
             int parentCount = context.Size;
             if (context.HasEmpty)
             {
                 parentCount--;
             }
             PredictionContext[] updatedParents = new PredictionContext[parentCount];
             int[] updatedReturnStates = new int[parentCount];
             for (int i = 0; i < parentCount; i++)
             {
                 updatedReturnStates[i] = context.GetReturnState(i);
             }
             for (int i_1 = 0; i_1 < parentCount; i_1++)
             {
                 updatedParents[i_1] = AppendContext(context.GetParent(i_1), suffix, visited);
             }
             if (updatedParents.Length == 1)
             {
                 result = new SingletonPredictionContext(updatedParents[0], updatedReturnStates[0]);
             }
             else
             {
                 System.Diagnostics.Debug.Assert(updatedParents.Length > 1);
                 result = new Antlr4.Runtime.Atn.ArrayPredictionContext(updatedParents, updatedReturnStates);
             }
             if (context.HasEmpty)
             {
                 result = PredictionContext.Join(result, suffix);
             }
         }
         visited[context] = result;
     }
     return result;
 }
コード例 #5
0
        // side-effect: can alter configs.hasSemanticContext

        protected LexerATNConfig GetEpsilonTarget(ICharStream input,
                                                  LexerATNConfig config,
                                                  Transition t,
                                                  ATNConfigSet configs,
                                                  bool speculative,
                                                  bool treatEofAsEpsilon)
        {
            LexerATNConfig c = null;

            switch (t.TransitionType)
            {
            case TransitionType.RULE:
                RuleTransition    ruleTransition = (RuleTransition)t;
                PredictionContext newContext     = new SingletonPredictionContext(config.context, ruleTransition.followState.stateNumber);
                c = new LexerATNConfig(config, t.target, newContext);
                break;

            case TransitionType.PRECEDENCE:
                throw new Exception("Precedence predicates are not supported in lexers.");

            case TransitionType.PREDICATE:
                /*  Track traversing semantic predicates. If we traverse,
                 * we cannot add a DFA state for this "reach" computation
                 * because the DFA would not test the predicate again in the
                 * future. Rather than creating collections of semantic predicates
                 * like v3 and testing them on prediction, v4 will test them on the
                 * fly all the time using the ATN not the DFA. This is slower but
                 * semantically it's not used that often. One of the key elements to
                 * this predicate mechanism is not adding DFA states that see
                 * predicates immediately afterwards in the ATN. For example,
                 *
                 * a : ID {p1}? | ID {p2}? ;
                 *
                 * should create the start state for rule 'a' (to save start state
                 * competition), but should not create target of ID state. The
                 * collection of ATN states the following ID references includes
                 * states reached by traversing predicates. Since this is when we
                 * test them, we cannot cash the DFA state target of ID.
                 */
                PredicateTransition pt = (PredicateTransition)t;
                if (debug)
                {
                    ConsoleWriteLine("EVAL rule " + pt.ruleIndex + ":" + pt.predIndex);
                }
                configs.hasSemanticContext = true;
                if (EvaluatePredicate(input, pt.ruleIndex, pt.predIndex, speculative))
                {
                    c = new LexerATNConfig(config, t.target);
                }
                break;

            case TransitionType.ACTION:
                if (config.context == null || config.context.HasEmptyPath)
                {
                    // execute actions anywhere in the start rule for a token.
                    //
                    // TODO: if the entry rule is invoked recursively, some
                    // actions may be executed during the recursive call. The
                    // problem can appear when hasEmptyPath() is true but
                    // isEmpty() is false. In this case, the config needs to be
                    // split into two contexts - one with just the empty path
                    // and another with everything but the empty path.
                    // Unfortunately, the current algorithm does not allow
                    // getEpsilonTarget to return two configurations, so
                    // additional modifications are needed before we can support
                    // the split operation.
                    LexerActionExecutor lexerActionExecutor = LexerActionExecutor.Append(config.getLexerActionExecutor(), atn.lexerActions[((ActionTransition)t).actionIndex]);
                    c = new LexerATNConfig(config, t.target, lexerActionExecutor);
                    break;
                }
                else
                {
                    // ignore actions in referenced rules
                    c = new LexerATNConfig(config, t.target);
                    break;
                }

            case TransitionType.EPSILON:
                c = new LexerATNConfig(config, t.target);
                break;

            case TransitionType.ATOM:
            case TransitionType.RANGE:
            case TransitionType.SET:
                if (treatEofAsEpsilon)
                {
                    if (t.Matches(IntStreamConstants.EOF, Lexer.MinCharValue, Lexer.MaxCharValue))
                    {
                        c = new LexerATNConfig(config, t.target);
                        break;
                    }
                }

                break;
            }

            return(c);
        }
コード例 #6
0
        private static PredictionContext AppendContext(PredictionContext context, PredictionContext suffix, PredictionContext.IdentityHashMap visited)
        {
            if (suffix.IsEmpty)
            {
                if (IsEmptyLocal(suffix))
                {
                    if (context.HasEmpty)
                    {
                        return(EmptyLocal);
                    }
                    throw new NotSupportedException("what to do here?");
                }
                return(context);
            }
            if (suffix.Size != 1)
            {
                throw new NotSupportedException("Appending a tree suffix is not yet supported.");
            }
            PredictionContext result;

            if (!visited.TryGetValue(context, out result))
            {
                if (context.IsEmpty)
                {
                    result = suffix;
                }
                else
                {
                    int parentCount = context.Size;
                    if (context.HasEmpty)
                    {
                        parentCount--;
                    }
                    PredictionContext[] updatedParents = new PredictionContext[parentCount];
                    int[] updatedReturnStates          = new int[parentCount];
                    for (int i = 0; i < parentCount; i++)
                    {
                        updatedReturnStates[i] = context.GetReturnState(i);
                    }
                    for (int i_1 = 0; i_1 < parentCount; i_1++)
                    {
                        updatedParents[i_1] = AppendContext(context.GetParent(i_1), suffix, visited);
                    }
                    if (updatedParents.Length == 1)
                    {
                        result = new SingletonPredictionContext(updatedParents[0], updatedReturnStates[0]);
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(updatedParents.Length > 1);
                        result = new Antlr4.Runtime.Atn.ArrayPredictionContext(updatedParents, updatedReturnStates);
                    }
                    if (context.HasEmpty)
                    {
                        result = PredictionContext.Join(result, suffix);
                    }
                }
                visited[context] = result;
            }
            return(result);
        }
コード例 #7
0
 public ArrayPredictionContext(SingletonPredictionContext a)
     : this(new PredictionContext[] { a.parent }, new int[] { a.returnState })
 {
 }
コード例 #8
0
        /// <summary>
        /// Compute set of tokens that can follow
        /// <paramref name="s"/>
        /// in the ATN in the
        /// specified
        /// <paramref name="ctx"/>
        /// .
        /// <p/>
        /// If
        /// <paramref name="ctx"/>
        /// is
        /// <see cref="PredictionContext.EmptyLocal"/>
        /// and
        /// <paramref name="stopState"/>
        /// or the end of the rule containing
        /// <paramref name="s"/>
        /// is reached,
        /// <see cref="TokenConstants.EPSILON"/>
        /// is added to the result set. If
        /// <paramref name="ctx"/>
        /// is not
        /// <see cref="PredictionContext.EmptyLocal"/>
        /// and
        /// <paramref name="addEOF"/>
        /// is
        /// <see langword="true"/>
        /// and
        /// <paramref name="stopState"/>
        /// or the end of the outermost rule is reached,
        /// <see cref="TokenConstants.EOF"/>
        /// is added to the result set.
        /// </summary>
        /// <param name="s">the ATN state.</param>
        /// <param name="stopState">
        /// the ATN state to stop at. This can be a
        /// <see cref="BlockEndState"/>
        /// to detect epsilon paths through a closure.
        /// </param>
        /// <param name="ctx">
        /// The outer context, or
        /// <see cref="PredictionContext.EmptyLocal"/>
        /// if
        /// the outer context should not be used.
        /// </param>
        /// <param name="look">The result lookahead set.</param>
        /// <param name="lookBusy">
        /// A set used for preventing epsilon closures in the ATN
        /// from causing a stack overflow. Outside code should pass
        /// <c>new HashSet&lt;ATNConfig&gt;</c>
        /// for this argument.
        /// </param>
        /// <param name="calledRuleStack">
        /// A set used for preventing left recursion in the
        /// ATN from causing a stack overflow. Outside code should pass
        /// <c>new BitSet()</c>
        /// for this argument.
        /// </param>
        /// <param name="seeThruPreds">
        ///
        /// <see langword="true"/>
        /// to true semantic predicates as
        /// implicitly
        /// <see langword="true"/>
        /// and "see through them", otherwise
        /// <see langword="false"/>
        /// to treat semantic predicates as opaque and add
        /// <see cref="HitPred"/>
        /// to the
        /// result if one is encountered.
        /// </param>
        /// <param name="addEOF">
        /// Add
        /// <see cref="TokenConstants.EOF"/>
        /// to the result if the end of the
        /// outermost context is reached. This parameter has no effect if
        /// <paramref name="ctx"/>
        /// is
        /// <see cref="PredictionContext.EmptyLocal"/>
        /// .
        /// </param>
        protected internal virtual void Look(ATNState s, ATNState stopState, PredictionContext ctx, IntervalSet look, HashSet <ATNConfig> lookBusy, BitSet calledRuleStack, bool seeThruPreds, bool addEOF)
        {
            //		System.out.println("_LOOK("+s.stateNumber+", ctx="+ctx);
            ATNConfig c = new ATNConfig(s, 0, ctx);

            if (!lookBusy.Add(c))
            {
                return;
            }
            if (s == stopState)
            {
                if (ctx == null)
                {
                    look.Add(TokenConstants.EPSILON);
                    return;
                }
                else if (ctx.IsEmpty && addEOF)
                {
                    look.Add(TokenConstants.EOF);
                    return;
                }
            }
            if (s is RuleStopState)
            {
                if (ctx == null)
                {
                    look.Add(TokenConstants.EPSILON);
                    return;
                }
                else if (ctx.IsEmpty && addEOF)
                {
                    look.Add(TokenConstants.EOF);
                    return;
                }
                if (ctx != PredictionContext.EMPTY)
                {
                    for (int i = 0; i < ctx.Size; i++)
                    {
                        ATNState returnState = atn.states[ctx.GetReturnState(i)];
                        bool     removed     = calledRuleStack.Get(returnState.ruleIndex);
                        try
                        {
                            calledRuleStack.Clear(returnState.ruleIndex);
                            Look(returnState, stopState, ctx.GetParent(i), look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
                        }
                        finally
                        {
                            if (removed)
                            {
                                calledRuleStack.Set(returnState.ruleIndex);
                            }
                        }
                    }
                    return;
                }
            }
            int n = s.NumberOfTransitions;

            for (int i_1 = 0; i_1 < n; i_1++)
            {
                Transition t = s.Transition(i_1);
                if (t is RuleTransition)
                {
                    RuleTransition ruleTransition = (RuleTransition)t;
                    if (calledRuleStack.Get(ruleTransition.ruleIndex))
                    {
                        continue;
                    }
                    PredictionContext newContext = SingletonPredictionContext.Create(ctx, ruleTransition.followState.stateNumber);
                    try
                    {
                        calledRuleStack.Set(ruleTransition.target.ruleIndex);
                        Look(t.target, stopState, newContext, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
                    }
                    finally
                    {
                        calledRuleStack.Clear(ruleTransition.target.ruleIndex);
                    }
                }
                else
                {
                    if (t is AbstractPredicateTransition)
                    {
                        if (seeThruPreds)
                        {
                            Look(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
                        }
                        else
                        {
                            look.Add(HitPred);
                        }
                    }
                    else
                    {
                        if (t.IsEpsilon)
                        {
                            Look(t.target, stopState, ctx, look, lookBusy, calledRuleStack, seeThruPreds, addEOF);
                        }
                        else
                        {
                            if (t is WildcardTransition)
                            {
                                look.AddAll(IntervalSet.Of(TokenConstants.MinUserTokenType, atn.maxTokenType));
                            }
                            else
                            {
                                IntervalSet set = t.Label;
                                if (set != null)
                                {
                                    if (t is NotSetTransition)
                                    {
                                        set = set.Complement(IntervalSet.Of(TokenConstants.MinUserTokenType, atn.maxTokenType));
                                    }
                                    look.AddAll(set);
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        public static PredictionContext MergeArrays(
            ArrayPredictionContext a,
            ArrayPredictionContext b,
            bool rootIsWildcard,
            MergeCache mergeCache)
        {
            if (mergeCache != null)
            {
                PredictionContext previous = mergeCache.Get(a, b);
                if (previous != null)
                {
                    return(previous);
                }
                previous = mergeCache.Get(b, a);
                if (previous != null)
                {
                    return(previous);
                }
            }

            // merge sorted payloads a + b => M
            int i = 0;             // walks a
            int j = 0;             // walks b
            int k = 0;             // walks target M array

            int[] mergedReturnStates =
                new int[a.returnStates.Length + b.returnStates.Length];
            PredictionContext[] mergedParents =
                new PredictionContext[a.returnStates.Length + b.returnStates.Length];
            // walk and merge to yield mergedParents, mergedReturnStates
            while (i < a.returnStates.Length && j < b.returnStates.Length)
            {
                PredictionContext a_parent = a.parents[i];
                PredictionContext b_parent = b.parents[j];
                if (a.returnStates[i] == b.returnStates[j])
                {
                    // same payload (stack tops are equal), must yield merged singleton
                    int payload = a.returnStates[i];
                    // $+$ = $
                    bool both_dollar = payload == EMPTY_RETURN_STATE &&
                                       a_parent == null && b_parent == null;
                    bool ax_ax = (a_parent != null && b_parent != null) &&
                                 a_parent.Equals(b_parent);                                        // ax+ax -> ax
                    if (both_dollar || ax_ax)
                    {
                        mergedParents[k]      = a_parent;                    // choose left
                        mergedReturnStates[k] = payload;
                    }
                    else               // ax+ay -> a'[x,y]
                    {
                        PredictionContext mergedParent =
                            Merge(a_parent, b_parent, rootIsWildcard, mergeCache);
                        mergedParents[k]      = mergedParent;
                        mergedReturnStates[k] = payload;
                    }
                    i++;                     // hop over left one as usual
                    j++;                     // but also skip one in right side since we merge
                }
                else if (a.returnStates[i] < b.returnStates[j])
                {                 // copy a[i] to M
                    mergedParents[k]      = a_parent;
                    mergedReturnStates[k] = a.returnStates[i];
                    i++;
                }
                else                   // b > a, copy b[j] to M
                {
                    mergedParents[k]      = b_parent;
                    mergedReturnStates[k] = b.returnStates[j];
                    j++;
                }
                k++;
            }

            // copy over any payloads remaining in either array
            if (i < a.returnStates.Length)
            {
                for (int p = i; p < a.returnStates.Length; p++)
                {
                    mergedParents[k]      = a.parents[p];
                    mergedReturnStates[k] = a.returnStates[p];
                    k++;
                }
            }
            else
            {
                for (int p = j; p < b.returnStates.Length; p++)
                {
                    mergedParents[k]      = b.parents[p];
                    mergedReturnStates[k] = b.returnStates[p];
                    k++;
                }
            }

            // trim merged if we combined a few that had same stack tops
            if (k < mergedParents.Length)
            {             // write index < last position; trim
                if (k == 1)
                {         // for just one merged element, return singleton top
                    PredictionContext a_ = SingletonPredictionContext.Create(mergedParents[0], mergedReturnStates[0]);
                    if (mergeCache != null)
                    {
                        mergeCache.Put(a, b, a_);
                    }
                    return(a_);
                }
                mergedParents      = Arrays.CopyOf(mergedParents, k);
                mergedReturnStates = Arrays.CopyOf(mergedReturnStates, k);
            }

            PredictionContext M = new ArrayPredictionContext(mergedParents, mergedReturnStates);

            // if we created same array as a or b, return that instead
            // TODO: track whether this is possible above during merge sort for speed
            if (M.Equals(a))
            {
                if (mergeCache != null)
                {
                    mergeCache.Put(a, b, a);
                }
                return(a);
            }
            if (M.Equals(b))
            {
                if (mergeCache != null)
                {
                    mergeCache.Put(a, b, b);
                }
                return(b);
            }

            CombineCommonParents(mergedParents);

            if (mergeCache != null)
            {
                mergeCache.Put(a, b, M);
            }
            return(M);
        }
コード例 #11
0
        public static PredictionContext MergeSingletons(
            SingletonPredictionContext a,
            SingletonPredictionContext b,
            bool rootIsWildcard,
            MergeCache mergeCache)
        {
            if (mergeCache != null)
            {
                PredictionContext previous = mergeCache.Get(a, b);
                if (previous != null)
                {
                    return(previous);
                }
                previous = mergeCache.Get(b, a);
                if (previous != null)
                {
                    return(previous);
                }
            }

            PredictionContext rootMerge = MergeRoot(a, b, rootIsWildcard);

            if (rootMerge != null)
            {
                if (mergeCache != null)
                {
                    mergeCache.Put(a, b, rootMerge);
                }
                return(rootMerge);
            }

            if (a.returnState == b.returnState)
            {             // a == b
                PredictionContext parent = Merge(a.parent, b.parent, rootIsWildcard, mergeCache);
                // if parent is same as existing a or b parent or reduced to a parent, return it
                if (parent == a.parent)
                {
                    return(a);                                    // ax + bx = ax, if a=b
                }
                if (parent == b.parent)
                {
                    return(b);                                    // ax + bx = bx, if a=b
                }
                // else: ax + ay = a'[x,y]
                // merge parents x and y, giving array node with x,y then remainders
                // of those graphs.  dup a, a' points at merged array
                // new joined parent so create new singleton pointing to it, a'
                PredictionContext a_ = SingletonPredictionContext.Create(parent, a.returnState);
                if (mergeCache != null)
                {
                    mergeCache.Put(a, b, a_);
                }
                return(a_);
            }
            else               // a != b payloads differ
            // see if we can collapse parents due to $+x parents if local ctx
            {
                int[] payloads = new int[2];
                PredictionContext[] parents = new PredictionContext[2];
                PredictionContext   pc;
                PredictionContext   singleParent = null;
                if (a == b || (a.parent != null && a.parent.Equals(b.parent)))
                {                 // ax + bx = [a,b]x
                    singleParent = a.parent;
                }
                if (singleParent != null)
                {                   // parents are same
                    // sort payloads and use same parent
                    if (a.returnState > b.returnState)
                    {
                        payloads[0] = b.returnState;
                        payloads[1] = a.returnState;
                    }
                    else
                    {
                        payloads[0] = a.returnState;
                        payloads[1] = b.returnState;
                    }
                    parents[0] = singleParent;
                    parents[1] = singleParent;
                    pc         = new ArrayPredictionContext(parents, payloads);
                    if (mergeCache != null)
                    {
                        mergeCache.Put(a, b, pc);
                    }
                    return(pc);
                }
                // parents differ and can't merge them. Just pack together
                // into array; can't merge.
                // ax + by = [ax,by]
                // sort by payload
                if (a.returnState > b.returnState)
                {
                    payloads[0] = b.returnState;
                    payloads[1] = a.returnState;
                    parents[0]  = b.parent;
                    parents[1]  = a.parent;
                }
                else
                {
                    payloads[0] = a.returnState;
                    payloads[1] = b.returnState;
                    parents[0]  = a.parent;
                    parents[1]  = b.parent;
                }
                pc = new ArrayPredictionContext(parents, payloads);
                if (mergeCache != null)
                {
                    mergeCache.Put(a, b, pc);
                }
                return(pc);
            }
        }
コード例 #12
0
ファイル: LexerATNSimulator.cs プロジェクト: antlr/antlr4
        // side-effect: can alter configs.hasSemanticContext
        protected LexerATNConfig GetEpsilonTarget(ICharStream input,
											   LexerATNConfig config,
											   Transition t,
											   ATNConfigSet configs,
											   bool speculative,
											   bool treatEofAsEpsilon)
        {
            LexerATNConfig c = null;
            switch (t.TransitionType)
            {
                case TransitionType.RULE:
                    RuleTransition ruleTransition = (RuleTransition)t;
                    PredictionContext newContext = new SingletonPredictionContext(config.context, ruleTransition.followState.stateNumber);
                    c = new LexerATNConfig(config, t.target, newContext);
                    break;

                case TransitionType.PRECEDENCE:
                    throw new Exception("Precedence predicates are not supported in lexers.");

                case TransitionType.PREDICATE:
                    /*  Track traversing semantic predicates. If we traverse,
                     we cannot add a DFA state for this "reach" computation
                     because the DFA would not test the predicate again in the
                     future. Rather than creating collections of semantic predicates
                     like v3 and testing them on prediction, v4 will test them on the
                     fly all the time using the ATN not the DFA. This is slower but
                     semantically it's not used that often. One of the key elements to
                     this predicate mechanism is not adding DFA states that see
                     predicates immediately afterwards in the ATN. For example,

                     a : ID {p1}? | ID {p2}? ;

                     should create the start state for rule 'a' (to save start state
                     competition), but should not create target of ID state. The
                     collection of ATN states the following ID references includes
                     states reached by traversing predicates. Since this is when we
                     test them, we cannot cash the DFA state target of ID.
                 */
                    PredicateTransition pt = (PredicateTransition)t;
                    if (debug)
                    {
                        Console.WriteLine("EVAL rule " + pt.ruleIndex + ":" + pt.predIndex);
                    }
                    configs.hasSemanticContext = true;
                    if (EvaluatePredicate(input, pt.ruleIndex, pt.predIndex, speculative))
                    {
                        c = new LexerATNConfig(config, t.target);
                    }
                    break;

                case TransitionType.ACTION:
                    if (config.context == null || config.context.HasEmptyPath)
                    {
                        // execute actions anywhere in the start rule for a token.
                        //
                        // TODO: if the entry rule is invoked recursively, some
                        // actions may be executed during the recursive call. The
                        // problem can appear when hasEmptyPath() is true but
                        // isEmpty() is false. In this case, the config needs to be
                        // split into two contexts - one with just the empty path
                        // and another with everything but the empty path.
                        // Unfortunately, the current algorithm does not allow
                        // getEpsilonTarget to return two configurations, so
                        // additional modifications are needed before we can support
                        // the split operation.
                        LexerActionExecutor lexerActionExecutor = LexerActionExecutor.Append(config.getLexerActionExecutor(), atn.lexerActions[((ActionTransition)t).actionIndex]);
                        c = new LexerATNConfig(config, t.target, lexerActionExecutor);
                        break;
                    }
                    else {
                        // ignore actions in referenced rules
                        c = new LexerATNConfig(config, t.target);
                        break;
                    }

                case TransitionType.EPSILON:
                    c = new LexerATNConfig(config, t.target);
                    break;

                case TransitionType.ATOM:
                case TransitionType.RANGE:
                case TransitionType.SET:
                    if (treatEofAsEpsilon)
                    {
                        if (t.Matches(IntStreamConstants.EOF, char.MinValue, char.MaxValue))
                        {
                            c = new LexerATNConfig(config, t.target);
                            break;
                        }
                    }

                    break;
            }

            return c;
        }