Fix lexing of numbers with trailing decimal point and exponent
Numbers with a trailing dot and an exponent were incorrectly read as integers (with the exponent ignored) instead of the floats they should be. For example, 1.e6 was read as the integer 1, not 1000000.0 as every sane person would agree was meant. (Bug#48678) Numbers with a trailing dot but no exponent are still read as integers. * src/lread.c (string_to_number): Fix float lexing. * test/src/lread-tests.el (lread-float): Add test. * doc/lispref/numbers.texi (Float Basics): Clarify syntax.
This commit is contained in:
parent
40d2970f43
commit
de45864cf7
3 changed files with 74 additions and 6 deletions
|
@ -237,7 +237,8 @@ precede the number and its exponent. For example, @samp{1500.0},
|
|||
@samp{+15e2}, @samp{15.0e+2}, @samp{+1500000e-3}, and @samp{.15e4} are
|
||||
five ways of writing a floating-point number whose value is 1500.
|
||||
They are all equivalent. Like Common Lisp, Emacs Lisp requires at
|
||||
least one digit after any decimal point in a floating-point number;
|
||||
least one digit after a decimal point in a floating-point number that
|
||||
does not have an exponent;
|
||||
@samp{1500.} is an integer, not a floating-point number.
|
||||
|
||||
Emacs Lisp treats @code{-0.0} as numerically equal to ordinary zero
|
||||
|
|
10
src/lread.c
10
src/lread.c
|
@ -3938,8 +3938,7 @@ string_to_number (char const *string, int base, ptrdiff_t *plen)
|
|||
bool signedp = negative | positive;
|
||||
cp += signedp;
|
||||
|
||||
enum { INTOVERFLOW = 1, LEAD_INT = 2, DOT_CHAR = 4, TRAIL_INT = 8,
|
||||
E_EXP = 16 };
|
||||
enum { INTOVERFLOW = 1, LEAD_INT = 2, TRAIL_INT = 4, E_EXP = 16 };
|
||||
int state = 0;
|
||||
int leading_digit = digit_to_number (*cp, base);
|
||||
uintmax_t n = leading_digit;
|
||||
|
@ -3959,7 +3958,6 @@ string_to_number (char const *string, int base, ptrdiff_t *plen)
|
|||
char const *after_digits = cp;
|
||||
if (*cp == '.')
|
||||
{
|
||||
state |= DOT_CHAR;
|
||||
cp++;
|
||||
}
|
||||
|
||||
|
@ -4008,8 +4006,10 @@ string_to_number (char const *string, int base, ptrdiff_t *plen)
|
|||
cp = ecp;
|
||||
}
|
||||
|
||||
float_syntax = ((state & (DOT_CHAR|TRAIL_INT)) == (DOT_CHAR|TRAIL_INT)
|
||||
|| (state & ~INTOVERFLOW) == (LEAD_INT|E_EXP));
|
||||
/* A float has digits after the dot or an exponent.
|
||||
This excludes numbers like "1." which are lexed as integers. */
|
||||
float_syntax = ((state & TRAIL_INT)
|
||||
|| ((state & LEAD_INT) && (state & E_EXP)));
|
||||
}
|
||||
|
||||
if (plen)
|
||||
|
|
|
@ -196,4 +196,71 @@ literals (Bug#20852)."
|
|||
(should-error (read-event "foo: "))
|
||||
(should-error (read-char-exclusive "foo: "))))
|
||||
|
||||
(ert-deftest lread-float ()
|
||||
(should (equal (read "13") 13))
|
||||
(should (equal (read "+13") 13))
|
||||
(should (equal (read "-13") -13))
|
||||
(should (equal (read "13.") 13))
|
||||
(should (equal (read "+13.") 13))
|
||||
(should (equal (read "-13.") -13))
|
||||
(should (equal (read "13.25") 13.25))
|
||||
(should (equal (read "+13.25") 13.25))
|
||||
(should (equal (read "-13.25") -13.25))
|
||||
(should (equal (read ".25") 0.25))
|
||||
(should (equal (read "+.25") 0.25))
|
||||
(should (equal (read "-.25") -0.25))
|
||||
(should (equal (read "13e4") 130000.0))
|
||||
(should (equal (read "+13e4") 130000.0))
|
||||
(should (equal (read "-13e4") -130000.0))
|
||||
(should (equal (read "13e+4") 130000.0))
|
||||
(should (equal (read "+13e+4") 130000.0))
|
||||
(should (equal (read "-13e+4") -130000.0))
|
||||
(should (equal (read "625e-4") 0.0625))
|
||||
(should (equal (read "+625e-4") 0.0625))
|
||||
(should (equal (read "-625e-4") -0.0625))
|
||||
(should (equal (read "1.25e2") 125.0))
|
||||
(should (equal (read "+1.25e2") 125.0))
|
||||
(should (equal (read "-1.25e2") -125.0))
|
||||
(should (equal (read "1.25e+2") 125.0))
|
||||
(should (equal (read "+1.25e+2") 125.0))
|
||||
(should (equal (read "-1.25e+2") -125.0))
|
||||
(should (equal (read "1.25e-1") 0.125))
|
||||
(should (equal (read "+1.25e-1") 0.125))
|
||||
(should (equal (read "-1.25e-1") -0.125))
|
||||
(should (equal (read "4.e3") 4000.0))
|
||||
(should (equal (read "+4.e3") 4000.0))
|
||||
(should (equal (read "-4.e3") -4000.0))
|
||||
(should (equal (read "4.e+3") 4000.0))
|
||||
(should (equal (read "+4.e+3") 4000.0))
|
||||
(should (equal (read "-4.e+3") -4000.0))
|
||||
(should (equal (read "5.e-1") 0.5))
|
||||
(should (equal (read "+5.e-1") 0.5))
|
||||
(should (equal (read "-5.e-1") -0.5))
|
||||
(should (equal (read "0") 0))
|
||||
(should (equal (read "+0") 0))
|
||||
(should (equal (read "-0") 0))
|
||||
(should (equal (read "0.") 0))
|
||||
(should (equal (read "+0.") 0))
|
||||
(should (equal (read "-0.") 0))
|
||||
(should (equal (read "0.0") 0.0))
|
||||
(should (equal (read "+0.0") 0.0))
|
||||
(should (equal (read "-0.0") -0.0))
|
||||
(should (equal (read "0e5") 0.0))
|
||||
(should (equal (read "+0e5") 0.0))
|
||||
(should (equal (read "-0e5") -0.0))
|
||||
(should (equal (read "0e-5") 0.0))
|
||||
(should (equal (read "+0e-5") 0.0))
|
||||
(should (equal (read "-0e-5") -0.0))
|
||||
(should (equal (read ".0e-5") 0.0))
|
||||
(should (equal (read "+.0e-5") 0.0))
|
||||
(should (equal (read "-.0e-5") -0.0))
|
||||
(should (equal (read "0.0e-5") 0.0))
|
||||
(should (equal (read "+0.0e-5") 0.0))
|
||||
(should (equal (read "-0.0e-5") -0.0))
|
||||
(should (equal (read "0.e-5") 0.0))
|
||||
(should (equal (read "+0.e-5") 0.0))
|
||||
(should (equal (read "-0.e-5") -0.0))
|
||||
)
|
||||
|
||||
|
||||
;;; lread-tests.el ends here
|
||||
|
|
Loading…
Add table
Reference in a new issue