Tue, 15 Oct 2013 22:15:35 +0200
8026510: The name of com.sun.tools.javac.comp.Annotate.Annotator is confusing
Summary: A mostly automated rename Annotate.Annotator->Annotate.Worker and enterAnnotation->run.
Reviewed-by: emc, jjg
mcimadamore@1113 | 1 | /* |
jjg@1679 | 2 | * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
mcimadamore@1113 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
mcimadamore@1113 | 4 | * |
mcimadamore@1113 | 5 | * This code is free software; you can redistribute it and/or modify it |
mcimadamore@1113 | 6 | * under the terms of the GNU General Public License version 2 only, as |
mcimadamore@1113 | 7 | * published by the Free Software Foundation. Oracle designates this |
mcimadamore@1113 | 8 | * particular file as subject to the "Classpath" exception as provided |
mcimadamore@1113 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
mcimadamore@1113 | 10 | * |
mcimadamore@1113 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
mcimadamore@1113 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
mcimadamore@1113 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
mcimadamore@1113 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
mcimadamore@1113 | 15 | * accompanied this code). |
mcimadamore@1113 | 16 | * |
mcimadamore@1113 | 17 | * You should have received a copy of the GNU General Public License version |
mcimadamore@1113 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
mcimadamore@1113 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
mcimadamore@1113 | 20 | * |
mcimadamore@1113 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
mcimadamore@1113 | 22 | * or visit www.oracle.com if you need additional information or have any |
mcimadamore@1113 | 23 | * questions. |
mcimadamore@1113 | 24 | */ |
mcimadamore@1113 | 25 | |
mcimadamore@1113 | 26 | package com.sun.tools.javac.parser; |
mcimadamore@1113 | 27 | |
mcimadamore@1113 | 28 | import com.sun.tools.javac.code.Source; |
mcimadamore@1125 | 29 | import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; |
mcimadamore@1113 | 30 | import com.sun.tools.javac.util.*; |
mcimadamore@1113 | 31 | |
mcimadamore@1125 | 32 | import java.nio.CharBuffer; |
mcimadamore@1113 | 33 | |
mcimadamore@1113 | 34 | import static com.sun.tools.javac.parser.Tokens.*; |
mcimadamore@1113 | 35 | import static com.sun.tools.javac.util.LayoutCharacters.*; |
mcimadamore@1113 | 36 | |
mcimadamore@1113 | 37 | /** The lexical analyzer maps an input stream consisting of |
mcimadamore@1113 | 38 | * ASCII characters and Unicode escapes into a token sequence. |
mcimadamore@1113 | 39 | * |
mcimadamore@1113 | 40 | * <p><b>This is NOT part of any supported API. |
mcimadamore@1113 | 41 | * If you write code that depends on this, you do so at your own risk. |
mcimadamore@1113 | 42 | * This code and its internal interfaces are subject to change or |
mcimadamore@1113 | 43 | * deletion without notice.</b> |
mcimadamore@1113 | 44 | */ |
mcimadamore@1113 | 45 | public class JavaTokenizer { |
mcimadamore@1113 | 46 | |
vromero@1442 | 47 | private static final boolean scannerDebug = false; |
mcimadamore@1113 | 48 | |
mcimadamore@1113 | 49 | /** Allow hex floating-point literals. |
mcimadamore@1113 | 50 | */ |
mcimadamore@1113 | 51 | private boolean allowHexFloats; |
mcimadamore@1113 | 52 | |
mcimadamore@1113 | 53 | /** Allow binary literals. |
mcimadamore@1113 | 54 | */ |
mcimadamore@1113 | 55 | private boolean allowBinaryLiterals; |
mcimadamore@1113 | 56 | |
mcimadamore@1113 | 57 | /** Allow underscores in literals. |
mcimadamore@1113 | 58 | */ |
mcimadamore@1113 | 59 | private boolean allowUnderscoresInLiterals; |
mcimadamore@1113 | 60 | |
mcimadamore@1113 | 61 | /** The source language setting. |
mcimadamore@1113 | 62 | */ |
mcimadamore@1113 | 63 | private Source source; |
mcimadamore@1113 | 64 | |
mcimadamore@1113 | 65 | /** The log to be used for error reporting. |
mcimadamore@1113 | 66 | */ |
mcimadamore@1113 | 67 | private final Log log; |
mcimadamore@1113 | 68 | |
mcimadamore@1113 | 69 | /** The token factory. */ |
mcimadamore@1113 | 70 | private final Tokens tokens; |
mcimadamore@1113 | 71 | |
mcimadamore@1113 | 72 | /** The token kind, set by nextToken(). |
mcimadamore@1113 | 73 | */ |
mcimadamore@1113 | 74 | protected TokenKind tk; |
mcimadamore@1113 | 75 | |
mcimadamore@1113 | 76 | /** The token's radix, set by nextToken(). |
mcimadamore@1113 | 77 | */ |
mcimadamore@1113 | 78 | protected int radix; |
mcimadamore@1113 | 79 | |
mcimadamore@1113 | 80 | /** The token's name, set by nextToken(). |
mcimadamore@1113 | 81 | */ |
mcimadamore@1113 | 82 | protected Name name; |
mcimadamore@1113 | 83 | |
mcimadamore@1113 | 84 | /** The position where a lexical error occurred; |
mcimadamore@1113 | 85 | */ |
mcimadamore@1113 | 86 | protected int errPos = Position.NOPOS; |
mcimadamore@1113 | 87 | |
mcimadamore@1125 | 88 | /** The Unicode reader (low-level stream reader). |
mcimadamore@1113 | 89 | */ |
mcimadamore@1125 | 90 | protected UnicodeReader reader; |
mcimadamore@1113 | 91 | |
mcimadamore@1125 | 92 | protected ScannerFactory fac; |
mcimadamore@1113 | 93 | |
mcimadamore@1113 | 94 | private static final boolean hexFloatsWork = hexFloatsWork(); |
mcimadamore@1113 | 95 | private static boolean hexFloatsWork() { |
mcimadamore@1113 | 96 | try { |
mcimadamore@1113 | 97 | Float.valueOf("0x1.0p1"); |
mcimadamore@1113 | 98 | return true; |
mcimadamore@1113 | 99 | } catch (NumberFormatException ex) { |
mcimadamore@1113 | 100 | return false; |
mcimadamore@1113 | 101 | } |
mcimadamore@1113 | 102 | } |
mcimadamore@1113 | 103 | |
mcimadamore@1113 | 104 | /** |
mcimadamore@1113 | 105 | * Create a scanner from the input array. This method might |
mcimadamore@1113 | 106 | * modify the array. To avoid copying the input array, ensure |
mcimadamore@1113 | 107 | * that {@code inputLength < input.length} or |
mcimadamore@1113 | 108 | * {@code input[input.length -1]} is a white space character. |
mcimadamore@1113 | 109 | * |
mcimadamore@1113 | 110 | * @param fac the factory which created this Scanner |
jjg@1358 | 111 | * @param buf the input, might be modified |
mcimadamore@1113 | 112 | * Must be positive and less than or equal to input.length. |
mcimadamore@1113 | 113 | */ |
mcimadamore@1113 | 114 | protected JavaTokenizer(ScannerFactory fac, CharBuffer buf) { |
mcimadamore@1113 | 115 | this(fac, new UnicodeReader(fac, buf)); |
mcimadamore@1113 | 116 | } |
mcimadamore@1113 | 117 | |
mcimadamore@1113 | 118 | protected JavaTokenizer(ScannerFactory fac, char[] buf, int inputLength) { |
mcimadamore@1113 | 119 | this(fac, new UnicodeReader(fac, buf, inputLength)); |
mcimadamore@1113 | 120 | } |
mcimadamore@1113 | 121 | |
mcimadamore@1113 | 122 | protected JavaTokenizer(ScannerFactory fac, UnicodeReader reader) { |
mcimadamore@1125 | 123 | this.fac = fac; |
mcimadamore@1125 | 124 | this.log = fac.log; |
mcimadamore@1125 | 125 | this.tokens = fac.tokens; |
mcimadamore@1125 | 126 | this.source = fac.source; |
mcimadamore@1113 | 127 | this.reader = reader; |
mcimadamore@1125 | 128 | this.allowBinaryLiterals = source.allowBinaryLiterals(); |
mcimadamore@1125 | 129 | this.allowHexFloats = source.allowHexFloats(); |
mcimadamore@1125 | 130 | this.allowUnderscoresInLiterals = source.allowUnderscoresInLiterals(); |
mcimadamore@1113 | 131 | } |
mcimadamore@1113 | 132 | |
mcimadamore@1113 | 133 | /** Report an error at the given position using the provided arguments. |
mcimadamore@1113 | 134 | */ |
mcimadamore@1113 | 135 | protected void lexError(int pos, String key, Object... args) { |
mcimadamore@1113 | 136 | log.error(pos, key, args); |
mcimadamore@1113 | 137 | tk = TokenKind.ERROR; |
mcimadamore@1113 | 138 | errPos = pos; |
mcimadamore@1113 | 139 | } |
mcimadamore@1113 | 140 | |
mcimadamore@1113 | 141 | /** Read next character in character or string literal and copy into sbuf. |
mcimadamore@1113 | 142 | */ |
mcimadamore@1113 | 143 | private void scanLitChar(int pos) { |
mcimadamore@1113 | 144 | if (reader.ch == '\\') { |
mcimadamore@1113 | 145 | if (reader.peekChar() == '\\' && !reader.isUnicode()) { |
mcimadamore@1113 | 146 | reader.skipChar(); |
mcimadamore@1125 | 147 | reader.putChar('\\', true); |
mcimadamore@1113 | 148 | } else { |
mcimadamore@1113 | 149 | reader.scanChar(); |
mcimadamore@1113 | 150 | switch (reader.ch) { |
mcimadamore@1113 | 151 | case '0': case '1': case '2': case '3': |
mcimadamore@1113 | 152 | case '4': case '5': case '6': case '7': |
mcimadamore@1113 | 153 | char leadch = reader.ch; |
mcimadamore@1113 | 154 | int oct = reader.digit(pos, 8); |
mcimadamore@1113 | 155 | reader.scanChar(); |
mcimadamore@1113 | 156 | if ('0' <= reader.ch && reader.ch <= '7') { |
mcimadamore@1113 | 157 | oct = oct * 8 + reader.digit(pos, 8); |
mcimadamore@1113 | 158 | reader.scanChar(); |
mcimadamore@1113 | 159 | if (leadch <= '3' && '0' <= reader.ch && reader.ch <= '7') { |
mcimadamore@1113 | 160 | oct = oct * 8 + reader.digit(pos, 8); |
mcimadamore@1113 | 161 | reader.scanChar(); |
mcimadamore@1113 | 162 | } |
mcimadamore@1113 | 163 | } |
mcimadamore@1125 | 164 | reader.putChar((char)oct); |
mcimadamore@1113 | 165 | break; |
mcimadamore@1113 | 166 | case 'b': |
mcimadamore@1125 | 167 | reader.putChar('\b', true); break; |
mcimadamore@1113 | 168 | case 't': |
mcimadamore@1125 | 169 | reader.putChar('\t', true); break; |
mcimadamore@1113 | 170 | case 'n': |
mcimadamore@1125 | 171 | reader.putChar('\n', true); break; |
mcimadamore@1113 | 172 | case 'f': |
mcimadamore@1125 | 173 | reader.putChar('\f', true); break; |
mcimadamore@1113 | 174 | case 'r': |
mcimadamore@1125 | 175 | reader.putChar('\r', true); break; |
mcimadamore@1113 | 176 | case '\'': |
mcimadamore@1125 | 177 | reader.putChar('\'', true); break; |
mcimadamore@1113 | 178 | case '\"': |
mcimadamore@1125 | 179 | reader.putChar('\"', true); break; |
mcimadamore@1113 | 180 | case '\\': |
mcimadamore@1125 | 181 | reader.putChar('\\', true); break; |
mcimadamore@1113 | 182 | default: |
mcimadamore@1113 | 183 | lexError(reader.bp, "illegal.esc.char"); |
mcimadamore@1113 | 184 | } |
mcimadamore@1113 | 185 | } |
mcimadamore@1113 | 186 | } else if (reader.bp != reader.buflen) { |
mcimadamore@1125 | 187 | reader.putChar(true); |
mcimadamore@1113 | 188 | } |
mcimadamore@1113 | 189 | } |
mcimadamore@1113 | 190 | |
mcimadamore@1113 | 191 | private void scanDigits(int pos, int digitRadix) { |
mcimadamore@1113 | 192 | char saveCh; |
mcimadamore@1113 | 193 | int savePos; |
mcimadamore@1113 | 194 | do { |
mcimadamore@1113 | 195 | if (reader.ch != '_') { |
mcimadamore@1125 | 196 | reader.putChar(false); |
mcimadamore@1113 | 197 | } else { |
mcimadamore@1113 | 198 | if (!allowUnderscoresInLiterals) { |
mcimadamore@1113 | 199 | lexError(pos, "unsupported.underscore.lit", source.name); |
mcimadamore@1113 | 200 | allowUnderscoresInLiterals = true; |
mcimadamore@1113 | 201 | } |
mcimadamore@1113 | 202 | } |
mcimadamore@1113 | 203 | saveCh = reader.ch; |
mcimadamore@1113 | 204 | savePos = reader.bp; |
mcimadamore@1113 | 205 | reader.scanChar(); |
mcimadamore@1113 | 206 | } while (reader.digit(pos, digitRadix) >= 0 || reader.ch == '_'); |
mcimadamore@1113 | 207 | if (saveCh == '_') |
mcimadamore@1113 | 208 | lexError(savePos, "illegal.underscore"); |
mcimadamore@1113 | 209 | } |
mcimadamore@1113 | 210 | |
mcimadamore@1113 | 211 | /** Read fractional part of hexadecimal floating point number. |
mcimadamore@1113 | 212 | */ |
mcimadamore@1113 | 213 | private void scanHexExponentAndSuffix(int pos) { |
mcimadamore@1113 | 214 | if (reader.ch == 'p' || reader.ch == 'P') { |
mcimadamore@1125 | 215 | reader.putChar(true); |
mcimadamore@1113 | 216 | skipIllegalUnderscores(); |
mcimadamore@1113 | 217 | if (reader.ch == '+' || reader.ch == '-') { |
mcimadamore@1125 | 218 | reader.putChar(true); |
mcimadamore@1113 | 219 | } |
mcimadamore@1113 | 220 | skipIllegalUnderscores(); |
mcimadamore@1113 | 221 | if ('0' <= reader.ch && reader.ch <= '9') { |
mcimadamore@1113 | 222 | scanDigits(pos, 10); |
mcimadamore@1113 | 223 | if (!allowHexFloats) { |
mcimadamore@1113 | 224 | lexError(pos, "unsupported.fp.lit", source.name); |
mcimadamore@1113 | 225 | allowHexFloats = true; |
mcimadamore@1113 | 226 | } |
mcimadamore@1113 | 227 | else if (!hexFloatsWork) |
mcimadamore@1113 | 228 | lexError(pos, "unsupported.cross.fp.lit"); |
mcimadamore@1113 | 229 | } else |
mcimadamore@1113 | 230 | lexError(pos, "malformed.fp.lit"); |
mcimadamore@1113 | 231 | } else { |
mcimadamore@1113 | 232 | lexError(pos, "malformed.fp.lit"); |
mcimadamore@1113 | 233 | } |
mcimadamore@1113 | 234 | if (reader.ch == 'f' || reader.ch == 'F') { |
mcimadamore@1125 | 235 | reader.putChar(true); |
mcimadamore@1113 | 236 | tk = TokenKind.FLOATLITERAL; |
mcimadamore@1113 | 237 | radix = 16; |
mcimadamore@1113 | 238 | } else { |
mcimadamore@1113 | 239 | if (reader.ch == 'd' || reader.ch == 'D') { |
mcimadamore@1125 | 240 | reader.putChar(true); |
mcimadamore@1113 | 241 | } |
mcimadamore@1113 | 242 | tk = TokenKind.DOUBLELITERAL; |
mcimadamore@1113 | 243 | radix = 16; |
mcimadamore@1113 | 244 | } |
mcimadamore@1113 | 245 | } |
mcimadamore@1113 | 246 | |
mcimadamore@1113 | 247 | /** Read fractional part of floating point number. |
mcimadamore@1113 | 248 | */ |
mcimadamore@1113 | 249 | private void scanFraction(int pos) { |
mcimadamore@1113 | 250 | skipIllegalUnderscores(); |
mcimadamore@1113 | 251 | if ('0' <= reader.ch && reader.ch <= '9') { |
mcimadamore@1113 | 252 | scanDigits(pos, 10); |
mcimadamore@1113 | 253 | } |
mcimadamore@1125 | 254 | int sp1 = reader.sp; |
mcimadamore@1113 | 255 | if (reader.ch == 'e' || reader.ch == 'E') { |
mcimadamore@1125 | 256 | reader.putChar(true); |
mcimadamore@1113 | 257 | skipIllegalUnderscores(); |
mcimadamore@1113 | 258 | if (reader.ch == '+' || reader.ch == '-') { |
mcimadamore@1125 | 259 | reader.putChar(true); |
mcimadamore@1113 | 260 | } |
mcimadamore@1113 | 261 | skipIllegalUnderscores(); |
mcimadamore@1113 | 262 | if ('0' <= reader.ch && reader.ch <= '9') { |
mcimadamore@1113 | 263 | scanDigits(pos, 10); |
mcimadamore@1113 | 264 | return; |
mcimadamore@1113 | 265 | } |
mcimadamore@1113 | 266 | lexError(pos, "malformed.fp.lit"); |
mcimadamore@1125 | 267 | reader.sp = sp1; |
mcimadamore@1113 | 268 | } |
mcimadamore@1113 | 269 | } |
mcimadamore@1113 | 270 | |
mcimadamore@1113 | 271 | /** Read fractional part and 'd' or 'f' suffix of floating point number. |
mcimadamore@1113 | 272 | */ |
mcimadamore@1113 | 273 | private void scanFractionAndSuffix(int pos) { |
mcimadamore@1113 | 274 | radix = 10; |
mcimadamore@1113 | 275 | scanFraction(pos); |
mcimadamore@1113 | 276 | if (reader.ch == 'f' || reader.ch == 'F') { |
mcimadamore@1125 | 277 | reader.putChar(true); |
mcimadamore@1113 | 278 | tk = TokenKind.FLOATLITERAL; |
mcimadamore@1113 | 279 | } else { |
mcimadamore@1113 | 280 | if (reader.ch == 'd' || reader.ch == 'D') { |
mcimadamore@1125 | 281 | reader.putChar(true); |
mcimadamore@1113 | 282 | } |
mcimadamore@1113 | 283 | tk = TokenKind.DOUBLELITERAL; |
mcimadamore@1113 | 284 | } |
mcimadamore@1113 | 285 | } |
mcimadamore@1113 | 286 | |
mcimadamore@1113 | 287 | /** Read fractional part and 'd' or 'f' suffix of floating point number. |
mcimadamore@1113 | 288 | */ |
mcimadamore@1113 | 289 | private void scanHexFractionAndSuffix(int pos, boolean seendigit) { |
mcimadamore@1113 | 290 | radix = 16; |
mcimadamore@1113 | 291 | Assert.check(reader.ch == '.'); |
mcimadamore@1125 | 292 | reader.putChar(true); |
mcimadamore@1113 | 293 | skipIllegalUnderscores(); |
mcimadamore@1113 | 294 | if (reader.digit(pos, 16) >= 0) { |
mcimadamore@1113 | 295 | seendigit = true; |
mcimadamore@1113 | 296 | scanDigits(pos, 16); |
mcimadamore@1113 | 297 | } |
mcimadamore@1113 | 298 | if (!seendigit) |
mcimadamore@1113 | 299 | lexError(pos, "invalid.hex.number"); |
mcimadamore@1113 | 300 | else |
mcimadamore@1113 | 301 | scanHexExponentAndSuffix(pos); |
mcimadamore@1113 | 302 | } |
mcimadamore@1113 | 303 | |
mcimadamore@1113 | 304 | private void skipIllegalUnderscores() { |
mcimadamore@1113 | 305 | if (reader.ch == '_') { |
mcimadamore@1113 | 306 | lexError(reader.bp, "illegal.underscore"); |
mcimadamore@1113 | 307 | while (reader.ch == '_') |
mcimadamore@1113 | 308 | reader.scanChar(); |
mcimadamore@1113 | 309 | } |
mcimadamore@1113 | 310 | } |
mcimadamore@1113 | 311 | |
mcimadamore@1113 | 312 | /** Read a number. |
mcimadamore@1113 | 313 | * @param radix The radix of the number; one of 2, j8, 10, 16. |
mcimadamore@1113 | 314 | */ |
mcimadamore@1113 | 315 | private void scanNumber(int pos, int radix) { |
mcimadamore@1113 | 316 | // for octal, allow base-10 digit in case it's a float literal |
mcimadamore@1113 | 317 | this.radix = radix; |
mcimadamore@1113 | 318 | int digitRadix = (radix == 8 ? 10 : radix); |
mcimadamore@1113 | 319 | boolean seendigit = false; |
mcimadamore@1113 | 320 | if (reader.digit(pos, digitRadix) >= 0) { |
mcimadamore@1113 | 321 | seendigit = true; |
mcimadamore@1113 | 322 | scanDigits(pos, digitRadix); |
mcimadamore@1113 | 323 | } |
mcimadamore@1113 | 324 | if (radix == 16 && reader.ch == '.') { |
mcimadamore@1113 | 325 | scanHexFractionAndSuffix(pos, seendigit); |
mcimadamore@1113 | 326 | } else if (seendigit && radix == 16 && (reader.ch == 'p' || reader.ch == 'P')) { |
mcimadamore@1113 | 327 | scanHexExponentAndSuffix(pos); |
mcimadamore@1113 | 328 | } else if (digitRadix == 10 && reader.ch == '.') { |
mcimadamore@1125 | 329 | reader.putChar(true); |
mcimadamore@1113 | 330 | scanFractionAndSuffix(pos); |
mcimadamore@1113 | 331 | } else if (digitRadix == 10 && |
mcimadamore@1113 | 332 | (reader.ch == 'e' || reader.ch == 'E' || |
mcimadamore@1113 | 333 | reader.ch == 'f' || reader.ch == 'F' || |
mcimadamore@1113 | 334 | reader.ch == 'd' || reader.ch == 'D')) { |
mcimadamore@1113 | 335 | scanFractionAndSuffix(pos); |
mcimadamore@1113 | 336 | } else { |
mcimadamore@1113 | 337 | if (reader.ch == 'l' || reader.ch == 'L') { |
mcimadamore@1113 | 338 | reader.scanChar(); |
mcimadamore@1113 | 339 | tk = TokenKind.LONGLITERAL; |
mcimadamore@1113 | 340 | } else { |
mcimadamore@1113 | 341 | tk = TokenKind.INTLITERAL; |
mcimadamore@1113 | 342 | } |
mcimadamore@1113 | 343 | } |
mcimadamore@1113 | 344 | } |
mcimadamore@1113 | 345 | |
mcimadamore@1113 | 346 | /** Read an identifier. |
mcimadamore@1113 | 347 | */ |
mcimadamore@1113 | 348 | private void scanIdent() { |
mcimadamore@1113 | 349 | boolean isJavaIdentifierPart; |
mcimadamore@1113 | 350 | char high; |
vromero@1431 | 351 | reader.putChar(true); |
mcimadamore@1113 | 352 | do { |
mcimadamore@1113 | 353 | switch (reader.ch) { |
mcimadamore@1113 | 354 | case 'A': case 'B': case 'C': case 'D': case 'E': |
mcimadamore@1113 | 355 | case 'F': case 'G': case 'H': case 'I': case 'J': |
mcimadamore@1113 | 356 | case 'K': case 'L': case 'M': case 'N': case 'O': |
mcimadamore@1113 | 357 | case 'P': case 'Q': case 'R': case 'S': case 'T': |
mcimadamore@1113 | 358 | case 'U': case 'V': case 'W': case 'X': case 'Y': |
mcimadamore@1113 | 359 | case 'Z': |
mcimadamore@1113 | 360 | case 'a': case 'b': case 'c': case 'd': case 'e': |
mcimadamore@1113 | 361 | case 'f': case 'g': case 'h': case 'i': case 'j': |
mcimadamore@1113 | 362 | case 'k': case 'l': case 'm': case 'n': case 'o': |
mcimadamore@1113 | 363 | case 'p': case 'q': case 'r': case 's': case 't': |
mcimadamore@1113 | 364 | case 'u': case 'v': case 'w': case 'x': case 'y': |
mcimadamore@1113 | 365 | case 'z': |
mcimadamore@1113 | 366 | case '$': case '_': |
mcimadamore@1113 | 367 | case '0': case '1': case '2': case '3': case '4': |
mcimadamore@1113 | 368 | case '5': case '6': case '7': case '8': case '9': |
vromero@1431 | 369 | break; |
mcimadamore@1113 | 370 | case '\u0000': case '\u0001': case '\u0002': case '\u0003': |
mcimadamore@1113 | 371 | case '\u0004': case '\u0005': case '\u0006': case '\u0007': |
mcimadamore@1113 | 372 | case '\u0008': case '\u000E': case '\u000F': case '\u0010': |
mcimadamore@1113 | 373 | case '\u0011': case '\u0012': case '\u0013': case '\u0014': |
mcimadamore@1113 | 374 | case '\u0015': case '\u0016': case '\u0017': |
mcimadamore@1113 | 375 | case '\u0018': case '\u0019': case '\u001B': |
mcimadamore@1113 | 376 | case '\u007F': |
vromero@1431 | 377 | reader.scanChar(); |
vromero@1431 | 378 | continue; |
mcimadamore@1113 | 379 | case '\u001A': // EOI is also a legal identifier part |
mcimadamore@1113 | 380 | if (reader.bp >= reader.buflen) { |
mcimadamore@1125 | 381 | name = reader.name(); |
mcimadamore@1113 | 382 | tk = tokens.lookupKind(name); |
mcimadamore@1113 | 383 | return; |
mcimadamore@1113 | 384 | } |
vromero@1431 | 385 | reader.scanChar(); |
vromero@1431 | 386 | continue; |
mcimadamore@1113 | 387 | default: |
mcimadamore@1113 | 388 | if (reader.ch < '\u0080') { |
mcimadamore@1113 | 389 | // all ASCII range chars already handled, above |
mcimadamore@1113 | 390 | isJavaIdentifierPart = false; |
mcimadamore@1113 | 391 | } else { |
vromero@1431 | 392 | if (Character.isIdentifierIgnorable(reader.ch)) { |
vromero@1431 | 393 | reader.scanChar(); |
vromero@1431 | 394 | continue; |
mcimadamore@1113 | 395 | } else { |
vromero@1431 | 396 | high = reader.scanSurrogates(); |
vromero@1431 | 397 | if (high != 0) { |
vromero@1431 | 398 | reader.putChar(high); |
vromero@1431 | 399 | isJavaIdentifierPart = Character.isJavaIdentifierPart( |
vromero@1431 | 400 | Character.toCodePoint(high, reader.ch)); |
vromero@1431 | 401 | } else { |
vromero@1431 | 402 | isJavaIdentifierPart = Character.isJavaIdentifierPart(reader.ch); |
vromero@1431 | 403 | } |
mcimadamore@1113 | 404 | } |
mcimadamore@1113 | 405 | } |
mcimadamore@1113 | 406 | if (!isJavaIdentifierPart) { |
mcimadamore@1125 | 407 | name = reader.name(); |
mcimadamore@1113 | 408 | tk = tokens.lookupKind(name); |
mcimadamore@1113 | 409 | return; |
mcimadamore@1113 | 410 | } |
mcimadamore@1113 | 411 | } |
vromero@1431 | 412 | reader.putChar(true); |
mcimadamore@1113 | 413 | } while (true); |
mcimadamore@1113 | 414 | } |
mcimadamore@1113 | 415 | |
mcimadamore@1113 | 416 | /** Return true if reader.ch can be part of an operator. |
mcimadamore@1113 | 417 | */ |
mcimadamore@1113 | 418 | private boolean isSpecial(char ch) { |
mcimadamore@1113 | 419 | switch (ch) { |
mcimadamore@1113 | 420 | case '!': case '%': case '&': case '*': case '?': |
mcimadamore@1113 | 421 | case '+': case '-': case ':': case '<': case '=': |
mcimadamore@1113 | 422 | case '>': case '^': case '|': case '~': |
mcimadamore@1113 | 423 | case '@': |
mcimadamore@1113 | 424 | return true; |
mcimadamore@1113 | 425 | default: |
mcimadamore@1113 | 426 | return false; |
mcimadamore@1113 | 427 | } |
mcimadamore@1113 | 428 | } |
mcimadamore@1113 | 429 | |
mcimadamore@1113 | 430 | /** Read longest possible sequence of special characters and convert |
mcimadamore@1113 | 431 | * to token. |
mcimadamore@1113 | 432 | */ |
mcimadamore@1113 | 433 | private void scanOperator() { |
mcimadamore@1113 | 434 | while (true) { |
mcimadamore@1125 | 435 | reader.putChar(false); |
mcimadamore@1125 | 436 | Name newname = reader.name(); |
mcimadamore@1113 | 437 | TokenKind tk1 = tokens.lookupKind(newname); |
mcimadamore@1113 | 438 | if (tk1 == TokenKind.IDENTIFIER) { |
mcimadamore@1125 | 439 | reader.sp--; |
mcimadamore@1113 | 440 | break; |
mcimadamore@1113 | 441 | } |
mcimadamore@1113 | 442 | tk = tk1; |
mcimadamore@1113 | 443 | reader.scanChar(); |
mcimadamore@1113 | 444 | if (!isSpecial(reader.ch)) break; |
mcimadamore@1113 | 445 | } |
mcimadamore@1113 | 446 | } |
mcimadamore@1113 | 447 | |
mcimadamore@1113 | 448 | /** Read token. |
mcimadamore@1113 | 449 | */ |
mcimadamore@1113 | 450 | public Token readToken() { |
mcimadamore@1113 | 451 | |
mcimadamore@1125 | 452 | reader.sp = 0; |
mcimadamore@1113 | 453 | name = null; |
mcimadamore@1113 | 454 | radix = 0; |
mcimadamore@1125 | 455 | |
mcimadamore@1113 | 456 | int pos = 0; |
mcimadamore@1113 | 457 | int endPos = 0; |
mcimadamore@1125 | 458 | List<Comment> comments = null; |
mcimadamore@1113 | 459 | |
mcimadamore@1113 | 460 | try { |
mcimadamore@1113 | 461 | loop: while (true) { |
mcimadamore@1113 | 462 | pos = reader.bp; |
mcimadamore@1113 | 463 | switch (reader.ch) { |
mcimadamore@1113 | 464 | case ' ': // (Spec 3.6) |
mcimadamore@1113 | 465 | case '\t': // (Spec 3.6) |
mcimadamore@1113 | 466 | case FF: // (Spec 3.6) |
mcimadamore@1113 | 467 | do { |
mcimadamore@1113 | 468 | reader.scanChar(); |
mcimadamore@1113 | 469 | } while (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF); |
mcimadamore@1113 | 470 | processWhiteSpace(pos, reader.bp); |
mcimadamore@1113 | 471 | break; |
mcimadamore@1113 | 472 | case LF: // (Spec 3.4) |
mcimadamore@1113 | 473 | reader.scanChar(); |
mcimadamore@1113 | 474 | processLineTerminator(pos, reader.bp); |
mcimadamore@1113 | 475 | break; |
mcimadamore@1113 | 476 | case CR: // (Spec 3.4) |
mcimadamore@1113 | 477 | reader.scanChar(); |
mcimadamore@1113 | 478 | if (reader.ch == LF) { |
mcimadamore@1113 | 479 | reader.scanChar(); |
mcimadamore@1113 | 480 | } |
mcimadamore@1113 | 481 | processLineTerminator(pos, reader.bp); |
mcimadamore@1113 | 482 | break; |
mcimadamore@1113 | 483 | case 'A': case 'B': case 'C': case 'D': case 'E': |
mcimadamore@1113 | 484 | case 'F': case 'G': case 'H': case 'I': case 'J': |
mcimadamore@1113 | 485 | case 'K': case 'L': case 'M': case 'N': case 'O': |
mcimadamore@1113 | 486 | case 'P': case 'Q': case 'R': case 'S': case 'T': |
mcimadamore@1113 | 487 | case 'U': case 'V': case 'W': case 'X': case 'Y': |
mcimadamore@1113 | 488 | case 'Z': |
mcimadamore@1113 | 489 | case 'a': case 'b': case 'c': case 'd': case 'e': |
mcimadamore@1113 | 490 | case 'f': case 'g': case 'h': case 'i': case 'j': |
mcimadamore@1113 | 491 | case 'k': case 'l': case 'm': case 'n': case 'o': |
mcimadamore@1113 | 492 | case 'p': case 'q': case 'r': case 's': case 't': |
mcimadamore@1113 | 493 | case 'u': case 'v': case 'w': case 'x': case 'y': |
mcimadamore@1113 | 494 | case 'z': |
mcimadamore@1113 | 495 | case '$': case '_': |
mcimadamore@1113 | 496 | scanIdent(); |
mcimadamore@1113 | 497 | break loop; |
mcimadamore@1113 | 498 | case '0': |
mcimadamore@1113 | 499 | reader.scanChar(); |
mcimadamore@1113 | 500 | if (reader.ch == 'x' || reader.ch == 'X') { |
mcimadamore@1113 | 501 | reader.scanChar(); |
mcimadamore@1113 | 502 | skipIllegalUnderscores(); |
mcimadamore@1113 | 503 | if (reader.ch == '.') { |
mcimadamore@1113 | 504 | scanHexFractionAndSuffix(pos, false); |
mcimadamore@1113 | 505 | } else if (reader.digit(pos, 16) < 0) { |
mcimadamore@1113 | 506 | lexError(pos, "invalid.hex.number"); |
mcimadamore@1113 | 507 | } else { |
mcimadamore@1113 | 508 | scanNumber(pos, 16); |
mcimadamore@1113 | 509 | } |
mcimadamore@1113 | 510 | } else if (reader.ch == 'b' || reader.ch == 'B') { |
mcimadamore@1113 | 511 | if (!allowBinaryLiterals) { |
mcimadamore@1113 | 512 | lexError(pos, "unsupported.binary.lit", source.name); |
mcimadamore@1113 | 513 | allowBinaryLiterals = true; |
mcimadamore@1113 | 514 | } |
mcimadamore@1113 | 515 | reader.scanChar(); |
mcimadamore@1113 | 516 | skipIllegalUnderscores(); |
mcimadamore@1113 | 517 | if (reader.digit(pos, 2) < 0) { |
mcimadamore@1113 | 518 | lexError(pos, "invalid.binary.number"); |
mcimadamore@1113 | 519 | } else { |
mcimadamore@1113 | 520 | scanNumber(pos, 2); |
mcimadamore@1113 | 521 | } |
mcimadamore@1113 | 522 | } else { |
mcimadamore@1125 | 523 | reader.putChar('0'); |
mcimadamore@1113 | 524 | if (reader.ch == '_') { |
mcimadamore@1113 | 525 | int savePos = reader.bp; |
mcimadamore@1113 | 526 | do { |
mcimadamore@1113 | 527 | reader.scanChar(); |
mcimadamore@1113 | 528 | } while (reader.ch == '_'); |
mcimadamore@1113 | 529 | if (reader.digit(pos, 10) < 0) { |
mcimadamore@1113 | 530 | lexError(savePos, "illegal.underscore"); |
mcimadamore@1113 | 531 | } |
mcimadamore@1113 | 532 | } |
mcimadamore@1113 | 533 | scanNumber(pos, 8); |
mcimadamore@1113 | 534 | } |
mcimadamore@1113 | 535 | break loop; |
mcimadamore@1113 | 536 | case '1': case '2': case '3': case '4': |
mcimadamore@1113 | 537 | case '5': case '6': case '7': case '8': case '9': |
mcimadamore@1113 | 538 | scanNumber(pos, 10); |
mcimadamore@1113 | 539 | break loop; |
mcimadamore@1113 | 540 | case '.': |
mcimadamore@1113 | 541 | reader.scanChar(); |
mcimadamore@1113 | 542 | if ('0' <= reader.ch && reader.ch <= '9') { |
mcimadamore@1125 | 543 | reader.putChar('.'); |
mcimadamore@1113 | 544 | scanFractionAndSuffix(pos); |
mcimadamore@1113 | 545 | } else if (reader.ch == '.') { |
jjg@1171 | 546 | int savePos = reader.bp; |
mcimadamore@1125 | 547 | reader.putChar('.'); reader.putChar('.', true); |
mcimadamore@1113 | 548 | if (reader.ch == '.') { |
mcimadamore@1113 | 549 | reader.scanChar(); |
mcimadamore@1125 | 550 | reader.putChar('.'); |
mcimadamore@1113 | 551 | tk = TokenKind.ELLIPSIS; |
mcimadamore@1113 | 552 | } else { |
jjg@1171 | 553 | lexError(savePos, "illegal.dot"); |
mcimadamore@1113 | 554 | } |
mcimadamore@1113 | 555 | } else { |
mcimadamore@1113 | 556 | tk = TokenKind.DOT; |
mcimadamore@1113 | 557 | } |
mcimadamore@1113 | 558 | break loop; |
mcimadamore@1113 | 559 | case ',': |
mcimadamore@1113 | 560 | reader.scanChar(); tk = TokenKind.COMMA; break loop; |
mcimadamore@1113 | 561 | case ';': |
mcimadamore@1113 | 562 | reader.scanChar(); tk = TokenKind.SEMI; break loop; |
mcimadamore@1113 | 563 | case '(': |
mcimadamore@1113 | 564 | reader.scanChar(); tk = TokenKind.LPAREN; break loop; |
mcimadamore@1113 | 565 | case ')': |
mcimadamore@1113 | 566 | reader.scanChar(); tk = TokenKind.RPAREN; break loop; |
mcimadamore@1113 | 567 | case '[': |
mcimadamore@1113 | 568 | reader.scanChar(); tk = TokenKind.LBRACKET; break loop; |
mcimadamore@1113 | 569 | case ']': |
mcimadamore@1113 | 570 | reader.scanChar(); tk = TokenKind.RBRACKET; break loop; |
mcimadamore@1113 | 571 | case '{': |
mcimadamore@1113 | 572 | reader.scanChar(); tk = TokenKind.LBRACE; break loop; |
mcimadamore@1113 | 573 | case '}': |
mcimadamore@1113 | 574 | reader.scanChar(); tk = TokenKind.RBRACE; break loop; |
mcimadamore@1113 | 575 | case '/': |
mcimadamore@1113 | 576 | reader.scanChar(); |
mcimadamore@1113 | 577 | if (reader.ch == '/') { |
mcimadamore@1113 | 578 | do { |
mcimadamore@1125 | 579 | reader.scanCommentChar(); |
mcimadamore@1113 | 580 | } while (reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen); |
mcimadamore@1113 | 581 | if (reader.bp < reader.buflen) { |
jjg@1280 | 582 | comments = addComment(comments, processComment(pos, reader.bp, CommentStyle.LINE)); |
mcimadamore@1113 | 583 | } |
mcimadamore@1113 | 584 | break; |
mcimadamore@1113 | 585 | } else if (reader.ch == '*') { |
mcimadamore@1125 | 586 | boolean isEmpty = false; |
mcimadamore@1113 | 587 | reader.scanChar(); |
mcimadamore@1113 | 588 | CommentStyle style; |
mcimadamore@1113 | 589 | if (reader.ch == '*') { |
mcimadamore@1113 | 590 | style = CommentStyle.JAVADOC; |
mcimadamore@1125 | 591 | reader.scanCommentChar(); |
mcimadamore@1125 | 592 | if (reader.ch == '/') { |
mcimadamore@1125 | 593 | isEmpty = true; |
mcimadamore@1125 | 594 | } |
mcimadamore@1113 | 595 | } else { |
mcimadamore@1113 | 596 | style = CommentStyle.BLOCK; |
mcimadamore@1125 | 597 | } |
mcimadamore@1125 | 598 | while (!isEmpty && reader.bp < reader.buflen) { |
mcimadamore@1125 | 599 | if (reader.ch == '*') { |
mcimadamore@1125 | 600 | reader.scanChar(); |
mcimadamore@1125 | 601 | if (reader.ch == '/') break; |
mcimadamore@1125 | 602 | } else { |
mcimadamore@1125 | 603 | reader.scanCommentChar(); |
mcimadamore@1113 | 604 | } |
mcimadamore@1113 | 605 | } |
mcimadamore@1113 | 606 | if (reader.ch == '/') { |
mcimadamore@1113 | 607 | reader.scanChar(); |
jjg@1280 | 608 | comments = addComment(comments, processComment(pos, reader.bp, style)); |
mcimadamore@1113 | 609 | break; |
mcimadamore@1113 | 610 | } else { |
mcimadamore@1113 | 611 | lexError(pos, "unclosed.comment"); |
mcimadamore@1113 | 612 | break loop; |
mcimadamore@1113 | 613 | } |
mcimadamore@1113 | 614 | } else if (reader.ch == '=') { |
mcimadamore@1113 | 615 | tk = TokenKind.SLASHEQ; |
mcimadamore@1113 | 616 | reader.scanChar(); |
mcimadamore@1113 | 617 | } else { |
mcimadamore@1113 | 618 | tk = TokenKind.SLASH; |
mcimadamore@1113 | 619 | } |
mcimadamore@1113 | 620 | break loop; |
mcimadamore@1113 | 621 | case '\'': |
mcimadamore@1113 | 622 | reader.scanChar(); |
mcimadamore@1113 | 623 | if (reader.ch == '\'') { |
mcimadamore@1113 | 624 | lexError(pos, "empty.char.lit"); |
mcimadamore@1113 | 625 | } else { |
mcimadamore@1113 | 626 | if (reader.ch == CR || reader.ch == LF) |
mcimadamore@1113 | 627 | lexError(pos, "illegal.line.end.in.char.lit"); |
mcimadamore@1113 | 628 | scanLitChar(pos); |
mcimadamore@1113 | 629 | char ch2 = reader.ch; |
mcimadamore@1113 | 630 | if (reader.ch == '\'') { |
mcimadamore@1113 | 631 | reader.scanChar(); |
mcimadamore@1113 | 632 | tk = TokenKind.CHARLITERAL; |
mcimadamore@1113 | 633 | } else { |
mcimadamore@1113 | 634 | lexError(pos, "unclosed.char.lit"); |
mcimadamore@1113 | 635 | } |
mcimadamore@1113 | 636 | } |
mcimadamore@1113 | 637 | break loop; |
mcimadamore@1113 | 638 | case '\"': |
mcimadamore@1113 | 639 | reader.scanChar(); |
mcimadamore@1113 | 640 | while (reader.ch != '\"' && reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen) |
mcimadamore@1113 | 641 | scanLitChar(pos); |
mcimadamore@1113 | 642 | if (reader.ch == '\"') { |
mcimadamore@1113 | 643 | tk = TokenKind.STRINGLITERAL; |
mcimadamore@1113 | 644 | reader.scanChar(); |
mcimadamore@1113 | 645 | } else { |
mcimadamore@1113 | 646 | lexError(pos, "unclosed.str.lit"); |
mcimadamore@1113 | 647 | } |
mcimadamore@1113 | 648 | break loop; |
mcimadamore@1113 | 649 | default: |
mcimadamore@1113 | 650 | if (isSpecial(reader.ch)) { |
mcimadamore@1113 | 651 | scanOperator(); |
mcimadamore@1113 | 652 | } else { |
mcimadamore@1113 | 653 | boolean isJavaIdentifierStart; |
mcimadamore@1113 | 654 | if (reader.ch < '\u0080') { |
mcimadamore@1113 | 655 | // all ASCII range chars already handled, above |
mcimadamore@1113 | 656 | isJavaIdentifierStart = false; |
mcimadamore@1113 | 657 | } else { |
mcimadamore@1113 | 658 | char high = reader.scanSurrogates(); |
mcimadamore@1113 | 659 | if (high != 0) { |
mcimadamore@1125 | 660 | reader.putChar(high); |
mcimadamore@1113 | 661 | |
mcimadamore@1113 | 662 | isJavaIdentifierStart = Character.isJavaIdentifierStart( |
mcimadamore@1113 | 663 | Character.toCodePoint(high, reader.ch)); |
mcimadamore@1113 | 664 | } else { |
mcimadamore@1113 | 665 | isJavaIdentifierStart = Character.isJavaIdentifierStart(reader.ch); |
mcimadamore@1113 | 666 | } |
mcimadamore@1113 | 667 | } |
mcimadamore@1113 | 668 | if (isJavaIdentifierStart) { |
mcimadamore@1113 | 669 | scanIdent(); |
mcimadamore@1113 | 670 | } else if (reader.bp == reader.buflen || reader.ch == EOI && reader.bp + 1 == reader.buflen) { // JLS 3.5 |
mcimadamore@1113 | 671 | tk = TokenKind.EOF; |
mcimadamore@1113 | 672 | pos = reader.buflen; |
mcimadamore@1113 | 673 | } else { |
vromero@1385 | 674 | String arg = (32 < reader.ch && reader.ch < 127) ? |
vromero@1385 | 675 | String.format("%s", reader.ch) : |
vromero@1385 | 676 | String.format("\\u%04x", (int)reader.ch); |
vromero@1385 | 677 | lexError(pos, "illegal.char", arg); |
mcimadamore@1113 | 678 | reader.scanChar(); |
mcimadamore@1113 | 679 | } |
mcimadamore@1113 | 680 | } |
mcimadamore@1113 | 681 | break loop; |
mcimadamore@1113 | 682 | } |
mcimadamore@1113 | 683 | } |
mcimadamore@1113 | 684 | endPos = reader.bp; |
mcimadamore@1113 | 685 | switch (tk.tag) { |
mcimadamore@1125 | 686 | case DEFAULT: return new Token(tk, pos, endPos, comments); |
mcimadamore@1125 | 687 | case NAMED: return new NamedToken(tk, pos, endPos, name, comments); |
mcimadamore@1125 | 688 | case STRING: return new StringToken(tk, pos, endPos, reader.chars(), comments); |
mcimadamore@1125 | 689 | case NUMERIC: return new NumericToken(tk, pos, endPos, reader.chars(), radix, comments); |
mcimadamore@1113 | 690 | default: throw new AssertionError(); |
mcimadamore@1113 | 691 | } |
mcimadamore@1113 | 692 | } |
mcimadamore@1113 | 693 | finally { |
mcimadamore@1113 | 694 | if (scannerDebug) { |
mcimadamore@1113 | 695 | System.out.println("nextToken(" + pos |
mcimadamore@1113 | 696 | + "," + endPos + ")=|" + |
mcimadamore@1113 | 697 | new String(reader.getRawCharacters(pos, endPos)) |
mcimadamore@1113 | 698 | + "|"); |
mcimadamore@1113 | 699 | } |
mcimadamore@1113 | 700 | } |
mcimadamore@1113 | 701 | } |
mcimadamore@1125 | 702 | //where |
jjg@1280 | 703 | List<Comment> addComment(List<Comment> comments, Comment comment) { |
jjg@1280 | 704 | return comments == null ? |
jjg@1280 | 705 | List.of(comment) : |
jjg@1280 | 706 | comments.prepend(comment); |
mcimadamore@1125 | 707 | } |
mcimadamore@1113 | 708 | |
mcimadamore@1113 | 709 | /** Return the position where a lexical error occurred; |
mcimadamore@1113 | 710 | */ |
mcimadamore@1113 | 711 | public int errPos() { |
mcimadamore@1113 | 712 | return errPos; |
mcimadamore@1113 | 713 | } |
mcimadamore@1113 | 714 | |
mcimadamore@1113 | 715 | /** Set the position where a lexical error occurred; |
mcimadamore@1113 | 716 | */ |
mcimadamore@1113 | 717 | public void errPos(int pos) { |
mcimadamore@1113 | 718 | errPos = pos; |
mcimadamore@1113 | 719 | } |
mcimadamore@1113 | 720 | |
mcimadamore@1113 | 721 | /** |
mcimadamore@1113 | 722 | * Called when a complete comment has been scanned. pos and endPos |
mcimadamore@1113 | 723 | * will mark the comment boundary. |
mcimadamore@1113 | 724 | */ |
mcimadamore@1125 | 725 | protected Tokens.Comment processComment(int pos, int endPos, CommentStyle style) { |
mcimadamore@1113 | 726 | if (scannerDebug) |
mcimadamore@1113 | 727 | System.out.println("processComment(" + pos |
mcimadamore@1113 | 728 | + "," + endPos + "," + style + ")=|" |
mcimadamore@1113 | 729 | + new String(reader.getRawCharacters(pos, endPos)) |
mcimadamore@1113 | 730 | + "|"); |
mcimadamore@1125 | 731 | char[] buf = reader.getRawCharacters(pos, endPos); |
mcimadamore@1125 | 732 | return new BasicComment<UnicodeReader>(new UnicodeReader(fac, buf, buf.length), style); |
mcimadamore@1113 | 733 | } |
mcimadamore@1113 | 734 | |
mcimadamore@1113 | 735 | /** |
mcimadamore@1113 | 736 | * Called when a complete whitespace run has been scanned. pos and endPos |
mcimadamore@1113 | 737 | * will mark the whitespace boundary. |
mcimadamore@1113 | 738 | */ |
mcimadamore@1113 | 739 | protected void processWhiteSpace(int pos, int endPos) { |
mcimadamore@1113 | 740 | if (scannerDebug) |
mcimadamore@1113 | 741 | System.out.println("processWhitespace(" + pos |
mcimadamore@1113 | 742 | + "," + endPos + ")=|" + |
mcimadamore@1113 | 743 | new String(reader.getRawCharacters(pos, endPos)) |
mcimadamore@1113 | 744 | + "|"); |
mcimadamore@1113 | 745 | } |
mcimadamore@1113 | 746 | |
mcimadamore@1113 | 747 | /** |
mcimadamore@1113 | 748 | * Called when a line terminator has been processed. |
mcimadamore@1113 | 749 | */ |
mcimadamore@1113 | 750 | protected void processLineTerminator(int pos, int endPos) { |
mcimadamore@1113 | 751 | if (scannerDebug) |
mcimadamore@1113 | 752 | System.out.println("processTerminator(" + pos |
mcimadamore@1113 | 753 | + "," + endPos + ")=|" + |
mcimadamore@1113 | 754 | new String(reader.getRawCharacters(pos, endPos)) |
mcimadamore@1113 | 755 | + "|"); |
mcimadamore@1113 | 756 | } |
mcimadamore@1113 | 757 | |
mcimadamore@1113 | 758 | /** Build a map for translating between line numbers and |
mcimadamore@1113 | 759 | * positions in the input. |
mcimadamore@1113 | 760 | * |
mcimadamore@1113 | 761 | * @return a LineMap */ |
mcimadamore@1113 | 762 | public Position.LineMap getLineMap() { |
mcimadamore@1113 | 763 | return Position.makeLineMap(reader.getRawCharacters(), reader.buflen, false); |
mcimadamore@1113 | 764 | } |
mcimadamore@1125 | 765 | |
mcimadamore@1125 | 766 | |
mcimadamore@1125 | 767 | /** |
mcimadamore@1125 | 768 | * Scan a documentation comment; determine if a deprecated tag is present. |
mcimadamore@1125 | 769 | * Called once the initial /, * have been skipped, positioned at the second * |
mcimadamore@1125 | 770 | * (which is treated as the beginning of the first line). |
mcimadamore@1125 | 771 | * Stops positioned at the closing '/'. |
mcimadamore@1125 | 772 | */ |
jjg@1679 | 773 | protected static class BasicComment<U extends UnicodeReader> implements Comment { |
mcimadamore@1125 | 774 | |
mcimadamore@1125 | 775 | CommentStyle cs; |
mcimadamore@1125 | 776 | U comment_reader; |
mcimadamore@1125 | 777 | |
mcimadamore@1125 | 778 | protected boolean deprecatedFlag = false; |
mcimadamore@1125 | 779 | protected boolean scanned = false; |
mcimadamore@1125 | 780 | |
mcimadamore@1125 | 781 | protected BasicComment(U comment_reader, CommentStyle cs) { |
mcimadamore@1125 | 782 | this.comment_reader = comment_reader; |
mcimadamore@1125 | 783 | this.cs = cs; |
mcimadamore@1125 | 784 | } |
mcimadamore@1125 | 785 | |
mcimadamore@1125 | 786 | public String getText() { |
mcimadamore@1125 | 787 | return null; |
mcimadamore@1125 | 788 | } |
mcimadamore@1125 | 789 | |
jjg@1281 | 790 | public int getSourcePos(int pos) { |
jjg@1281 | 791 | return -1; |
jjg@1281 | 792 | } |
jjg@1281 | 793 | |
mcimadamore@1125 | 794 | public CommentStyle getStyle() { |
mcimadamore@1125 | 795 | return cs; |
mcimadamore@1125 | 796 | } |
mcimadamore@1125 | 797 | |
mcimadamore@1125 | 798 | public boolean isDeprecated() { |
mcimadamore@1125 | 799 | if (!scanned && cs == CommentStyle.JAVADOC) { |
mcimadamore@1125 | 800 | scanDocComment(); |
mcimadamore@1125 | 801 | } |
mcimadamore@1125 | 802 | return deprecatedFlag; |
mcimadamore@1125 | 803 | } |
mcimadamore@1125 | 804 | |
mcimadamore@1125 | 805 | @SuppressWarnings("fallthrough") |
mcimadamore@1125 | 806 | protected void scanDocComment() { |
mcimadamore@1125 | 807 | try { |
mcimadamore@1125 | 808 | boolean deprecatedPrefix = false; |
mcimadamore@1125 | 809 | |
mcimadamore@1125 | 810 | comment_reader.bp += 3; // '/**' |
mcimadamore@1125 | 811 | comment_reader.ch = comment_reader.buf[comment_reader.bp]; |
mcimadamore@1125 | 812 | |
mcimadamore@1125 | 813 | forEachLine: |
mcimadamore@1125 | 814 | while (comment_reader.bp < comment_reader.buflen) { |
mcimadamore@1125 | 815 | |
mcimadamore@1125 | 816 | // Skip optional WhiteSpace at beginning of line |
mcimadamore@1125 | 817 | while (comment_reader.bp < comment_reader.buflen && (comment_reader.ch == ' ' || comment_reader.ch == '\t' || comment_reader.ch == FF)) { |
mcimadamore@1125 | 818 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 819 | } |
mcimadamore@1125 | 820 | |
mcimadamore@1125 | 821 | // Skip optional consecutive Stars |
mcimadamore@1125 | 822 | while (comment_reader.bp < comment_reader.buflen && comment_reader.ch == '*') { |
mcimadamore@1125 | 823 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 824 | if (comment_reader.ch == '/') { |
mcimadamore@1125 | 825 | return; |
mcimadamore@1125 | 826 | } |
mcimadamore@1125 | 827 | } |
mcimadamore@1125 | 828 | |
mcimadamore@1125 | 829 | // Skip optional WhiteSpace after Stars |
mcimadamore@1125 | 830 | while (comment_reader.bp < comment_reader.buflen && (comment_reader.ch == ' ' || comment_reader.ch == '\t' || comment_reader.ch == FF)) { |
mcimadamore@1125 | 831 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 832 | } |
mcimadamore@1125 | 833 | |
mcimadamore@1125 | 834 | deprecatedPrefix = false; |
mcimadamore@1125 | 835 | // At beginning of line in the JavaDoc sense. |
mcimadamore@1125 | 836 | if (!deprecatedFlag) { |
mcimadamore@1125 | 837 | String deprecated = "@deprecated"; |
mcimadamore@1125 | 838 | int i = 0; |
mcimadamore@1125 | 839 | while (comment_reader.bp < comment_reader.buflen && comment_reader.ch == deprecated.charAt(i)) { |
mcimadamore@1125 | 840 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 841 | i++; |
mcimadamore@1125 | 842 | if (i == deprecated.length()) { |
mcimadamore@1125 | 843 | deprecatedPrefix = true; |
mcimadamore@1125 | 844 | break; |
mcimadamore@1125 | 845 | } |
mcimadamore@1125 | 846 | } |
mcimadamore@1125 | 847 | } |
mcimadamore@1125 | 848 | |
mcimadamore@1125 | 849 | if (deprecatedPrefix && comment_reader.bp < comment_reader.buflen) { |
mcimadamore@1125 | 850 | if (Character.isWhitespace(comment_reader.ch)) { |
mcimadamore@1125 | 851 | deprecatedFlag = true; |
mcimadamore@1125 | 852 | } else if (comment_reader.ch == '*') { |
mcimadamore@1125 | 853 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 854 | if (comment_reader.ch == '/') { |
mcimadamore@1125 | 855 | deprecatedFlag = true; |
mcimadamore@1125 | 856 | return; |
mcimadamore@1125 | 857 | } |
mcimadamore@1125 | 858 | } |
mcimadamore@1125 | 859 | } |
mcimadamore@1125 | 860 | |
mcimadamore@1125 | 861 | // Skip rest of line |
mcimadamore@1125 | 862 | while (comment_reader.bp < comment_reader.buflen) { |
mcimadamore@1125 | 863 | switch (comment_reader.ch) { |
mcimadamore@1125 | 864 | case '*': |
mcimadamore@1125 | 865 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 866 | if (comment_reader.ch == '/') { |
mcimadamore@1125 | 867 | return; |
mcimadamore@1125 | 868 | } |
mcimadamore@1125 | 869 | break; |
mcimadamore@1125 | 870 | case CR: // (Spec 3.4) |
mcimadamore@1125 | 871 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 872 | if (comment_reader.ch != LF) { |
mcimadamore@1125 | 873 | continue forEachLine; |
mcimadamore@1125 | 874 | } |
mcimadamore@1125 | 875 | /* fall through to LF case */ |
mcimadamore@1125 | 876 | case LF: // (Spec 3.4) |
mcimadamore@1125 | 877 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 878 | continue forEachLine; |
mcimadamore@1125 | 879 | default: |
mcimadamore@1125 | 880 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 881 | } |
mcimadamore@1125 | 882 | } // rest of line |
mcimadamore@1125 | 883 | } // forEachLine |
mcimadamore@1125 | 884 | return; |
mcimadamore@1125 | 885 | } finally { |
mcimadamore@1125 | 886 | scanned = true; |
mcimadamore@1125 | 887 | } |
mcimadamore@1125 | 888 | } |
mcimadamore@1125 | 889 | } |
mcimadamore@1113 | 890 | } |