Example #1
0
        /** Walk each configuration and if they are all the same alt, return
         *  that alt else return NFA.INVALID_ALT_NUMBER.  Ignore resolved
         *  configurations, but don't ignore resolveWithPredicate configs
         *  because this state should not be an accept state.  We need to add
         *  this to the work list and then have semantic predicate edges
         *  emanating from it.
         */
        public virtual int GetUniquelyPredictedAlt()
        {
            if (cachedUniquelyPredicatedAlt != PREDICTED_ALT_UNSET)
            {
                return(cachedUniquelyPredicatedAlt);
            }
            int alt        = NFA.INVALID_ALT_NUMBER;
            int numConfigs = nfaConfigurations.Size();

            for (int i = 0; i < numConfigs; i++)
            {
                NFAConfiguration configuration = (NFAConfiguration)nfaConfigurations.Get(i);
                // ignore anything we resolved; predicates will still result
                // in transitions out of this state, so must count those
                // configurations; i.e., don't ignore resolveWithPredicate configs
                if (configuration.resolved)
                {
                    continue;
                }
                if (alt == NFA.INVALID_ALT_NUMBER)
                {
                    alt = configuration.alt; // found first nonresolved alt
                }
                else if (configuration.alt != alt)
                {
                    return(NFA.INVALID_ALT_NUMBER);
                }
            }
            this.cachedUniquelyPredicatedAlt = alt;
            return(alt);
        }
Example #2
0
        /** Walk each configuration and if they are all the same alt, return
         *  that alt else return NFA.INVALID_ALT_NUMBER.  Ignore resolved
         *  configurations, but don't ignore resolveWithPredicate configs
         *  because this state should not be an accept state.  We need to add
         *  this to the work list and then have semantic predicate edges
         *  emanating from it.
         */
        public virtual int GetUniquelyPredictedAlt()
        {
            if (_cachedUniquelyPredicatedAlt.HasValue)
            {
                return(_cachedUniquelyPredicatedAlt.Value);
            }

            int alt        = NFA.INVALID_ALT_NUMBER;
            int numConfigs = _nfaConfigurations.Count;

            for (int i = 0; i < numConfigs; i++)
            {
                NFAConfiguration configuration = _nfaConfigurations[i];
                // ignore anything we resolved; predicates will still result
                // in transitions out of this state, so must count those
                // configurations; i.e., don't ignore resolveWithPredicate configs
                if (configuration.Resolved)
                {
                    continue;
                }

                if (alt == NFA.INVALID_ALT_NUMBER)
                {
                    alt = configuration.Alt; // found first nonresolved alt
                }
                else if (configuration.Alt != alt)
                {
                    return(NFA.INVALID_ALT_NUMBER);
                }
            }

            this._cachedUniquelyPredicatedAlt = alt;
            return(alt);
        }
Example #3
0
        public virtual NFAConfiguration AddNFAConfiguration(NFAState state,
                                                            int alt,
                                                            NFAContext context,
                                                            SemanticContext semanticContext)
        {
            NFAConfiguration c = new NFAConfiguration(state.StateNumber,
                                                      alt,
                                                      context,
                                                      semanticContext);

            AddNFAConfiguration(state, c);
            return(c);
        }
Example #4
0
        /** An NFA configuration is equal to another if both have
         *  the same state, the predict the same alternative, and
         *  syntactic/semantic contexts are the same.  I don't think
         *  the state|alt|ctx could be the same and have two different
         *  semantic contexts, but might as well define equals to be
         *  everything.
         */
        public override bool Equals(object o)
        {
            if (o == null)
            {
                return(false);
            }
            NFAConfiguration other = (NFAConfiguration)o;

            return(this.state == other.state &&
                   this.alt == other.alt &&
                   this.context.Equals(other.context) &&
                   this.semanticContext.Equals(other.semanticContext));
        }
Example #5
0
        /** When more than one alternative can match the same input, the first
         *  alternative is chosen to resolve the conflict.  The other alts
         *  are "turned off" by setting the "resolved" flag in the NFA
         *  configurations.  Return the set of disabled alternatives.  For
         *
         *  a : A | A | A ;
         *
         *  this method returns {2,3} as disabled.  This does not mean that
         *  the alternative is totally unreachable, it just means that for this
         *  DFA state, that alt is disabled.  There may be other accept states
         *  for that alt.
         */
        public virtual ICollection <int> GetDisabledAlternatives()
        {
            HashSet <int> disabled   = new HashSet <int>();
            int           numConfigs = nfaConfigurations.Size();

            for (int i = 0; i < numConfigs; i++)
            {
                NFAConfiguration configuration = (NFAConfiguration)nfaConfigurations.Get(i);
                if (configuration.resolved)
                {
                    disabled.Add(configuration.alt);
                }
            }
            return(disabled);
        }
