Example #1
0
        private SerializableDfa <TResult> _build(IList <ISet <TResult> > languages, DfaAmbiguityResolver <TResult> ambiguityResolver)
        {
            var nfa = new Nfa <TResult>();

            var nfaStartStates = new int[languages.Count];

            for (var i = 0; i < languages.Count; ++i)
            {
                nfaStartStates[i] = nfa.AddState();
            }

            ambiguityResolver ??= DefaultAmbiguityResolver;

            foreach (var patEntry in patterns)
            {
                var patList = patEntry.Value;
                if (patList == null || patList.Count < 1)
                {
                    continue;
                }

                var matchState = -1; //start state for matching this token
                for (var i = 0; i < languages.Count; ++i)
                {
                    if (!languages[i].Contains(patEntry.Key))
                    {
                        continue;
                    }

                    if (matchState < 0)
                    {
                        var acceptState = nfa.AddState(patEntry.Key); //final state accepting this token
                        if (patList.Count > 1)
                        {
                            //we have multiple patterns.  Make a union
                            matchState = nfa.AddState();
                            foreach (var pat in patList)
                            {
                                nfa.AddEpsilon(matchState, pat.AddToNfa(nfa, acceptState));
                            }
                        }
                        else
                        {
                            //only one pattern no union necessary
                            matchState = patList[0].AddToNfa(nfa, acceptState);
                        }
                    }

                    //language i matches these patterns
                    nfa.AddEpsilon(nfaStartStates[i], matchState);
                }
            }

            var rawDfa          = new DfaFromNfa <TResult>(nfa, nfaStartStates, ambiguityResolver).GetDfa();
            var minimalDfa      = new DfaMinimizer <TResult>(rawDfa).GetMinimizedDfa();
            var serializableDfa = new SerializableDfa <TResult>(minimalDfa);

            return(serializableDfa);
        }
Example #2
0
        private SerializableDfa <bool> _buildReverseFinders(IList <ISet <TResult> > languages)
        {
            var nfa = new Nfa <bool>();

            var startState = nfa.AddState();
            var endState   = nfa.AddState(true);
            DfaAmbiguityResolver <bool> ambiguityResolver = DefaultAmbiguityResolver;

            //First, make an NFA that matches the reverse of all the patterns
            foreach (var patEntry in patterns)
            {
                var patList = patEntry.Value;
                if (patList == null || patList.Count < 1)
                {
                    continue;
                }

                foreach (var language in languages)
                {
                    if (!language.Contains(patEntry.Key))
                    {
                        continue;
                    }

                    foreach (var pat in patEntry.Value)
                    {
                        var st = pat.Reversed.AddToNfa(nfa, endState);
                        nfa.AddEpsilon(startState, st);
                    }
                }
            }

            //omit the empty string
            startState = nfa.Disemptify(startState);

            //allow anything first
            startState = Pattern.MaybeRepeat(CharRange.All).AddToNfa(nfa, startState);

            //build the DFA
            var rawDfa          = new DfaFromNfa <bool>(nfa, new[] { startState }, ambiguityResolver).GetDfa();
            var minimalDfa      = new DfaMinimizer <bool>(rawDfa).GetMinimizedDfa();
            var serializableDfa = new SerializableDfa <bool>(minimalDfa);

            return(serializableDfa);
        }
Example #3
0
        /// <summary>
        /// Build DFAs from a provided NFA
        ///
        /// This method is used when you want to build the NFA yourself instead of letting this class do it.
        ///
        /// Languages built simultaneously will be globally minimized and will share as many states as possible.
        /// </summary>
        /// <param name="nfa">The NFA</param>
        /// <param name="nfaStartStates">The return value will include the DFA states corresponding to these NFA states, in the same order</param>
        /// <param name="ambiguityResolver">When patterns for multiple results match the same string, this is called to
        /// combine the multiple results into one.  If this is null, then a DfaAmbiguityException will be thrown in that case.</param>
        /// <param name="cache">If this cache is non-null, it will be checked for a memoized result for this NFA, and will be populated
        /// with a memoized result when the call is complete.</param>
        /// <returns>DFA start states that are equivalent to the given NFA start states.  This will have the same length as nfaStartStates, with
        /// corresponding start states in corresponding positions.</returns>
        public static IList <DfaState <TResult> > BuildFromNfa(Nfa <TResult> nfa, int[] nfaStartStates, DfaAmbiguityResolver <TResult> ambiguityResolver,
                                                               IBuilderCache cache)
        {
            string cacheKey = null;
            SerializableDfa <TResult> serializableDfa = null;

            if (cache != null)
            {
                var hashAlg = new SHA256Managed();
                using (var ms = new MemoryStream())
                {
                    using var cs = new CryptoStream(ms, hashAlg, CryptoStreamMode.Write);
                    var bf = new BinaryFormatter();
                    bf.Serialize(ms, nfaStartStates);
                    bf.Serialize(ms, nfa);
                    bf.Serialize(ms, ambiguityResolver);
                    ms.Flush();
                    cs.FlushFinalBlock();

                    cacheKey = Base32.GetDigest(hashAlg.Hash);
                }

                serializableDfa = (SerializableDfa <TResult>)cache.GetCachedItem(cacheKey);
            }

            if (serializableDfa == null)
            {
                var rawDfa     = new DfaFromNfa <TResult>(nfa, nfaStartStates, ambiguityResolver).GetDfa();
                var minimalDfa = new DfaMinimizer <TResult>(rawDfa).GetMinimizedDfa();
                serializableDfa = new SerializableDfa <TResult>(minimalDfa);
                if (cacheKey != null)
                {
                    cache.MaybeCacheItem(cacheKey, serializableDfa);
                }
            }

            return(serializableDfa.GetStartStates());
        }