anchor.diff:          // Return the closure of the item set.
           closure grammar analysis items
   
  +
  +//
  +type internal Lr1ParserState<'NonterminalId, 'Token
  +        when 'NonterminalId : comparison
  +        and 'Token : comparison> = Set<Lr1Item<'NonterminalId, 'Token>>
  +
  +//
  +[<RequireQualifiedAccess>]
  +module Lr1 =
       //
       let createTable (grammar : Grammar<'NonterminalId, 'Token>) =
           // Augment the grammar with the start production and end-of-file token.
  
positive.code:         sb.ToString ()
  
  //
  type internal Lr0ParserState<'NonterminalId, 'Token
          when 'NonterminalId : comparison
          and 'Token : comparison> = Set<Lr0Item<'NonterminalId, 'Token>>
  
  /// LR(0) parser table generation state.
  type internal Lr0TableGenState<'NonterminalId, 'Token
          when 'NonterminalId : comparison
          and 'Token : comparison> = {
      //
      Table : Map<LrParserStateId * Symbol<'NonterminalId, 'Token>, Set<LrParserTableAction>>;
      //
      ParserStates : Map<Lr0ParserState<'NonterminalId, 'Token>, LrParserStateId>;
      //
      ReductionRules : Map<'NonterminalId * Symbol<'NonterminalId, 'Token>[], LrReductionRuleId>;
      //
      ReductionRulesById : Map<LrReductionRuleId, 'NonterminalId * Symbol<'NonterminalId, 'Token>[]>;
  }
  
  //
  [<RequireQualifiedAccess; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
  module internal Lr0TableGenState =
      /// Returns an empty Lr0TableGenState with the given
      /// nonterminal and terminal types.
      let empty : Lr0TableGenState<'NonterminalId, 'Token> = {
          Table = Map.empty;
          ParserStates = Map.empty;
          ReductionRules = Map.empty;
          ReductionRulesById = Map.empty; }
  
      /// Retrives the identifier for a given parser state (set of items).
      /// If the state has not been assigned an identifier, one is created
      /// and added to the table-generation state before returning.
      let stateId (parserState : Lr0ParserState<'NonterminalId, 'Token>) (tableGenState : Lr0TableGenState<'NonterminalId, 'Token>) =
          // Try to retrieve an existing id for this state.
          match Map.tryFind parserState tableGenState.ParserStates with
          | Some parserStateId ->
              parserStateId, tableGenState
  
          | None ->
              // Create a new ID for this state.
              let parserStateId = LanguagePrimitives.Int32WithMeasure <| tableGenState.ParserStates.Count + 1
  
              // Return the id, along with the updated table-gen state.
              parserStateId,
              { tableGenState with
                  ParserStates = Map.add parserState parserStateId tableGenState.ParserStates; }
  
      //
      let reductionRuleId (reductionRule : 'NonterminalId * Symbol<'NonterminalId, 'Token>[]) (tableGenState : Lr0TableGenState<'NonterminalId, 'Token>) =
          // Reduction rules should only be added, but for safety we'll check to
          // see if the rule has already been assigned an identifier.
          match Map.tryFind reductionRule tableGenState.ReductionRules with
          | Some reductionRuleId ->
              reductionRuleId, tableGenState
  
          | None ->
              // Create a new ID for this reduction rule.
              let reductionRuleId = LanguagePrimitives.Int32WithMeasure <| tableGenState.ReductionRules.Count + 1
  
              // Return the id, along with the updated table-gen state.
              reductionRuleId,
              { tableGenState with
                  ReductionRules = Map.add reductionRule reductionRuleId tableGenState.ReductionRules;
                  ReductionRulesById = Map.add reductionRuleId reductionRule tableGenState.ReductionRulesById; }
  
      /// Add a 'shift' action to the parser table.
      let shift (sourceState : LrParserStateId)
                  (transitionSymbol : 'Token)
                  (targetState : LrParserStateId)
                  (tableGenState : Lr0TableGenState<'NonterminalId, 'Token>) =
          //
          let tableKey = sourceState, Symbol.Terminal transitionSymbol
  
          //
          let entry =
              let action = Shift targetState
              match Map.tryFind tableKey tableGenState.Table with
              | None ->
                  Set.singleton action
              | Some entry ->
                  Set.add action entry
  
          // Update the table with the new entry.
          (),
          { tableGenState with
              Table = Map.add tableKey entry tableGenState.Table; }
  
      /// Add a 'goto' action to the parser table.
      let goto (sourceState : LrParserStateId)
                  (transitionSymbol : 'NonterminalId)
                  (targetState : LrParserStateId)
                  (tableGenState : Lr0TableGenState<'NonterminalId, 'Token>) =
          //
          let tableKey = sourceState, Symbol.Nonterminal transitionSymbol
  
          //
          let entry =
              let action = Goto targetState
              match Map.tryFind tableKey tableGenState.Table with
              | None ->
                  Set.singleton action
              | Some entry ->
                  Set.add action entry
  
          // Update the table with the new entry.
          (),
          { tableGenState with
              Table = Map.add tableKey entry tableGenState.Table; }
  
      /// Add an 'accept' action to the parser table.
      let accept (sourceState : LrParserStateId) (tableGenState : Lr0TableGenState<'NonterminalId, AugmentedTerminal<'Token>>) =
          //
          let tableKey = sourceState, Symbol.Terminal EndOfFile
  
          //
          let entry =
              match Map.tryFind tableKey tableGenState.Table with
              | None ->
                  // Create a new 'accept' action for this table entry.
                  Set.singleton Accept
              | Some entry ->
                  // Create a new 'accept' action and add it to the existing table entry.
                  Set.add Accept entry
  
          // Update the table with the new entry.
          (),
          { tableGenState with
              Table = Map.add tableKey entry tableGenState.Table; }
  
      /// Add 'reduce' actions to the parser table for each terminal (token) in the grammar.
      let reduce (sourceState : LrParserStateId) (reductionRuleId : LrReductionRuleId) (terminals : Set<_>) (tableGenState : Lr0TableGenState<'NonterminalId, AugmentedTerminal<'Token>>) =
          // Fold over the set of terminals (tokens) in the grammar.
          let table =
              (tableGenState.Table, terminals)
              ||> Set.fold (fun table token ->
                  //
                  let tableKey = sourceState, Symbol.Terminal token
  
                  //
                  let entry =
                      let action = Reduce reductionRuleId
                      match Map.tryFind tableKey table with
                      | None ->
                          Set.singleton action
                      | Some entry ->
                          Set.add action entry
  
                  // Update the table with the entry.
                  Map.add tableKey entry table)
  
          // Return the updated table-gen state.
          (),
          { tableGenState with
              Table = table; }
  
  //
  [<RequireQualifiedAccess>]
  module Lr0 =
      /// Computes the LR(0) closure of a set of items.
      // TODO : Modify this to use a worklist-style algorithm to avoid
      // reprocessing items which already exist in the set (i.e., when iterating,
      // we only process items added to the set in the previous iteration).
      let internal closure (productions : Map<'NonterminalId, Set<Symbol<'NonterminalId, 'Token>[]>>) items =
          /// Implementation of the LR(0) closure algorithm.
          let rec closure items =
              let items' =
  
negative.code:         sb.ToString ()
  
  //
  [<RequireQualifiedAccess; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
  module internal Lr1Item =
      /// Computes the FIRST set of a string of symbols.
      /// The string is a "substring" of a production, followed by a lookahead token.
      let firstSetOfString (production : Symbol<'NonterminalId, 'Token>[]) startIndex (lookahead : 'Token) (analysis : GrammarAnalysis<'NonterminalId, 'Token>) : Set<'Token> =
          // Preconditions
          if startIndex < 0 then
              invalidArg "startIndex" "The start index cannot be negative."
          elif startIndex > Array.length production then
              invalidArg "startIndex" "The start index cannot be greater than the length of the production."
  
          let productionLength = Array.length production
  
          //
          let rec firstSetOfString firstSet symbolIndex =
              // If we've reached the end of the production,
              // add the lookahead token to the set and return.
              if symbolIndex = productionLength then
                  Set.add lookahead firstSet
              else
                  // Match on the current symbol of the production.
                  match production.[symbolIndex] with
                  | Symbol.Terminal token ->
                      // Add the token to the set; then, return
                      // because tokens are never nullable.
                      Set.add token firstSet
  
                  | Symbol.Nonterminal nontermId ->
                      /// The FIRST set of this nonterminal symbol.
                      let nontermFirstSet = Map.find nontermId analysis.First
  
                      // Merge the FIRST set of this nonterminal symbol into
                      // the FIRST set of the string.
                      let firstSet = Set.union firstSet nontermFirstSet
  
                      // If this symbol is nullable, continue processing with
                      // the next symbol in the production; otherwise, return.
                      if Map.find nontermId analysis.Nullable then
                          firstSetOfString firstSet (symbolIndex + 1)
                      else
                          firstSet
  
          // Call the recursive implementation to compute the FIRST set.
          firstSetOfString Set.empty startIndex
  
      /// Computes the LR(1) closure of a set of items.
      // TODO : Modify this to use a worklist-style algorithm to avoid
      // reprocessing items which already exist in the set (i.e., when iterating,
      // we only process items added to the set in the previous iteration).
      let closure (grammar : Grammar<'NonterminalId, 'Token>) (analysis : GrammarAnalysis<'NonterminalId, 'Token>) items =
          /// Implementation of the LR(1) closure algorithm.
          let rec closure items =
              let items' =
  