Example #6
0
        public virtual void ReportRecursionOverflow(DFAState d,
                                                    NFAConfiguration recursionNFAConfiguration)
        {
            // track the state number rather than the state as d will change
            // out from underneath us; hash wouldn't return any value

            // left-recursion is detected in start state.  Since we can't
            // call resolveNondeterminism() on the start state (it would
            // not look k=1 to get min single token lookahead), we must
            // prevent errors derived from this state.  Avoid start state
            if (d.stateNumber > 0)
            {
                int stateI = d.stateNumber;
                _stateToRecursionOverflowConfigurationsMap.Map(stateI, recursionNFAConfiguration);
            }
        }
Example #7
0
        /** Get the set of all alts mentioned by all NFA configurations in this
         *  DFA state.
         */
        public virtual HashSet <int> GetAltSet()
        {
            int           numConfigs = nfaConfigurations.Size();
            HashSet <int> alts       = new HashSet <int>();

            for (int i = 0; i < numConfigs; i++)
            {
                NFAConfiguration configuration = (NFAConfiguration)nfaConfigurations.Get(i);
                alts.Add(configuration.alt);
            }
            if (alts.Count == 0)
            {
                return(null);
            }
            return(alts);
        }
Example #8
0
        /** Print all NFA states plus what alts they predict */
        public override String ToString()
        {
            StringBuilder buf = new StringBuilder();

            buf.Append(StateNumber + ":{");
            for (int i = 0; i < _nfaConfigurations.Count; i++)
            {
                NFAConfiguration configuration = (NFAConfiguration)_nfaConfigurations[i];
                if (i > 0)
                {
                    buf.Append(", ");
                }
                buf.Append(configuration);
            }
            buf.Append("}");
            return(buf.ToString());
        }
Example #9
0
        /** Print all NFA states plus what alts they predict */
        public override String ToString()
        {
            StringBuilder buf = new StringBuilder();

            buf.Append(stateNumber + ":{");
            for (int i = 0; i < nfaConfigurations.Size(); i++)
            {
                NFAConfiguration configuration = (NFAConfiguration)nfaConfigurations.Get(i);
                if (i > 0)
                {
                    buf.Append(", ");
                }
                buf.Append(configuration);
            }
            buf.Append("}");
            return(buf.ToString());
        }
Example #10
0
        /** Add an NFA configuration to this DFA node.  Add uniquely
         *  an NFA state/alt/syntactic&semantic context (chain of invoking state(s)
         *  and semantic predicate contexts).
         *
         *  I don't see how there could be two configurations with same
         *  state|alt|synCtx and different semantic contexts because the
         *  semantic contexts are computed along the path to a particular state
         *  so those two configurations would have to have the same predicate.
         *  Nonetheless, the addition of configurations is unique on all
         *  configuration info.  I guess I'm saying that syntactic context
         *  implies semantic context as the latter is computed according to the
         *  former.
         *
         *  As we add configurations to this DFA state, track the set of all possible
         *  transition labels so we can simply walk it later rather than doing a
         *  loop over all possible labels in the NFA.
         */
        public virtual void AddNFAConfiguration(NFAState state, NFAConfiguration c)
        {
            if (_nfaConfigurations.Contains(c))
            {
                return;
            }

            _nfaConfigurations.Add(c);

            // track min alt rather than compute later
            if (c.Alt < _minAltInConfigurations)
            {
                _minAltInConfigurations = c.Alt;
            }

            if (c.SemanticContext != SemanticContext.EmptySemanticContext)
            {
                _atLeastOneConfigurationHasAPredicate = true;
            }

            // update hashCode; for some reason using context.hashCode() also
            // makes the GC take like 70% of the CPU and is slow!
            _cachedHashCode += c.State + c.Alt;

            // update reachableLabels
            // We're adding an NFA state; check to see if it has a non-epsilon edge
            if (state.transition[0] != null)
            {
                Label label = state.transition[0].Label;
                if (!(label.IsEpsilon || label.IsSemanticPredicate))
                {
                    // this NFA state has a non-epsilon edge, track for fast
                    // walking later when we do reach on this DFA state we're
                    // building.
                    _configurationsWithLabeledEdges.Add(c);
                    if (state.transition[1] == null)
                    {
                        // later we can check this to ignore o-A->o states in closure
                        c.SingleAtomTransitionEmanating = true;
                    }
                    AddReachableLabel(label);
                }
            }
        }
