changeset 63:c29229fbf2f7

- Recognizing floats that start with a dot. - Fixed while loop of integer scanner. - Consuming octal as well as decimal digits in octal number scanner. - Implemented scanReal() function. - Added finalizeFloat() function to convert the recognized float string and complete the token.
author aziz
date Fri, 29 Jun 2007 18:15:01 +0000
parents 96af5653acef
children dd4c5a0e47dd
files trunk/src/Lexer.d trunk/src/Messages.d
diffstat 2 files changed, 95 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/Lexer.d	Fri Jun 29 15:07:05 2007 +0000
+++ b/trunk/src/Lexer.d	Fri Jun 29 18:15:01 2007 +0000
@@ -398,7 +398,7 @@
           goto Lcommon2;
         }
         assert(0);
-      case '.': /* .  ..  ... */
+      case '.': /* .  .[0-9]  ..  ... */
         if (p[1] == '.')
         {
           ++p;
@@ -409,6 +409,10 @@
           else
             t.type = TOK.Slice;
         }
+        else if (isdigit(p[1]))
+        {
+          return scanReal(t);
+        }
         else
           t.type = TOK.Dot;
         goto Lcommon;
@@ -891,13 +895,6 @@
     Suffix:= (L|[uU]|L[uU]|[uU]L)?
     HexDigits:= [0-9a-zA-Z_]+
 
-    FloatLiteral:= Float[fFL]?i?
-    Float:= DecFloat | HexFloat
-    DecFloat:= ([0-9][0-9_]*[.]([0-9_]*DecExponent?)?) | [.][0-9][0-9_]*DecExponent? | [0-9][0-9_]*DecExponent
-    DecExponent:= [eE][+-]?[0-9_]+
-    HexFloat:= 0[xX](HexDigits[.]HexDigits | [.][0-9a-zA-Z]HexDigits? | HexDigits)HexExponent
-    HexExponent:= [pP][+-]?[0-9_]+
-
     Invalid: "0b_", "0x_", "._"
   */
   void scanNumber(ref Token t)
@@ -939,10 +936,12 @@
 
   LscanInteger:
     isDecimal = true;
-    while (isdigit(*++p))
+    while (1)
     {
-      if (*p == '_')
+      if (*++p == '_')
         continue;
+      if (!isdigit(*p))
+        break;
       if (ulong_ < ulong.max/10 || (ulong_ == ulong.max/10 && *p <= '5'))
       {
         ulong_ *= 10;
@@ -1063,11 +1062,18 @@
       }
       // Overflow: skip following digits.
       overflow = true;
-      while (isoctal(*++p)) {}
+      while (isdigit(*++p)) {}
       break;
     }
 
-    // The number could be a float, so check overflow below.
+    bool hasDecimalDigits;
+    if (isdigit(*p))
+    {
+      hasDecimalDigits = true;
+      while (isdigit(*++p)) {}
+    }
+
+    // The number could be a float, so check errors below.
     switch (*p)
     {
     case '.':
@@ -1079,8 +1085,11 @@
         break;
     case 'i', 'f', 'F', 'e', 'E':
       goto LscanReal;
+    default:
     }
 
+    if (hasDecimalDigits)
+      error(MID.OctalNumberHasDecimals);
     if (overflow)
       error(MID.OverflowOctalNumber);
 //     goto Lfinalize;
@@ -1158,14 +1167,64 @@
     t.end = p;
     return;
   LscanReal:
-    p = t.start;
     scanReal(t);
     return;
   }
 
