Bug 894026 - Implement ES6 binary and octal literals. r=till

--HG--
extra : rebase_source : 8b38dbc0f3c98f7246137d21ae9b3a29be640e2b
This commit is contained in:
Jeff Walden 2013-07-23 14:12:36 -07:00
parent afc4f3df3f
commit e6943aa105
6 changed files with 247 additions and 9 deletions

View File

@ -1003,7 +1003,7 @@ enum FirstCharKind {
Dec,
Colon,
Plus,
HexOct,
BasePrefix,
/* These two must be last, so that |c >= Space| matches both. */
Space,
@ -1022,7 +1022,7 @@ enum FirstCharKind {
* Dec: 49..57: '1'..'9'
* Colon: 58: ':'
* Plus: 43: '+'
* HexOct: 48: '0'
* BasePrefix: 48: '0'
* Space: 9, 11, 12: '\t', '\v', '\f'
* EOL: 10, 13: '\n', '\r'
*/
@ -1032,7 +1032,7 @@ static const uint8_t firstCharKinds[] = {
/* 10+ */ EOL, Space, Space, EOL, _______, _______, _______, _______, _______, _______,
/* 20+ */ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
/* 30+ */ _______, _______, Space, _______, String, _______, Ident, _______, _______, String,
/* 40+ */ OneChar, OneChar, _______, Plus, OneChar, _______, Dot, _______, HexOct, Dec,
/* 40+ */ OneChar, OneChar, _______, Plus, OneChar, _______, Dot, _______, BasePrefix, Dec,
/* 50+ */ Dec, Dec, Dec, Dec, Dec, Dec, Dec, Dec, Colon, OneChar,
/* 60+ */ _______, Equals, _______, OneChar, _______, Ident, Ident, Ident, Ident, Ident,
/* 70+ */ Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident, Ident,
@ -1397,10 +1397,8 @@ TokenStream::getTokenInternal()
goto out;
}
/*
* Look for a hexadecimal or octal number.
*/
if (c1kind == HexOct) {
// Look for a hexadecimal, octal, or binary number.
if (c1kind == BasePrefix) {
int radix;
c = getCharIgnoreEOL();
if (c == 'x' || c == 'X') {
@ -1414,6 +1412,28 @@ TokenStream::getTokenInternal()
numStart = userbuf.addressOfNextRawChar() - 1; /* one past the '0x' */
while (JS7_ISHEX(c))
c = getCharIgnoreEOL();
} else if (c == 'b' || c == 'B') {
radix = 2;
c = getCharIgnoreEOL();
if (c != '0' && c != '1') {
ungetCharIgnoreEOL(c);
reportError(JSMSG_MISSING_BINARY_DIGITS);
goto error;
}
numStart = userbuf.addressOfNextRawChar() - 1; /* one past the '0b' */
while (c == '0' || c == '1')
c = getCharIgnoreEOL();
} else if (c == 'o' || c == 'O') {
radix = 8;
c = getCharIgnoreEOL();
if (c < '0' || c > '7') {
ungetCharIgnoreEOL(c);
reportError(JSMSG_MISSING_OCTAL_DIGITS);
goto error;
}
numStart = userbuf.addressOfNextRawChar() - 1; /* one past the '0o' */
while ('0' <= c && c <= '7')
c = getCharIgnoreEOL();
} else if (JS7_ISDEC(c)) {
radix = 8;
numStart = userbuf.addressOfNextRawChar() - 1; /* one past the '0' */

View File

@ -184,7 +184,7 @@ MSG_DEF(JSMSG_BAD_OPERAND, 130, 1, JSEXN_SYNTAXERR, "invalid {0} oper
MSG_DEF(JSMSG_BAD_PROP_ID, 131, 0, JSEXN_SYNTAXERR, "invalid property id")
MSG_DEF(JSMSG_RESERVED_ID, 132, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier")
MSG_DEF(JSMSG_SYNTAX_ERROR, 133, 0, JSEXN_SYNTAXERR, "syntax error")
MSG_DEF(JSMSG_UNUSED134, 134, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_MISSING_BINARY_DIGITS, 134, 0, JSEXN_SYNTAXERR, "missing binary digits after '0b'")
MSG_DEF(JSMSG_BAD_PROTOTYPE, 135, 1, JSEXN_TYPEERR, "'prototype' property of {0} is not an object")
MSG_DEF(JSMSG_MISSING_EXPONENT, 136, 0, JSEXN_SYNTAXERR, "missing exponent")
MSG_DEF(JSMSG_OUT_OF_MEMORY, 137, 0, JSEXN_ERR, "out of memory")
@ -193,7 +193,7 @@ MSG_DEF(JSMSG_TOO_MANY_PARENS, 139, 0, JSEXN_INTERNALERR, "too many paren
MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 140, 0, JSEXN_SYNTAXERR, "unterminated comment")
MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 141, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal")
MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE, 142, 0, JSEXN_TYPEERR, "bad cloned function scope chain")
MSG_DEF(JSMSG_UNUSED143, 143, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_MISSING_OCTAL_DIGITS, 143, 0, JSEXN_SYNTAXERR, "missing octal digits after '0o'")
MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 144, 0, JSEXN_SYNTAXERR, "illegal character")
MSG_DEF(JSMSG_BAD_OCTAL, 145, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant")
MSG_DEF(JSMSG_REPEAT_RANGE, 146, 0, JSEXN_RANGEERR, "repeat count must be positive and less than inifinity")

View File

@ -0,0 +1,115 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
//-----------------------------------------------------------------------------
var BUGNUMBER = 894026;
var summary = "Implement ES6 binary literals";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var chars = ['b', 'B'];
for (var i = 0; i < 2; i++)
{
if (i === 2)
{
chars.forEach(function(v)
{
try
{
eval('0' + v + i);
throw "didn't throw";
}
catch (e)
{
assertEq(e instanceof SyntaxError, true,
"no syntax error evaluating 0" + v + i + ", " +
"got " + e);
}
});
continue;
}
for (var j = 0; j < 2; j++)
{
if (j === 2)
{
chars.forEach(function(v)
{
try
{
eval('0' + v + i + j);
throw "didn't throw";
}
catch (e)
{
assertEq(e instanceof SyntaxError, true,
"no syntax error evaluating 0" + v + i + j + ", " +
"got " + e);
}
});
continue;
}
for (var k = 0; k < 2; k++)
{
if (k === 2)
{
chars.forEach(function(v)
{
try
{
eval('0' + v + i + j + k);
throw "didn't throw";
}
catch (e)
{
assertEq(e instanceof SyntaxError, true,
"no syntax error evaluating 0" + v + i + j + k + ", " +
"got " + e);
}
});
continue;
}
chars.forEach(function(v)
{
assertEq(eval('0' + v + i + j + k), i * 4 + j * 2 + k);
});
}
}
}
chars.forEach(function(v)
{
try
{
}
catch (e)
{
assertEq(e instanceof SyntaxError, true,
"no syntax error evaluating 0" + v + ", got " + e);
}
});
// Off-by-one check: '/' immediately precedes '0'.
assertEq(0b110/1, 6);
assertEq(0B10110/1, 22);
function strict()
{
"use strict";
return 0b11010101;
}
assertEq(strict(), 128 + 64 + 16 + 4 + 1);
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");

View File

@ -0,0 +1,103 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
//-----------------------------------------------------------------------------
var BUGNUMBER = 894026;
var summary = "Implement ES6 octal literals";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var chars = ['o', 'O'];
for (var i = 0; i < 8; i++)
{
if (i === 8)
{
chars.forEach(function(v)
{
try
{
eval('0' + v + i);
throw "didn't throw";
}
catch (e)
{
assertEq(e instanceof SyntaxError, true,
"no syntax error evaluating 0" + v + i + ", " +
"got " + e);
}
});
continue;
}
for (var j = 0; j < 8; j++)
{
if (j === 8)
{
chars.forEach(function(v)
{
try
{
eval('0' + v + i + j);
throw "didn't throw";
}
catch (e)
{
assertEq(e instanceof SyntaxError, true,
"no syntax error evaluating 0" + v + i + j + ", " +
"got " + e);
}
});
continue;
}
for (var k = 0; k < 8; k++)
{
if (k === 8)
{
chars.forEach(function(v)
{
try
{
eval('0' + v + i + j + k);
throw "didn't throw";
}
catch (e)
{
assertEq(e instanceof SyntaxError, true,
"no syntax error evaluating 0" + v + i + j + k + ", " +
"got " + e);
}
});
continue;
}
chars.forEach(function(v)
{
assertEq(eval('0' + v + i + j + k), i * 64 + j * 8 + k);
});
}
}
}
// Off-by-one check: '/' immediately precedes '0'.
assertEq(0o110/2, 36);
assertEq(0O644/2, 210);
function strict()
{
"use strict";
return 0o755;
}
assertEq(strict(), 7 * 64 + 5 * 8 + 5);
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");

View File