anchor.diff:                      "failwithf \"tokenTagToTokenId: Invalid token. (Tag = %i)\" " + catchAllVariableName)
           writer.WriteLine ()
   
  +        /// Maps production indices to the symbolic name of the nonterminal produced by each production rule.
  +        let productionIndices =
  +            let productionIndices_productionIndex =
  +                ((Map.empty, 0), processedSpec.StartSymbols)
  +                ||> Set.fold (fun (productionIndices, productionIndex) startSymbol ->
  +                    /// The symbolic name of the nonterminal produced by this start symbol.
  +                    let nonterminalName = "NONTERM__start" + startSymbol
  +                    
  +                    // Increment the production index for the next iteration.
  +                    Map.add productionIndex nonterminalName productionIndices,
  +                    productionIndex + 1)
  +
  +            // Add the production rules.
  +            (productionIndices_productionIndex, processedSpec.ProductionRules)
  +            ||> Map.fold (fun productionIndices_productionIndex nonterminal rules ->
  +                /// The symbolic name of this nonterminal.
  +                let nonterminalSymbolicName = Map.find nonterminal symbolicNonterminalNames
  +
  +                // OPTIMIZE : There's no need to fold over the array of rules, since the
  +                // only thing that matters is the _number_ of rules.
  +                // Replace this with a call to Range.fold.
  +                (productionIndices_productionIndex, rules)
  +                ||> Array.fold (fun (productionIndices, productionIndex) _ ->
  +                    Map.add productionIndex nonterminalSymbolicName productionIndices,
  +                    productionIndex + 1))
  +            // Discard the production index counter.
  +            |> fst
  +
           // Emit the production-index -> symbolic-nonterminal-name function.
           quickSummary writer "Maps production indexes returned in syntax errors to strings representing
                                the non-terminal that would be produced by that production."
           writer.WriteLine "let private prodIdxToNonTerminal = function"
           IndentedTextWriter.indented writer <| fun writer ->
  -            // TODO : Emit a case for each production rule.
  -            // (Make sure to include a case for the starting production!)
  +            // Emit cases based on the production-index -> symbolic-nonterminal-name map.
  +            productionIndices
  +            |> Map.iter (fun productionIndex nonterminalSymbolicName ->
  +                sprintf "| %i -> %s" productionIndex nonterminalSymbolicName
  +                |> writer.WriteLine)
   
               // Emit a catch-all case to handle invalid values.
               let catchAllVariableName = "prodIdx"
  
positive.code:                 |> writer.WriteLine)
          writer.WriteLine ()
  
          // TODO : Emit the parser tables
          // _fsyacc_gotos
          // _fsyacc_sparseGotoTableRowOffsets
          // _fsyacc_stateToProdIdxsTableElements
          // _fsyacc_stateToProdIdxsTableRowOffsets
          // _fsyacc_action_rows (constant value)
          // _fsyacc_actionTableElements
          // _fsyacc_actionTableRowOffsets
          // _fsyacc_reductionSymbolCounts
          // _fsyacc_productionToNonTerminalTable
          // _fsyacc_immediateActions
          // _fsyacc_reductions
  
          // TODO : Emit the parser "tables" record and parser functions
          //
  
negative.code:         else
              sprintf "let [<Literal>] private %s = %i" name value
          |> writer.WriteLine
  
      /// Emits code which creates an array of UInt16 constants into a TextWriter.
      let private oneLineArrayUInt16 (name, isPublic, array : uint16[]) (writer : #TextWriter) =
          // Preconditions
          if System.String.IsNullOrWhiteSpace name then
              invalidArg "name" "The variable name cannot be null/empty/whitespace."
  
          // Emit the 'let' binding and opening bracket of the array.
          if isPublic then
              sprintf "let %s = [| " name
          else
              sprintf "let private %s = [| " name
          |> writer.Write
  
          // Emit the array values.
          array
          |> Array.iter (fun x ->
              writer.Write (x.ToString() + "us; "))
  
          // Emit the closing bracket of the array.
          writer.WriteLine "|]"
  
      /// Creates a Map whose keys are the values of the given Map.
      /// The value associated with each key is None.
  