Floating Numbers

Syntax

//$ Floating point literals.
//$
//$ Follows ISO C89, except that we allow underscores;
//$ AND we require both leading and trailing digits so that
//$ x.0 works for tuple projections and 0.f is a function
//$ application
syntax felix_float_lexer {
  regdef decimal_string = digit (underscore ? digit) *;
  regdef hexadecimal_string = hexdigit (underscore ? hexdigit) *;

  regdef decimal_fractional_constant =
    decimal_string '.' decimal_string;

  regdef hexadecimal_fractional_constant =
    ("0x" |"0X")
    hexadecimal_string '.' hexadecimal_string;

  regdef decimal_exponent = ('E'|'e') ('+'|'-')? decimal_string;
  regdef binary_exponent = ('P'|'p') ('+'|'-')? decimal_string;

  regdef floating_suffix = 'L' | 'l' | 'F' | 'f' | 'D' | 'd';
  regdef floating_literal =
    (
      decimal_fractional_constant decimal_exponent ? |
      hexadecimal_fractional_constant binary_exponent ?
    )
    floating_suffix ?;

 // Floating constant.
  regdef sfloat = floating_literal;
  literal sfloat =># """
  (let*
     (
       (val (stripus _1))
       (val (tolower-string val))
       (n (string-length val))
       (n-1 (- n 1))
       (ch (substring val n-1 n))
       (rest (substring val 0 n-1))
       (result
         (if (equal? ch "l") `("ldouble" ,val ,val)
           (if (equal? ch "f") `("float" ,val ,val) `("double" ,val ,val))
         )
       )
     )
     result
   )
   """;

  strfloat := sfloat =># "(second _1)";

  // Floating literal.
  sliteral := sfloat =># "`(ast_literal ,_sr ,@_1)";

}