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); } }