/// <summary>
        /// Creates a state machine representing this expression
        /// </summary>
        /// <typeparam name="TAccept">The type of accept symbol to use for this expression</typeparam>
        /// <param name="accept">The accept symbol to use for this expression</param>
        /// <returns>A new <see cref="CharFA{TAccept}"/> finite state machine representing this expression</returns>
        public override CharFA <TAccept> ToFA <TAccept>(TAccept accept)
        {
            var left  = (null != Left) ? Left.ToFA(accept) : null;
            var right = (null != Right) ? Right.ToFA(accept) : null;

            return(CharFA <TAccept> .Or(new CharFA <TAccept>[] { left, right }, accept));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates a state machine representing this expression
        /// </summary>
        /// <typeparam name="TAccept">The type of accept symbol to use for this expression</typeparam>
        /// <param name="accept">The accept symbol to use for this expression</param>
        /// <returns>A new <see cref="CharFA{TAccept}"/> finite state machine representing this expression</returns>
        public override CharFA <TAccept> ToFA <TAccept>(TAccept accept)
        {
            var ranges = new List <CharRange>();

            for (int ic = Entries.Count, i = 0; i < ic; ++i)
            {
                var entry = Entries[i];
                var crc   = entry as RegexCharsetCharEntry;
                if (null != crc)
                {
                    ranges.Add(new CharRange(crc.Value, crc.Value));
                }
                var crr = entry as RegexCharsetRangeEntry;
                if (null != crr)
                {
                    ranges.Add(new CharRange(crr.First, crr.Last));
                }
                var crcl = entry as RegexCharsetClassEntry;
                if (null != crcl)
                {
                    ranges.AddRange(CharFA <TAccept> .CharacterClasses[crcl.Name]);
                }
            }
            if (HasNegatedRanges)
            {
                return(CharFA <TAccept> .Set(CharRange.NotRanges(ranges), accept));
            }
            return(CharFA <TAccept> .Set(ranges, accept));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Returns a duplicate state machine, except one that only goes from this state to any state specified in <paramref name="to"/>. Any state that does not lead to one of those states is eliminated from the resulting graph.
        /// </summary>
        /// <param name="to">The collection of destination states</param>
        /// <returns>A new state machine that only goes from this state to the states indicated by <paramref name="to"/></returns>
        public CharFA <TAccept> ClonePathToAny(IEnumerable <CharFA <TAccept> > to)
        {
            var closure  = FillClosure();
            var nclosure = new CharFA <TAccept> [closure.Count];

            for (var i = 0; i < nclosure.Length; i++)
            {
                nclosure[i]     = new CharFA <TAccept>(closure[i].IsAccepting, closure[i].AcceptSymbol);
                nclosure[i].Tag = closure[i].Tag;
            }
            for (var i = 0; i < nclosure.Length; i++)
            {
                var t = nclosure[i].InputTransitions;
                var e = nclosure[i].EpsilonTransitions;
                foreach (var trns in closure[i].InputTransitions)
                {
                    if (_ContainsAny(trns.Value.FillClosure(), to))
                    {
                        var id = closure.IndexOf(trns.Value);

                        t.Add(trns.Key, nclosure[id]);
                    }
                }
                foreach (var trns in closure[i].EpsilonTransitions)
                {
                    if (_ContainsAny(trns.FillClosure(), to))
                    {
                        var id = closure.IndexOf(trns);
                        e.Add(nclosure[id]);
                    }
                }
            }
            return(nclosure[0]);
        }
        /// <summary>
        /// Creates a new FA that matches the specified FA expression or empty
        /// </summary>
        /// <param name="expr">The expression to make optional</param>
        /// <param name="accept">The symbol to accept</param>
        /// <returns>A new FA that will match the specified expression or empty</returns>
        public static CharFA <TAccept> Optional(CharFA <TAccept> expr, TAccept accept = default(TAccept))
        {
            var result = expr.Clone();
            var f      = result.FirstAcceptingState;

            f.AcceptSymbol = accept;
            result.EpsilonTransitions.Add(f);
            return(result);
        }
        static void _Concat(CharFA <TAccept> lhs, CharFA <TAccept> rhs)
        {
            //Debug.Assert(lhs != rhs);
            var f = lhs.FirstAcceptingState;

            //Debug.Assert(null != rhs.FirstAcceptingState);
            f.IsAccepting = false;
            f.EpsilonTransitions.Add(rhs);
            //Debug.Assert(null!= lhs.FirstAcceptingState);
        }
 public void Add(CharRange inputRange, CharFA <TAccept> fa)
 {
     _rangeTransitions.Add(new RangeWithFa(inputRange, fa));
     if (!_charactersByState.TryGetValue(fa, out var chars))
     {
         chars = new CharactersAndRanges(new List <char>(), new List <CharRange>());
         _charactersByState[fa] = chars;
     }
     chars.ranges.Add(inputRange);
 }
 public void Add(char input, CharFA <TAccept> fa)
 {
     _charactersTransitions.Add(input, fa);
     if (!_charactersByState.TryGetValue(fa, out var chars))
     {
         chars = new CharactersAndRanges(new List <char>(), new List <CharRange>());
         _charactersByState[fa] = chars;
     }
     chars.characters.Add(input);
 }
Exemplo n.º 8
0
 static bool _TryForwardNeutral(CharFA <TAccept> fa, out CharFA <TAccept> result)
 {
     if (!fa.IsNeutral)
     {
         result = fa;
         return(false);
     }
     result = fa.EpsilonTransitions[0];
     return(fa != result);            // false if circular
 }
Exemplo n.º 9
0
        /// <summary>
        /// Creates a lexer out of the specified FSM "expressions"
        /// </summary>
        /// <param name="exprs">The expressions to compose the lexer with</param>
        /// <returns>An FSM representing the lexer.</returns>
        public static CharFA <TAccept> ToLexer(params CharFA <TAccept>[] exprs)
        {
            var result = new CharFA <TAccept>();

            for (var i = 0; i < exprs.Length; i++)
            {
                result.EpsilonTransitions.Add(exprs[i]);
            }
            return(result);
        }
 public void Add(CharFA <TAccept> fa, CharactersAndRanges inputs)
 {
     foreach (var input in inputs.characters)
     {
         Add(input, fa);
     }
     foreach (var inputsRange in inputs.ranges)
     {
         Add(inputsRange, fa);
     }
 }
Exemplo n.º 11
0
        /// <summary>
        /// Creates an FA that will match any one of a set of a characters
        /// </summary>
        /// <param name="set">The set of characters that will be matched</param>
        /// <param name="accept">The symbol to accept</param>
        /// <returns>An FA that will match the specified set</returns>
        public static CharFA <TAccept> Set(IEnumerable <char> set, TAccept accept = default(TAccept))
        {
            var result = new CharFA <TAccept>();
            var final  = new CharFA <TAccept>(true, accept);

            foreach (var ch in set)
            {
                result.InputTransitions[ch] = final;
            }
            return(result);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Creates an FA that will match any one of a set of a characters
        /// </summary>
        /// <param name="ranges">The set ranges of characters that will be matched</param>
        /// <param name="accept">The symbol to accept</param>
        /// <returns>An FA that will match the specified set</returns>
        public static CharFA <TAccept> Set(IEnumerable <CharRange> ranges, TAccept accept = default(TAccept))
        {
            var result = new CharFA <TAccept>();
            var final  = new CharFA <TAccept>(true, accept);

            foreach (var ch in CharRange.ExpandRanges(ranges))
            {
                result.InputTransitions[ch] = final;
            }
            return(result);
        }
        /// <summary>
        /// Creates an FA that will match any one of a set of a characters
        /// </summary>
        /// <param name="ranges">The set ranges of characters that will be matched</param>
        /// <param name="accept">The symbol to accept</param>
        /// <returns>An FA that will match the specified set</returns>
        public static CharFA <TAccept> Set(IEnumerable <CharRange> ranges, TAccept accept = default(TAccept))
        {
            var result = new CharFA <TAccept>();
            var final  = new CharFA <TAccept>(true, accept);

            foreach (var charRange in ranges)
            {
                result.InputTransitions.Add(charRange, final);
            }

            return(result);
        }
        /// <summary>
        /// Creates an FA that matches a literal string
        /// </summary>
        /// <param name="string">The string to match</param>
        /// <param name="accept">The symbol to accept</param>
        /// <returns>A new FA machine that will match this literal</returns>
        public static CharFA <TAccept> Literal(IEnumerable <char> @string, TAccept accept = default(TAccept))
        {
            var result  = new CharFA <TAccept>();
            var current = result;

            foreach (var ch in @string)
            {
                current.IsAccepting = false;
                var fa = new CharFA <TAccept>(true, accept);
                current.InputTransitions.Add(ch, fa);
                current = fa;
            }
            return(result);
        }
Exemplo n.º 15
0
        static CharFA <TAccept> _ForwardNeutrals(CharFA <TAccept> fa)
        {
            if (null == fa)
            {
                throw new ArgumentNullException(nameof(fa));
            }
            var result = fa;

            while (_TryForwardNeutral(result, out result))
            {
                ;
            }


            return(result);
        }
            public void Remove(CharFA <TAccept> fa)
            {
                _charactersByState.Remove(fa);
                var keys = _charactersTransitions.Where(x => x.Value == fa).ToList();

                foreach (var key in keys)
                {
                    _charactersTransitions.Remove(key.Key);
                }
                var rangeKeys = _rangeTransitions.Where(x => x.fa == fa).Select((x, i) => i).ToList();

                foreach (var i in rangeKeys.OrderByDescending(x => x))
                {
                    _rangeTransitions.RemoveAt(i);
                }
            }
            public bool TryGetValue(char input, out CharFA <TAccept> fa)
            {
                if (_charactersTransitions.TryGetValue(input, out fa))
                {
                    return(true);
                }
                foreach (var rangeTransition in _rangeTransitions)
                {
                    if (rangeTransition.range.First <= input && input <= rangeTransition.range.Last)
                    {
                        fa = rangeTransition.fa;
                        return(true);
                    }
                }

                return(false);
            }
        /// <summary>
        /// Creates a new FA that is a concatenation of two other FA expressions
        /// </summary>
        /// <param name="exprs">The FAs to concatenate</param>
        /// <param name="accept">The symbol to accept</param>
        /// <returns>A new FA that is the concatenation of the specified FAs</returns>
        public static CharFA <TAccept> Concat(IEnumerable <CharFA <TAccept> > exprs, TAccept accept = default(TAccept))
        {
            CharFA <TAccept> left = null;
            var right             = left;

            foreach (var val in exprs)
            {
                if (null == val)
                {
                    continue;
                }
                //Debug.Assert(null != val.FirstAcceptingState);
                var nval = val.Clone();
                //Debug.Assert(null != nval.FirstAcceptingState);
                if (null == left)
                {
                    left = nval;
                    //Debug.Assert(null != left.FirstAcceptingState);
                    continue;
                }
                else if (null == right)
                {
                    right = nval;
                    //Debug.Assert(null != right.FirstAcceptingState);
                }
                else
                {
                    //Debug.Assert(null != right.FirstAcceptingState);
                    _Concat(right, nval);
                    //Debug.Assert(null != right.FirstAcceptingState);
                }
                //Debug.Assert(null != left.FirstAcceptingState);
                _Concat(left, right.Clone());
                //Debug.Assert(null != left.FirstAcceptingState);
            }
            if (null != right)
            {
                right.FirstAcceptingState.AcceptSymbol = accept;
            }
            else
            {
                left.FirstAcceptingState.AcceptSymbol = accept;
            }
            return(left);
        }
Exemplo n.º 19
0
        /// <summary>
        /// Makes all accepting states transition to a new accepting final state, and sets them as non-accepting
        /// </summary>
        /// <param name="accept">The symbol to accept</param>
        public void Finalize(TAccept accept = default(TAccept))
        {
            var asc  = FillAcceptingStates();
            var ascc = asc.Count;

            if (1 == ascc)
            {
                return;                        // don't need to do anything
            }
            var final = new CharFA <TAccept>(true, accept);

            for (var i = 0; i < ascc; ++i)
            {
                var fa = asc[i];
                fa.IsAccepting = false;
                fa.EpsilonTransitions.Add(final);
            }
        }
Exemplo n.º 20
0
        /// <summary>
        /// Creates a state machine representing this expression
        /// </summary>
        /// <typeparam name="TAccept">The type of accept symbol to use for this expression</typeparam>
        /// <param name="accept">The accept symbol to use for this expression</param>
        /// <returns>A new <see cref="CharFA{TAccept}"/> finite state machine representing this expression</returns>
        public override CharFA <TAccept> ToFA <TAccept>(TAccept accept)
        {
            if (null == Left)
            {
                return((null != Right) ? Right.ToFA(accept) : null);
            }
            else if (null == Right)
            {
                return(Left.ToFA(accept));
            }
            var result = CharFA <TAccept> .Concat(new CharFA <TAccept>[] { Left.ToFA(accept), Right.ToFA(accept) }, accept);

            if (null != Left as RegexConcatExpression || null != Right as RegexConcatExpression)
            {
                result.TrimNeutrals();
            }
            return(result);
        }
        /// <summary>
        /// Creates a new FA that matches any one of the FA expressions passed
        /// </summary>
        /// <param name="exprs">The expressions to match</param>
        /// <param name="accept">The symbol to accept</param>
        /// <returns>A new FA that will match the union of the FA expressions passed</returns>
        public static CharFA <TAccept> Or(IEnumerable <CharFA <TAccept> > exprs, TAccept accept = default(TAccept))
        {
            var result = new CharFA <TAccept>();
            var final  = new CharFA <TAccept>(true, accept);

            foreach (var fa in exprs)
            {
                if (null != fa)
                {
                    var nfa = fa.Clone();
                    result.EpsilonTransitions.Add(nfa);
                    var nffa = nfa.FirstAcceptingState;
                    nffa.IsAccepting = false;
                    nffa.EpsilonTransitions.Add(final);
                }
                else if (!result.EpsilonTransitions.Contains(final))
                {
                    result.EpsilonTransitions.Add(final);
                }
            }
            return(result);
        }
Exemplo n.º 22
0
        /// <summary>
        /// Deep copies the finite state machine to a new state machine
        /// </summary>
        /// <returns>The new machine</returns>
        public CharFA <TAccept> Clone()
        {
            var closure  = FillClosure();
            var nclosure = new CharFA <TAccept> [closure.Count];

            for (var i = 0; i < nclosure.Length; i++)
            {
                nclosure[i]     = new CharFA <TAccept>(closure[i].IsAccepting, closure[i].AcceptSymbol);
                nclosure[i].Tag = closure[i].Tag;
            }
            for (var i = 0; i < nclosure.Length; i++)
            {
                var t = nclosure[i].InputTransitions;
                var e = nclosure[i].EpsilonTransitions;
                foreach (var trns in closure[i].InputTransitions.RangesTransitions)
                {
                    var id = closure.IndexOf(trns.fa);
                    if (id != -1)
                    {
                        t.Add(trns.range, nclosure[id]);
                    }
                }
                foreach (var trns in closure[i].InputTransitions.CharactersTransitions)
                {
                    var id = closure.IndexOf(trns.Value);
                    if (id != -1)
                    {
                        t.Add(trns.Key, nclosure[id]);
                    }
                }
                foreach (var trns in closure[i].EpsilonTransitions)
                {
                    var id = closure.IndexOf(trns);
                    e.Add(nclosure[id]);
                }
            }
            return(nclosure[0]);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Makes the specified expression case insensitive
        /// </summary>
        /// <param name="expr">The target expression</param>
        /// <param name="accept">The accept symbol</param>
        /// <returns>A new expression that is the case insensitive equivelent of <paramref name="expr"/></returns>
        public static CharFA <TAccept> CaseInsensitive(CharFA <TAccept> expr, TAccept accept = default(TAccept))
        {
            var fa      = expr.Clone();
            var closure = fa.FillClosure();

            for (int ic = closure.Count, i = 0; i < ic; ++i)
            {
                var ffa = closure[i];
                if (ffa.IsAccepting)
                {
                    ffa.AcceptSymbol = accept;
                }
                foreach (var trns in ffa.InputTransitions as IDictionary <CharFA <TAccept>, ICollection <char> > )
                {
                    foreach (var ch in new List <char>(trns.Value))
                    {
                        if (char.IsLower(ch))
                        {
                            var cch = char.ToUpperInvariant(ch);
                            if (!trns.Value.Contains(cch))
                            {
                                ffa.InputTransitions.Add(cch, trns.Key);
                            }
                        }
                        else if (char.IsUpper(ch))
                        {
                            var cch = char.ToLowerInvariant(ch);
                            if (!trns.Value.Contains(cch))
                            {
                                ffa.InputTransitions.Add(cch, trns.Key);
                            }
                        }
                    }
                }
            }
            return(fa);
        }
 public bool Remove(CharFA <TAccept> item)
 {
     _ThrowReadOnly();
     return(false);
 }
 public bool Contains(CharFA <TAccept> item)
 {
     return(_inner.Keys.Contains(item));
 }
 public void Add(CharFA <TAccept> item)
 {
     _ThrowReadOnly();
 }
Exemplo n.º 27
0
 } = -1;                                          // kleene by default
 /// <summary>
 /// Creates a state machine representing this expression
 /// </summary>
 /// <typeparam name="TAccept">The type of accept symbol to use for this expression</typeparam>
 /// <param name="accept">The accept symbol to use for this expression</param>
 /// <returns>A new <see cref="CharFA{TAccept}"/> finite state machine representing this expression</returns>
 public override CharFA <TAccept> ToFA <TAccept>(TAccept accept)
 => null != Expression ? CharFA <TAccept> .Repeat(Expression.ToFA(accept), MinOccurs, MaxOccurs, accept) : null;
Exemplo n.º 28
0
 /// <summary>
 /// Indicates whether this state is a duplicate of another state.
 /// </summary>
 /// <param name="rhs">The state to compare with</param>
 /// <returns>True if the states are duplicates (one can be removed without changing the language of the machine)</returns>
 public bool IsDuplicate(CharFA <TAccept> rhs)
 {
     return(null != rhs && IsAccepting == rhs.IsAccepting &&
            _SetComparer.Default.Equals(EpsilonTransitions, rhs.EpsilonTransitions) &&
            _SetComparer.Default.Equals((IDictionary <CharFA <TAccept>, ICollection <char> >)InputTransitions, (IDictionary <CharFA <TAccept>, ICollection <char> >)rhs.InputTransitions));
 }
Exemplo n.º 29
0
 /// <summary>
 /// Creates a state machine representing this expression
 /// </summary>
 /// <typeparam name="TAccept">The type of accept symbol to use for this expression</typeparam>
 /// <param name="accept">The accept symbol to use for this expression</param>
 /// <returns>A new <see cref="CharFA{TAccept}"/> finite state machine representing this expression</returns>
 public override CharFA <TAccept> ToFA <TAccept>(TAccept accept)
 => CharFA <TAccept> .Literal(new char[] { Value }, accept);
        /// <summary>
        /// Creates a new FA that will match a repetition of the specified FA expression
        /// </summary>
        /// <param name="expr">The expression to repeat</param>
        /// <param name="minOccurs">The minimum number of times to repeat or -1 for unspecified (0)</param>
        /// <param name="maxOccurs">The maximum number of times to repeat or -1 for unspecified (unbounded)</param>
        /// <param name="accept">The symbol to accept</param>
        /// <returns>A new FA that matches the specified FA one or more times</returns>
        public static CharFA <TAccept> Repeat(CharFA <TAccept> expr, int minOccurs = -1, int maxOccurs = -1, TAccept accept = default(TAccept))
        {
            expr = expr.Clone();
            if (minOccurs > 0 && maxOccurs > 0 && minOccurs > maxOccurs)
            {
                throw new ArgumentOutOfRangeException(nameof(maxOccurs));
            }
            CharFA <TAccept> result;

            switch (minOccurs)
            {
            case -1:
            case 0:
                switch (maxOccurs)
                {
                case -1:
                case 0:
                    result = new CharFA <TAccept>();
                    var final = new CharFA <TAccept>(true, accept);
                    final.EpsilonTransitions.Add(result);
                    foreach (var afa in expr.FillAcceptingStates())
                    {
                        afa.IsAccepting = false;
                        afa.EpsilonTransitions.Add(final);
                    }
                    result.EpsilonTransitions.Add(expr);
                    result.EpsilonTransitions.Add(final);
                    //Debug.Assert(null != result.FirstAcceptingState);
                    return(result);

                case 1:
                    result = Optional(expr, accept);
                    //Debug.Assert(null != result.FirstAcceptingState);
                    return(result);

                default:
                    var l = new List <CharFA <TAccept> >();
                    expr = Optional(expr);
                    l.Add(expr);
                    for (int i = 1; i < maxOccurs; ++i)
                    {
                        l.Add(expr.Clone());
                    }
                    result = Concat(l, accept);
                    //Debug.Assert(null != result.FirstAcceptingState);
                    return(result);
                }

            case 1:
                switch (maxOccurs)
                {
                case -1:
                case 0:
                    result = new CharFA <TAccept>();
                    var final = new CharFA <TAccept>(true, accept);
                    final.EpsilonTransitions.Add(result);
                    foreach (var afa in expr.FillAcceptingStates())
                    {
                        afa.IsAccepting = false;
                        afa.EpsilonTransitions.Add(final);
                    }
                    result.EpsilonTransitions.Add(expr);
                    //Debug.Assert(null != result.FirstAcceptingState);
                    return(result);

                case 1:
                    //Debug.Assert(null != expr.FirstAcceptingState);
                    return(expr);

                default:
                    result = Concat(new[] { expr, Repeat(expr.Clone(), 0, maxOccurs - 1) }, accept);
                    //Debug.Assert(null != result.FirstAcceptingState);
                    return(result);
                }

            default:
                switch (maxOccurs)
                {
                case -1:
                case 0:
                    result = Concat(new[] { Repeat(expr, minOccurs, minOccurs, accept), Repeat(expr, 0, 0, accept) }, accept);
                    //Debug.Assert(null != result.FirstAcceptingState);
                    return(result);

                case 1:
                    throw new ArgumentOutOfRangeException(nameof(maxOccurs));

                default:
                    if (minOccurs == maxOccurs)
                    {
                        var l = new List <CharFA <TAccept> >();
                        l.Add(expr);
                        //Debug.Assert(null != expr.FirstAcceptingState);
                        for (int i = 1; i < minOccurs; ++i)
                        {
                            var e = expr.Clone();
                            //Debug.Assert(null != e.FirstAcceptingState);
                            l.Add(e);
                        }
                        result = Concat(l, accept);
                        //Debug.Assert(null != result.FirstAcceptingState);
                        return(result);
                    }
                    result = Concat(new[] { Repeat(expr.Clone(), minOccurs, minOccurs, accept), Repeat(Optional(expr.Clone()), maxOccurs - minOccurs, maxOccurs - minOccurs, accept) }, accept);
                    //Debug.Assert(null != result.FirstAcceptingState);
                    return(result);
                }
            }
        }