type t =
  | Int of int
  | Float of float
  | String of string
  | Ident of string
  | Plus
  | Minus
  | Asterisk
  | Slash
  | Carret
  | Percent
  | LParen
  | RParen
  | Equal
  | Not_equal
  | Greater
  | Less
  | Greater_equal
  | Less_equal
  | Hash
  | Right_arrow

(* list of tokens. because front tokens are detected first, longer
 * tokens must come earlier than shorter tokens. *)
let tokens = ref [
  "->", Right_arrow;
  "<>", Not_equal;
  ">=", Greater_equal;
  "<=", Less_equal;
  ">", Greater;
  "<", Less;
  "+", Plus;
  "-", Minus;
  "*", Asterisk;
  "/", Slash;
  "^", Carret;
  "%", Percent;
  "(", LParen;
  ")", RParen;
  "=", Equal;
  "#", Hash;
]

let to_string = function
  | Int n -> string_of_int n
  | Float n -> string_of_float n
  | String x -> x
  | Ident s -> s
  | t ->
    begin match List.find_opt (fun (_, tok) -> t = tok) !tokens with
      | None -> failwith "Token.to_string"
      | Some (s, _) -> s
    end