Example #11
0
        /** Return the uniquely mentioned alt from the NFA configurations;
         *  Ignore the resolved bit etc...  Return INVALID_ALT_NUMBER
         *  if there is more than one alt mentioned.
         */
        public virtual int GetUniqueAlt()
        {
            int alt        = NFA.INVALID_ALT_NUMBER;
            int numConfigs = _nfaConfigurations.Count;

            for (int i = 0; i < numConfigs; i++)
            {
                NFAConfiguration configuration = _nfaConfigurations[i];
                if (alt == NFA.INVALID_ALT_NUMBER)
                {
                    alt = configuration.Alt; // found first alt
                }
                else if (configuration.Alt != alt)
                {
                    return(NFA.INVALID_ALT_NUMBER);
                }
            }
            return(alt);
        }
Example #12
0
 private void ComputeAltToProblemMaps(IEnumerable <int> dfaStatesUnaliased,
                                      IDictionary <int, IList <NFAConfiguration> > configurationsMap,
                                      IDictionary <int, IDictionary <string, ICollection <NFAState> > > altToTargetToCallSitesMap,
                                      IDictionary <int, DFAState> altToDFAState)
 {
     foreach (int stateI in dfaStatesUnaliased)
     {
         // walk this DFA's config list
         IList <NFAConfiguration> configs;
         configurationsMap.TryGetValue(stateI, out configs);
         for (int i = 0; i < configs.Count; i++)
         {
             NFAConfiguration      c = (NFAConfiguration)configs[i];
             NFAState              ruleInvocationState = _dfa.Nfa.GetState(c.State);
             Transition            transition0         = ruleInvocationState.transition[0];
             RuleClosureTransition @ref = (RuleClosureTransition)transition0;
             string targetRule          = ((NFAState)@ref.Target).enclosingRule.Name;
             int    altI = c.Alt;
             IDictionary <string, ICollection <NFAState> > targetToCallSiteMap;
             altToTargetToCallSitesMap.TryGetValue(altI, out targetToCallSiteMap);
             if (targetToCallSiteMap == null)
             {
                 targetToCallSiteMap             = new Dictionary <string, ICollection <NFAState> >();
                 altToTargetToCallSitesMap[altI] = targetToCallSiteMap;
             }
             ICollection <NFAState> callSites;
             targetToCallSiteMap.TryGetValue(targetRule, out callSites);
             if (callSites == null)
             {
                 callSites = new HashSet <NFAState>();
                 targetToCallSiteMap[targetRule] = callSites;
             }
             callSites.Add(ruleInvocationState);
             // track one problem DFA state per alt
             DFAState state;
             if (!altToDFAState.TryGetValue(altI, out state) || state == null)
             {
                 DFAState sampleBadState = _dfa.GetState(stateI);
                 altToDFAState[altI] = sampleBadState;
             }
         }
     }
 }
