anchor.diff:  open LanguagePrimitives
   open ExtCore
   open ExtCore.Collections
  +open ExtCore.Control
   open SpecializedCollections
   open Graph
   open Regex
  
positive.code:         else
              Choice1Of2 <| results.ToArray ()
  
      //
      match simplifiedRuleClausePatterns with
      | Choice2Of2 errors ->
          Choice2Of2 errors
      | Choice1Of2 ruleClauseRegexes ->
          /// The DFA compiled from the rule clause patterns.
          let compiledPatternDfa =
              let regexOriginalClauseIndices, ruleClauseRegexes =
                  Array.unzip ruleClauseRegexes
              
              (* TEMP :   For compatibility with fslex, we need to determine the alphabet used
                          by the rule, then rewrite any negated character sets so the transition
                          table is generated in a way that fslex can handle. *)
              let ruleAlphabet =
                  ruleClauseRegexes
                  |> Array.map getAlphabet
                  |> Array.reduce CharSet.union
                  // Add the low ASCII characters too, like fslex does.
                  |> CharSet.union (CharSet.ofRange (char 0) (char 127))
  
              // Rewrite the regexes so they don't contain negated character sets.
              let ruleClauseRegexes =
                  ruleClauseRegexes
                  |> Array.map (rewriteNegatedCharSets ruleAlphabet)
  
              rulePatternsToDfa ruleClauseRegexes regexOriginalClauseIndices options
  
          // If this rule has a pattern accepting the end-of-file marker,
          // create an additional DFA state to serve as the EOF-accepting state
          // and create a transition edge labeled with the EOF symbol to it.
          let compiledPatternDfa =
              match eofAcceptingClauseIndex with
              | None ->
                  compiledPatternDfa
              | Some eofAcceptingClauseIndex ->
                  let eofAcceptingState, transitions =
                      LexerDfaGraph.createVertex compiledPatternDfa.Transitions
                  let transitions =
                      LexerDfaGraph.addEofEdge compiledPatternDfa.InitialState eofAcceptingState transitions
                  { compiledPatternDfa with
                      Transitions = transitions;
                      RuleClauseAcceptedByState =
                          compiledPatternDfa.RuleClauseAcceptedByState
                          |> Map.add eofAcceptingState eofAcceptingClauseIndex; }
  
          // If this rule has a clause with the wildcard pattern, create an additional
          // DFA state which accepts any single character which won't be matched by the
          // earlier patterns in the rule.
          let compiledPatternDfa =
              match wildcardAcceptingClauseIndex with
              | None ->
                  compiledPatternDfa
              | Some wildcardAcceptingClauseIndex ->
                  // TEMP : The way the transition characters are computed here is specific
                  // to fslex -- once we implement our own interpreter, we'll have to come
                  // up with a backend-specific way to handle this. Perhaps we can just store
                  // the wildcard-clause index in the returned DFA, and let the plugins themselves
                  // compute the transition characters.
  
                  /// The alphabet for this rule.
                  let ruleAlphabet =
                      // The alphabet for this rule is the edge-label-set of the transition graph.
                      (CharSet.empty, compiledPatternDfa.Transitions.AdjacencyMap)
                      ||> Map.fold (fun ruleAlphabet _ edgeChars ->
                          CharSet.union ruleAlphabet edgeChars)
  
                  /// The set of characters labelling the out-edges of the initial DFA state.
                  let initialEdgeLabels =
                      (CharSet.empty, compiledPatternDfa.Transitions.AdjacencyMap)
                      ||> Map.fold (fun initialEdgeLabels edgeKey edgeChars ->
                          // We only care about out-edges from the initial DFA state.
                          if edgeKey.Source = compiledPatternDfa.InitialState then
                              CharSet.union initialEdgeLabels edgeChars
                          else
                              initialEdgeLabels)
  
                  /// The characters matched by this rule's wildcard pattern.
                  let wildcardChars =
                      // Augment the rule alphabet with the low ASCII characters,
                      // because that's how fslex does it and we need to be compatible (for now).
                      let ruleAlphabet =
                          CharSet.ofRange (char 0) (char 127)
                          |> CharSet.union ruleAlphabet
  
                      CharSet.difference ruleAlphabet initialEdgeLabels
  
                  // If the set of characters matched by the wildcard pattern is not empty,
                  // create a new DFA state which accepts the wildcard pattern, then add
                  // transition edges to it from the initial state.
                  if CharSet.isEmpty wildcardChars then
                      // TODO : Emit a warning to let the user know this pattern will never be matched.
                      Debug.WriteLine "Warning: Wildcard pattern in rule will never be matched."
  
                      compiledPatternDfa
                  else
                      let wildcardAcceptingState, transitions =
                          LexerDfaGraph.createVertex compiledPatternDfa.Transitions
                      let transitions =
                          LexerDfaGraph.addEdges compiledPatternDfa.InitialState wildcardAcceptingState wildcardChars transitions
  
                      { compiledPatternDfa with
                          Transitions = transitions;
                          RuleClauseAcceptedByState =
                              compiledPatternDfa.RuleClauseAcceptedByState
                              |> Map.add wildcardAcceptingState wildcardAcceptingClauseIndex; }
  
          // TODO : Emit warnings about any overlapping patterns.
          // E.g., "This pattern will never be matched."
  
          // Create a CompiledRule record from the compiled DFA.
          Choice1Of2 {
              Dfa = compiledPatternDfa;
              Parameters =
                  // Reverse the list so it's in the correct left-to-right order.
                  List.rev rule.Parameters
                  |> List.toArray;
              RuleClauseActions =
                  ruleClauses
                  |> Array.map (fun clause ->
                      clause.Action); }
  
  
  /// A compiled lexer specification.
  
negative.code:     //
      Transitions : LexerDfaGraph;
      /// Final (accepting) DFA states.
      // OPTIMIZE : Use the TagSet type from ExtCore.
      FinalStates : Set<DfaStateId>;
      /// Maps regular vectors to the DFA state representing them.
      RegularVectorToDfaState : Map<RegularVector, DfaStateId>;
      /// Maps a DFA state to the regular vector it represents.
      // OPTIMIZE : Use the TagMap type from ExtCore.
      DfaStateToRegularVector : Map<DfaStateId, RegularVector>;
  }
  
  