anchor.diff:              prod.Head, handle
           isElementUnique getFormattingElements productions
   
  +    static let grammarMemberFilter = MemberFilterDelegate(fun mi ->
  +        match mi.Name with
  +        | "Properties"
  +        | "StartSymbol"
  +        | "Symbols"
  +        | "Productions"
  +        | "Groups"
  +        | "LALRStates"
  +        | "DFAStates" -> true
  +        | _ -> false)
  +
  +    let productions, grammarSO =
  +        let so = ScriptObject()
  +        so.Import(grammarObj, filter = grammarMemberFilter)
  +        let productions = so.["productions"] :?> Production ImmutableArray
  +        so.SetValue("productions_groupped", productions.ToLookup(fun x -> x.Head), true)
  +        productions, so
  +
  +    let fShouldPrintFullProduction = shouldPrintFullProduction productions
  +    static member upper_case = UpperCase
  +    static member lower_case = LowerCase
  +    static member pascal_case = PascalCase
  +    static member camel_case = CamelCase
  +
  +    member _.Grammar = grammarSO
  +
  +    member _.fmt (x: obj) case separator =
  +        match x with
  +        | :? Terminal as x -> match x with Terminal(_, name) -> toIdentifier name case separator
  +        | :? Production as x -> formatProduction (fShouldPrintFullProduction x) x case separator
  +        | _ -> invalidArg "x" (sprintf "Can only format terminals and productions, but got %O instead." <| x.GetType())
  +    static member group_dfa_edges {Edges = edges} =
  +        edges.ToLookup(fun x -> x.Value).OrderBy(fun x -> x.Key)
  +    abstract has_errors: bool
  +    abstract LoadInstanceMethods: ScriptObject -> unit
  +    default x.LoadInstanceMethods so =
  +        so.Import("fmt", Func<_,_,_,_> x.fmt)
  +
  +type GrammarFunctions(g) =
  +    inherit GrammarFunctionsBase(g.Grammar)
  +
       let grammar = g.Grammar
  -    let grammarSO =
  -        let so = ScriptObject()
  -        so.Import grammar
  -        so.SetValue("productions_groupped", grammar.Productions.ToLookup(fun x -> x.Head), true)
  -        so
  -
  -    let fShouldPrintFullProduction = shouldPrintFullProduction grammar.Productions
  -
       let bytesThunk = lazy(
           let ext = Path.GetExtension(g.GrammarPath).AsSpan()
           if isGrammarExtension ext then
  
positive.code:     | CamelCase
      | PascalCase
  
  type GrammarFunctions(g) =
  
      static let toIdentifier name case (separator: string) =
          let sb = StringBuilder()
  
negative.code: open Farkle.Tools
  open Scriban.Runtime
  open System
  open System.Collections.Immutable
  open System.IO
  open System.Linq
  open System.Text
  