public NondeterministicFiniteAutomaton(States q, Alphabet a, NondeterministicTransitionFunction d, State q0,
                                        AcceptingStates f) : base(q, a, d, q0, f)
 {
     Transitions = d;
 }
        private async Task <bool> Run(char[] x, State p, int i)
        {
            for (; i < x.Length; i++)
            {
                if (!Alphabet.Contains(x[i]))
                {
                    return(false);
                }
                if (x[i] == Alphabet.EmptyString)
                {
                    continue;
                }

                // get possible transitions
                var q = Transitions[p, x[i]];

                if (q.Length == 0)                // nothing to do, stop
                {
                    return(false);
                }

                if (q.Length == 1)
                {
                    p = q[0].Q;                     // switch states
                    if (q[0].A == Alphabet.EmptyString)
                    {
                        i--;                                                    // Don't increment on null transition!
                    }
                }

                else                   // we have a choice
                {
                    var tasks = new Task <bool> [q.Length];
                    // check each path asynchronously
                    for (var j = 0; j < q.Length; j++)
                    {
                        tasks[j] = Run(x, q[j].Q, q[j].A == Alphabet.EmptyString ? i : i + 1);
                    }

                    var result = false;
                    // check the result
                    foreach (var t in tasks)
                    {
                        result = result || await t;
                    }
                    return(result);                    // if one of them is successful, this branch accepts
                }
            }

            // No more moves!
            if (p.Accepting)
            {
                return(true);
            }

            // check for lambda transitions
            var r       = Transitions[p, Alphabet.EmptyString];
            var lambdas = new Task <bool> [r.Length];

            for (var k = 0; k < r.Length; k++)
            {
                lambdas[k] = Run(x, r[k].Q, i);
            }
            var accept = false;

            foreach (var t in lambdas)
            {
                accept = accept || await t;
            }
            return(accept);
        }
        private async Task <bool> Run(char[] x, State p, int i, Stack <char> stack)
        {
            for (; i < x.Length; i++)
            {
                if (!Alphabet.Contains(x[i]))
                {
                    return(false);
                }
                if (x[i] == Alphabet.EmptyString)
                {
                    continue;
                }

                // Get possible transitions
                var q = Transitions[p, x[i], stack.Peek()];

                if (q.Length == 0)                // nothing to do, stop
                {
                    return(false);
                }

                if (q.Length == 1)
                {
                    // try to update the stack. if we are out of bounds, reject
                    try { stack = updateStack(stack, q[0].Top, q[0].Replace); }
                    catch (Exception) { return(false); }

                    p = q[0].Q;
                    if (q[0].A == Alphabet.EmptyString)
                    {
                        i--;                                                    // Don't increment on null transition!
                    }
                }

                else
                {
                    var tasks = new Task <bool> [q.Length];
                    // check each path asynchronously
                    for (var j = 0; j < q.Length; j++)
                    {
                        var s = new Stack <char>(stack);
                        try { s = updateStack(s, q[j].Top, q[j].Replace); }
                        catch (Exception) { continue; }

                        tasks[j] = Run(x, q[j].Q, q[j].A == Alphabet.EmptyString ? i : i + 1, s);
                    }

                    var result = false;
                    foreach (var t in tasks)
                    {
                        result = result || (t != null && await t);
                    }
                    return(result);
                }
            }

            // No more moves!
            if (p.Accepting)
            {
                return(true);
            }

            // check for lambda transitions
            var r       = Transitions[p, Alphabet.EmptyString, stack.Peek()];
            var lambdas = new Task <bool> [r.Length];

            for (var k = 0; k < r.Length; k++)
            {
                var s = new Stack <char>(stack);
                try { s = updateStack(s, r[k].Top, r[k].Replace); }
                catch (Exception) { continue; }

                lambdas[k] = Run(x, r[k].Q, i, s);
            }
            var accept = false;

            foreach (var t in lambdas)
            {
                accept = accept || (t != null && await t);
            }
            return(accept);
        }