let parse_integer s =
    let max_int = get_max_value_of_type type_int in
    let max_unsigned_int = get_max_value_of_type type_unsigned_int in
    let max_long = get_max_value_of_type type_long in
    let max_unsigned_long = get_max_value_of_type type_unsigned_long in
    let max_long_long = get_max_value_of_type type_long_long in
    let max_default = zero_big_int in
    let is_octal c = '0' <= c && c <= '7' in
    let length = String.length s in
    let u_count = ref 0 in
    let l_count = ref 0 in
    for i = 0 to length - 1 do
        match s.[i] with
            'u' -> incr u_count
          | 'U' -> incr u_count
          | 'l' -> incr l_count
          | 'L' -> incr l_count
          | _ -> ()
    done;
    let decimal_type_list, octal_type_list =
        match !u_count, !l_count with
            0, 0 ->
              [ max_int, type_int;
                max_long, type_long;
                max_default, type_long_long ],
              [ max_int, type_int;
                max_unsigned_int, type_unsigned_int;
                max_long, type_long;
                max_unsigned_long, type_unsigned_long;
                max_long_long, type_long_long;
                max_default, type_unsigned_long_long ]
          | 0, 1 ->
              [ max_long, type_long;
                max_default, type_long_long ],
              [ max_long, type_long;
                max_unsigned_long, type_unsigned_long;
                max_long_long, type_long_long;
                max_default, type_unsigned_long_long ]
          | 0, 2 ->
              [ max_default, type_long_long ],
              [ max_long_long, type_long_long;
                max_default, type_unsigned_long_long ]
          | 1, 0 ->
              [ max_unsigned_int, type_unsigned_int;
                max_unsigned_long, type_unsigned_long;
                max_default, type_unsigned_long_long ],
              [ max_unsigned_int, type_unsigned_int;
                max_unsigned_long, type_unsigned_long;
                max_default, type_unsigned_long_long ]
          | 1, 1 ->
              [ max_unsigned_long, type_unsigned_long;
                max_default, type_unsigned_long_long ],
              [ max_unsigned_long, type_unsigned_long;
                max_default, type_unsigned_long_long ]
          | 1, 2 ->
              [ max_default, type_unsigned_long_long ],
              [ max_default, type_unsigned_long_long ]
          | _ -> failwith "parse_const"
    in
    let find_decimal_type n =
        let rec continue = function
            [] -> failwith "parse_const"
          | ( max, t )::l ->
              if max = max_default then
                  t
              else if le_big_int n max then
                  t
              else
                  continue l
        in
        continue decimal_type_list
    in
    let find_octal_type n =
        let rec continue = function
            [] -> failwith "parse_const"
          | ( max, t )::l ->
              if max = max_default then
                  t
              else if le_big_int n max then
                  t
              else
                  continue l
        in
        continue octal_type_list
    in
    let s = String.sub s 0 (length - !u_count - !l_count) in
    let length = String.length s in
    if length >= 3 && s.[0] = '0' && (s.[1] = 'x' || s.[1] = 'X'then
        let n = big_int_of_number 16 2 s in
        n, find_octal_type n
    else if s.[0] = '0' then begin
        let is_octal =
            let rec continue i =
                if i >= length then
                    true
                else
                    if is_octal s.[i] then continue (i + 1) else false
            in
            continue 1
        in
        if is_octal then
            let n = big_int_of_number 8 1 s in
            n, find_octal_type n
        else
            let n = big_int_of_number 10 0 s in
            n, find_decimal_type n
    end
    else
        let n = big_int_of_number 10 0 s in
        n, find_decimal_type n