Example #13
0
        /** For gated productions, we need an OR'd list of all predicates for the
         *  target of an edge so we can gate the edge based upon the predicates
         *  associated with taking that path (if any).
         *
         *  For syntactic predicates, we only want to generate predicate
         *  evaluations as it transitions to an accept state; waste to
         *  do it earlier.  So, only add gated preds derived from manually-
         *  specified syntactic predicates if this is an accept state.
         *
         *  Also, since configurations w/o gated predicates are like true
         *  gated predicates, finding a configuration whose alt has no gated
         *  predicate implies we should evaluate the predicate to true. This
         *  means the whole edge has to be ungated. Consider:
         *
         *	 X : ('a' | {p}?=> 'a')
         *	   | 'a' 'b'
         *	   ;
         *
         *  Here, you 'a' gets you from s0 to s1 but you can't test p because
         *  plain 'a' is ok.  It's also ok for starting alt 2.  Hence, you can't
         *  test p.  Even on the edge going to accept state for alt 1 of X, you
         *  can't test p.  You can get to the same place with and w/o the context.
         *  Therefore, it is never ok to test p in this situation.
         *
         *  TODO: cache this as it's called a lot; or at least set bit if >1 present in state
         */
        public virtual SemanticContext GetGatedPredicatesInNFAConfigurations()
        {
            SemanticContext unionOfPredicatesFromAllAlts = null;
            int             numConfigs = _nfaConfigurations.Count;

            for (int i = 0; i < numConfigs; i++)
            {
                NFAConfiguration configuration = (NFAConfiguration)_nfaConfigurations[i];
                SemanticContext  gatedPredExpr =
                    configuration.SemanticContext.GatedPredicateContext;
                if (gatedPredExpr == null)
                {
                    // if we ever find a configuration w/o a gated predicate
                    // (even if it's a nongated predicate), we cannot gate
                    // the indident edges.
                    return(null);
                }
                else if (IsAcceptState || !configuration.SemanticContext.IsSyntacticPredicate)
                {
                    // at this point we have a gated predicate and, due to elseif,
                    // we know it's an accept or not a syn pred.  In this case,
                    // it's safe to add the gated predicate to the union.  We
                    // only want to add syn preds if it's an accept state.  Other
                    // gated preds can be used with edges leading to accept states.
                    if (unionOfPredicatesFromAllAlts == null)
                    {
                        unionOfPredicatesFromAllAlts = gatedPredExpr;
                    }
                    else
                    {
                        unionOfPredicatesFromAllAlts =
                            SemanticContext.Or(unionOfPredicatesFromAllAlts, gatedPredExpr);
                    }
                }
            }
            if (unionOfPredicatesFromAllAlts is SemanticContext.TruePredicate)
            {
                return(null);
            }
            return(unionOfPredicatesFromAllAlts);
        }
Example #14
0
        public virtual HashSet <SemanticContext> GetGatedSyntacticPredicatesInNFAConfigurations()
        {
            int numConfigs = _nfaConfigurations.Count;
            HashSet <SemanticContext> synpreds = new HashSet <SemanticContext>();

            for (int i = 0; i < numConfigs; i++)
            {
                NFAConfiguration configuration = (NFAConfiguration)_nfaConfigurations[i];
                SemanticContext  gatedPredExpr =
                    configuration.SemanticContext.GatedPredicateContext;
                // if this is a manual syn pred (gated and syn pred), add
                if (gatedPredExpr != null &&
                    configuration.SemanticContext.IsSyntacticPredicate)
                {
                    synpreds.Add(configuration.SemanticContext);
                }
            }
            if (synpreds.Count == 0)
            {
                return(null);
            }
            return(synpreds);
        }
