diff -r 9dd34ed62341 -r 69eaccd3ea85 src/share/classes/com/sun/tools/javac/parser/Scanner.java --- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java Tue Sep 15 12:20:55 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java Tue Sep 15 18:36:21 2009 -0700 @@ -100,6 +100,18 @@ */ private boolean allowHexFloats; + /** Allow binary literals. + */ + private boolean allowBinaryLiterals; + + /** Allow underscores in literals. + */ + private boolean allowUnderscoresInLiterals; + + /** The source language setting. + */ + private Source source; + /** The token's position, 0-based offset from beginning of text. */ private int pos; @@ -162,10 +174,13 @@ /** Common code for constructors. */ private Scanner(Factory fac) { - this.log = fac.log; - this.names = fac.names; - this.keywords = fac.keywords; - this.allowHexFloats = fac.source.allowHexFloats(); + log = fac.log; + names = fac.names; + keywords = fac.keywords; + source = fac.source; + allowBinaryLiterals = source.allowBinaryLiterals(); + allowHexFloats = source.allowHexFloats(); + allowUnderscoresInLiterals = source.allowBinaryLiterals(); } private static final boolean hexFloatsWork = hexFloatsWork(); @@ -396,23 +411,42 @@ scanLitChar(true); } + private void scanDigits(int digitRadix) { + char saveCh; + int savePos; + do { + if (ch != '_') { + putChar(ch); + } else { + if (!allowUnderscoresInLiterals) { + lexError("unsupported.underscore", source.name); + allowUnderscoresInLiterals = true; + } + } + saveCh = ch; + savePos = bp; + scanChar(); + } while (digit(digitRadix) >= 0 || ch == '_'); + if (saveCh == '_') + lexError(savePos, "illegal.underscore"); + } + /** Read fractional part of hexadecimal floating point number. */ private void scanHexExponentAndSuffix() { if (ch == 'p' || ch == 'P') { putChar(ch); scanChar(); + skipIllegalUnderscores(); if (ch == '+' || ch == '-') { putChar(ch); scanChar(); } + skipIllegalUnderscores(); if ('0' <= ch && ch <= '9') { - do { - putChar(ch); - scanChar(); - } while ('0' <= ch && ch <= '9'); + scanDigits(10); if (!allowHexFloats) { - lexError("unsupported.fp.lit"); + lexError("unsupported.fp.lit", source.name); allowHexFloats = true; } else if (!hexFloatsWork) @@ -438,23 +472,22 @@ /** Read fractional part of floating point number. */ private void scanFraction() { - while (digit(10) >= 0) { - putChar(ch); - scanChar(); + skipIllegalUnderscores(); + if ('0' <= ch && ch <= '9') { + scanDigits(10); } int sp1 = sp; if (ch == 'e' || ch == 'E') { putChar(ch); scanChar(); + skipIllegalUnderscores(); if (ch == '+' || ch == '-') { putChar(ch); scanChar(); } + skipIllegalUnderscores(); if ('0' <= ch && ch <= '9') { - do { - putChar(ch); - scanChar(); - } while ('0' <= ch && ch <= '9'); + scanDigits(10); return; } lexError("malformed.fp.lit"); @@ -487,10 +520,10 @@ assert ch == '.'; putChar(ch); scanChar(); - while (digit(16) >= 0) { + skipIllegalUnderscores(); + if (digit(16) >= 0) { seendigit = true; - putChar(ch); - scanChar(); + scanDigits(16); } if (!seendigit) lexError("invalid.hex.number"); @@ -498,28 +531,35 @@ scanHexExponentAndSuffix(); } + private void skipIllegalUnderscores() { + if (ch == '_') { + lexError(bp, "illegal.underscore"); + while (ch == '_') + scanChar(); + } + } + /** Read a number. - * @param radix The radix of the number; one of 8, 10, 16. + * @param radix The radix of the number; one of 2, j8, 10, 16. */ private void scanNumber(int radix) { this.radix = radix; // for octal, allow base-10 digit in case it's a float literal - int digitRadix = (radix <= 10) ? 10 : 16; + int digitRadix = (radix == 8 ? 10 : radix); boolean seendigit = false; - while (digit(digitRadix) >= 0) { + if (digit(digitRadix) >= 0) { seendigit = true; - putChar(ch); - scanChar(); + scanDigits(digitRadix); } if (radix == 16 && ch == '.') { scanHexFractionAndSuffix(seendigit); } else if (seendigit && radix == 16 && (ch == 'p' || ch == 'P')) { scanHexExponentAndSuffix(); - } else if (radix <= 10 && ch == '.') { + } else if (digitRadix == 10 && ch == '.') { putChar(ch); scanChar(); scanFractionAndSuffix(); - } else if (radix <= 10 && + } else if (digitRadix == 10 && (ch == 'e' || ch == 'E' || ch == 'f' || ch == 'F' || ch == 'd' || ch == 'D')) { @@ -821,6 +861,7 @@ scanChar(); if (ch == 'x' || ch == 'X') { scanChar(); + skipIllegalUnderscores(); if (ch == '.') { scanHexFractionAndSuffix(false); } else if (digit(16) < 0) { @@ -828,8 +869,25 @@ } else { scanNumber(16); } + } else if (ch == 'b' || ch == 'B') { + if (!allowBinaryLiterals) { + lexError("unsupported.binary.lit", source.name); + allowBinaryLiterals = true; + } + scanChar(); + skipIllegalUnderscores(); + scanNumber(2); } else { putChar('0'); + if (ch == '_') { + int savePos = bp; + do { + scanChar(); + } while (ch == '_'); + if (digit(10) < 0) { + lexError(savePos, "illegal.underscore"); + } + } scanNumber(8); } return;