64 |
64 |
65 /** Allow underscores in literals. |
65 /** Allow underscores in literals. |
66 */ |
66 */ |
67 private boolean allowUnderscoresInLiterals; |
67 private boolean allowUnderscoresInLiterals; |
68 |
68 |
69 /** Allow exotic identifiers. |
|
70 */ |
|
71 private boolean allowExoticIdentifiers; |
|
72 |
|
73 /** The source language setting. |
69 /** The source language setting. |
74 */ |
70 */ |
75 private Source source; |
71 private Source source; |
76 |
72 |
77 /** The token's position, 0-based offset from beginning of text. |
73 /** The token's position, 0-based offset from beginning of text. |
141 keywords = fac.keywords; |
137 keywords = fac.keywords; |
142 source = fac.source; |
138 source = fac.source; |
143 allowBinaryLiterals = source.allowBinaryLiterals(); |
139 allowBinaryLiterals = source.allowBinaryLiterals(); |
144 allowHexFloats = source.allowHexFloats(); |
140 allowHexFloats = source.allowHexFloats(); |
145 allowUnderscoresInLiterals = source.allowBinaryLiterals(); |
141 allowUnderscoresInLiterals = source.allowBinaryLiterals(); |
146 allowExoticIdentifiers = source.allowExoticIdentifiers(); // for invokedynamic |
|
147 } |
142 } |
148 |
143 |
149 private static final boolean hexFloatsWork = hexFloatsWork(); |
144 private static final boolean hexFloatsWork = hexFloatsWork(); |
150 private static boolean hexFloatsWork() { |
145 private static boolean hexFloatsWork() { |
151 try { |
146 try { |
333 putChar('\''); scanChar(); break; |
328 putChar('\''); scanChar(); break; |
334 case '\"': |
329 case '\"': |
335 putChar('\"'); scanChar(); break; |
330 putChar('\"'); scanChar(); break; |
336 case '\\': |
331 case '\\': |
337 putChar('\\'); scanChar(); break; |
332 putChar('\\'); scanChar(); break; |
338 case '|': case ',': case '?': case '%': |
|
339 case '^': case '_': case '{': case '}': |
|
340 case '!': case '-': case '=': |
|
341 if (forBytecodeName) { |
|
342 // Accept escape sequences for dangerous bytecode chars. |
|
343 // This is illegal in normal Java string or character literals. |
|
344 // Note that the escape sequence itself is passed through. |
|
345 putChar('\\'); putChar(ch); scanChar(); |
|
346 } else { |
|
347 lexError(bp, "illegal.esc.char"); |
|
348 } |
|
349 break; |
|
350 default: |
333 default: |
351 lexError(bp, "illegal.esc.char"); |
334 lexError(bp, "illegal.esc.char"); |
352 } |
335 } |
353 } |
336 } |
354 } else if (bp != buflen) { |
337 } else if (bp != buflen) { |
355 putChar(ch); scanChar(); |
338 putChar(ch); scanChar(); |
356 } |
339 } |
357 } |
|
358 private void scanLitChar() { |
|
359 scanLitChar(false); |
|
360 } |
|
361 |
|
362 /** Read next character in an exotic name #"foo" |
|
363 */ |
|
364 private void scanBytecodeNameChar() { |
|
365 switch (ch) { |
|
366 // reject any "dangerous" char which is illegal somewhere in the JVM spec |
|
367 // cf. http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm |
|
368 case '/': case '.': case ';': // illegal everywhere |
|
369 case '<': case '>': // illegal in methods, dangerous in classes |
|
370 case '[': // illegal in classes |
|
371 lexError(bp, "illegal.bytecode.ident.char", String.valueOf((int)ch)); |
|
372 break; |
|
373 } |
|
374 scanLitChar(true); |
|
375 } |
340 } |
376 |
341 |
377 private void scanDigits(int digitRadix) { |
342 private void scanDigits(int digitRadix) { |
378 char saveCh; |
343 char saveCh; |
379 int savePos; |
344 int savePos; |
968 scanChar(); |
933 scanChar(); |
969 } else { |
934 } else { |
970 lexError(pos, "unclosed.str.lit"); |
935 lexError(pos, "unclosed.str.lit"); |
971 } |
936 } |
972 return; |
937 return; |
973 case '#': |
|
974 scanChar(); |
|
975 if (ch == '\"') { |
|
976 if (!allowExoticIdentifiers) { |
|
977 lexError("unsupported.exotic.id", source.name); |
|
978 allowExoticIdentifiers = true; |
|
979 } |
|
980 scanChar(); |
|
981 if (ch == '\"') |
|
982 lexError(pos, "empty.bytecode.ident"); |
|
983 while (ch != '\"' && ch != CR && ch != LF && bp < buflen) { |
|
984 scanBytecodeNameChar(); |
|
985 } |
|
986 if (ch == '\"') { |
|
987 name = names.fromChars(sbuf, 0, sp); |
|
988 token = IDENTIFIER; // even if #"int" or #"do" |
|
989 scanChar(); |
|
990 } else { |
|
991 lexError(pos, "unclosed.bytecode.ident"); |
|
992 } |
|
993 } else { |
|
994 lexError("illegal.char", String.valueOf((int)'#')); |
|
995 } |
|
996 return; |
|
997 default: |
938 default: |
998 if (isSpecial(ch)) { |
939 if (isSpecial(ch)) { |
999 scanOperator(); |
940 scanOperator(); |
1000 } else { |
941 } else { |
1001 boolean isJavaIdentifierStart; |
942 boolean isJavaIdentifierStart; |