in AjaxMinDll/JavaScript/jsscanner.cs [1878:2038]
private JSToken ScanNumber(char leadChar)
{
bool noMoreDot = '.' == leadChar;
JSToken token = noMoreDot ? JSToken.NumericLiteral : JSToken.IntegerLiteral;
bool exponent = false;
char c;
m_literalIssues = false;
if ('0' == leadChar)
{
// c is now the character AFTER the leading zero
c = GetChar(m_currentPosition);
if ('x' == c || 'X' == c)
{
if (JSScanner.IsHexDigit(GetChar(m_currentPosition + 1)))
{
while (JSScanner.IsHexDigit(GetChar(++m_currentPosition)))
{
// empty
}
}
return CheckForNumericBadEnding(token);
}
else if ('b' == c || 'B' == c)
{
// ES6 binary literal?
c = GetChar(m_currentPosition + 1);
if (c == '1' || c == '0')
{
while ('0' == (c = GetChar(++m_currentPosition)) || c == '1')
{
// iterator handled in the condition
}
}
return CheckForNumericBadEnding(token);
}
else if ('o' == c || 'O' == c)
{
// ES6 octal literal?
c = GetChar(m_currentPosition + 1);
if ('0' <= c && c <= '7')
{
while ('0' <= (c = GetChar(++m_currentPosition)) && c <= '7')
{
// iterator handled in the condition
}
}
return CheckForNumericBadEnding(token);
}
else if ('0' <= c && c <= '7')
{
// this is a zero followed by a digit between 0 and 7.
// This could be interpreted as an octal literal, which isn't strictly supported.
while ('0' <= c && c <= '7')
{
c = GetChar(++m_currentPosition);
}
// bad octal?
if (IsDigit(c) && '7' < c)
{
// bad octal. Skip any other digits, throw an error, mark it has having issues
m_literalIssues = true;
while ('0' <= c && c <= '9')
{
c = GetChar(++m_currentPosition);
}
HandleError(JSError.BadNumericLiteral);
}
// return the integer token with issues, which should cause it to be output
// as-is and not combined with other literals or anything.
m_literalIssues = true;
HandleError(JSError.OctalLiteralsDeprecated);
return token;
}
else if (c != 'e' && c != 'E' && IsValidIdentifierStart(m_strSourceCode, m_currentPosition))
{
// invalid for an integer (in this case '0') the be followed by
// an identifier part. The 'e' is okay, though, because that will
// be the exponent part.
// we know the 0 and the next character are both invalid, so skip them and
// anything else after it that's identifier-like, and throw an error.
return CheckForNumericBadEnding(token);
}
}
for (;;)
{
c = GetChar(m_currentPosition);
if (!IsDigit(c))
{
if ('.' == c)
{
if (noMoreDot)
{
break;
}
noMoreDot = true;
token = JSToken.NumericLiteral;
}
else if ('e' == c || 'E' == c)
{
if (exponent)
{
break;
}
exponent = noMoreDot = true;
token = JSToken.NumericLiteral;
}
else if ('+' == c || '-' == c)
{
char e = GetChar(m_currentPosition - 1);
if ('e' != e && 'E' != e)
{
break;
}
}
else
{
break;
}
}
m_currentPosition++;
}
// get the last character of the number
c = GetChar(m_currentPosition - 1);
if ('+' == c || '-' == c)
{
// if it's a + or -, then it's not part of the number; back it up one
m_currentPosition--;
c = GetChar(m_currentPosition - 1);
}
if ('e' == c || 'E' == c)
{
// if it's an e, it's not part of the number; back it up one
m_currentPosition--;
c = GetChar(m_currentPosition - 1);
}
if (token == JSToken.NumericLiteral && c == '.')
{
// if we thought this was a numeric value and not an integer, but the last
// value was the decimal point, treat it as an integer.
token = JSToken.IntegerLiteral;
}
// it is invalid for a numeric literal to be immediately followed by another
// digit or an identifier start character. So check for those and return an
// invalid numeric literal if true.
return CheckForNumericBadEnding(token);
}