/// <summary> /// Builds the parse table from the given node and starting element. /// </summary> /// <param name="node"></param> /// <param name="startingElement"></param> private void buildParseTable(StateNode <GrammarElement <T>, LRItem <T>[]> node, NonTerminal <T> startingElement) { if (node == null) { throw new ArgumentNullException("node"); } if (startingElement == null) { throw new ArgumentNullException("startingElement"); } //clear the tables ActionTable.Clear(); GotoTable.Clear(); //get the breadth-first traversal of the graph List <StateNode <GrammarElement <T>, LRItem <T>[]> > t = node.GetBreadthFirstTraversal().ToList(); //add the transitions for each node in the traversal for (var i = 0; i < t.Count; i++) { //for each transition in the node, add either a shift action or goto action foreach (KeyValuePair <GrammarElement <T>, StateNode <GrammarElement <T>, LRItem <T>[]> > transition in t[i].FromTransitions) { if (transition.Key is Terminal <T> ) { //add a shift from this state to the next state addAction((Terminal <T>)transition.Key, i, new ShiftAction <T>(this, t.IndexOf(transition.Value))); } else { addGoto((NonTerminal <T>)transition.Key, i, t.IndexOf(transition.Value)); } } //for each of the items in the state that are at the end of a production, //add either a reduce action or accept action foreach (LRItem <T> item in t[i].Value.Where(a => a.IsAtEndOfProduction())) { //if we would reduce to the starting element, then accept if (item.LeftHandSide.Equals(startingElement)) { addAction(item.LookaheadElement, i, new AcceptAction <T>(this, item)); } //otherwise, add a reduce action else { addAction(item.LookaheadElement, i, new ReduceAction <T>(this, item)); } } } }
/// <summary> /// Adds the given key and value as a transition from this node to the given node. /// </summary> /// <param name="key"></param> /// <param name="value"></param> public void AddTransition(TKey key, StateNode <TKey, T> value) { //add a "from" transition so that the value knows //that we lead to it. if (!value.toTransitions.Contains(this)) { value.toTransitions.Add(this); } fromTransitions.Add(key, value); }
/// <summary> /// Determines if the given node is contained by this node. /// </summary> /// <param name="node"></param> /// <returns></returns> /// <summary> /// Returns whether a node is contained by this node(and linked "from" nodes). /// </summary> /// <param name="comparer">The predicate used to determine if a node is contained.</param> /// <returns></returns> /// <summary> /// Gets the depth first traversal of the children of this node. /// </summary> /// <exception cref="System.StackOverflowException" /> /// <returns></returns> public IEnumerable <StateNode <TKey, T> > GetDepthFirstTraversal() { var stack = new Stack <StateNode <TKey, T> >(); var traversal = new Stack <StateNode <TKey, T> >(); traversal.Push(this); stack.Push(this); while (stack.Count != 0) { StateNode <TKey, T> node = stack.Pop(); foreach (KeyValuePair <TKey, StateNode <TKey, T> > transition in node.FromTransitions) { stack.Push(transition.Value); traversal.Push(transition.Value); } } return(traversal); }
/// <summary> /// Returns whether a node is contained by this node(and linked "from" nodes). /// </summary> /// <param name="comparer"></param> /// <param name="currentLoop"></param> /// <param name="maxLoop"></param> /// <returns></returns> /// <summary> /// Returns whether the given node is contained in a "from" transition. /// </summary> /// <param name="node"></param> /// <returns></returns> public bool ContainsFromTransition(StateNode <TKey, T> node) { return(GetBreadthFirstTraversal().Any(a => a == node)); }
/// <summary> /// Determines if the graph contains the given node. /// </summary> /// <param name="node"></param> /// <returns></returns> public bool Contains(StateNode <TKey, T> node) { return(Root.ContainsFromTransition(node)); }
/// <summary> /// Creates a new StateGraph with the given rootNode as the Root. /// </summary> /// <param name="rootNode"></param> public StateGraph(StateNode <TKey, T> rootNode) { Root = rootNode; }