anchor.diff:      when 'Nonterminal : comparison
       and 'Terminal : comparison
       and 'Lookahead : comparison> =
  -    Set<LrItem<'Nonterminal, 'Terminal, 'Lookahead> *
  -        ParserStatePositionGraphNode<'Nonterminal, 'Terminal, 'Lookahead>>
  +    LabeledSparseDigraph<ParserStatePositionGraphNode<'Nonterminal, 'Terminal, 'Lookahead>, unit>
   
   //
   [<RequireQualifiedAccess>]
   module internal FreePositions =
  -    //
  -    let private dominators (pspg : ParserStatePositionGraph<'Nonterminal, 'Terminal, 'Lookahead>)
  -        : Map<LrItem<'Nonterminal, 'Terminal, 'Lookahead>, Set<ParserStatePositionGraphNode<'Nonterminal, 'Terminal, 'Lookahead>>> =
  -        // TODO
  -        raise <| System.NotImplementedException "FreePositions.dominators"
  -
  -    //
  -    let private reachable (pspg : ParserStatePositionGraph<'Nonterminal, 'Terminal, 'Lookahead>)
  -        : Map<LrItem<'Nonterminal, 'Terminal, 'Lookahead>, Set<ParserStatePositionGraphNode<'Nonterminal, 'Terminal, 'Lookahead>>> =
  -        // TODO
  -        raise <| System.NotImplementedException "FreePositions.reachable"
  +    module Graph = LabeledSparseDigraph
   
       /// Computes the Parser State Position Graph of an LR(0) parser state.
       let private positionGraph (productions : Map<'Nonterminal, Symbol<'Nonterminal, 'Terminal>[][]>) (parserState : Lr0ParserState<'Nonterminal, 'Terminal>)
           : ParserStatePositionGraph<_,_,_> =
  -        // OPTIMIZE : The code below can be improved slightly (for correctness and speed)
  -        // by using our Set.mapPartition function.
  +        // The initial parser state graph.
  +        // Contains all items in the LR(0) state as vertices,
  +        // but it is an _empty_ graph (i.e., a graph with an empty edge-set).
  +        let positionGraph =
  +            (LabeledSparseDigraph.empty, parserState)
  +            ||> Set.fold (fun positionGraph item ->
  +                // Add the item to the graph.
  +                Graph.addVertex (Item item) positionGraph)
  +
  +        (* OPTIMIZE :   The code below can be improved slightly (for correctness
  +                        and speed) by using our Set.mapPartition function. *)
   
           //
           let transitionItems, actionItems =
  
positive.code:                 | Symbol.Terminal _ ->
                      invalidOp "A terminal was found where a nonterminal was expected."
  
              (pspgEdges, parserState)
              ||> Set.fold (fun pspgEdges item ->
                  // A derivation edge exists iff the nonterminal produced by this item
                  // is the one we're trying to derive AND the parser position of this
                  // item is the initial position.
                  if item.Nonterminal = derivingNonterminal && item.Position = 0<_> then
                      Set.add (nonterminalDerivingItem, Item item) pspgEdges
                  else
                      pspgEdges))
  
      //
      let private positionGraphs (grammar : AugmentedGrammar<'Nonterminal, 'Terminal>) =
  
negative.code:             ReductionRulesById = finalTableGenState.ReductionRulesById; }
  
  
  /// An immutable implementation of a vertex- and edge-labeled sparse digraph.
  type private LabeledSparseDigraph<[<EqualityConditionalOn>]'Vertex, [<EqualityConditionalOn; ComparisonConditionalOn>]'Edge when 'Vertex : comparison>
          private (vertices : Set<'Vertex>, edges : Map<'Vertex * 'Vertex, 'Edge>) =
      //
      static member internal Empty
          with get () = LabeledSparseDigraph<'Vertex, 'Edge> (Set.empty, Map.empty)
  
      //
      member __.IsEmpty
          with get () = Set.isEmpty vertices
  
      //
      member __.Edges
          with get () = edges
      
      //
      member __.Vertices
          with get () = vertices
  
      //
      member __.ContainsVertex (vertex : 'Vertex) =
          Set.contains vertex vertices
  
      //
      member __.ContainsEdge (source : 'Vertex, target : 'Vertex) =
          // Preconditions
          if not <| Set.contains source vertices then
              invalidArg "source" "The vertex is not in the graph's vertex-set."
          elif not <| Set.contains target vertices then
              invalidArg "target" "The vertex is not in the graph's vertex-set."
  
          Map.containsKey (source, target) edges
  
      //
      member __.GetEdge (source : 'Vertex, target : 'Vertex) =
          // Preconditions
          if not <| Set.contains source vertices then
              invalidArg "source" "The vertex is not in the graph's vertex-set."
          elif not <| Set.contains target vertices then
              invalidArg "target" "The vertex is not in the graph's vertex-set."
  
          Map.find (source, target) edges
  
      //
      member __.TryGetEdge (source : 'Vertex, target : 'Vertex) =
          // Preconditions
          if not <| Set.contains source vertices then
              invalidArg "source" "The vertex is not in the graph's vertex-set."
          elif not <| Set.contains target vertices then
              invalidArg "target" "The vertex is not in the graph's vertex-set."
  
          Map.tryFind (source, target) edges
  
      //
      member __.AddVertex (vertex : 'Vertex) =
          LabeledSparseDigraph (
              Set.add vertex vertices,
              edges)
  
      //
      member __.AddEdge (source : 'Vertex, target : 'Vertex, edge : 'Edge) =
          // Preconditions
          if not <| Set.contains source vertices then
              invalidArg "source" "The vertex is not in the graph's vertex-set."
          elif not <| Set.contains target vertices then
              invalidArg "target" "The vertex is not in the graph's vertex-set."
  
          LabeledSparseDigraph (
              vertices,
              Map.add (source, target) edge edges)
  
      //
      member __.RemoveVertex (vertex : 'Vertex) =
          // Preconditions
          if not <| Set.contains vertex vertices then
              invalidArg "vertex" "The vertex is not in the graph's vertex-set."
  
          // Remove in- and out-edges of the vertex.
          let edges =
              edges
              |> Map.filter (fun (source, target) _ ->
                  source <> vertex
                  && target <> vertex)
  
          LabeledSparseDigraph (
              Set.remove vertex vertices,
              edges)
  
      //
      member __.RemoveEdge (source : 'Vertex, target : 'Vertex) =
          // Preconditions
          if not <| Set.contains source vertices then
              invalidArg "source" "The vertex is not in the graph's vertex-set."
          elif not <| Set.contains target vertices then
              invalidArg "target" "The vertex is not in the graph's vertex-set."
  
          LabeledSparseDigraph (
              vertices,
              Map.remove (source, target) edges)
  
  /// Functions on LabeledSparseDigraphs.
  [<RequireQualifiedAccess; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
  module private LabeledSparseDigraph =
      /// The empty graph.
      [<GeneralizableValue>]
      let empty<'Vertex, 'Edge when 'Vertex : comparison> =
          LabeledSparseDigraph<'Vertex,'Edge>.Empty
  
      /// Determines if the graph is empty -- i.e., if it's vertex set is empty.
      let inline isEmpty (graph : LabeledSparseDigraph<'Vertex, 'Edge>) =
          graph.IsEmpty
  
      //
      let inline addVertex (vertex : 'Vertex) (graph : LabeledSparseDigraph<'Vertex, 'Edge>) =
          graph.AddVertex vertex
  
      //
      let inline addEdge source target edge (graph : LabeledSparseDigraph<'Vertex, 'Edge>) =
          graph.AddEdge (source, target, edge)
  
      //
      let inline removeVertex (vertex : 'Vertex) (graph : LabeledSparseDigraph<'Vertex, 'Edge>) =
          graph.RemoveVertex vertex
  
      //
      let inline removeEdge source target (graph : LabeledSparseDigraph<'Vertex, 'Edge>) =
          graph.RemoveEdge (source, target)
  
      //
      let inline containsVertex (vertex : 'Vertex) (graph : LabeledSparseDigraph<'Vertex, 'Edge>) =
          graph.ContainsVertex vertex
  
      //
      let inline containsEdge source target (graph : LabeledSparseDigraph<'Vertex, 'Edge>) =
          graph.ContainsEdge (source, target)
  
      //
      let inline getEdge source target (graph : LabeledSparseDigraph<'Vertex, 'Edge>) =
          graph.GetEdge (source, target)
  
      //
      let inline tryGetEdge source target (graph : LabeledSparseDigraph<'Vertex, 'Edge>) =
          graph.TryGetEdge (source, target)
  
      //
      let dominators (graph : LabeledSparseDigraph<'Vertex, 'Edge>)
          : Map<'Vertex, Set<'Vertex>> =
          // TODO
          raise <| System.NotImplementedException "LabeledSparseDigraph.dominators"
  
      //
      let reachable (graph : LabeledSparseDigraph<'Vertex, 'Edge>)
          : Map<'Vertex, Set<'Vertex>> =
          // TODO
          raise <| System.NotImplementedException "LabeledSparseDigraph.reachable"
  
  
  //
  type internal ParserStatePositionGraphAction<'Nonterminal, 'Terminal
      when 'Nonterminal : comparison
  