Skip to content

Commit

Permalink
Remove support for float literals starting with a period
Browse files Browse the repository at this point in the history
Before this patch, writing .0 instead of 0.0 was allowed, as in C, C++, D,
Java, Go, Perl, Python and many other languages. This required a hack in the
form of an additional entry pointer for our scanner. We now get rid of it,
matching languages like Ada, Haskell, OCaml, Rust, Swift.
  • Loading branch information
fingolfin committed Feb 12, 2019
1 parent df547af commit bb15065
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 62 deletions.
13 changes: 4 additions & 9 deletions src/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -1404,8 +1404,10 @@ static void ReadFuncExprAbbrevSingle(TypSymbolSet follow)
** all symbols up to one contained in <follow>.
**
** <Literal> := <Int>
** | <Float>
** | 'true'
** | 'false'
** | '~'
** | <Char>
** | <Perm>
** | <String>
Expand All @@ -1423,13 +1425,6 @@ static void ReadLiteral (
TypSymbolSet follow,
Char mode)
{
if (STATE(Symbol) == S_DOT) {
// HACK: The only way a dot could turn up here is in a floating point
// literal that starts with '.'. Call back to the scanner to deal
// with this.
ScanForFloatAfterDotHACK();
}

switch (STATE(Symbol)) {

/* <Int> */
Expand Down Expand Up @@ -1472,7 +1467,7 @@ static void ReadLiteral (
Match( S_CHAR, "character", follow );
break;

/* string */
/* <String> */
case S_STRING:
GAP_ASSERT(STATE(ValueObj) != 0);
TRY_IF_NO_ERROR { IntrStringExpr(STATE(ValueObj)); }
Expand All @@ -1485,7 +1480,7 @@ static void ReadLiteral (
ReadListExpr( follow );
break;

/* <Rec> */
/* <Record> */
case S_REC:
ReadRecExpr( follow );
break;
Expand Down
25 changes: 3 additions & 22 deletions src/scanner.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,6 @@ static UInt GetIdent(Int i)
**
** When 'STATE(Value)' is completely filled, then a GAP string object is
** created in 'STATE(ValueObj)' and all data is stored there.
**
** The argument is used to signal if a decimal point was already read,
** or whether we are starting from scratch..
**
*/
static UInt AddCharToBuf(Obj * string, Char * buf, UInt bufsize, UInt pos, Char c)
{
Expand All @@ -381,7 +377,7 @@ static UInt AddCharToValue(UInt pos, Char c)
return AddCharToBuf(&STATE(ValueObj), STATE(Value), MAX_VALUE_LEN - 1, pos, c);
}

static UInt GetNumber(Int readDecimalPoint)
static UInt GetNumber(void)
{
UInt symbol = S_ILLEGAL;
UInt i = 0;
Expand All @@ -393,10 +389,7 @@ static UInt GetNumber(Int readDecimalPoint)
STATE(ValueObj) = 0;

c = PEEK_CURR_CHAR();
if (readDecimalPoint) {
STATE(Value)[i++] = '.';
}
else {

// read initial sequence of digits into 'Value'
while (IsDigit(c)) {
i = AddCharToValue(i, c);
Expand Down Expand Up @@ -449,7 +442,6 @@ static UInt GetNumber(Int readDecimalPoint)
symbol = S_INT;
goto finish;
}
}


// When we get here we have read possibly some digits, a . and possibly
Expand Down Expand Up @@ -594,17 +586,6 @@ static UInt GetNumber(Int readDecimalPoint)
}


/****************************************************************************
**
*F ScanForFloatAfterDotHACK()
**
*/
void ScanForFloatAfterDotHACK(void)
{
STATE(Symbol) = GetNumber(1);
}


/****************************************************************************
**
*F GetOctalDigits()
Expand Down Expand Up @@ -1014,7 +995,7 @@ static UInt NextSymbol(void)

case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return GetNumber(0);
return GetNumber();

case '\377': symbol = S_EOF; *STATE(In) = '\0'; break;

Expand Down
12 changes: 0 additions & 12 deletions src/scanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,18 +344,6 @@ EXPORT_INLINE void SyntaxWarning(const Char * msg)
void Match(UInt symbol, const Char * msg, TypSymbolSet skipto);


/****************************************************************************
**
*F ScanForFloatAfterDotHACK()
**
** This function is called by 'ReadLiteral' if it encounters a single dot in
** form the of the symbol 'S_DOT'. The only legal way this could happen is
** if the dot is the start of a float literal like '.123'. As the scanner
** cannot detect this without being context aware, we must provide this
** function to allow the reader to signal to the scanner about this.
*/
void ScanForFloatAfterDotHACK(void);

/****************************************************************************
**
*F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * *
Expand Down
5 changes: 2 additions & 3 deletions tst/testbugfix/2013-08-21-t00295.tst
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# 2013/08/21 (MH)
gap> . . . .
Syntax error: Badly formed number: need a digit before or after the decimal po\
int in stream:1
Syntax error: literal expected in stream:1
. . . .
^
Syntax error: Record component name expected in stream:2
Syntax error: ; expected in stream:2

2 changes: 1 addition & 1 deletion tst/testinstall/float.tst
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ gap> ComplexConjugate(1.3);
#
gap> Display(1.3);
1.3
gap> Display(-.4e6);
gap> Display(-0.4e6);
-400000.
gap> PrintObj(1.3); Print("Q\n");
1.3Q
Expand Down
25 changes: 10 additions & 15 deletions tst/testinstall/longnumber.tst
Original file line number Diff line number Diff line change
Expand Up @@ -152,40 +152,35 @@ gap> 1.;
1.
gap> 0.;
0.
gap> .1;
0.1
gap> 0.1;
0.1
gap> 1111111111111111111111111111111111111.1;
1.11111e+36
gap> 1.11111111111111111111111111111111111111;
1.11111
gap> .;
Syntax error: Badly formed number: need a digit before or after the decimal po\
int in stream:1
Syntax error: literal expected in stream:1
.;
^
gap> .n;
Syntax error: Badly formed number: need a digit before or after the decimal po\
int in stream:1
Syntax error: literal expected in stream:1
.n;
^
gap> .q;
Syntax error: Badly formed number: need a digit before or after the decimal po\
int in stream:1
Syntax error: literal expected in stream:1
.q;
^
gap> .0n;
Error, failed to convert float literal
Syntax error: literal expected in stream:1
.0n;
^
gap> .0q;
Syntax error: Badly formed number: need at least one digit in the exponent in \
stream:1
Syntax error: literal expected in stream:1
.0q;
^^^
^
gap> .0qn;
Syntax error: Badly formed number: need at least one digit in the exponent in \
stream:1
Syntax error: literal expected in stream:1
.0qn;
^^^
^
gap> Unbind(x);
gap> STOP_TEST( "longnumber.tst", 1);

0 comments on commit bb15065

Please sign in to comment.