--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Wed Sep 02 22:28:31 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Tue Sep 01 16:11:09 2015 +0200
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.parser;
import static jdk.nashorn.internal.parser.TokenType.ADD;
+import static jdk.nashorn.internal.parser.TokenType.BINARY_NUMBER;
import static jdk.nashorn.internal.parser.TokenType.COMMENT;
import static jdk.nashorn.internal.parser.TokenType.DECIMAL;
import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
@@ -40,6 +41,7 @@
import static jdk.nashorn.internal.parser.TokenType.LBRACE;
import static jdk.nashorn.internal.parser.TokenType.LPAREN;
import static jdk.nashorn.internal.parser.TokenType.OCTAL;
+import static jdk.nashorn.internal.parser.TokenType.OCTAL_LEGACY;
import static jdk.nashorn.internal.parser.TokenType.RBRACE;
import static jdk.nashorn.internal.parser.TokenType.REGEX;
import static jdk.nashorn.internal.parser.TokenType.RPAREN;
@@ -47,6 +49,7 @@
import static jdk.nashorn.internal.parser.TokenType.XML;
import java.io.Serializable;
+
import jdk.nashorn.internal.runtime.ECMAErrors;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.JSErrorType;
@@ -75,6 +78,9 @@
/** True if here and edit strings are supported. */
private final boolean scripting;
+ /** True if parsing in ECMAScript 6 mode. */
+ private final boolean es6;
+
/** True if a nested scan. (scan to completion, no EOF.) */
private final boolean nested;
@@ -173,7 +179,7 @@
* @param stream the token stream to lex
*/
public Lexer(final Source source, final TokenStream stream) {
- this(source, stream, false);
+ this(source, stream, false, false);
}
/**
@@ -182,9 +188,10 @@
* @param source the source
* @param stream the token stream to lex
* @param scripting are we in scripting mode
+ * @param es6 are we in ECMAScript 6 mode
*/
- public Lexer(final Source source, final TokenStream stream, final boolean scripting) {
- this(source, 0, source.getLength(), stream, scripting, false);
+ public Lexer(final Source source, final TokenStream stream, final boolean scripting, final boolean es6) {
+ this(source, 0, source.getLength(), stream, scripting, es6, false);
}
/**
@@ -195,16 +202,18 @@
* @param len length of source segment to lex
* @param stream token stream to lex
* @param scripting are we in scripting mode
+ * @param es6 are we in ECMAScript 6 mode
* @param pauseOnFunctionBody if true, lexer will return from {@link #lexify()} when it encounters a
* function body. This is used with the feature where the parser is skipping nested function bodies to
* avoid reading ahead unnecessarily when we skip the function bodies.
*/
- public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean pauseOnFunctionBody) {
+ public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting, final boolean es6, final boolean pauseOnFunctionBody) {
super(source.getContent(), 1, start, len);
this.source = source;
this.stream = stream;
this.scripting = scripting;
+ this.es6 = es6;
this.nested = false;
this.pendingLine = 1;
this.last = EOL;
@@ -218,6 +227,7 @@
source = lexer.source;
stream = lexer.stream;
scripting = lexer.scripting;
+ es6 = lexer.es6;
nested = true;
pendingLine = state.pendingLine;
@@ -1088,6 +1098,24 @@
}
type = HEXADECIMAL;
+ } else if (digit == 0 && es6 && (ch1 == 'o' || ch1 == 'O') && convertDigit(ch2, 8) != -1) {
+ // Skip over 0oN.
+ skip(3);
+ // Skip over remaining digits.
+ while (convertDigit(ch0, 8) != -1) {
+ skip(1);
+ }
+
+ type = OCTAL;
+ } else if (digit == 0 && es6 && (ch1 == 'b' || ch1 == 'B') && convertDigit(ch2, 2) != -1) {
+ // Skip over 0bN.
+ skip(3);
+ // Skip over remaining digits.
+ while (convertDigit(ch0, 2) != -1) {
+ skip(1);
+ }
+
+ type = BINARY_NUMBER;
} else {
// Check for possible octal constant.
boolean octal = digit == 0;
@@ -1105,7 +1133,7 @@
}
if (octal && position - start > 1) {
- type = OCTAL;
+ type = OCTAL_LEGACY;
} else if (ch0 == '.' || ch0 == 'E' || ch0 == 'e') {
// Must be a double.
if (ch0 == '.') {
@@ -1637,10 +1665,14 @@
switch (Token.descType(token)) {
case DECIMAL:
return Lexer.valueOf(source.getString(start, len), 10); // number
- case OCTAL:
- return Lexer.valueOf(source.getString(start, len), 8); // number
case HEXADECIMAL:
return Lexer.valueOf(source.getString(start + 2, len - 2), 16); // number
+ case OCTAL_LEGACY:
+ return Lexer.valueOf(source.getString(start, len), 8); // number
+ case OCTAL:
+ return Lexer.valueOf(source.getString(start + 2, len - 2), 8); // number
+ case BINARY_NUMBER:
+ return Lexer.valueOf(source.getString(start + 2, len - 2), 2); // number
case FLOATING:
final String str = source.getString(start, len);
final double value = Double.valueOf(str);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Wed Sep 02 22:28:31 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Tue Sep 01 16:11:09 2015 +0200
@@ -273,7 +273,7 @@
try {
stream = new TokenStream();
- lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, reparsedFunction != null);
+ lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
lexer.line = lexer.pendingLine = lineOffset + 1;
line = lineOffset;
@@ -309,7 +309,7 @@
public List<IdentNode> parseFormalParameterList() {
try {
stream = new TokenStream();
- lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
+ lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
// Set up first token (skips opening EOL.)
k = -1;
@@ -333,7 +333,7 @@
public FunctionNode parseFunctionBody() {
try {
stream = new TokenStream();
- lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
+ lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
final int functionLine = line;
// Set up first token (skips opening EOL.)
@@ -1955,7 +1955,7 @@
}
detectSpecialProperty(ident);
return ident;
- case OCTAL:
+ case OCTAL_LEGACY:
if (isStrictMode) {
throw error(AbstractParser.message("strict.no.octal"), token);
}
@@ -1963,6 +1963,8 @@
case ESCSTRING:
case DECIMAL:
case HEXADECIMAL:
+ case OCTAL:
+ case BINARY_NUMBER:
case FLOATING:
case REGEX:
case XML:
@@ -2224,7 +2226,7 @@
switch (type) {
case IDENT:
return getIdent().setIsPropertyName();
- case OCTAL:
+ case OCTAL_LEGACY:
if (isStrictMode) {
throw error(AbstractParser.message("strict.no.octal"), token);
}
@@ -2232,6 +2234,8 @@
case ESCSTRING:
case DECIMAL:
case HEXADECIMAL:
+ case OCTAL:
+ case BINARY_NUMBER:
case FLOATING:
return getLiteral();
default:
@@ -3035,7 +3039,7 @@
assert parserState != null;
stream.reset();
- lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions);
+ lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
line = parserState.line;
linePosition = parserState.linePosition;
// Doesn't really matter, but it's safe to treat it as if there were a semicolon before
@@ -3064,8 +3068,8 @@
this.linePosition = linePosition;
}
- Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting) {
- final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, true);
+ Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
+ final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
return newLexer;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java Wed Sep 02 22:28:31 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java Tue Sep 01 16:11:09 2015 +0200
@@ -170,8 +170,10 @@
YIELD (FUTURESTRICT, "yield"),
DECIMAL (LITERAL, null),
+ HEXADECIMAL (LITERAL, null),
+ OCTAL_LEGACY (LITERAL, null),
OCTAL (LITERAL, null),
- HEXADECIMAL (LITERAL, null),
+ BINARY_NUMBER (LITERAL, null),
FLOATING (LITERAL, null),
STRING (LITERAL, null),
ESCSTRING (LITERAL, null),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/numeric-literals.js Tue Sep 01 16:11:09 2015 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8134873: ECMAScript 6 Numeric Literals
+ *
+ * @test
+ * @option --language=es6
+ */
+
+function assertEquals(expected, actual) {
+ if (expected !== actual) {
+ throw new Error("expected: " + expected + ", actual: " + actual);
+ }
+}
+
+assertEquals(0b0, 0);
+assertEquals(0B0, 0);
+assertEquals(0b01, 1);
+assertEquals(0B10, 2);
+assertEquals(0b11111111, 255);
+assertEquals(0b11111111111111111111111111111111, 4294967295);
+
+assertEquals(0o0, 0);
+assertEquals(0O0, 0);
+assertEquals(0o01, 1);
+assertEquals(0O10, 8);
+assertEquals(0o777, 511);
+