Convert CamelCase string to Capitalized_snake_case without regex

I wrote a blog post Recipes for OCamlLex. Edit: and here is a sketch. The idea is to use a scanner to split a string into a list of words. It would now be easy to add special cases, for example for common abbreviations. The file below is camel.mll for OCamlLex.

{
  exception Error of string
  
  let error fmt = Printf.kprintf (fun msg -> raise (Error msg)) fmt
  let get       = Lexing.lexeme
}

let digit   = ['0'-'9']
let lower   = ['a'-'z']
let upper   = ['A'-'Z']
let punct   = ['_']

rule split = parse
| upper+ (lower|digit)* { let word = get lexbuf in word :: split lexbuf } 
| eof                   { [] }
| _                     { get lexbuf |> error "illegal character '%s'" } 

{

let snake_case str =
  Lexing.from_string str 
  |> split 
  |> ( function 
     | []    -> []
     | x::xs -> x :: List.map String.lowercase_ascii xs
     )
  |> String.concat "_"


let main () =
  Array.to_list Sys.argv 
  |> List.tl
  |> List.map snake_case
  |> List.iter print_endline


let () = main (); exit 0

}

$ ./_build/default/camel.exe PollFD DoubleIEEE754 MemVTable
Poll_fd
Double_ieee754
Mem_vtable