--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Tue Sep 15 12:20:55 2009 -0700
+++ b/langtools/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;