Fri, 04 Nov 2011 12:36:40 +0000
7104201: Refactor DocCommentScanner
Summary: Add new Comment helper class to parse contents of comments in source code
Reviewed-by: jjg
mcimadamore@1113 | 1 | /* |
mcimadamore@1113 | 2 | * Copyright (c) 1999, 2011, 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 | |
mcimadamore@1113 | 47 | private static 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 |
mcimadamore@1113 | 111 | * @param input the input, might be modified |
mcimadamore@1113 | 112 | * @param inputLength the size of the input. |
mcimadamore@1113 | 113 | * Must be positive and less than or equal to input.length. |
mcimadamore@1113 | 114 | */ |
mcimadamore@1113 | 115 | protected JavaTokenizer(ScannerFactory fac, CharBuffer buf) { |
mcimadamore@1113 | 116 | this(fac, new UnicodeReader(fac, buf)); |
mcimadamore@1113 | 117 | } |
mcimadamore@1113 | 118 | |
mcimadamore@1113 | 119 | protected JavaTokenizer(ScannerFactory fac, char[] buf, int inputLength) { |
mcimadamore@1113 | 120 | this(fac, new UnicodeReader(fac, buf, inputLength)); |
mcimadamore@1113 | 121 | } |
mcimadamore@1113 | 122 | |
mcimadamore@1113 | 123 | protected JavaTokenizer(ScannerFactory fac, UnicodeReader reader) { |
mcimadamore@1125 | 124 | this.fac = fac; |
mcimadamore@1125 | 125 | this.log = fac.log; |
mcimadamore@1125 | 126 | this.tokens = fac.tokens; |
mcimadamore@1125 | 127 | this.source = fac.source; |
mcimadamore@1113 | 128 | this.reader = reader; |
mcimadamore@1125 | 129 | this.allowBinaryLiterals = source.allowBinaryLiterals(); |
mcimadamore@1125 | 130 | this.allowHexFloats = source.allowHexFloats(); |
mcimadamore@1125 | 131 | this.allowUnderscoresInLiterals = source.allowUnderscoresInLiterals(); |
mcimadamore@1113 | 132 | } |
mcimadamore@1113 | 133 | |
mcimadamore@1113 | 134 | /** Report an error at the given position using the provided arguments. |
mcimadamore@1113 | 135 | */ |
mcimadamore@1113 | 136 | protected void lexError(int pos, String key, Object... args) { |
mcimadamore@1113 | 137 | log.error(pos, key, args); |
mcimadamore@1113 | 138 | tk = TokenKind.ERROR; |
mcimadamore@1113 | 139 | errPos = pos; |
mcimadamore@1113 | 140 | } |
mcimadamore@1113 | 141 | |
mcimadamore@1113 | 142 | /** Read next character in character or string literal and copy into sbuf. |
mcimadamore@1113 | 143 | */ |
mcimadamore@1113 | 144 | private void scanLitChar(int pos) { |
mcimadamore@1113 | 145 | if (reader.ch == '\\') { |
mcimadamore@1113 | 146 | if (reader.peekChar() == '\\' && !reader.isUnicode()) { |
mcimadamore@1113 | 147 | reader.skipChar(); |
mcimadamore@1125 | 148 | reader.putChar('\\', true); |
mcimadamore@1113 | 149 | } else { |
mcimadamore@1113 | 150 | reader.scanChar(); |
mcimadamore@1113 | 151 | switch (reader.ch) { |
mcimadamore@1113 | 152 | case '0': case '1': case '2': case '3': |
mcimadamore@1113 | 153 | case '4': case '5': case '6': case '7': |
mcimadamore@1113 | 154 | char leadch = reader.ch; |
mcimadamore@1113 | 155 | int oct = reader.digit(pos, 8); |
mcimadamore@1113 | 156 | reader.scanChar(); |
mcimadamore@1113 | 157 | if ('0' <= reader.ch && reader.ch <= '7') { |
mcimadamore@1113 | 158 | oct = oct * 8 + reader.digit(pos, 8); |
mcimadamore@1113 | 159 | reader.scanChar(); |
mcimadamore@1113 | 160 | if (leadch <= '3' && '0' <= reader.ch && reader.ch <= '7') { |
mcimadamore@1113 | 161 | oct = oct * 8 + reader.digit(pos, 8); |
mcimadamore@1113 | 162 | reader.scanChar(); |
mcimadamore@1113 | 163 | } |
mcimadamore@1113 | 164 | } |
mcimadamore@1125 | 165 | reader.putChar((char)oct); |
mcimadamore@1113 | 166 | break; |
mcimadamore@1113 | 167 | case 'b': |
mcimadamore@1125 | 168 | reader.putChar('\b', true); break; |
mcimadamore@1113 | 169 | case 't': |
mcimadamore@1125 | 170 | reader.putChar('\t', true); break; |
mcimadamore@1113 | 171 | case 'n': |
mcimadamore@1125 | 172 | reader.putChar('\n', true); break; |
mcimadamore@1113 | 173 | case 'f': |
mcimadamore@1125 | 174 | reader.putChar('\f', true); break; |
mcimadamore@1113 | 175 | case 'r': |
mcimadamore@1125 | 176 | reader.putChar('\r', true); break; |
mcimadamore@1113 | 177 | case '\'': |
mcimadamore@1125 | 178 | reader.putChar('\'', true); break; |
mcimadamore@1113 | 179 | case '\"': |
mcimadamore@1125 | 180 | reader.putChar('\"', true); break; |
mcimadamore@1113 | 181 | case '\\': |
mcimadamore@1125 | 182 | reader.putChar('\\', true); break; |
mcimadamore@1113 | 183 | default: |
mcimadamore@1113 | 184 | lexError(reader.bp, "illegal.esc.char"); |
mcimadamore@1113 | 185 | } |
mcimadamore@1113 | 186 | } |
mcimadamore@1113 | 187 | } else if (reader.bp != reader.buflen) { |
mcimadamore@1125 | 188 | reader.putChar(true); |
mcimadamore@1113 | 189 | } |
mcimadamore@1113 | 190 | } |
mcimadamore@1113 | 191 | |
mcimadamore@1113 | 192 | private void scanDigits(int pos, int digitRadix) { |
mcimadamore@1113 | 193 | char saveCh; |
mcimadamore@1113 | 194 | int savePos; |
mcimadamore@1113 | 195 | do { |
mcimadamore@1113 | 196 | if (reader.ch != '_') { |
mcimadamore@1125 | 197 | reader.putChar(false); |
mcimadamore@1113 | 198 | } else { |
mcimadamore@1113 | 199 | if (!allowUnderscoresInLiterals) { |
mcimadamore@1113 | 200 | lexError(pos, "unsupported.underscore.lit", source.name); |
mcimadamore@1113 | 201 | allowUnderscoresInLiterals = true; |
mcimadamore@1113 | 202 | } |
mcimadamore@1113 | 203 | } |
mcimadamore@1113 | 204 | saveCh = reader.ch; |
mcimadamore@1113 | 205 | savePos = reader.bp; |
mcimadamore@1113 | 206 | reader.scanChar(); |
mcimadamore@1113 | 207 | } while (reader.digit(pos, digitRadix) >= 0 || reader.ch == '_'); |
mcimadamore@1113 | 208 | if (saveCh == '_') |
mcimadamore@1113 | 209 | lexError(savePos, "illegal.underscore"); |
mcimadamore@1113 | 210 | } |
mcimadamore@1113 | 211 | |
mcimadamore@1113 | 212 | /** Read fractional part of hexadecimal floating point number. |
mcimadamore@1113 | 213 | */ |
mcimadamore@1113 | 214 | private void scanHexExponentAndSuffix(int pos) { |
mcimadamore@1113 | 215 | if (reader.ch == 'p' || reader.ch == 'P') { |
mcimadamore@1125 | 216 | reader.putChar(true); |
mcimadamore@1113 | 217 | skipIllegalUnderscores(); |
mcimadamore@1113 | 218 | if (reader.ch == '+' || reader.ch == '-') { |
mcimadamore@1125 | 219 | reader.putChar(true); |
mcimadamore@1113 | 220 | } |
mcimadamore@1113 | 221 | skipIllegalUnderscores(); |
mcimadamore@1113 | 222 | if ('0' <= reader.ch && reader.ch <= '9') { |
mcimadamore@1113 | 223 | scanDigits(pos, 10); |
mcimadamore@1113 | 224 | if (!allowHexFloats) { |
mcimadamore@1113 | 225 | lexError(pos, "unsupported.fp.lit", source.name); |
mcimadamore@1113 | 226 | allowHexFloats = true; |
mcimadamore@1113 | 227 | } |
mcimadamore@1113 | 228 | else if (!hexFloatsWork) |
mcimadamore@1113 | 229 | lexError(pos, "unsupported.cross.fp.lit"); |
mcimadamore@1113 | 230 | } else |
mcimadamore@1113 | 231 | lexError(pos, "malformed.fp.lit"); |
mcimadamore@1113 | 232 | } else { |
mcimadamore@1113 | 233 | lexError(pos, "malformed.fp.lit"); |
mcimadamore@1113 | 234 | } |
mcimadamore@1113 | 235 | if (reader.ch == 'f' || reader.ch == 'F') { |
mcimadamore@1125 | 236 | reader.putChar(true); |
mcimadamore@1113 | 237 | tk = TokenKind.FLOATLITERAL; |
mcimadamore@1113 | 238 | radix = 16; |
mcimadamore@1113 | 239 | } else { |
mcimadamore@1113 | 240 | if (reader.ch == 'd' || reader.ch == 'D') { |
mcimadamore@1125 | 241 | reader.putChar(true); |
mcimadamore@1113 | 242 | } |
mcimadamore@1113 | 243 | tk = TokenKind.DOUBLELITERAL; |
mcimadamore@1113 | 244 | radix = 16; |
mcimadamore@1113 | 245 | } |
mcimadamore@1113 | 246 | } |
mcimadamore@1113 | 247 | |
mcimadamore@1113 | 248 | /** Read fractional part of floating point number. |
mcimadamore@1113 | 249 | */ |
mcimadamore@1113 | 250 | private void scanFraction(int pos) { |
mcimadamore@1113 | 251 | skipIllegalUnderscores(); |
mcimadamore@1113 | 252 | if ('0' <= reader.ch && reader.ch <= '9') { |
mcimadamore@1113 | 253 | scanDigits(pos, 10); |
mcimadamore@1113 | 254 | } |
mcimadamore@1125 | 255 | int sp1 = reader.sp; |
mcimadamore@1113 | 256 | if (reader.ch == 'e' || reader.ch == 'E') { |
mcimadamore@1125 | 257 | reader.putChar(true); |
mcimadamore@1113 | 258 | skipIllegalUnderscores(); |
mcimadamore@1113 | 259 | if (reader.ch == '+' || reader.ch == '-') { |
mcimadamore@1125 | 260 | reader.putChar(true); |
mcimadamore@1113 | 261 | } |
mcimadamore@1113 | 262 | skipIllegalUnderscores(); |
mcimadamore@1113 | 263 | if ('0' <= reader.ch && reader.ch <= '9') { |
mcimadamore@1113 | 264 | scanDigits(pos, 10); |
mcimadamore@1113 | 265 | return; |
mcimadamore@1113 | 266 | } |
mcimadamore@1113 | 267 | lexError(pos, "malformed.fp.lit"); |
mcimadamore@1125 | 268 | reader.sp = sp1; |
mcimadamore@1113 | 269 | } |
mcimadamore@1113 | 270 | } |
mcimadamore@1113 | 271 | |
mcimadamore@1113 | 272 | /** Read fractional part and 'd' or 'f' suffix of floating point number. |
mcimadamore@1113 | 273 | */ |
mcimadamore@1113 | 274 | private void scanFractionAndSuffix(int pos) { |
mcimadamore@1113 | 275 | radix = 10; |
mcimadamore@1113 | 276 | scanFraction(pos); |
mcimadamore@1113 | 277 | if (reader.ch == 'f' || reader.ch == 'F') { |
mcimadamore@1125 | 278 | reader.putChar(true); |
mcimadamore@1113 | 279 | tk = TokenKind.FLOATLITERAL; |
mcimadamore@1113 | 280 | } else { |
mcimadamore@1113 | 281 | if (reader.ch == 'd' || reader.ch == 'D') { |
mcimadamore@1125 | 282 | reader.putChar(true); |
mcimadamore@1113 | 283 | } |
mcimadamore@1113 | 284 | tk = TokenKind.DOUBLELITERAL; |
mcimadamore@1113 | 285 | } |
mcimadamore@1113 | 286 | } |
mcimadamore@1113 | 287 | |
mcimadamore@1113 | 288 | /** Read fractional part and 'd' or 'f' suffix of floating point number. |
mcimadamore@1113 | 289 | */ |
mcimadamore@1113 | 290 | private void scanHexFractionAndSuffix(int pos, boolean seendigit) { |
mcimadamore@1113 | 291 | radix = 16; |
mcimadamore@1113 | 292 | Assert.check(reader.ch == '.'); |
mcimadamore@1125 | 293 | reader.putChar(true); |
mcimadamore@1113 | 294 | skipIllegalUnderscores(); |
mcimadamore@1113 | 295 | if (reader.digit(pos, 16) >= 0) { |
mcimadamore@1113 | 296 | seendigit = true; |
mcimadamore@1113 | 297 | scanDigits(pos, 16); |
mcimadamore@1113 | 298 | } |
mcimadamore@1113 | 299 | if (!seendigit) |
mcimadamore@1113 | 300 | lexError(pos, "invalid.hex.number"); |
mcimadamore@1113 | 301 | else |
mcimadamore@1113 | 302 | scanHexExponentAndSuffix(pos); |
mcimadamore@1113 | 303 | } |
mcimadamore@1113 | 304 | |
mcimadamore@1113 | 305 | private void skipIllegalUnderscores() { |
mcimadamore@1113 | 306 | if (reader.ch == '_') { |
mcimadamore@1113 | 307 | lexError(reader.bp, "illegal.underscore"); |
mcimadamore@1113 | 308 | while (reader.ch == '_') |
mcimadamore@1113 | 309 | reader.scanChar(); |
mcimadamore@1113 | 310 | } |
mcimadamore@1113 | 311 | } |
mcimadamore@1113 | 312 | |
mcimadamore@1113 | 313 | /** Read a number. |
mcimadamore@1113 | 314 | * @param radix The radix of the number; one of 2, j8, 10, 16. |
mcimadamore@1113 | 315 | */ |
mcimadamore@1113 | 316 | private void scanNumber(int pos, int radix) { |
mcimadamore@1113 | 317 | // for octal, allow base-10 digit in case it's a float literal |
mcimadamore@1113 | 318 | this.radix = radix; |
mcimadamore@1113 | 319 | int digitRadix = (radix == 8 ? 10 : radix); |
mcimadamore@1113 | 320 | boolean seendigit = false; |
mcimadamore@1113 | 321 | if (reader.digit(pos, digitRadix) >= 0) { |
mcimadamore@1113 | 322 | seendigit = true; |
mcimadamore@1113 | 323 | scanDigits(pos, digitRadix); |
mcimadamore@1113 | 324 | } |
mcimadamore@1113 | 325 | if (radix == 16 && reader.ch == '.') { |
mcimadamore@1113 | 326 | scanHexFractionAndSuffix(pos, seendigit); |
mcimadamore@1113 | 327 | } else if (seendigit && radix == 16 && (reader.ch == 'p' || reader.ch == 'P')) { |
mcimadamore@1113 | 328 | scanHexExponentAndSuffix(pos); |
mcimadamore@1113 | 329 | } else if (digitRadix == 10 && reader.ch == '.') { |
mcimadamore@1125 | 330 | reader.putChar(true); |
mcimadamore@1113 | 331 | scanFractionAndSuffix(pos); |
mcimadamore@1113 | 332 | } else if (digitRadix == 10 && |
mcimadamore@1113 | 333 | (reader.ch == 'e' || reader.ch == 'E' || |
mcimadamore@1113 | 334 | reader.ch == 'f' || reader.ch == 'F' || |
mcimadamore@1113 | 335 | reader.ch == 'd' || reader.ch == 'D')) { |
mcimadamore@1113 | 336 | scanFractionAndSuffix(pos); |
mcimadamore@1113 | 337 | } else { |
mcimadamore@1113 | 338 | if (reader.ch == 'l' || reader.ch == 'L') { |
mcimadamore@1113 | 339 | reader.scanChar(); |
mcimadamore@1113 | 340 | tk = TokenKind.LONGLITERAL; |
mcimadamore@1113 | 341 | } else { |
mcimadamore@1113 | 342 | tk = TokenKind.INTLITERAL; |
mcimadamore@1113 | 343 | } |
mcimadamore@1113 | 344 | } |
mcimadamore@1113 | 345 | } |
mcimadamore@1113 | 346 | |
mcimadamore@1113 | 347 | /** Read an identifier. |
mcimadamore@1113 | 348 | */ |
mcimadamore@1113 | 349 | private void scanIdent() { |
mcimadamore@1113 | 350 | boolean isJavaIdentifierPart; |
mcimadamore@1113 | 351 | char high; |
mcimadamore@1113 | 352 | do { |
mcimadamore@1125 | 353 | reader.putChar(true); |
mcimadamore@1113 | 354 | switch (reader.ch) { |
mcimadamore@1113 | 355 | case 'A': case 'B': case 'C': case 'D': case 'E': |
mcimadamore@1113 | 356 | case 'F': case 'G': case 'H': case 'I': case 'J': |
mcimadamore@1113 | 357 | case 'K': case 'L': case 'M': case 'N': case 'O': |
mcimadamore@1113 | 358 | case 'P': case 'Q': case 'R': case 'S': case 'T': |
mcimadamore@1113 | 359 | case 'U': case 'V': case 'W': case 'X': case 'Y': |
mcimadamore@1113 | 360 | case 'Z': |
mcimadamore@1113 | 361 | case 'a': case 'b': case 'c': case 'd': case 'e': |
mcimadamore@1113 | 362 | case 'f': case 'g': case 'h': case 'i': case 'j': |
mcimadamore@1113 | 363 | case 'k': case 'l': case 'm': case 'n': case 'o': |
mcimadamore@1113 | 364 | case 'p': case 'q': case 'r': case 's': case 't': |
mcimadamore@1113 | 365 | case 'u': case 'v': case 'w': case 'x': case 'y': |
mcimadamore@1113 | 366 | case 'z': |
mcimadamore@1113 | 367 | case '$': case '_': |
mcimadamore@1113 | 368 | case '0': case '1': case '2': case '3': case '4': |
mcimadamore@1113 | 369 | case '5': case '6': case '7': case '8': case '9': |
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': |
mcimadamore@1113 | 377 | break; |
mcimadamore@1113 | 378 | case '\u001A': // EOI is also a legal identifier part |
mcimadamore@1113 | 379 | if (reader.bp >= reader.buflen) { |
mcimadamore@1125 | 380 | name = reader.name(); |
mcimadamore@1113 | 381 | tk = tokens.lookupKind(name); |
mcimadamore@1113 | 382 | return; |
mcimadamore@1113 | 383 | } |
mcimadamore@1113 | 384 | break; |
mcimadamore@1113 | 385 | default: |
mcimadamore@1113 | 386 | if (reader.ch < '\u0080') { |
mcimadamore@1113 | 387 | // all ASCII range chars already handled, above |
mcimadamore@1113 | 388 | isJavaIdentifierPart = false; |
mcimadamore@1113 | 389 | } else { |
mcimadamore@1113 | 390 | high = reader.scanSurrogates(); |
mcimadamore@1113 | 391 | if (high != 0) { |
mcimadamore@1125 | 392 | reader.putChar(high); |
mcimadamore@1113 | 393 | isJavaIdentifierPart = Character.isJavaIdentifierPart( |
mcimadamore@1113 | 394 | Character.toCodePoint(high, reader.ch)); |
mcimadamore@1113 | 395 | } else { |
mcimadamore@1113 | 396 | isJavaIdentifierPart = Character.isJavaIdentifierPart(reader.ch); |
mcimadamore@1113 | 397 | } |
mcimadamore@1113 | 398 | } |
mcimadamore@1113 | 399 | if (!isJavaIdentifierPart) { |
mcimadamore@1125 | 400 | name = reader.name(); |
mcimadamore@1113 | 401 | tk = tokens.lookupKind(name); |
mcimadamore@1113 | 402 | return; |
mcimadamore@1113 | 403 | } |
mcimadamore@1113 | 404 | } |
mcimadamore@1113 | 405 | } while (true); |
mcimadamore@1113 | 406 | } |
mcimadamore@1113 | 407 | |
mcimadamore@1113 | 408 | /** Return true if reader.ch can be part of an operator. |
mcimadamore@1113 | 409 | */ |
mcimadamore@1113 | 410 | private boolean isSpecial(char ch) { |
mcimadamore@1113 | 411 | switch (ch) { |
mcimadamore@1113 | 412 | case '!': case '%': case '&': case '*': case '?': |
mcimadamore@1113 | 413 | case '+': case '-': case ':': case '<': case '=': |
mcimadamore@1113 | 414 | case '>': case '^': case '|': case '~': |
mcimadamore@1113 | 415 | case '@': |
mcimadamore@1113 | 416 | return true; |
mcimadamore@1113 | 417 | default: |
mcimadamore@1113 | 418 | return false; |
mcimadamore@1113 | 419 | } |
mcimadamore@1113 | 420 | } |
mcimadamore@1113 | 421 | |
mcimadamore@1113 | 422 | /** Read longest possible sequence of special characters and convert |
mcimadamore@1113 | 423 | * to token. |
mcimadamore@1113 | 424 | */ |
mcimadamore@1113 | 425 | private void scanOperator() { |
mcimadamore@1113 | 426 | while (true) { |
mcimadamore@1125 | 427 | reader.putChar(false); |
mcimadamore@1125 | 428 | Name newname = reader.name(); |
mcimadamore@1113 | 429 | TokenKind tk1 = tokens.lookupKind(newname); |
mcimadamore@1113 | 430 | if (tk1 == TokenKind.IDENTIFIER) { |
mcimadamore@1125 | 431 | reader.sp--; |
mcimadamore@1113 | 432 | break; |
mcimadamore@1113 | 433 | } |
mcimadamore@1113 | 434 | tk = tk1; |
mcimadamore@1113 | 435 | reader.scanChar(); |
mcimadamore@1113 | 436 | if (!isSpecial(reader.ch)) break; |
mcimadamore@1113 | 437 | } |
mcimadamore@1113 | 438 | } |
mcimadamore@1113 | 439 | |
mcimadamore@1113 | 440 | /** Read token. |
mcimadamore@1113 | 441 | */ |
mcimadamore@1113 | 442 | public Token readToken() { |
mcimadamore@1113 | 443 | |
mcimadamore@1125 | 444 | reader.sp = 0; |
mcimadamore@1113 | 445 | name = null; |
mcimadamore@1113 | 446 | radix = 0; |
mcimadamore@1125 | 447 | |
mcimadamore@1113 | 448 | int pos = 0; |
mcimadamore@1113 | 449 | int endPos = 0; |
mcimadamore@1125 | 450 | List<Comment> comments = null; |
mcimadamore@1113 | 451 | |
mcimadamore@1113 | 452 | try { |
mcimadamore@1113 | 453 | loop: while (true) { |
mcimadamore@1113 | 454 | pos = reader.bp; |
mcimadamore@1113 | 455 | switch (reader.ch) { |
mcimadamore@1113 | 456 | case ' ': // (Spec 3.6) |
mcimadamore@1113 | 457 | case '\t': // (Spec 3.6) |
mcimadamore@1113 | 458 | case FF: // (Spec 3.6) |
mcimadamore@1113 | 459 | do { |
mcimadamore@1113 | 460 | reader.scanChar(); |
mcimadamore@1113 | 461 | } while (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF); |
mcimadamore@1113 | 462 | processWhiteSpace(pos, reader.bp); |
mcimadamore@1113 | 463 | break; |
mcimadamore@1113 | 464 | case LF: // (Spec 3.4) |
mcimadamore@1113 | 465 | reader.scanChar(); |
mcimadamore@1113 | 466 | processLineTerminator(pos, reader.bp); |
mcimadamore@1113 | 467 | break; |
mcimadamore@1113 | 468 | case CR: // (Spec 3.4) |
mcimadamore@1113 | 469 | reader.scanChar(); |
mcimadamore@1113 | 470 | if (reader.ch == LF) { |
mcimadamore@1113 | 471 | reader.scanChar(); |
mcimadamore@1113 | 472 | } |
mcimadamore@1113 | 473 | processLineTerminator(pos, reader.bp); |
mcimadamore@1113 | 474 | break; |
mcimadamore@1113 | 475 | case 'A': case 'B': case 'C': case 'D': case 'E': |
mcimadamore@1113 | 476 | case 'F': case 'G': case 'H': case 'I': case 'J': |
mcimadamore@1113 | 477 | case 'K': case 'L': case 'M': case 'N': case 'O': |
mcimadamore@1113 | 478 | case 'P': case 'Q': case 'R': case 'S': case 'T': |
mcimadamore@1113 | 479 | case 'U': case 'V': case 'W': case 'X': case 'Y': |
mcimadamore@1113 | 480 | case 'Z': |
mcimadamore@1113 | 481 | case 'a': case 'b': case 'c': case 'd': case 'e': |
mcimadamore@1113 | 482 | case 'f': case 'g': case 'h': case 'i': case 'j': |
mcimadamore@1113 | 483 | case 'k': case 'l': case 'm': case 'n': case 'o': |
mcimadamore@1113 | 484 | case 'p': case 'q': case 'r': case 's': case 't': |
mcimadamore@1113 | 485 | case 'u': case 'v': case 'w': case 'x': case 'y': |
mcimadamore@1113 | 486 | case 'z': |
mcimadamore@1113 | 487 | case '$': case '_': |
mcimadamore@1113 | 488 | scanIdent(); |
mcimadamore@1113 | 489 | break loop; |
mcimadamore@1113 | 490 | case '0': |
mcimadamore@1113 | 491 | reader.scanChar(); |
mcimadamore@1113 | 492 | if (reader.ch == 'x' || reader.ch == 'X') { |
mcimadamore@1113 | 493 | reader.scanChar(); |
mcimadamore@1113 | 494 | skipIllegalUnderscores(); |
mcimadamore@1113 | 495 | if (reader.ch == '.') { |
mcimadamore@1113 | 496 | scanHexFractionAndSuffix(pos, false); |
mcimadamore@1113 | 497 | } else if (reader.digit(pos, 16) < 0) { |
mcimadamore@1113 | 498 | lexError(pos, "invalid.hex.number"); |
mcimadamore@1113 | 499 | } else { |
mcimadamore@1113 | 500 | scanNumber(pos, 16); |
mcimadamore@1113 | 501 | } |
mcimadamore@1113 | 502 | } else if (reader.ch == 'b' || reader.ch == 'B') { |
mcimadamore@1113 | 503 | if (!allowBinaryLiterals) { |
mcimadamore@1113 | 504 | lexError(pos, "unsupported.binary.lit", source.name); |
mcimadamore@1113 | 505 | allowBinaryLiterals = true; |
mcimadamore@1113 | 506 | } |
mcimadamore@1113 | 507 | reader.scanChar(); |
mcimadamore@1113 | 508 | skipIllegalUnderscores(); |
mcimadamore@1113 | 509 | if (reader.digit(pos, 2) < 0) { |
mcimadamore@1113 | 510 | lexError(pos, "invalid.binary.number"); |
mcimadamore@1113 | 511 | } else { |
mcimadamore@1113 | 512 | scanNumber(pos, 2); |
mcimadamore@1113 | 513 | } |
mcimadamore@1113 | 514 | } else { |
mcimadamore@1125 | 515 | reader.putChar('0'); |
mcimadamore@1113 | 516 | if (reader.ch == '_') { |
mcimadamore@1113 | 517 | int savePos = reader.bp; |
mcimadamore@1113 | 518 | do { |
mcimadamore@1113 | 519 | reader.scanChar(); |
mcimadamore@1113 | 520 | } while (reader.ch == '_'); |
mcimadamore@1113 | 521 | if (reader.digit(pos, 10) < 0) { |
mcimadamore@1113 | 522 | lexError(savePos, "illegal.underscore"); |
mcimadamore@1113 | 523 | } |
mcimadamore@1113 | 524 | } |
mcimadamore@1113 | 525 | scanNumber(pos, 8); |
mcimadamore@1113 | 526 | } |
mcimadamore@1113 | 527 | break loop; |
mcimadamore@1113 | 528 | case '1': case '2': case '3': case '4': |
mcimadamore@1113 | 529 | case '5': case '6': case '7': case '8': case '9': |
mcimadamore@1113 | 530 | scanNumber(pos, 10); |
mcimadamore@1113 | 531 | break loop; |
mcimadamore@1113 | 532 | case '.': |
mcimadamore@1113 | 533 | reader.scanChar(); |
mcimadamore@1113 | 534 | if ('0' <= reader.ch && reader.ch <= '9') { |
mcimadamore@1125 | 535 | reader.putChar('.'); |
mcimadamore@1113 | 536 | scanFractionAndSuffix(pos); |
mcimadamore@1113 | 537 | } else if (reader.ch == '.') { |
mcimadamore@1125 | 538 | reader.putChar('.'); reader.putChar('.', true); |
mcimadamore@1113 | 539 | if (reader.ch == '.') { |
mcimadamore@1113 | 540 | reader.scanChar(); |
mcimadamore@1125 | 541 | reader.putChar('.'); |
mcimadamore@1113 | 542 | tk = TokenKind.ELLIPSIS; |
mcimadamore@1113 | 543 | } else { |
mcimadamore@1113 | 544 | lexError(pos, "malformed.fp.lit"); |
mcimadamore@1113 | 545 | } |
mcimadamore@1113 | 546 | } else { |
mcimadamore@1113 | 547 | tk = TokenKind.DOT; |
mcimadamore@1113 | 548 | } |
mcimadamore@1113 | 549 | break loop; |
mcimadamore@1113 | 550 | case ',': |
mcimadamore@1113 | 551 | reader.scanChar(); tk = TokenKind.COMMA; break loop; |
mcimadamore@1113 | 552 | case ';': |
mcimadamore@1113 | 553 | reader.scanChar(); tk = TokenKind.SEMI; break loop; |
mcimadamore@1113 | 554 | case '(': |
mcimadamore@1113 | 555 | reader.scanChar(); tk = TokenKind.LPAREN; break loop; |
mcimadamore@1113 | 556 | case ')': |
mcimadamore@1113 | 557 | reader.scanChar(); tk = TokenKind.RPAREN; break loop; |
mcimadamore@1113 | 558 | case '[': |
mcimadamore@1113 | 559 | reader.scanChar(); tk = TokenKind.LBRACKET; break loop; |
mcimadamore@1113 | 560 | case ']': |
mcimadamore@1113 | 561 | reader.scanChar(); tk = TokenKind.RBRACKET; break loop; |
mcimadamore@1113 | 562 | case '{': |
mcimadamore@1113 | 563 | reader.scanChar(); tk = TokenKind.LBRACE; break loop; |
mcimadamore@1113 | 564 | case '}': |
mcimadamore@1113 | 565 | reader.scanChar(); tk = TokenKind.RBRACE; break loop; |
mcimadamore@1113 | 566 | case '/': |
mcimadamore@1113 | 567 | reader.scanChar(); |
mcimadamore@1113 | 568 | if (reader.ch == '/') { |
mcimadamore@1113 | 569 | do { |
mcimadamore@1125 | 570 | reader.scanCommentChar(); |
mcimadamore@1113 | 571 | } while (reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen); |
mcimadamore@1113 | 572 | if (reader.bp < reader.buflen) { |
mcimadamore@1125 | 573 | comments = addDocReader(comments, processComment(pos, reader.bp, CommentStyle.LINE)); |
mcimadamore@1113 | 574 | } |
mcimadamore@1113 | 575 | break; |
mcimadamore@1113 | 576 | } else if (reader.ch == '*') { |
mcimadamore@1125 | 577 | boolean isEmpty = false; |
mcimadamore@1113 | 578 | reader.scanChar(); |
mcimadamore@1113 | 579 | CommentStyle style; |
mcimadamore@1113 | 580 | if (reader.ch == '*') { |
mcimadamore@1113 | 581 | style = CommentStyle.JAVADOC; |
mcimadamore@1125 | 582 | reader.scanCommentChar(); |
mcimadamore@1125 | 583 | if (reader.ch == '/') { |
mcimadamore@1125 | 584 | isEmpty = true; |
mcimadamore@1125 | 585 | } |
mcimadamore@1113 | 586 | } else { |
mcimadamore@1113 | 587 | style = CommentStyle.BLOCK; |
mcimadamore@1125 | 588 | } |
mcimadamore@1125 | 589 | while (!isEmpty && reader.bp < reader.buflen) { |
mcimadamore@1125 | 590 | if (reader.ch == '*') { |
mcimadamore@1125 | 591 | reader.scanChar(); |
mcimadamore@1125 | 592 | if (reader.ch == '/') break; |
mcimadamore@1125 | 593 | } else { |
mcimadamore@1125 | 594 | reader.scanCommentChar(); |
mcimadamore@1113 | 595 | } |
mcimadamore@1113 | 596 | } |
mcimadamore@1113 | 597 | if (reader.ch == '/') { |
mcimadamore@1113 | 598 | reader.scanChar(); |
mcimadamore@1125 | 599 | comments = addDocReader(comments, processComment(pos, reader.bp, style)); |
mcimadamore@1113 | 600 | break; |
mcimadamore@1113 | 601 | } else { |
mcimadamore@1113 | 602 | lexError(pos, "unclosed.comment"); |
mcimadamore@1113 | 603 | break loop; |
mcimadamore@1113 | 604 | } |
mcimadamore@1113 | 605 | } else if (reader.ch == '=') { |
mcimadamore@1113 | 606 | tk = TokenKind.SLASHEQ; |
mcimadamore@1113 | 607 | reader.scanChar(); |
mcimadamore@1113 | 608 | } else { |
mcimadamore@1113 | 609 | tk = TokenKind.SLASH; |
mcimadamore@1113 | 610 | } |
mcimadamore@1113 | 611 | break loop; |
mcimadamore@1113 | 612 | case '\'': |
mcimadamore@1113 | 613 | reader.scanChar(); |
mcimadamore@1113 | 614 | if (reader.ch == '\'') { |
mcimadamore@1113 | 615 | lexError(pos, "empty.char.lit"); |
mcimadamore@1113 | 616 | } else { |
mcimadamore@1113 | 617 | if (reader.ch == CR || reader.ch == LF) |
mcimadamore@1113 | 618 | lexError(pos, "illegal.line.end.in.char.lit"); |
mcimadamore@1113 | 619 | scanLitChar(pos); |
mcimadamore@1113 | 620 | char ch2 = reader.ch; |
mcimadamore@1113 | 621 | if (reader.ch == '\'') { |
mcimadamore@1113 | 622 | reader.scanChar(); |
mcimadamore@1113 | 623 | tk = TokenKind.CHARLITERAL; |
mcimadamore@1113 | 624 | } else { |
mcimadamore@1113 | 625 | lexError(pos, "unclosed.char.lit"); |
mcimadamore@1113 | 626 | } |
mcimadamore@1113 | 627 | } |
mcimadamore@1113 | 628 | break loop; |
mcimadamore@1113 | 629 | case '\"': |
mcimadamore@1113 | 630 | reader.scanChar(); |
mcimadamore@1113 | 631 | while (reader.ch != '\"' && reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen) |
mcimadamore@1113 | 632 | scanLitChar(pos); |
mcimadamore@1113 | 633 | if (reader.ch == '\"') { |
mcimadamore@1113 | 634 | tk = TokenKind.STRINGLITERAL; |
mcimadamore@1113 | 635 | reader.scanChar(); |
mcimadamore@1113 | 636 | } else { |
mcimadamore@1113 | 637 | lexError(pos, "unclosed.str.lit"); |
mcimadamore@1113 | 638 | } |
mcimadamore@1113 | 639 | break loop; |
mcimadamore@1113 | 640 | default: |
mcimadamore@1113 | 641 | if (isSpecial(reader.ch)) { |
mcimadamore@1113 | 642 | scanOperator(); |
mcimadamore@1113 | 643 | } else { |
mcimadamore@1113 | 644 | boolean isJavaIdentifierStart; |
mcimadamore@1113 | 645 | if (reader.ch < '\u0080') { |
mcimadamore@1113 | 646 | // all ASCII range chars already handled, above |
mcimadamore@1113 | 647 | isJavaIdentifierStart = false; |
mcimadamore@1113 | 648 | } else { |
mcimadamore@1113 | 649 | char high = reader.scanSurrogates(); |
mcimadamore@1113 | 650 | if (high != 0) { |
mcimadamore@1125 | 651 | reader.putChar(high); |
mcimadamore@1113 | 652 | |
mcimadamore@1113 | 653 | isJavaIdentifierStart = Character.isJavaIdentifierStart( |
mcimadamore@1113 | 654 | Character.toCodePoint(high, reader.ch)); |
mcimadamore@1113 | 655 | } else { |
mcimadamore@1113 | 656 | isJavaIdentifierStart = Character.isJavaIdentifierStart(reader.ch); |
mcimadamore@1113 | 657 | } |
mcimadamore@1113 | 658 | } |
mcimadamore@1113 | 659 | if (isJavaIdentifierStart) { |
mcimadamore@1113 | 660 | scanIdent(); |
mcimadamore@1113 | 661 | } else if (reader.bp == reader.buflen || reader.ch == EOI && reader.bp + 1 == reader.buflen) { // JLS 3.5 |
mcimadamore@1113 | 662 | tk = TokenKind.EOF; |
mcimadamore@1113 | 663 | pos = reader.buflen; |
mcimadamore@1113 | 664 | } else { |
mcimadamore@1113 | 665 | lexError(pos, "illegal.char", String.valueOf((int)reader.ch)); |
mcimadamore@1113 | 666 | reader.scanChar(); |
mcimadamore@1113 | 667 | } |
mcimadamore@1113 | 668 | } |
mcimadamore@1113 | 669 | break loop; |
mcimadamore@1113 | 670 | } |
mcimadamore@1113 | 671 | } |
mcimadamore@1113 | 672 | endPos = reader.bp; |
mcimadamore@1113 | 673 | switch (tk.tag) { |
mcimadamore@1125 | 674 | case DEFAULT: return new Token(tk, pos, endPos, comments); |
mcimadamore@1125 | 675 | case NAMED: return new NamedToken(tk, pos, endPos, name, comments); |
mcimadamore@1125 | 676 | case STRING: return new StringToken(tk, pos, endPos, reader.chars(), comments); |
mcimadamore@1125 | 677 | case NUMERIC: return new NumericToken(tk, pos, endPos, reader.chars(), radix, comments); |
mcimadamore@1113 | 678 | default: throw new AssertionError(); |
mcimadamore@1113 | 679 | } |
mcimadamore@1113 | 680 | } |
mcimadamore@1113 | 681 | finally { |
mcimadamore@1113 | 682 | if (scannerDebug) { |
mcimadamore@1113 | 683 | System.out.println("nextToken(" + pos |
mcimadamore@1113 | 684 | + "," + endPos + ")=|" + |
mcimadamore@1113 | 685 | new String(reader.getRawCharacters(pos, endPos)) |
mcimadamore@1113 | 686 | + "|"); |
mcimadamore@1113 | 687 | } |
mcimadamore@1113 | 688 | } |
mcimadamore@1113 | 689 | } |
mcimadamore@1125 | 690 | //where |
mcimadamore@1125 | 691 | List<Comment> addDocReader(List<Comment> docReaders, Comment docReader) { |
mcimadamore@1125 | 692 | return docReaders == null ? |
mcimadamore@1125 | 693 | List.of(docReader) : |
mcimadamore@1125 | 694 | docReaders.prepend(docReader); |
mcimadamore@1125 | 695 | } |
mcimadamore@1113 | 696 | |
mcimadamore@1113 | 697 | /** Return the position where a lexical error occurred; |
mcimadamore@1113 | 698 | */ |
mcimadamore@1113 | 699 | public int errPos() { |
mcimadamore@1113 | 700 | return errPos; |
mcimadamore@1113 | 701 | } |
mcimadamore@1113 | 702 | |
mcimadamore@1113 | 703 | /** Set the position where a lexical error occurred; |
mcimadamore@1113 | 704 | */ |
mcimadamore@1113 | 705 | public void errPos(int pos) { |
mcimadamore@1113 | 706 | errPos = pos; |
mcimadamore@1113 | 707 | } |
mcimadamore@1113 | 708 | |
mcimadamore@1113 | 709 | /** |
mcimadamore@1113 | 710 | * Called when a complete comment has been scanned. pos and endPos |
mcimadamore@1113 | 711 | * will mark the comment boundary. |
mcimadamore@1113 | 712 | */ |
mcimadamore@1125 | 713 | protected Tokens.Comment processComment(int pos, int endPos, CommentStyle style) { |
mcimadamore@1113 | 714 | if (scannerDebug) |
mcimadamore@1113 | 715 | System.out.println("processComment(" + pos |
mcimadamore@1113 | 716 | + "," + endPos + "," + style + ")=|" |
mcimadamore@1113 | 717 | + new String(reader.getRawCharacters(pos, endPos)) |
mcimadamore@1113 | 718 | + "|"); |
mcimadamore@1125 | 719 | char[] buf = reader.getRawCharacters(pos, endPos); |
mcimadamore@1125 | 720 | return new BasicComment<UnicodeReader>(new UnicodeReader(fac, buf, buf.length), style); |
mcimadamore@1113 | 721 | } |
mcimadamore@1113 | 722 | |
mcimadamore@1113 | 723 | /** |
mcimadamore@1113 | 724 | * Called when a complete whitespace run has been scanned. pos and endPos |
mcimadamore@1113 | 725 | * will mark the whitespace boundary. |
mcimadamore@1113 | 726 | */ |
mcimadamore@1113 | 727 | protected void processWhiteSpace(int pos, int endPos) { |
mcimadamore@1113 | 728 | if (scannerDebug) |
mcimadamore@1113 | 729 | System.out.println("processWhitespace(" + pos |
mcimadamore@1113 | 730 | + "," + endPos + ")=|" + |
mcimadamore@1113 | 731 | new String(reader.getRawCharacters(pos, endPos)) |
mcimadamore@1113 | 732 | + "|"); |
mcimadamore@1113 | 733 | } |
mcimadamore@1113 | 734 | |
mcimadamore@1113 | 735 | /** |
mcimadamore@1113 | 736 | * Called when a line terminator has been processed. |
mcimadamore@1113 | 737 | */ |
mcimadamore@1113 | 738 | protected void processLineTerminator(int pos, int endPos) { |
mcimadamore@1113 | 739 | if (scannerDebug) |
mcimadamore@1113 | 740 | System.out.println("processTerminator(" + pos |
mcimadamore@1113 | 741 | + "," + endPos + ")=|" + |
mcimadamore@1113 | 742 | new String(reader.getRawCharacters(pos, endPos)) |
mcimadamore@1113 | 743 | + "|"); |
mcimadamore@1113 | 744 | } |
mcimadamore@1113 | 745 | |
mcimadamore@1113 | 746 | /** Build a map for translating between line numbers and |
mcimadamore@1113 | 747 | * positions in the input. |
mcimadamore@1113 | 748 | * |
mcimadamore@1113 | 749 | * @return a LineMap */ |
mcimadamore@1113 | 750 | public Position.LineMap getLineMap() { |
mcimadamore@1113 | 751 | return Position.makeLineMap(reader.getRawCharacters(), reader.buflen, false); |
mcimadamore@1113 | 752 | } |
mcimadamore@1125 | 753 | |
mcimadamore@1125 | 754 | |
mcimadamore@1125 | 755 | /** |
mcimadamore@1125 | 756 | * Scan a documentation comment; determine if a deprecated tag is present. |
mcimadamore@1125 | 757 | * Called once the initial /, * have been skipped, positioned at the second * |
mcimadamore@1125 | 758 | * (which is treated as the beginning of the first line). |
mcimadamore@1125 | 759 | * Stops positioned at the closing '/'. |
mcimadamore@1125 | 760 | */ |
mcimadamore@1125 | 761 | protected class BasicComment<U extends UnicodeReader> implements Comment { |
mcimadamore@1125 | 762 | |
mcimadamore@1125 | 763 | CommentStyle cs; |
mcimadamore@1125 | 764 | U comment_reader; |
mcimadamore@1125 | 765 | |
mcimadamore@1125 | 766 | protected boolean deprecatedFlag = false; |
mcimadamore@1125 | 767 | protected boolean scanned = false; |
mcimadamore@1125 | 768 | |
mcimadamore@1125 | 769 | protected BasicComment(U comment_reader, CommentStyle cs) { |
mcimadamore@1125 | 770 | this.comment_reader = comment_reader; |
mcimadamore@1125 | 771 | this.cs = cs; |
mcimadamore@1125 | 772 | } |
mcimadamore@1125 | 773 | |
mcimadamore@1125 | 774 | public String getText() { |
mcimadamore@1125 | 775 | return null; |
mcimadamore@1125 | 776 | } |
mcimadamore@1125 | 777 | |
mcimadamore@1125 | 778 | public CommentStyle getStyle() { |
mcimadamore@1125 | 779 | return cs; |
mcimadamore@1125 | 780 | } |
mcimadamore@1125 | 781 | |
mcimadamore@1125 | 782 | public boolean isDeprecated() { |
mcimadamore@1125 | 783 | if (!scanned && cs == CommentStyle.JAVADOC) { |
mcimadamore@1125 | 784 | scanDocComment(); |
mcimadamore@1125 | 785 | } |
mcimadamore@1125 | 786 | return deprecatedFlag; |
mcimadamore@1125 | 787 | } |
mcimadamore@1125 | 788 | |
mcimadamore@1125 | 789 | @SuppressWarnings("fallthrough") |
mcimadamore@1125 | 790 | protected void scanDocComment() { |
mcimadamore@1125 | 791 | try { |
mcimadamore@1125 | 792 | boolean deprecatedPrefix = false; |
mcimadamore@1125 | 793 | |
mcimadamore@1125 | 794 | comment_reader.bp += 3; // '/**' |
mcimadamore@1125 | 795 | comment_reader.ch = comment_reader.buf[comment_reader.bp]; |
mcimadamore@1125 | 796 | |
mcimadamore@1125 | 797 | forEachLine: |
mcimadamore@1125 | 798 | while (comment_reader.bp < comment_reader.buflen) { |
mcimadamore@1125 | 799 | |
mcimadamore@1125 | 800 | // Skip optional WhiteSpace at beginning of line |
mcimadamore@1125 | 801 | while (comment_reader.bp < comment_reader.buflen && (comment_reader.ch == ' ' || comment_reader.ch == '\t' || comment_reader.ch == FF)) { |
mcimadamore@1125 | 802 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 803 | } |
mcimadamore@1125 | 804 | |
mcimadamore@1125 | 805 | // Skip optional consecutive Stars |
mcimadamore@1125 | 806 | while (comment_reader.bp < comment_reader.buflen && comment_reader.ch == '*') { |
mcimadamore@1125 | 807 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 808 | if (comment_reader.ch == '/') { |
mcimadamore@1125 | 809 | return; |
mcimadamore@1125 | 810 | } |
mcimadamore@1125 | 811 | } |
mcimadamore@1125 | 812 | |
mcimadamore@1125 | 813 | // Skip optional WhiteSpace after Stars |
mcimadamore@1125 | 814 | while (comment_reader.bp < comment_reader.buflen && (comment_reader.ch == ' ' || comment_reader.ch == '\t' || comment_reader.ch == FF)) { |
mcimadamore@1125 | 815 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 816 | } |
mcimadamore@1125 | 817 | |
mcimadamore@1125 | 818 | deprecatedPrefix = false; |
mcimadamore@1125 | 819 | // At beginning of line in the JavaDoc sense. |
mcimadamore@1125 | 820 | if (!deprecatedFlag) { |
mcimadamore@1125 | 821 | String deprecated = "@deprecated"; |
mcimadamore@1125 | 822 | int i = 0; |
mcimadamore@1125 | 823 | while (comment_reader.bp < comment_reader.buflen && comment_reader.ch == deprecated.charAt(i)) { |
mcimadamore@1125 | 824 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 825 | i++; |
mcimadamore@1125 | 826 | if (i == deprecated.length()) { |
mcimadamore@1125 | 827 | deprecatedPrefix = true; |
mcimadamore@1125 | 828 | break; |
mcimadamore@1125 | 829 | } |
mcimadamore@1125 | 830 | } |
mcimadamore@1125 | 831 | } |
mcimadamore@1125 | 832 | |
mcimadamore@1125 | 833 | if (deprecatedPrefix && comment_reader.bp < comment_reader.buflen) { |
mcimadamore@1125 | 834 | if (Character.isWhitespace(comment_reader.ch)) { |
mcimadamore@1125 | 835 | deprecatedFlag = true; |
mcimadamore@1125 | 836 | } else if (comment_reader.ch == '*') { |
mcimadamore@1125 | 837 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 838 | if (comment_reader.ch == '/') { |
mcimadamore@1125 | 839 | deprecatedFlag = true; |
mcimadamore@1125 | 840 | return; |
mcimadamore@1125 | 841 | } |
mcimadamore@1125 | 842 | } |
mcimadamore@1125 | 843 | } |
mcimadamore@1125 | 844 | |
mcimadamore@1125 | 845 | // Skip rest of line |
mcimadamore@1125 | 846 | while (comment_reader.bp < comment_reader.buflen) { |
mcimadamore@1125 | 847 | switch (comment_reader.ch) { |
mcimadamore@1125 | 848 | case '*': |
mcimadamore@1125 | 849 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 850 | if (comment_reader.ch == '/') { |
mcimadamore@1125 | 851 | return; |
mcimadamore@1125 | 852 | } |
mcimadamore@1125 | 853 | break; |
mcimadamore@1125 | 854 | case CR: // (Spec 3.4) |
mcimadamore@1125 | 855 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 856 | if (comment_reader.ch != LF) { |
mcimadamore@1125 | 857 | continue forEachLine; |
mcimadamore@1125 | 858 | } |
mcimadamore@1125 | 859 | /* fall through to LF case */ |
mcimadamore@1125 | 860 | case LF: // (Spec 3.4) |
mcimadamore@1125 | 861 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 862 | continue forEachLine; |
mcimadamore@1125 | 863 | default: |
mcimadamore@1125 | 864 | comment_reader.scanCommentChar(); |
mcimadamore@1125 | 865 | } |
mcimadamore@1125 | 866 | } // rest of line |
mcimadamore@1125 | 867 | } // forEachLine |
mcimadamore@1125 | 868 | return; |
mcimadamore@1125 | 869 | } finally { |
mcimadamore@1125 | 870 | scanned = true; |
mcimadamore@1125 | 871 | } |
mcimadamore@1125 | 872 | } |
mcimadamore@1125 | 873 | } |
mcimadamore@1113 | 874 | } |