changeset 62:96af5653acef

- Fixed loop of hex number scanner. Moved checks under the switch block. - Fixed loop of octal number scanner. - Implemented hex floating number scanner.
author aziz
date Fri, 29 Jun 2007 15:07:05 +0000
parents 512cd2248dfc
children c29229fbf2f7
files trunk/src/Lexer.d trunk/src/Messages.d trunk/src/Token.d trunk/src/main.d
diffstat 4 files changed, 127 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/Lexer.d	Fri Jun 29 07:52:05 2007 +0000
+++ b/trunk/src/Lexer.d	Fri Jun 29 15:07:05 2007 +0000
@@ -10,7 +10,7 @@
 import std.stdio;
 import std.utf;
 import std.uni;
-import std.conv;
+import std.c.stdlib;
 
 const char[3] LS = \u2028;
 const char[3] PS = \u2029;
@@ -78,7 +78,7 @@
 
     uint c = *p;
 
-    while(1)
+    while (1)
     {
       t.start = p;
 
@@ -978,10 +978,12 @@
 
   LscanHex:
     assert(digits == 0);
-    while (ishexad(*++p))
+    while (1)
     {
-      if (*p == '_')
+      if (*++p == '_')
         continue;
+      if (!ishexad(*p))
+        break;
       ++digits;
       ulong_ *= 16;
       if (*p <= '9')
@@ -992,30 +994,30 @@
         ulong_ += *p - 'a' + 10;
     }
 
+    switch (*p)
+    {
+    case '.':
+      if (p[1] != '.')
+        goto LscanHexReal;
+      break;
+    case 'L':
+      if (p[1] != 'i')
+        break;
+    case 'i', 'p', 'P':
+      goto LscanHexReal;
+    default:
+    }
     if (digits == 0)
       error(MID.NoDigitsInHexNumber);
-
-    if (digits > 16)
+    else if (digits > 16)
     {
       // Overflow: skip following digits.
       error(MID.OverflowHexNumber);
       while (ishexad(*++p)) {}
     }
-
-    switch (*p)
-    {
-    case '.':
-      if (p[1] != '.')
-        goto LscanReal;
-      break;
-    case 'L':
-      if (p[1] != 'i')
-        break;
-    case 'i', 'p', 'P':
-      goto LscanReal;
-    default:
-    }
     goto Lfinalize;
+  LscanHexReal:
+    return scanHexReal(t);
 
   LscanBin:
     assert(digits == 0);
@@ -1046,10 +1048,12 @@
     goto Lfinalize;
 
   LscanOct:
-    while (isoctal(*++p))
+    while (1)
     {
-      if (*p == '_')
+      if (*++p == '_')
         continue;
+      if (!isoctal(*p))
+        break;
       if (ulong_ < ulong.max/2 || (ulong_ == ulong.max/2 && *p <= '1'))
       {
         ulong_ *= 8;
@@ -1063,6 +1067,7 @@
       break;
     }
 
+    // The number could be a float, so check overflow below.
     switch (*p)
     {
     case '.':
@@ -1075,6 +1080,7 @@
     case 'i', 'f', 'F', 'e', 'E':
       goto LscanReal;
     }
+
     if (overflow)
       error(MID.OverflowOctalNumber);
 //     goto Lfinalize;
@@ -1162,6 +1168,85 @@
     assert(*p == '.' || isdigit(*p));
   }
 
+  void scanHexReal(ref Token t)
+  {
+    assert(*p == '.' || *p == 'i' || *p == 'p' || *p == 'P' || (*p == 'L' && p[1] == 'i'));
+    MID mid;
+    if (*p == '.')
+      while (ishexad(*++p) || *p == '_') {}
+    if (*p != 'p' && *p != 'P')
+    {
+      mid = MID.HexFloatExponentRequired;
+      goto Lerr;
+    }
+    // Copy mantissa to a buffer ignoring underscores.
+    char* end = p;
+    p = t.start;
+    char[] buffer;
+    do
+    {
+      if (*p == '_')
+        continue;
+      else
+        buffer ~= *p;
+      ++p;
+    } while (p != end)
+
+    assert(p == end && (*p == 'p' || *p == 'P'));
+    // Scan and copy the exponent.
+    buffer ~= 'p';
+    size_t bufflen = buffer.length;
+    while (1)
+    {
+      if (*++p == '_')
+        continue;
+      if (isdigit(*p))
+        buffer ~= *p;
+      else
+        break;
+    }
+    // When the buffer length hasn't changed, no digits were copied.
+    if (bufflen == buffer.length) {
+      mid = MID.HexFloatMissingExpDigits;
+      goto Lerr;
+    }
+    buffer ~= 0; // Terminate for C functions.
+    // Float number is well-formed. Check suffixes and do conversion.
+    switch (*p)
+    {
+    case 'f', 'F':
+      t.type = TOK.Float32;
+      t.float_ = strtof(buffer.ptr, null);
+      ++p;
+      break;
+    case 'L':
+      t.type = TOK.Float80;
+      t.real_ = strtold(buffer.ptr, null);
+      ++p;
+      break;
+    default:
+      t.type = TOK.Float64;
+      t.double_ = strtod(buffer.ptr, null);
+      break;
+    }
+    if (*p == 'i')
+    {
+      ++p;
+      t.type += 3; // Switch to imaginary version.
+    }
+    if (getErrno == ERANGE)
+    {
+      mid = MID.OverflowHexFloatNumber;
+      goto Lerr;
+    }
+    t.end = p;
+    return;
+  Lerr:
+    t.type = TOK.Float32;
+    t.end = p;
+    error(mid);
+  }
+
   /// Scan special token: #line Integer [Filespec] EndOfLine
   // TODO: Handle case like: #line 0 #line 2
   void scanSpecialToken()
--- a/trunk/src/Messages.d	Fri Jun 29 07:52:05 2007 +0000
+++ b/trunk/src/Messages.d	Fri Jun 29 15:07:05 2007 +0000
@@ -42,8 +42,11 @@
   OverflowHexNumber,
   OverflowBinaryNumber,
   OverflowOctalNumber,
+  OverflowHexFloatNumber,
   NoDigitsInHexNumber,
   NoDigitsInBinNumber,
+  HexFloatExponentRequired,
+  HexFloatMissingExpDigits,
 }
 
 string[] messages = [
@@ -82,6 +85,9 @@
   "overflow in hexadecimal number.",
   "overflow in binary number.",
   "overflow in octal number.",
+  "overflow in hexadecimal float number.",
   "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.",
 ];
