Beispiel #1
0
        private static SimulationPath <A, char> RunSimulationWithCFGForEmptyStack(PDA <A, char> pda, A[] word, CancellationToken token)
        {
            Assertion.Assert(pda.AcceptanceCondition.IsEmptyStack(), "the pda has not empty stack as acceptance condition");

            var cfg1 = PDAToCFGConverter <A, char> .ToCFG(pda, token);

            var cfg = CFGCleaner.RemoveUselessSymbols(cfg1, token);

            if (cfg == null)
            {
                throw new NoAcceptanceException(wordNotAcceptedMessage);
            }

            var cfgIn2NF = CFGTo2NFConverter <A, char> .To2NF(cfg);

            var cykTable = new CYKTable <A>(word, cfgIn2NF);

            if (!cykTable.AcceptsWord())
            {
                throw new NoAcceptanceException(wordNotAcceptedMessage);
            }

            var startDerivationNode = cykTable.GetStartDerivationNode();

            return(startDerivationNode.ConvertToPDASimulationPath(pda, cfg.StartSymbol, word));
        }
        //FIXME: create own subclass class for derivation start node
        /// <summary>
        /// converts a derivation of a word in a CFG in 2NF, that was originally created from a PDA, back to a path in this PDA;
        /// this path is generated according to the converting-algorithm of a PDA to a CFG implemented in <see cref="PDAToCFGConverter{A, S}"/>;
        /// if this method is called on a CFG that does not fulfill the described conditions, it produces not useful result
        /// </summary>
        /// <param name="pda">pda</param>
        /// <param name="startSymbol">start symbol of the cfg</param>
        /// <param name="word">word of the derivation</param>
        /// <returns></returns>
        public SimulationPath <A, char> ConvertToPDASimulationPath(PDA <A, char> pda, GrammarSymbol startSymbol, A[] word)
        {
            Assertion.Assert(Symbol == startSymbol, "this method should only be called on the start node; FIXME to make it only availabe there");
            Assertion.Assert(productionFromHere.Rhs.Count() == 1, "the first production should only lead to one element");
            Assertion.Assert(children.Count() == 1, "the start symbol should only have one child");

            var symbol   = productionFromHere.Rhs[0].Name;
            var splitted = PDAToCFGConverter <A, char> .SplitNonTerminalId(symbol);

            var firstNode = Node <A, char> .InitialNode(new Configuration <A, char>(pda.States[splitted.Item1],
                                                                                    new Word <A>(word),
                                                                                    CurrentStack <char> .WithSingleSymbol(splitted.Item2)));

            var nodes = new List <Node <A, char> >()
            {
                firstNode
            };

            children.First().ConvertToPDASimulationPath(nodes, pda);

            return(new SimulationPath <A, char>(nodes));
        }
        private void ConvertToPDASimulationPath(List <Node <A, char> > nodes, PDA <A, char> pda)
        {
            Assertion.Assert(!ContainsHelperVariable(), "should not be called for a helper variable");

            var rightHandsSideNodes = children.SelectMany(c => c.EliminateHelperVariables()).ToList();

            var parent   = nodes.Last();
            var splitted = PDAToCFGConverter <A, char> .SplitNonTerminalId(Symbol.Name);

            Assertion.Assert(parent.Config.State.Id == splitted.Item1, "illegal path");

            var isEpsilonTransition = rightHandsSideNodes.Count == 0 || !rightHandsSideNodes.First().ContainsTerminal();

            var inputLetter = isEpsilonTransition ? Symbol <A> .EpsilonIn() :
                              Symbol <A> .SymbolIn((A)Convert.ChangeType(rightHandsSideNodes.First().Symbol.Name, typeof(A)));

            var stackSymbolIn = splitted.Item2;

            char stackSymbolFromNode(DerivationNode <A> n) => PDAToCFGConverter <A, char> .SplitNonTerminalId(n.Symbol.Name).Item2;

            var stackSymbolsOut = isEpsilonTransition ? rightHandsSideNodes.Select(stackSymbolFromNode).ToList() : rightHandsSideNodes.Skip(1).Select(stackSymbolFromNode);

            int targetStateId;

            int getFirstStateIfFromNode(DerivationNode <A> n) => PDAToCFGConverter <A, char> .SplitNonTerminalId(n.Symbol.Name).Item1;

            if (isEpsilonTransition)
            {
                if (rightHandsSideNodes.Count == 0)
                {
                    targetStateId = splitted.Item3;
                }
                else
                {
                    targetStateId = getFirstStateIfFromNode(rightHandsSideNodes.First());
                }
            }
            else
            {
                if (rightHandsSideNodes.Count == 1)
                {
                    targetStateId = splitted.Item3;
                }
                else
                {
                    targetStateId = getFirstStateIfFromNode(rightHandsSideNodes[1]);
                }
            }

            var transition = parent.Config.State.Transitions.First(t =>
                                                                   t.Target.Id == targetStateId &&
                                                                   t.SymbolIn.Equals(inputLetter) &&
                                                                   t.StackSymbolIn.Equals(stackSymbolIn) &&
                                                                   t.StackSymbolsWritten.SequenceEqual(stackSymbolsOut));

            nodes.Add(Node <A, char> .ApplyTransitionToParentNode(transition, parent));

            var rightHandSideWithNonterminals = isEpsilonTransition ? rightHandsSideNodes : rightHandsSideNodes.Skip(1);

            foreach (var node in rightHandSideWithNonterminals)
            {
                node.ConvertToPDASimulationPath(nodes, pda);
            }
        }