Example #15
0
        /** Walk each NFA configuration in this DFA state looking for a conflict
         *  where (s|i|ctx) and (s|j|ctx) exist, indicating that state s with
         *  context conflicting ctx predicts alts i and j.  Return an Integer set
         *  of the alternative numbers that conflict.  Two contexts conflict if
         *  they are equal or one is a stack suffix of the other or one is
         *  the empty context.
         *
         *  Use a hash table to record the lists of configs for each state
         *  as they are encountered.  We need only consider states for which
         *  there is more than one configuration.  The configurations' predicted
         *  alt must be different or must have different contexts to avoid a
         *  conflict.
         *
         *  Don't report conflicts for DFA states that have conflicting Tokens
         *  rule NFA states; they will be resolved in favor of the first rule.
         */
        protected virtual HashSet <int> GetConflictingAlts()
        {
            // TODO this is called multiple times: cache result?
            //[email protected]("getNondetAlts for DFA state "+stateNumber);
            HashSet <int> nondeterministicAlts = new HashSet <int>();

            // If only 1 NFA conf then no way it can be nondeterministic;
            // save the overhead.  There are many o-a->o NFA transitions
            // and so we save a hash map and iterator creation for each
            // state.
            int numConfigs = _nfaConfigurations.Count;

            if (numConfigs <= 1)
            {
                return(null);
            }

            // First get a list of configurations for each state.
            // Most of the time, each state will have one associated configuration.
            MultiMap <int, NFAConfiguration> stateToConfigListMap =
                new MultiMap <int, NFAConfiguration>();

            for (int i = 0; i < numConfigs; i++)
            {
                NFAConfiguration configuration = (NFAConfiguration)_nfaConfigurations[i];
                int stateI = configuration.State;
                stateToConfigListMap.Map(stateI, configuration);
            }
            // potential conflicts are states with > 1 configuration and diff alts
            ICollection <int> states  = stateToConfigListMap.Keys.ToArray();
            int numPotentialConflicts = 0;

            foreach (int stateI in states)
            {
                bool thisStateHasPotentialProblem = false;
                IList <NFAConfiguration> configsForState;
                stateToConfigListMap.TryGetValue(stateI, out configsForState);
                int alt = 0;
                int numConfigsForState = configsForState.Count;
                for (int i = 0; i < numConfigsForState && numConfigsForState > 1; i++)
                {
                    NFAConfiguration c = (NFAConfiguration)configsForState[i];
                    if (alt == 0)
                    {
                        alt = c.Alt;
                    }
                    else if (c.Alt != alt)
                    {
                        /*
                         * [email protected]("potential conflict in state "+stateI+
                         *                 " configs: "+configsForState);
                         */
                        // 11/28/2005: don't report closures that pinch back
                        // together in Tokens rule.  We want to silently resolve
                        // to the first token definition ala lex/flex by ignoring
                        // these conflicts.
                        // Also this ensures that lexers look for more and more
                        // characters (longest match) before resorting to predicates.
                        // TestSemanticPredicates.testLexerMatchesLongestThenTestPred()
                        // for example would terminate at state s1 and test predicate
                        // meaning input "ab" would test preds to decide what to
                        // do but it should match rule C w/o testing preds.
                        if (dfa.Nfa.Grammar.type != GrammarType.Lexer ||
                            !dfa.NFADecisionStartState.enclosingRule.Name.Equals(Grammar.ArtificialTokensRuleName))
                        {
                            numPotentialConflicts++;
                            thisStateHasPotentialProblem = true;
                        }
                    }
                }
                if (!thisStateHasPotentialProblem)
                {
                    // remove NFA state's configurations from
                    // further checking; no issues with it
                    // (can't remove as it's concurrent modification; set to null)
                    stateToConfigListMap[stateI] = null;
                }
            }

            // a fast check for potential issues; most states have none
            if (numPotentialConflicts == 0)
            {
                return(null);
            }

            // we have a potential problem, so now go through config lists again
            // looking for different alts (only states with potential issues
            // are left in the states set).  Now we will check context.
            // For example, the list of configs for NFA state 3 in some DFA
            // state might be:
            //   [3|2|[28 18 $], 3|1|[28 $], 3|1, 3|2]
            // I want to create a map from context to alts looking for overlap:
            //   [28 18 $] -> 2
            //   [28 $] -> 1
            //   [$] -> 1,2
            // Indeed a conflict exists as same state 3, same context [$], predicts
            // alts 1 and 2.
            // walk each state with potential conflicting configurations
            foreach (int stateI in states)
            {
                IList <NFAConfiguration> configsForState;
                stateToConfigListMap.TryGetValue(stateI, out configsForState);
                // compare each configuration pair s, t to ensure:
                // s.ctx different than t.ctx if s.alt != t.alt
                int numConfigsForState = 0;
                if (configsForState != null)
                {
                    numConfigsForState = configsForState.Count;
                }
                for (int i = 0; i < numConfigsForState; i++)
                {
                    NFAConfiguration s = configsForState[i];
                    for (int j = i + 1; j < numConfigsForState; j++)
                    {
                        NFAConfiguration t = configsForState[j];
                        // conflicts means s.ctx==t.ctx or s.ctx is a stack
                        // suffix of t.ctx or vice versa (if alts differ).
                        // Also a conflict if s.ctx or t.ctx is empty
                        if (s.Alt != t.Alt && s.Context.ConflictsWith(t.Context))
                        {
                            nondeterministicAlts.Add(s.Alt);
                            nondeterministicAlts.Add(t.Alt);
                        }
                    }
                }
            }

            if (nondeterministicAlts.Count == 0)
            {
                return(null);
            }
            return(nondeterministicAlts);
        }
 public AnalysisRecursionOverflowException(DFAState ovfState, NFAConfiguration proposedNFAConfiguration)
 {
     _ovfState = ovfState;
     _proposedNFAConfiguration = proposedNFAConfiguration;
 }