+  /*
+    FloatLiteral:= Float[fFL]?i?
+    Float:= DecFloat | HexFloat
+    DecFloat:= ([0-9][0-9_]*[.]([0-9_]*DecExponent?)?) | [.][0-9][0-9_]*DecExponent? | [0-9][0-9_]*DecExponent
+    DecExponent:= [eE][+-]?[0-9][0-9_]*
+    HexFloat:= 0[xX](HexDigits[.]HexDigits | [.][0-9a-zA-Z]HexDigits? | HexDigits)HexExponent
+    HexExponent:= [pP][+-]?[0-9][0-9_]*
+  */
   void scanReal(ref Token t)
   {
-    assert(*p == '.' || isdigit(*p));
+    if (*p == '.')
+      // This function was called by scan() or scanNumber().
+      while (isdigit(*++p) || *p == '_') {}
+    else
+    {
+      // This function was called by scanNumber().
+      debug switch (*p)
+      {
+      case 'L':
+        if (p[1] != 'i')
+          assert(0);
+      case 'i', 'f', 'F', 'e', 'E': break;
+      default: assert(0);
+      }
+    }
+
+    // Scan exponent.
+    if (*p == 'e' || *p == 'E')
+    {
+      ++p;
+      if (*p == '-' || *p == '+')
+        ++p;
+      if (!isdigit(*p))
+        error(MID.FloatExponentDigitExpected);
+      else
+        while (isdigit(*p) || *p == '_') { ++p; }
+    }
+
+    // Copy string to buffer ignoring underscores.
+    char[] buffer;
+    char* end = p;
+    p = t.start;
+    do
+    {
+      if (*p == '_')
+      {
+        ++p;
+        continue;
+      }
+      buffer ~= *p;
+      ++p;
+    } while (p != end)
+    buffer ~= 0;
+    finalizeFloat(t, buffer);
   }
 
   void scanHexReal(ref Token t)
@@ -1186,9 +1245,11 @@
     do
     {
       if (*p == '_')
+      {
+        ++p;
         continue;
-      else
-        buffer ~= *p;
+      }
+      buffer ~= *p;
       ++p;
     } while (p != end)
 
@@ -1211,6 +1272,16 @@
       goto Lerr;
     }
     buffer ~= 0; // Terminate for C functions.
+    finalizeFloat(t, buffer);
+    return;
+  Lerr:
+    t.type = TOK.Float32;
+    t.end = p;
+    error(mid);
+  }
+
+  void finalizeFloat(ref Token t, string buffer)
+  {
     // Float number is well-formed. Check suffixes and do conversion.
     switch (*p)
     {
@@ -1232,19 +1303,11 @@
     if (*p == 'i')
     {
       ++p;
-      t.type += 3; // Switch to imaginary version.
+      t.type += 3; // Switch to imaginary counterpart.
     }
     if (getErrno == ERANGE)
-    {
-      mid = MID.OverflowHexFloatNumber;
-      goto Lerr;
-    }
+      error(MID.OverflowFloatNumber);
     t.end = p;
-    return;
-  Lerr:
-    t.type = TOK.Float32;
-    t.end = p;
-    error(mid);
   }
 
   /// Scan special token: #line Integer [Filespec] EndOfLine
--- a/trunk/src/Messages.d	Fri Jun 29 15:07:05 2007 +0000
+++ b/trunk/src/Messages.d	Fri Jun 29 18:15:01 2007 +0000
@@ -42,11 +42,13 @@
   OverflowHexNumber,
   OverflowBinaryNumber,
   OverflowOctalNumber,
-  OverflowHexFloatNumber,
+  OverflowFloatNumber,
+  OctalNumberHasDecimals,
   NoDigitsInHexNumber,
   NoDigitsInBinNumber,
   HexFloatExponentRequired,
   HexFloatMissingExpDigits,
+  FloatExponentDigitExpected,
 }
 
 string[] messages = [
@@ -85,9 +87,11 @@
   "overflow in hexadecimal number.",
   "overflow in binary number.",
   "overflow in octal number.",
-  "overflow in hexadecimal float number.",
+  "overflow in float number.",
+  "decimal digits are not allowed in octal numbers.",
   "invalid hex number; at least one hex digit expected.",
   "invalid binary number; at least one binary digit expected.",
   "the exponent of a hexadecimal float number is required.",
   "missing decimal digits in hexadecimal float exponent.",
+  "exponents have to start with a digit.",
 ];