Mercurial > projects > dil
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,