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)