--- a/trunk/src/Token.d	Fri Jun 29 07:52:05 2007 +0000
+++ b/trunk/src/Token.d	Fri Jun 29 15:07:05 2007 +0000
@@ -20,6 +20,9 @@
   // Numbers
   Number,
   Int32, Int64, Uint32, Uint64,
+  // Floating point scanner relies on this order. (FloatXY + 3 == ImaginaryXY)
+  Float32, Float64, Float80,
+  Imaginary32, Imaginary64, Imaginary80,
 
 
   // Brackets
@@ -105,13 +108,14 @@
       string str;
       char pf;
     }
-    dchar dchar_;
-    long  long_;
-    ulong ulong_;
-    int   int_;
-    uint  uint_;
-    float f;
-    double d;
+    dchar  dchar_;
+    long   long_;
+    ulong  ulong_;
+    int    int_;
+    uint   uint_;
+    float  float_;
+    double double_;
+    real   real_;
   }
 
   string span()
--- a/trunk/src/main.d	Fri Jun 29 07:52:05 2007 +0000
+++ b/trunk/src/main.d	Fri Jun 29 15:07:05 2007 +0000
@@ -112,7 +112,9 @@
       case TOK.Not:
         writef(`<op c="n">!</op>`);
       break;
-      case TOK.Int32, TOK.Int64, TOK.Uint32, TOK.Uint64:
+      case TOK.Int32, TOK.Int64, TOK.Uint32, TOK.Uint64,
+           TOK.Float32, TOK.Float64, TOK.Float80,
+           TOK.Imaginary32, TOK.Imaginary64, TOK.Imaginary80:
         writef("<n>%s</n>", span);
       break;
       case TOK.LParen, TOK.RParen, TOK.LBracket,