let rec compare_token a b ka kb =
let ca = letter a ka in
let cb = letter b kb in
match ca , cb with
| End , End -> 0
| End , _ -> (-1)
| _ , End -> 1
| Letter , Letter ->
let pa = extend a ka Letter in
let pb = extend b kb Letter in
let sa = String.sub a ka (pa-ka) in
let sb = String.sub b kb (pb-kb) in
let ua = String.uppercase sa in
let ub = String.uppercase sb in
let ucmp = String.compare ua ub in
if ucmp <> 0 then ucmp else
let scmp = String.compare sa sb in
if scmp <> 0 then scmp else
compare_token a b pa pb
| Letter , _ -> (-1)
| _ , Letter -> 1
| Digit , Digit ->
let pa = extend a ka Digit in
let pb = extend b kb Digit in
let sa = String.sub a ka (pa-ka) in
let sb = String.sub b kb (pb-kb) in
let kcmp = Pervasives.compare (int_of_string sa) (int_of_string sb) in
if kcmp <> 0 then kcmp else
let scmp = String.compare sa sb in
if scmp <> 0 then scmp else
compare_token a b pa pb
| Digit , _ -> (-1)
| _ , Digit -> 1
| Symbol , Symbol ->
let cmp = Char.compare a.[ka] b.[kb] in
if cmp <> 0 then cmp else
compare_token a b (succ ka) (succ kb)