langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java
changeset 3895 3b3c2a1e5e8a
parent 2723 b659ca23d5f5
child 4072 70eaf9773f81
--- 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;