src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java
changeset 48054 702043a4cdeb
parent 47216 71c04702a3d5
child 49580 62b908c9f0e6
equal deleted inserted replaced
48053:6dcbdc9f99fc 48054:702043a4cdeb
    24  */
    24  */
    25 
    25 
    26 package com.sun.tools.javac.parser;
    26 package com.sun.tools.javac.parser;
    27 
    27 
    28 import com.sun.tools.javac.code.Source;
    28 import com.sun.tools.javac.code.Source;
       
    29 import com.sun.tools.javac.code.Source.Feature;
    29 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
    30 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
       
    31 import com.sun.tools.javac.resources.CompilerProperties.Errors;
    30 import com.sun.tools.javac.util.*;
    32 import com.sun.tools.javac.util.*;
       
    33 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
    31 
    34 
    32 import java.nio.CharBuffer;
    35 import java.nio.CharBuffer;
    33 
    36 
    34 import static com.sun.tools.javac.parser.Tokens.*;
    37 import static com.sun.tools.javac.parser.Tokens.*;
    35 import static com.sun.tools.javac.util.LayoutCharacters.*;
    38 import static com.sun.tools.javac.util.LayoutCharacters.*;
    44  */
    47  */
    45 public class JavaTokenizer {
    48 public class JavaTokenizer {
    46 
    49 
    47     private static final boolean scannerDebug = false;
    50     private static final boolean scannerDebug = false;
    48 
    51 
    49     /** Allow binary literals.
       
    50      */
       
    51     private boolean allowBinaryLiterals;
       
    52 
       
    53     /** Allow underscores in literals.
       
    54      */
       
    55     private boolean allowUnderscoresInLiterals;
       
    56 
       
    57     /** The source language setting.
    52     /** The source language setting.
    58      */
    53      */
    59     private Source source;
    54     private Source source;
    60 
    55 
    61     /** The log to be used for error reporting.
    56     /** The log to be used for error reporting.
   119         this.fac = fac;
   114         this.fac = fac;
   120         this.log = fac.log;
   115         this.log = fac.log;
   121         this.tokens = fac.tokens;
   116         this.tokens = fac.tokens;
   122         this.source = fac.source;
   117         this.source = fac.source;
   123         this.reader = reader;
   118         this.reader = reader;
   124         this.allowBinaryLiterals = source.allowBinaryLiterals();
   119     }
   125         this.allowUnderscoresInLiterals = source.allowUnderscoresInLiterals();
   120 
       
   121     private void checkSourceLevel(int pos, Feature feature) {
       
   122         if (!feature.allowedInSource(source)) {
       
   123             lexError(DiagnosticFlag.SOURCE_LEVEL, pos, feature.error(source.name));
       
   124         }
   126     }
   125     }
   127 
   126 
   128     /** Report an error at the given position using the provided arguments.
   127     /** Report an error at the given position using the provided arguments.
   129      */
   128      */
   130     protected void lexError(int pos, String key, Object... args) {
   129     protected void lexError(int pos, JCDiagnostic.Error key) {
   131         log.error(pos, key, args);
   130         log.error(pos, key);
       
   131         tk = TokenKind.ERROR;
       
   132         errPos = pos;
       
   133     }
       
   134 
       
   135     protected void lexError(DiagnosticFlag flags, int pos, JCDiagnostic.Error key) {
       
   136         log.error(flags, pos, key);
   132         tk = TokenKind.ERROR;
   137         tk = TokenKind.ERROR;
   133         errPos = pos;
   138         errPos = pos;
   134     }
   139     }
   135 
   140 
   136     /** Read next character in character or string literal and copy into sbuf.
   141     /** Read next character in character or string literal and copy into sbuf.
   173                 case '\"':
   178                 case '\"':
   174                     reader.putChar('\"', true); break;
   179                     reader.putChar('\"', true); break;
   175                 case '\\':
   180                 case '\\':
   176                     reader.putChar('\\', true); break;
   181                     reader.putChar('\\', true); break;
   177                 default:
   182                 default:
   178                     lexError(reader.bp, "illegal.esc.char");
   183                     lexError(reader.bp, Errors.IllegalEscChar);
   179                 }
   184                 }
   180             }
   185             }
   181         } else if (reader.bp != reader.buflen) {
   186         } else if (reader.bp != reader.buflen) {
   182             reader.putChar(true);
   187             reader.putChar(true);
   183         }
   188         }
   188         int savePos;
   193         int savePos;
   189         do {
   194         do {
   190             if (reader.ch != '_') {
   195             if (reader.ch != '_') {
   191                 reader.putChar(false);
   196                 reader.putChar(false);
   192             } else {
   197             } else {
   193                 if (!allowUnderscoresInLiterals) {
   198                 checkSourceLevel(pos, Feature.UNDERSCORES_IN_LITERALS);
   194                     lexError(pos, "unsupported.underscore.lit", source.name);
       
   195                     allowUnderscoresInLiterals = true;
       
   196                 }
       
   197             }
   199             }
   198             saveCh = reader.ch;
   200             saveCh = reader.ch;
   199             savePos = reader.bp;
   201             savePos = reader.bp;
   200             reader.scanChar();
   202             reader.scanChar();
   201         } while (reader.digit(pos, digitRadix) >= 0 || reader.ch == '_');
   203         } while (reader.digit(pos, digitRadix) >= 0 || reader.ch == '_');
   202         if (saveCh == '_')
   204         if (saveCh == '_')
   203             lexError(savePos, "illegal.underscore");
   205             lexError(savePos, Errors.IllegalUnderscore);
   204     }
   206     }
   205 
   207 
   206     /** Read fractional part of hexadecimal floating point number.
   208     /** Read fractional part of hexadecimal floating point number.
   207      */
   209      */
   208     private void scanHexExponentAndSuffix(int pos) {
   210     private void scanHexExponentAndSuffix(int pos) {
   214             }
   216             }
   215             skipIllegalUnderscores();
   217             skipIllegalUnderscores();
   216             if (reader.digit(pos, 10) >= 0) {
   218             if (reader.digit(pos, 10) >= 0) {
   217                 scanDigits(pos, 10);
   219                 scanDigits(pos, 10);
   218                 if (!hexFloatsWork)
   220                 if (!hexFloatsWork)
   219                     lexError(pos, "unsupported.cross.fp.lit");
   221                     lexError(pos, Errors.UnsupportedCrossFpLit);
   220             } else
   222             } else
   221                 lexError(pos, "malformed.fp.lit");
   223                 lexError(pos, Errors.MalformedFpLit);
   222         } else {
   224         } else {
   223             lexError(pos, "malformed.fp.lit");
   225             lexError(pos, Errors.MalformedFpLit);
   224         }
   226         }
   225         if (reader.ch == 'f' || reader.ch == 'F') {
   227         if (reader.ch == 'f' || reader.ch == 'F') {
   226             reader.putChar(true);
   228             reader.putChar(true);
   227             tk = TokenKind.FLOATLITERAL;
   229             tk = TokenKind.FLOATLITERAL;
   228             radix = 16;
   230             radix = 16;
   252             skipIllegalUnderscores();
   254             skipIllegalUnderscores();
   253             if (reader.digit(pos, 10) >= 0) {
   255             if (reader.digit(pos, 10) >= 0) {
   254                 scanDigits(pos, 10);
   256                 scanDigits(pos, 10);
   255                 return;
   257                 return;
   256             }
   258             }
   257             lexError(pos, "malformed.fp.lit");
   259             lexError(pos, Errors.MalformedFpLit);
   258             reader.sp = sp1;
   260             reader.sp = sp1;
   259         }
   261         }
   260     }
   262     }
   261 
   263 
   262     /** Read fractional part and 'd' or 'f' suffix of floating point number.
   264     /** Read fractional part and 'd' or 'f' suffix of floating point number.
   285         if (reader.digit(pos, 16) >= 0) {
   287         if (reader.digit(pos, 16) >= 0) {
   286             seendigit = true;
   288             seendigit = true;
   287             scanDigits(pos, 16);
   289             scanDigits(pos, 16);
   288         }
   290         }
   289         if (!seendigit)
   291         if (!seendigit)
   290             lexError(pos, "invalid.hex.number");
   292             lexError(pos, Errors.InvalidHexNumber);
   291         else
   293         else
   292             scanHexExponentAndSuffix(pos);
   294             scanHexExponentAndSuffix(pos);
   293     }
   295     }
   294 
   296 
   295     private void skipIllegalUnderscores() {
   297     private void skipIllegalUnderscores() {
   296         if (reader.ch == '_') {
   298         if (reader.ch == '_') {
   297             lexError(reader.bp, "illegal.underscore");
   299             lexError(reader.bp, Errors.IllegalUnderscore);
   298             while (reader.ch == '_')
   300             while (reader.ch == '_')
   299                 reader.scanChar();
   301                 reader.scanChar();
   300         }
   302         }
   301     }
   303     }
   302 
   304 
   327             scanFractionAndSuffix(pos);
   329             scanFractionAndSuffix(pos);
   328         } else {
   330         } else {
   329             if (!seenValidDigit) {
   331             if (!seenValidDigit) {
   330                 switch (radix) {
   332                 switch (radix) {
   331                 case 2:
   333                 case 2:
   332                     lexError(pos, "invalid.binary.number");
   334                     lexError(pos, Errors.InvalidBinaryNumber);
   333                     break;
   335                     break;
   334                 case 16:
   336                 case 16:
   335                     lexError(pos, "invalid.hex.number");
   337                     lexError(pos, Errors.InvalidHexNumber);
   336                     break;
   338                     break;
   337                 }
   339                 }
   338             }
   340             }
   339             if (reader.ch == 'l' || reader.ch == 'L') {
   341             if (reader.ch == 'l' || reader.ch == 'L') {
   340                 reader.scanChar();
   342                 reader.scanChar();
   502                     if (reader.ch == 'x' || reader.ch == 'X') {
   504                     if (reader.ch == 'x' || reader.ch == 'X') {
   503                         reader.scanChar();
   505                         reader.scanChar();
   504                         skipIllegalUnderscores();
   506                         skipIllegalUnderscores();
   505                         scanNumber(pos, 16);
   507                         scanNumber(pos, 16);
   506                     } else if (reader.ch == 'b' || reader.ch == 'B') {
   508                     } else if (reader.ch == 'b' || reader.ch == 'B') {
   507                         if (!allowBinaryLiterals) {
   509                         checkSourceLevel(pos, Feature.BINARY_LITERALS);
   508                             lexError(pos, "unsupported.binary.lit", source.name);
       
   509                             allowBinaryLiterals = true;
       
   510                         }
       
   511                         reader.scanChar();
   510                         reader.scanChar();
   512                         skipIllegalUnderscores();
   511                         skipIllegalUnderscores();
   513                         scanNumber(pos, 2);
   512                         scanNumber(pos, 2);
   514                     } else {
   513                     } else {
   515                         reader.putChar('0');
   514                         reader.putChar('0');
   517                             int savePos = reader.bp;
   516                             int savePos = reader.bp;
   518                             do {
   517                             do {
   519                                 reader.scanChar();
   518                                 reader.scanChar();
   520                             } while (reader.ch == '_');
   519                             } while (reader.ch == '_');
   521                             if (reader.digit(pos, 10) < 0) {
   520                             if (reader.digit(pos, 10) < 0) {
   522                                 lexError(savePos, "illegal.underscore");
   521                                 lexError(savePos, Errors.IllegalUnderscore);
   523                             }
   522                             }
   524                         }
   523                         }
   525                         scanNumber(pos, 8);
   524                         scanNumber(pos, 8);
   526                     }
   525                     }
   527                     break loop;
   526                     break loop;
   540                         if (reader.ch == '.') {
   539                         if (reader.ch == '.') {
   541                             reader.scanChar();
   540                             reader.scanChar();
   542                             reader.putChar('.');
   541                             reader.putChar('.');
   543                             tk = TokenKind.ELLIPSIS;
   542                             tk = TokenKind.ELLIPSIS;
   544                         } else {
   543                         } else {
   545                             lexError(savePos, "illegal.dot");
   544                             lexError(savePos, Errors.IllegalDot);
   546                         }
   545                         }
   547                     } else {
   546                     } else {
   548                         tk = TokenKind.DOT;
   547                         tk = TokenKind.DOT;
   549                     }
   548                     }
   550                     break loop;
   549                     break loop;
   598                         if (reader.ch == '/') {
   597                         if (reader.ch == '/') {
   599                             reader.scanChar();
   598                             reader.scanChar();
   600                             comments = addComment(comments, processComment(pos, reader.bp, style));
   599                             comments = addComment(comments, processComment(pos, reader.bp, style));
   601                             break;
   600                             break;
   602                         } else {
   601                         } else {
   603                             lexError(pos, "unclosed.comment");
   602                             lexError(pos, Errors.UnclosedComment);
   604                             break loop;
   603                             break loop;
   605                         }
   604                         }
   606                     } else if (reader.ch == '=') {
   605                     } else if (reader.ch == '=') {
   607                         tk = TokenKind.SLASHEQ;
   606                         tk = TokenKind.SLASHEQ;
   608                         reader.scanChar();
   607                         reader.scanChar();
   611                     }
   610                     }
   612                     break loop;
   611                     break loop;
   613                 case '\'':
   612                 case '\'':
   614                     reader.scanChar();
   613                     reader.scanChar();
   615                     if (reader.ch == '\'') {
   614                     if (reader.ch == '\'') {
   616                         lexError(pos, "empty.char.lit");
   615                         lexError(pos, Errors.EmptyCharLit);
   617                         reader.scanChar();
   616                         reader.scanChar();
   618                     } else {
   617                     } else {
   619                         if (reader.ch == CR || reader.ch == LF)
   618                         if (reader.ch == CR || reader.ch == LF)
   620                             lexError(pos, "illegal.line.end.in.char.lit");
   619                             lexError(pos, Errors.IllegalLineEndInCharLit);
   621                         scanLitChar(pos);
   620                         scanLitChar(pos);
   622                         if (reader.ch == '\'') {
   621                         if (reader.ch == '\'') {
   623                             reader.scanChar();
   622                             reader.scanChar();
   624                             tk = TokenKind.CHARLITERAL;
   623                             tk = TokenKind.CHARLITERAL;
   625                         } else {
   624                         } else {
   626                             lexError(pos, "unclosed.char.lit");
   625                             lexError(pos, Errors.UnclosedCharLit);
   627                         }
   626                         }
   628                     }
   627                     }
   629                     break loop;
   628                     break loop;
   630                 case '\"':
   629                 case '\"':
   631                     reader.scanChar();
   630                     reader.scanChar();
   633                         scanLitChar(pos);
   632                         scanLitChar(pos);
   634                     if (reader.ch == '\"') {
   633                     if (reader.ch == '\"') {
   635                         tk = TokenKind.STRINGLITERAL;
   634                         tk = TokenKind.STRINGLITERAL;
   636                         reader.scanChar();
   635                         reader.scanChar();
   637                     } else {
   636                     } else {
   638                         lexError(pos, "unclosed.str.lit");
   637                         lexError(pos, Errors.UnclosedStrLit);
   639                     }
   638                     }
   640                     break loop;
   639                     break loop;
   641                 default:
   640                 default:
   642                     if (isSpecial(reader.ch)) {
   641                     if (isSpecial(reader.ch)) {
   643                         scanOperator();
   642                         scanOperator();
   674                             } else {
   673                             } else {
   675                                 arg = (32 < reader.ch && reader.ch < 127) ?
   674                                 arg = (32 < reader.ch && reader.ch < 127) ?
   676                                                 String.format("%s", reader.ch) :
   675                                                 String.format("%s", reader.ch) :
   677                                                 String.format("\\u%04x", (int)reader.ch);
   676                                                 String.format("\\u%04x", (int)reader.ch);
   678                             }
   677                             }
   679                             lexError(pos, "illegal.char", arg);
   678                             lexError(pos, Errors.IllegalChar(arg));
   680                             reader.scanChar();
   679                             reader.scanChar();
   681                         }
   680                         }
   682                     }
   681                     }
   683                     break loop;
   682                     break loop;
   684                 }
   683                 }