private static Tuple<PDA<A, S>, PDA<A, S>> ConvertDPDAsToEmptyStack(PDA<A, S> pda1, PDA<A, S> pda2, A furtherAlphabetSymbol)
        {
            if (pda1.AcceptanceCondition.IsEmptyStack() && pda2.AcceptanceCondition.IsEmptyStack())
            {
                return new Tuple<PDA<A, S>, PDA<A, S>>(pda1, pda2);
            }

            if (pda1.AcceptanceCondition.IsFinalState() && pda2.AcceptanceCondition.IsEmptyStack())
            {
                var newPda1 = PDATransformer<A, S>.ToDPDAWithEmptyStack(pda1, furtherAlphabetSymbol);
                var newPda2 = PDATransformer<A, S>.ToDPDAWithAddedAlphabetSymbol(pda2, furtherAlphabetSymbol);
                return new Tuple<PDA<A, S>, PDA<A, S>>(newPda1, newPda2);
            }

            if (pda1.AcceptanceCondition.IsEmptyStack() && pda2.AcceptanceCondition.IsFinalState())
            {
                var newPda1 = PDATransformer<A, S>.ToDPDAWithAddedAlphabetSymbol(pda1, furtherAlphabetSymbol);
                var newPda2 = PDATransformer<A, S>.ToDPDAWithEmptyStack(pda2, furtherAlphabetSymbol);
                return new Tuple<PDA<A, S>, PDA<A, S>>(newPda1, newPda2);
            }

            if (pda1.AcceptanceCondition.IsFinalState() && pda2.AcceptanceCondition.IsFinalState())
            {
                var newPda1 = PDATransformer<A, S>.ToDPDAWithEmptyStack(pda1, furtherAlphabetSymbol);
                var newPda2 = PDATransformer<A, S>.ToDPDAWithEmptyStack(pda2, furtherAlphabetSymbol);
                return new Tuple<PDA<A, S>, PDA<A, S>>(newPda1, newPda2);
            }

            throw new InvalidOperationException("the given pdas have wrong configuration");
        }
        public void ToDPDAWithEmptyStackTest()
        {
            var dpda = new PDA <char, char>(new AcceptanceCondition.FinalState(), true, 'Z', false, "ZYX", 'B');

            dpda.AddState(1, false);
            dpda.AddState(2, true);

            dpda.AddTransition().From(0).To(0).Read('a').Pop('Z').Push("XZ");
            dpda.AddTransition().From(0).To(0).Read('a').Pop('X').Push("XX");
            dpda.AddTransition().From(0).To(0).Read('a').Pop('Y').Push("XY");
            dpda.AddTransition().From(0).To(0).Read('b').Pop('Z').Push("YZ");
            dpda.AddTransition().From(0).To(0).Read('b').Pop('X').Push("YX");
            dpda.AddTransition().From(0).To(0).Read('b').Pop('Y').Push("YY");

            dpda.AddTransition().From(0).To(1).Read('x').Pop('Z').Push("Z");
            dpda.AddTransition().From(0).To(1).Read('x').Pop('X').Push("X");
            dpda.AddTransition().From(0).To(1).Read('x').Pop('Y').Push("Y");

            dpda.AddTransition().From(1).To(1).Read('a').Pop('X').Push("");
            dpda.AddTransition().From(1).To(1).Read('b').Pop('Y').Push("");

            dpda.AddTransition().From(1).To(2).Read().Pop('Z').Push("Z");

            var exp = new PDA <char, char>(new AcceptanceCondition.EmptyStack(), true, 'B', false, "BZYX");

            exp.AddState(1, false);
            exp.AddState(2, false);
            exp.AddState(3, false);
            exp.AddState(4, false);

            exp.AddTransition().From(0).To(1).Read().Pop('B').Push("ZB");

            exp.AddTransition().From(1).To(1).Read('a').Pop('Z').Push("XZ");
            exp.AddTransition().From(1).To(1).Read('a').Pop('X').Push("XX");
            exp.AddTransition().From(1).To(1).Read('a').Pop('Y').Push("XY");
            exp.AddTransition().From(1).To(1).Read('b').Pop('Z').Push("YZ");
            exp.AddTransition().From(1).To(1).Read('b').Pop('X').Push("YX");
            exp.AddTransition().From(1).To(1).Read('b').Pop('Y').Push("YY");

            exp.AddTransition().From(1).To(2).Read('x').Pop('Z').Push("Z");
            exp.AddTransition().From(1).To(2).Read('x').Pop('X').Push("X");
            exp.AddTransition().From(1).To(2).Read('x').Pop('Y').Push("Y");

            exp.AddTransition().From(2).To(2).Read('a').Pop('X').Push("");
            exp.AddTransition().From(2).To(2).Read('b').Pop('Y').Push("");

            exp.AddTransition().From(2).To(3).Read().Pop('Z').Push("Z");

            exp.AddTransition().From(3).To(4).Read('$').Pop('Z').Push();
            exp.AddTransition().From(3).To(4).Read('$').Pop('X').Push();
            exp.AddTransition().From(3).To(4).Read('$').Pop('Y').Push();
            exp.AddTransition().From(3).To(4).Read('$').Pop('B').Push();

            exp.AddTransition().From(4).To(4).Read().Pop('Y').Push();
            exp.AddTransition().From(4).To(4).Read().Pop('X').Push();
            exp.AddTransition().From(4).To(4).Read().Pop('Z').Push();
            exp.AddTransition().From(4).To(4).Read().Pop('B').Push();

            var act = PDATransformer <char, char> .ToDPDAWithEmptyStack(dpda, '$');

            Assert.IsTrue(act.Equals(exp));

            act.CreateRunner();

            Assert.IsFalse(act.AcceptsWord("").Accepts());
            Assert.IsFalse(act.AcceptsWord("ax").Accepts());
            Assert.IsFalse(act.AcceptsWord("aaxa").Accepts());
            Assert.IsFalse(act.AcceptsWord("xa").Accepts());
            Assert.IsFalse(act.AcceptsWord("axaa").Accepts());
            Assert.IsFalse(act.AcceptsWord("ax$").Accepts());
            Assert.IsFalse(act.AcceptsWord("aaxa$").Accepts());
            Assert.IsFalse(act.AcceptsWord("xa$").Accepts());
            Assert.IsFalse(act.AcceptsWord("axaa$").Accepts());
            Assert.IsFalse(act.AcceptsWord("$").Accepts());

            Assert.IsTrue(act.AcceptsWord("x$").Accepts());
            Assert.IsTrue(act.AcceptsWord("axa$").Accepts());
            Assert.IsTrue(act.AcceptsWord("aaxaa$").Accepts());
            Assert.IsTrue(act.AcceptsWord("aaaxaaa$").Accepts());
        }